map-transform 1.6.0-rc.7 → 1.6.0-rc.9

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 (82) hide show
  1. package/NEXT.md +123 -0
  2. package/README.md +190 -71
  3. package/WRITING_PIPELINES.md +279 -106
  4. package/dist/index.d.ts +0 -1
  5. package/dist/index.js +0 -1
  6. package/dist/index.js.map +1 -1
  7. package/dist/internalOptions.d.ts +9 -0
  8. package/dist/internalOptions.js +21 -0
  9. package/dist/internalOptions.js.map +1 -0
  10. package/dist/legacy/createPathMapper.d.ts +4 -0
  11. package/dist/legacy/createPathMapper.js +21 -2
  12. package/dist/legacy/createPathMapper.js.map +1 -1
  13. package/dist/legacy/operations/lookup.js +2 -2
  14. package/dist/legacy/operations/lookup.js.map +1 -1
  15. package/dist/legacy/transformers/bucket.js +2 -1
  16. package/dist/legacy/transformers/bucket.js.map +1 -1
  17. package/dist/legacy/transformers/compare.js +3 -3
  18. package/dist/legacy/transformers/compare.js.map +1 -1
  19. package/dist/legacy/transformers/get.js +2 -2
  20. package/dist/legacy/transformers/get.js.map +1 -1
  21. package/dist/legacy/transformers/index.d.ts +1 -1
  22. package/dist/legacy/transformers/project.js +2 -2
  23. package/dist/legacy/transformers/project.js.map +1 -1
  24. package/dist/legacy/transformers/sort.js +2 -2
  25. package/dist/legacy/transformers/sort.js.map +1 -1
  26. package/dist/legacy/types.d.ts +17 -6
  27. package/dist/legacy/utils/prepareOptions.js +17 -10
  28. package/dist/legacy/utils/prepareOptions.js.map +1 -1
  29. package/dist/mapTransform.d.ts +3 -3
  30. package/dist/mapTransform.js +16 -25
  31. package/dist/mapTransform.js.map +1 -1
  32. package/dist/prep/alt.js +6 -0
  33. package/dist/prep/alt.js.map +1 -1
  34. package/dist/prep/apply.js +16 -3
  35. package/dist/prep/apply.js.map +1 -1
  36. package/dist/prep/array.js +6 -0
  37. package/dist/prep/array.js.map +1 -1
  38. package/dist/prep/filter.js +4 -1
  39. package/dist/prep/filter.js.map +1 -1
  40. package/dist/prep/index.d.ts +0 -1
  41. package/dist/prep/index.js +33 -12
  42. package/dist/prep/index.js.map +1 -1
  43. package/dist/prep/iterate.d.ts +1 -1
  44. package/dist/prep/iterate.js +2 -1
  45. package/dist/prep/iterate.js.map +1 -1
  46. package/dist/prep/mutation.js +17 -6
  47. package/dist/prep/mutation.js.map +1 -1
  48. package/dist/prep/path.js +3 -9
  49. package/dist/prep/path.js.map +1 -1
  50. package/dist/prep/transform.d.ts +1 -0
  51. package/dist/prep/transform.js +5 -4
  52. package/dist/prep/transform.js.map +1 -1
  53. package/dist/prepareOptions.d.ts +8 -0
  54. package/dist/prepareOptions.js +20 -0
  55. package/dist/prepareOptions.js.map +1 -0
  56. package/dist/run/alt.js +7 -5
  57. package/dist/run/alt.js.map +1 -1
  58. package/dist/run/index.d.ts +0 -5
  59. package/dist/run/index.js +33 -27
  60. package/dist/run/index.js.map +1 -1
  61. package/dist/run/iterate.js +2 -22
  62. package/dist/run/iterate.js.map +1 -1
  63. package/dist/run/mutation.d.ts +2 -1
  64. package/dist/run/mutation.js +2 -2
  65. package/dist/run/mutation.js.map +1 -1
  66. package/dist/run/path.d.ts +2 -1
  67. package/dist/run/path.js +11 -6
  68. package/dist/run/path.js.map +1 -1
  69. package/dist/run/resolveParentSets.d.ts +2 -0
  70. package/dist/run/resolveParentSets.js +46 -0
  71. package/dist/run/resolveParentSets.js.map +1 -0
  72. package/dist/run/transform.d.ts +3 -1
  73. package/dist/run/transform.js +9 -1
  74. package/dist/run/transform.js.map +1 -1
  75. package/dist/state.d.ts +2 -0
  76. package/dist/state.js +2 -0
  77. package/dist/state.js.map +1 -1
  78. package/dist/typesNext.d.ts +17 -5
  79. package/dist/utils/is.d.ts +1 -0
  80. package/dist/utils/is.js +1 -0
  81. package/dist/utils/is.js.map +1 -1
  82. package/package.json +2 -2
package/NEXT.md ADDED
@@ -0,0 +1,123 @@
1
+ # Proposals for MapTransform v2 (`next`)
2
+
3
+ A list of suggested changes to the `next` mutation language, to be taken on one
4
+ at a time. Each section is self-contained: what the problem is, what the change
5
+ is, and which verified findings it addresses. Findings marked _(verified)_ were
6
+ reproduced by running `mapTransform` from `src/mapTransform.ts` on small inputs.
7
+
8
+ ## Background: how the engine models context and reverse today
9
+
10
+ **Context is structural.** Only drilling down adds a level, operations are
11
+ opaque, set steps don't move, `^^` is depth zero of the current tree and `^^^`
12
+ the original input. In reverse, a target context mirrors the context, so parent
13
+ and root paths set on the parent or root target
14
+ (`src/run/resolveParentSets.ts`). See "Parent and root paths" in the README.
15
+
16
+ **Reverse is a syntactic reversal.** `adjustPipelineToDirection`
17
+ (`src/run/index.ts`) reverses the prepped steps. Pipelines whose first step is
18
+ not a path are silently prefixed with `.` or given a reverse plug
19
+ (`src/prep/mutation.ts`).
20
+
21
+ **`flip` is runtime state.** `isRev = xor(rev, flip)`. `$apply` clears it, `$if`
22
+ conditions force forward, `$array` forces a direction per branch, `$direction`
23
+ ignores it, and `lookup` special-cases it.
24
+
25
+ ## Reverse by rule, not by heuristic
26
+
27
+ ### Problem
28
+
29
+ - `$flip: false` is dropped at prep time, so a nested object cannot un-flip.
30
+ - `$direction` ignores `flip`, but paths honor it.
31
+ - Pipelines that do not start with a path are silently plugged or prefixed with
32
+ `.` in reverse (`addStepWhenNoGetStep` in `src/prep/mutation.ts`).
33
+
34
+ ### Change
35
+
36
+ - Add an explicit two-sided form for the hard cases, JSON-friendly:
37
+ `{ "$fwd": [...], "$rev": [...] }`. This replaces legacy `divide`, `fwd`, and
38
+ `rev`, and most uses of `$direction` on two adjacent steps.
39
+ - `$alt` in reverse: set with the first pipeline; if the value is a nonvalue,
40
+ use the last `$default`. Losing pipelines are never run as setters.
41
+ - `$flip` becomes a prep-time rewrite: swap key and value, reverse each
42
+ pipeline, toggle `>`. `flip` leaves `State`. Transformers that need to know,
43
+ such as `lookup`, get a flag on the transform step at prep time.
44
+
45
+ ## One modifier for "the other direction"
46
+
47
+ ### Problem
48
+
49
+ Direction pairs are spelled five ways: `$concat`/`$concatRev`,
50
+ `merge`/`mergeRev`, `$lookup`/`$lookdown`, `explode`/`implode`, and `$array`
51
+ with `$flip`.
52
+
53
+ ### Change
54
+
55
+ Allow `$flip: true` on any operation object, and drop `$concatRev`, `mergeRev`,
56
+ `$lookdown`, `implode`, and the special `$flip` handling on `$array`. Keep
57
+ `explode`/`implode` names only if they read better than `explode` + `$flip`.
58
+
59
+ ## Constants vs defaults
60
+
61
+ ### Problem
62
+
63
+ Two concepts have five spellings: `$value`, `$fixed`, `$value` with
64
+ `fixed: true`, and the `value` and `fixed` transformers. `$value` being
65
+ suppressed by `noDefaults` is surprising when it is used as a constant, which is
66
+ why `fixed` exists.
67
+
68
+ ### Change
69
+
70
+ - `$value: x` is a constant and is never suppressed.
71
+ - `$default: x` is a fallback and is suppressed by `noDefaults`.
72
+ - Drop `$fixed`, `fixed: true`, and the `fixed` transformer.
73
+
74
+ `$alt: ['fullname', { $default: 'Anon' }]` then reads as intended.
75
+
76
+ ## Reverse-only props without slashed keys
77
+
78
+ ### Problem
79
+
80
+ Reverse-only props use the lexical trick `name/1`, with `\/` escaping for
81
+ literal slashes.
82
+
83
+ ### Change
84
+
85
+ A `$rev: { name: [...] }` block on a mutation object holds props that only apply
86
+ in reverse, merged over the main props. `$fwd: { ... }` for symmetry. `name/1`
87
+ and its escaping go away.
88
+
89
+ ## Fail loudly at prep time
90
+
91
+ ### Problem
92
+
93
+ Bad input is accepted silently:
94
+
95
+ - Unknown `$direction` values, including typos, mean "both" _(verified)_.
96
+ - `[1:3]` and `[abc]` go through `parseInt` and become `[1]` and `[NaN]`
97
+ _(verified)_.
98
+ - Unknown `$`-keys on a mutation object, boolean values, `$alt: []`, non-array
99
+ `$nonvalues`, and unknown `compare` operators are dropped or ignored without a
100
+ message.
101
+ - Setting to parent or root degrades silently instead of failing.
102
+
103
+ ### Change
104
+
105
+ Throw at prep time on all of the above. Prep runs once, so this costs nothing at
106
+ run time.
107
+
108
+ ## Trim compatibility leftovers
109
+
110
+ ### Problem
111
+
112
+ Kept for compatibility but pure noise in v2: the `<` get prefix, the
113
+ `$undefined` alias of `$nonvalues`, `fwdAlias`/`revAlias`, `$value` accepting a
114
+ function, and `$if` using unprefixed `then`/`else` while everything else is
115
+ `$`-prefixed.
116
+
117
+ `$alwaysApply` is not inherited, so it must be repeated on every nested mutation
118
+ object.
119
+
120
+ ### Change
121
+
122
+ Drop the leftovers listed above. Make `$alwaysApply` inherited by nested
123
+ mutation objects.
package/README.md CHANGED
@@ -176,26 +176,16 @@ await mapTransform(def)(source, { target }) // We're reusing `def` from the prev
176
176
  ```
177
177
 
178
178
  Finally, if you're using the same `options` across several `mapTransform` calls,
179
- you may gain some optimization by preparing the options up front. Do this with
180
- the exported `prepareOptions` function like so:
179
+ pass the same options object each time. Calls with the same options object share
180
+ prepared pipelines automatically, so a pipeline is only prepared once. Changing
181
+ pipeline definitions on the options object after it has been used is not
182
+ supported.
181
183
 
182
- ```javascript
183
- import mapTransform, { prepareOptions, transform } from 'map-transform'
184
-
185
- // ...
186
-
187
- const preppedOptions = prepareOptions(options)
188
- await mapTransform(def1, preppedOptions)(source)
189
-
190
- // ...
191
-
192
- await mapTransform(def2, preppedOptions)(source)
193
- ```
194
-
195
- Most of the preparations are still done just-in-time, but when it's done once,
196
- it won't happen again on the next call. `prepareOptions` is idempotent, so
197
- passing already prepared options to `mapTransform` -- or calling
198
- `prepareOptions` on them again -- costs nothing.
184
+ `map-transform/next` works the same way. Like in the legacy API, the default
185
+ export is async, and it is also exported as `mapTransformAsync()`, with
186
+ `mapTransformSync()` as its sync counterpart. Note that `mapTransformSync()` and
187
+ the async `mapTransformAsync()` cache their prepared pipelines separately, so
188
+ mixing both on the same options object will prepare each pipeline twice.
199
189
 
200
190
  > [!NOTE] We are preparing for an upcoming 2.0 version, which will include
201
191
  > breaking changes.
@@ -221,6 +211,27 @@ passing already prepared options to `mapTransform` -- or calling
221
211
  > new `mapTransformSync` and `mapTransformAsync`, but there might still be gaps
222
212
  > in the documentation here.
223
213
 
214
+ #### Deviations from v1 behaviour in `next`
215
+
216
+ The following behaviours of `mapTransformSync` and `mapTransformAsync` differ
217
+ from the default export, on purpose:
218
+
219
+ - The root form without a dot after a single caret, `^path`, is removed. Write
220
+ `^^.path`.
221
+ - `$alt` no longer changes the levels for parent paths after it. Before, a
222
+ `$alt` that found no value added a level, so the next step needed `^.^` to
223
+ reach the parent. After, the next step sees the same levels as before the
224
+ `$alt`, so `^` is enough.
225
+ - Parent and root paths in reverse set on the parent or root level of the target
226
+ instead of on the current level. Before, `section: '^.^.meta.section'` inside
227
+ an iteration reversed to `items[].section`, and a root path in reverse set
228
+ nothing. After, the same definition sets `meta.section` on the object holding
229
+ `items`. When the parent level does not exist, the value is dropped.
230
+ - Mutation objects iterate arrays by default, just like get paths map over
231
+ arrays. Before, you had to set `$iterate: true`, and without it the entire
232
+ array was passed to the mutation object, giving one object with an array of
233
+ values on every property. Set `$iterate: false` to get that behaviour back.
234
+
224
235
  ### The mutation object
225
236
 
226
237
  Think of a mutation object as a description of the object structure you want.
@@ -267,6 +278,10 @@ mutation object. If you don't, the entire array will be passed to the mutation
267
278
  object. This will in most cases have the (propably unwanted) effect of returning
268
279
  one object with an array of values on every property.
269
280
 
281
+ > [!NOTE] In the next version, mutation objects iterate arrays by default, so
282
+ > `$iterate: true` is not needed. Set `$iterate: false` to pass the entire array
283
+ > to the mutation object instead.
284
+
270
285
  ```javascript
271
286
  const def = {
272
287
  $iterate: true,
@@ -307,8 +322,9 @@ as its value, this mutation object will be iterated by default (no need to set
307
322
  the `$iterate` property). This does not happen to pipelines, paths, or
308
323
  operations.
309
324
 
310
- > [!NOTE] This automatic iteration will disappear in v2.0 and is also removed in
311
- > the new `mapTransformSync` and `mapTransformAsync` exports.
325
+ > [!NOTE] This changes slightly in the next version, as mutation objects iterate
326
+ > by default. A key with the `[]` suffix will still be iterated, but not because
327
+ > of that suffix.
312
328
 
313
329
  #### Values on the mutation object
314
330
 
@@ -395,6 +411,25 @@ This will essentially make MapTransform treat `null` the same way as
395
411
  You could in principle include any primitive value in `nonvalues` and it will be
396
412
  treated as `undefined`, e.g. an empty string or the number `0`.
397
413
 
414
+ You may also set `$nonvalues` on an operation or mutation object, to use another
415
+ set of non-values for that operation and any pipelines within it. This overrides
416
+ the `nonvalues` option for that part of the definition. `$undefined` is an alias
417
+ of `$nonvalues`, and when both are set, `$nonvalues` is used. As a definition
418
+ may be written in JSON, where `undefined` cannot be expressed, the value
419
+ `'**undefined**'` is treated as `undefined` in these lists:
420
+
421
+ ```javascript
422
+ const def = {
423
+ // Treat an empty string as `undefined` when picking a default here
424
+ name: [
425
+ {
426
+ $alt: ['data.name', { $value: 'Anonymous' }],
427
+ $nonvalues: ['**undefined**', ''],
428
+ },
429
+ ],
430
+ }
431
+ ```
432
+
398
433
  A mutation object will be skipped in its entirety when it encounters a non-value
399
434
  in the pipeline. This is not always wanted, e.g. when the mutation object has
400
435
  defaults that we want to set in the mutation object. In these cases, you may set
@@ -459,8 +494,11 @@ const def = {
459
494
 
460
495
  The `$modify: true` notation is actually an alias for `$modify: '.'`.
461
496
 
462
- This is the way to set it for reverse direction (this is the exact same as the
463
- example above, just reversed):
497
+ `$modify` works like a path segment that merges instead of replacing, and it
498
+ takes effect on the side of the prop that is being set. When it is in a key, it
499
+ modifies going forward. When it is in a value, it modifies in reverse. This is
500
+ the way to set it for reverse direction (this is the exact same as the example
501
+ above, just reversed):
464
502
 
465
503
  ```javascript
466
504
  const def = {
@@ -479,6 +517,18 @@ const def = {
479
517
  }
480
518
  ```
481
519
 
520
+ > [!NOTE] In the next version, you may put `$modify` on both sides of a prop to
521
+ > modify in both directions. `$modify: '$modify'` modifies the pipeline value
522
+ > both going forward and in reverse, and `$modify: 'response.$modify'` does the
523
+ > same with the object at `response`:
524
+ >
525
+ > ```javascript
526
+ > const def = {
527
+ > $modify: 'response.$modify',
528
+ > data: 'response.data.deeply.placed.items',
529
+ > }
530
+ > ```
531
+
482
532
  ### Transform pipelines
483
533
 
484
534
  The idea of the transform pipeline, or "pipeline" for short, is that you
@@ -544,6 +594,10 @@ specified. In the example above, we have set `$iterate: true` on the mutation
544
594
  object, to signal that we want the mutation to be applied to each item of any
545
595
  array. See also [the `iterate` operation](#iteratepipeline-operation) for more.
546
596
 
597
+ > [!NOTE] In the next version, mutation objects will iterate by default, so to
598
+ > get the behavior described as default for mutation objects above, you will
599
+ > have to set `$iterate: false`.
600
+
547
601
  > Editors note: We should think through how we use the word "pipeline", as it is
548
602
  > sometimes ment to refer to an array of operations that a value may be
549
603
  > transformed through, other times any operation that could have been a part of
@@ -654,41 +708,68 @@ In the example with the `content` path, you may access the `id` with the path
654
708
  much the same way as `../` in file paths on any computer. You may go up several
655
709
  levels with e.g. `^.^.^.prop` (not applicable to our example).
656
710
 
657
- In an iteration you need to remember that the array counts as one level, so if
658
- iterating the `tags[]` array from our example, you would have to use the path
659
- `^.^.id` to get to the id. You could also use `^.[0]` to get the first item in
660
- the array you're iterating.
661
-
662
- > Editors note: We should probably have more examples here, especially on what
663
- > happens in a pipeline where we go up and down.
664
-
665
- The root notation follows the same logic, but will always go to the base level
666
- of the data structure, regardless of how many levels down you have moved. Roots
667
- are specified with double carets, so the path `^^.id` will get the id from our
668
- data from anywhere in the data structure, be it in `content` or when iterating
669
- through `tags[]`.
670
-
671
- There is a gotcha here, for both parent and root paths, relating to what data
672
- you're moving up in, as you are mutating the data as you move "down". The short
673
- answer is that you're moving in the mutated data if you are mutating it. Say
674
- you have a pipeline where you first mutate the data on the level you're at with
675
- a mutation object. The following steps in the pipeline will relate to the
676
- mutated object, and if you move into the mutated data with a path, and then go
677
- up again with a parent path, you are moving up in the mutated data. But if you
678
- instead just move into the data without mutating it, moving up with a parent
679
- path will give you the original data – there's nothing else, as you have not
680
- mutated it.
681
-
682
- This is probably as expected, but the confusing part comes into play when there
683
- is some "distance" between mutating the data and referencing it with a root or
684
- parent path, especially the root. Say you first mutate the root level with a
685
- mutation object, then move on with other operations, and then at some point,
686
- further down in the data, you want to reference something at the root level in
687
- _the original data_. This is where the **original root** notation comes in.
688
-
689
- Use triple carets (`^^^`) to always reference the original, untransformed source
690
- data, regardless of any prior transformations in the pipeline. This is useful in
691
- multi-step pipelines where earlier steps may have transformed the root:
711
+ The number of carets you need follows from the structure of the definition
712
+ alone, by these rules:
713
+
714
+ 1. **Only drilling down adds a level.** A key segment like `content` adds one
715
+ level, and so does an index like `[0]`. Entering an item in an array adds one
716
+ level too, whether you get there by iterating a path with `[]`, by a mutation
717
+ object iterating an array, or by an `$iterate` operation. A bare `[]` that
718
+ only makes sure you have an array, adds nothing. So when iterating the
719
+ `tags[]` array from our example above, you would use `^.^.id` to get to the
720
+ id: one caret to the array and one more to the object holding it. You could
721
+ also use `^.[0]` to get the first item in the array you're iterating.
722
+ 2. **Operations are opaque.** After a `$transform`, a mutation object, `$alt`,
723
+ `$if`, `$filter`, `$apply`, or `$array`, the levels are what they were before
724
+ the operation, no matter what the operation did on the inside. Inside an
725
+ operation, you inherit the levels from where the operation is used.
726
+ 3. **Set paths don't move.** A `>prop` step does not add a level, so `^` after
727
+ it is the same as `^` before it.
728
+ 4. **`^^` is the top of the tree you're in, `^^^` is the original data.** The
729
+ root notation `^^.id` goes to the base level of the data structure,
730
+ regardless of how many levels down you have moved.
731
+ 5. **In reverse, parent and root paths set on the parent or root level.** See
732
+ [Setting on parent and root](#setting-on-parent-and-root) below.
733
+
734
+ The parents you move up in, are the data you moved down in. When you first
735
+ mutate the data with a mutation object and then move into the result with a
736
+ path, going up again with a parent path takes you up in the mutated data:
737
+
738
+ ```javascript
739
+ const def = [
740
+ { id: 'key', item: { title: 'content.heading' } },
741
+ { title: 'item.title', id: ['item.title', '^.^.id'] },
742
+ ]
743
+ // From { key: 'ent1', content: { heading: 'The heading' } }
744
+ // we get { title: 'The heading', id: 'ent1' }
745
+ ```
746
+
747
+ Here, `item.title` in the second mutation object moves two levels down into the
748
+ object from the first, and `^.^.id` goes back up to the mutated object and gets
749
+ the `id` we set there. Note that within a mutation object, all pipelines start
750
+ from the same object, so the pipeline for `id` is not affected by the pipeline
751
+ for `title`.
752
+
753
+ Rule 2 means you don't have to know what an operation did to get the levels
754
+ right after it. In this example, `$alt` may find the article on different
755
+ depths, but the mutation object after it sees the same levels either way:
756
+
757
+ ```javascript
758
+ const def = [
759
+ 'items[]',
760
+ {
761
+ $iterate: true,
762
+ article: [
763
+ { $alt: ['content', 'original.content'] },
764
+ { title: 'title', section: '^.^.meta.section' },
765
+ ],
766
+ },
767
+ ]
768
+ // From { meta: { section: 'news' }, items: [{ content: { title: 'A' } }] }
769
+ // we get [{ article: { title: 'A', section: 'news' } }]
770
+ ```
771
+
772
+ Rule 4 in a multi-step pipeline, where the first step mutates the root:
692
773
 
693
774
  ```javascript
694
775
  const def = [
@@ -703,22 +784,43 @@ const def = [
703
784
  ]
704
785
  ```
705
786
 
706
- This is especially useful when you write a named pipeline and reference it with
707
- an `$apply` operation, as you have no knowledge in the named pipeline about any
708
- mutation of the root outside it. Using `^^^` guarantees access to the original
709
- source data in all cases.
787
+ The same holds inside a named pipeline applied with `$apply`: `^^` is the top of
788
+ the tree the pipeline is applied in, mutated or not, and `^^^` is the original
789
+ source data.
710
790
 
711
- Note also, that if you are within a mutation object and move down into the data,
712
- the data above where you are isn't transformed yet. As long as you are within a
713
- mutation object, you're referencing the data as it was before entering that
714
- mutation object. But as soon as you move to the next step in the pipeline –
715
- after the mutation object, you are left with the results of that mutation
716
- object.
791
+ ##### Setting on parent and root
717
792
 
718
- > Editor's note: We need examples.
793
+ When you go in reverse, a parent or root path becomes a set path, and it sets on
794
+ the parent or root level of the target, with the same number of carets as going
795
+ forward. In this example, `section` is read from two levels up going forward,
796
+ and in reverse it is set two levels up: on the object holding `items`.
719
797
 
720
- > [!NOTE] Setting on parent and root paths is currently not supported, but may
721
- > be in the future.
798
+ ```javascript
799
+ const def = [
800
+ 'items[]',
801
+ { $iterate: true, id: 'key', section: '^.^.meta.section' },
802
+ ]
803
+ // Forward, from { meta: { section: 'news' }, items: [{ key: 'ent1' }] }
804
+ // we get [{ id: 'ent1', section: 'news' }]
805
+ // In reverse, from [{ id: 'ent1', section: 'news' }]
806
+ // we get { meta: { section: 'news' }, items: [{ key: 'ent1' }] }
807
+ ```
808
+
809
+ A root path sets on the root level of the target in the same way, so
810
+ `'^^.meta.section'` in the example above would give the same result in reverse.
811
+ When you set on a parent level, nothing is set on the current level, so `id` is
812
+ the only prop on the items here.
813
+
814
+ Set paths may also use parent and root notation going forward, with a `>` prefix
815
+ or as a key on a mutation object. `{ '^.^.meta.section': 'section' }` sets
816
+ `meta.section` two levels up in the target.
817
+
818
+ When there is no parent level to set on, e.g. when a mutation object with
819
+ `section: '^.section'` is run in reverse at the top level, the value is dropped.
820
+
821
+ A parent path _within_ a path is different from these cases. The path
822
+ `item.^.count` moves down into `item` and up again, and is the same as `count`.
823
+ In reverse, it sets `count`, not `item.count`.
722
824
 
723
825
  #### Setting on a path
724
826
 
@@ -927,6 +1029,12 @@ would be a truly pure function.
927
1029
  > call the outer function yourself with any relevant props. This option will be
928
1030
  > removed in v2.0, but is still available to the regular MapTransform function.
929
1031
 
1032
+ Transformers may be asynchronous, but only when you run the transformation with
1033
+ `mapTransformAsync`. When you run it with `mapTransformSync` and a transformer
1034
+ returns a promise, MapTransform will throw, telling you the id of the offending
1035
+ transformer. This also applies to transformers used by other operations, like
1036
+ `filter`.
1037
+
930
1038
  #### `filter` operation
931
1039
 
932
1040
  The `filter` operation will use a transformer function or a pipeline to decide
@@ -1087,6 +1195,9 @@ const def = [
1087
1195
  For mutation objects, you may set `$iterate: true` to apply the mutation to each
1088
1196
  item in an array.
1089
1197
 
1198
+ > [!NOTE] In the next version, mutation objects do this by default, and
1199
+ > `$iterate: false` turns it off.
1200
+
1090
1201
  When you need to iterate a pipeline or an operation that is not a mutation
1091
1202
  object or an operation that supports the `$iterate` flag direction, you may wrap
1092
1203
  it in an `$iterate` operation object like this:
@@ -1238,6 +1349,10 @@ don't think too much about it. See
1238
1349
  [the `get` and `set` operations](#getpath-and-setpath-operation) for more on how
1239
1350
  `get` works in reverse.
1240
1351
 
1352
+ When the value is `undefined` in reverse, the alternative pipelines are used to
1353
+ look for a default value. Only pipelines without set paths (e.g. a `$value`
1354
+ pipeline) are used for this, so put the default in its own pipeline.
1355
+
1241
1356
  To apply the `alt` operation to each item in an array, set `$iterate: true` on
1242
1357
  the operation object. You may also set `$direction: 'fwd'` or
1243
1358
  `$direction: 'rev'` to limit it to one direction only.
@@ -1829,6 +1944,10 @@ except that the value set with `fixed` will be included even when
1829
1944
  `state.noDefaults` is `true`. Use `value` for default values, and `fixed` for
1830
1945
  values that should be set no matter what.
1831
1946
 
1947
+ Like the `value` transformer, `fixed` has its own short-hand operation object
1948
+ notation, so `{ $transform: 'fixed', value: 'customer' }` may be written
1949
+ `{ $fixed: 'customer' }`.
1950
+
1832
1951
  #### `flatten` transformer
1833
1952
 
1834
1953
  Will flatten an array in the pipeline. The default is to flatten one layer deep,