Skip to content

Commit bb96f85

Browse files
committed
Apply suggestions Mikey
1 parent 9bcaeed commit bb96f85

File tree

2 files changed

+152
-62
lines changed

2 files changed

+152
-62
lines changed

docs/reference/schemas/config/functions/shallowMerge.md

Lines changed: 103 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,30 @@ shallowMerge(<inputArray>)
1919

2020
The `shallowMerge()` function takes an array of objects and combines them into a single
2121
object by merging their properties. When the same property name appears in multiple objects,
22-
the value from the last object in the array takes precedence.
22+
the value from the last object in the array with that property takes precedence.
2323

24-
This is a **shallow merge**, meaning:
24+
This is a _shallow merge_, which applies the following rules:
2525

26-
- Top-level properties are merged from all objects
27-
- If a property value is an object, it replaces the entire object from previous objects
28-
rather than merging the nested properties
29-
- Arrays and other complex types are also replaced entirely, not combined
26+
- The first object in the array defines the base value for the merged object.
27+
- The function processes each object in the array in the order they're defined.
28+
- When processing each object, the function iterates over every top-level property defined for that
29+
object and:
30+
31+
- If the merged object doesn't already have the property, the function adds that property to the
32+
merged object with the value from the current object.
33+
- If the merged object does have the property, the function _replaces_ the existing value with
34+
the value from the current object, even when the value is an object or array.
3035

3136
This function is useful for:
3237

33-
- Building composite configuration objects from multiple sources
34-
- Applying configuration overrides where later values take precedence
35-
- Combining default settings with user-specified customizations
36-
- Merging environment-specific configurations
38+
- Building composite configuration objects from multiple sources.
39+
- Applying configuration overrides where later values take precedence.
40+
- Combining default settings with user-specified customizations.
41+
- Merging environment-specific configurations.
3742

38-
The shallow merge behavior differs from a deep merge (like [`union()`][00]) where nested
39-
objects would be recursively merged. With `shallowMerge()`, nested structures are replaced
40-
entirely by the last object's value.
43+
The shallow merge behavior differs from a deep merge (like [`union()`][00]) where nested
44+
objects are recursively merged. The `shallowMerge()` function replaces nested structures
45+
entirely with the value defined by the last object with that property in the input array.
4146

4247
## Examples
4348

@@ -53,7 +58,13 @@ resources:
5358
- name: Echo
5459
type: Microsoft.DSC.Debug/Echo
5560
properties:
56-
output: "[shallowMerge(createArray(createObject('host', 'localhost', 'port', 8080), createObject('port', 9000, 'ssl', true())))]"
61+
output: >-
62+
[shallowMerge(
63+
createArray(
64+
createObject('host', 'localhost', 'port', 8080),
65+
createObject('port', 9000, 'ssl', true())
66+
)
67+
)]
5768
```
5869
5970
```bash
@@ -74,9 +85,8 @@ messages: []
7485
hadErrors: false
7586
```
7687
77-
Notice how the `port` value from the second object (9000) replaces the value from the first
78-
object (8080), while properties that only exist in one object (`host` and `ssl`) are
79-
preserved.
88+
In this example, the `port` value from the second object (`9000`) replaces the value from the first
89+
object (`8080`), while properties that only exist in one object (`host` and `ssl`) are preserved.
8090

8191
### Example 2 - Apply multiple configuration layers
8292

@@ -105,7 +115,14 @@ resources:
105115
- name: Echo
106116
type: Microsoft.DSC.Debug/Echo
107117
properties:
108-
output: "[shallowMerge(createArray(parameters('defaults'), parameters('environment'), parameters('userPrefs')))]"
118+
output: >-
119+
[shallowMerge(
120+
createArray(
121+
parameters('defaults'),
122+
parameters('environment'),
123+
parameters('userPrefs')
124+
)
125+
)]
109126
```
110127

111128
```bash
@@ -141,7 +158,19 @@ resources:
141158
- name: Echo
142159
type: Microsoft.DSC.Debug/Echo
143160
properties:
144-
output: "[shallowMerge(createArray(createObject('database', createObject('host', 'localhost', 'port', 5432, 'ssl', true())), createObject('database', createObject('host', 'prod.db.local'))))]"
161+
output: >-
162+
[shallowMerge(
163+
createArray(
164+
createObject(
165+
'database',
166+
createObject('host', 'localhost', 'port', 5432, 'ssl', true())
167+
),
168+
createObject(
169+
'database',
170+
createObject('host', 'prod.db.local')
171+
)
172+
)
173+
)]
145174
```
146175

147176
```bash
@@ -175,7 +204,14 @@ resources:
175204
- name: Echo
176205
type: Microsoft.DSC.Debug/Echo
177206
properties:
178-
output: "[shallowMerge(createArray(createObject('name', 'Service1', 'enabled', true()), createObject(), createObject('version', '2.0')))]"
207+
output: >-
208+
[shallowMerge(
209+
createArray(
210+
createObject('name', 'Service1', 'enabled', true()),
211+
createObject(),
212+
createObject('version', '2.0')
213+
)
214+
)]
179215
```
180216

181217
```bash
@@ -210,7 +246,13 @@ resources:
210246
- name: Echo
211247
type: Microsoft.DSC.Debug/Echo
212248
properties:
213-
output: "[shallowMerge(createArray(createObject('newUI', false(), 'darkMode', true(), 'beta', false()), createObject('newUI', true()), createObject('beta', true())))]"
249+
output: >-
250+
[shallowMerge(
251+
createArray(
252+
createObject('newUI', false(), 'darkMode', true(), 'beta', false()),
253+
createObject('newUI', true()), createObject('beta', true())
254+
)
255+
)]
214256
```
215257

216258
```bash
@@ -302,9 +344,34 @@ resources:
302344
type: Microsoft.DSC.Debug/Echo
303345
properties:
304346
output:
305-
merged: "[shallowMerge(createArray(parameters('baseConfig'), parameters('overrides')))]"
306-
keys: "[objectKeys(shallowMerge(createArray(parameters('baseConfig'), parameters('overrides'))))]"
307-
hasRetries: "[contains(objectKeys(shallowMerge(createArray(parameters('baseConfig'), parameters('overrides')))), 'retries')]"
347+
merged: >-
348+
[shallowMerge(
349+
createArray(
350+
parameters('baseConfig'),
351+
parameters('overrides')
352+
)
353+
)]
354+
keys: >-
355+
[objectKeys(
356+
shallowMerge(
357+
createArray(
358+
parameters('baseConfig'),
359+
parameters('overrides')
360+
)
361+
)
362+
)]
363+
hasRetries: >-
364+
[contains(
365+
objectKeys(
366+
shallowMerge(
367+
createArray(
368+
parameters('baseConfig'),
369+
parameters('overrides')
370+
)
371+
)
372+
),
373+
'retries'
374+
)]
308375
```
309376

310377
```bash
@@ -381,8 +448,9 @@ Position: 1
381448

382449
## Output
383450

384-
Returns a single object containing all properties from the input objects. When the same
385-
property appears in multiple objects, the value from the last object in the array is used.
451+
Returns a single object containing all properties from the input objects. When the same property
452+
appears in multiple objects, the value from the last object in the array with that property is
453+
retained, replacing all prior values for the property.
386454

387455
```yaml
388456
Type: object
@@ -396,13 +464,15 @@ The function will return an error in the following cases:
396464

397465
## Notes
398466

399-
- This is a **shallow merge** - nested objects are replaced, not merged recursively
400-
- Properties from objects later in the array override properties from earlier objects
401-
- Empty objects in the array don't affect the merge
402-
- Non-object elements in the array are ignored
403-
- An empty array returns an empty object
404-
- The function processes objects in array order, so the last object has highest precedence
405-
- For recursive/deep merging of nested objects, consider using [`union()`][00] instead
467+
- This function performs a _shallow merge_ - the function replaces nested objects, it doesn't merge
468+
them recursively.
469+
- The function replaces the value for properties defined by earlier objects in the input array with
470+
the value from objects later in the array.
471+
- The function ignores empty objects in the input array.
472+
- The function ignores non-object elements in the input array.
473+
- The function returns an empty object when the input is an empty array.
474+
- The function processes objects in array order, so the last object has highest precedence
475+
- For recursive/deep merging of nested objects, consider using [`union()`][00] instead.
406476

407477
## Related functions
408478

docs/reference/schemas/config/functions/tryWhich.md

Lines changed: 49 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ title: tryWhich
77

88
## Synopsis
99

10-
Attempts to locate an executable in the system PATH and returns its full path, or null if not found.
10+
Looks for an executable in the `PATH` environment variable and returns the full path to that
11+
executable or null if not found.
1112

1213
## Syntax
1314

@@ -17,20 +18,20 @@ tryWhich(<commandName>)
1718

1819
## Description
1920

20-
The `tryWhich()` function searches for an executable in the system's PATH environment variable
21-
and returns the full path to the executable if found. If the executable is not found, the
22-
function returns `null` instead of generating an error.
21+
The `tryWhich()` function searches for an executable in the `PATH` environment variable and returns
22+
the full path to the executable if found. If the executable isn't discoverable, the function
23+
returns `null` instead of generating an error.
2324

2425
This function is useful for:
2526

26-
- Checking if a required command-line tool is available before using it
27-
- Conditionally configuring resources based on available system tools
28-
- Validating prerequisites in configurations
29-
- Finding the exact path to executables for use in scripts or commands
27+
- Checking whether a required command-line tool is available before invoking it.
28+
- Conditionally configuring resources based on available system tools.
29+
- Validating prerequisites in configurations.
30+
- Finding the exact path to executables for use in scripts or commands.
3031

31-
The function searches the PATH in the same way the operating system would when executing a
32-
command. On Windows, it automatically checks for common executable extensions (.exe, .cmd,
33-
.bat, etc.).
32+
The function searches the `PATH` in the same way the operating system would when executing a
33+
command. On Windows, it automatically checks for common executable extensions, like `.exe`, `.cmd`,
34+
and `.bat`, if no extension is provided.
3435

3536
Unlike a strict path lookup that would fail if the executable is missing, `tryWhich()`
3637
gracefully returns `null`, making it ideal for conditional logic with [`if()`][00] or
@@ -52,7 +53,12 @@ resources:
5253
properties:
5354
output:
5455
gitPath: "[tryWhich('git')]"
55-
hasGit: "[if(equals(tryWhich('git'), null()), false(), true())]"
56+
hasGit: >-
57+
[if(
58+
equals(tryWhich('git'), null()),
59+
false(),
60+
true()
61+
)]
5662
```
5763
5864
```bash
@@ -72,7 +78,8 @@ messages: []
7278
hadErrors: false
7379
```
7480
75-
If `git` is not installed, `gitPath` would be `null` and `hasGit` would be `false`.
81+
If `git` wasn't discoverable in the `PATH` environmental variable, `gitPath` would be `null` and `hasGit`
82+
would be `false`.
7683

7784
### Example 2 - Provide fallback paths with coalesce
7885

@@ -87,7 +94,12 @@ resources:
8794
type: Microsoft.DSC.Debug/Echo
8895
properties:
8996
output:
90-
pythonPath: "[coalesce(tryWhich('python3'), tryWhich('python'), '/usr/bin/python')]"
97+
pythonPath: >-
98+
[coalesce(
99+
tryWhich('python3'),
100+
tryWhich('python'),
101+
'/usr/bin/python'
102+
)]
91103
```
92104

93105
```bash
@@ -106,8 +118,9 @@ messages: []
106118
hadErrors: false
107119
```
108120

109-
This tries `python3` first, falls back to `python`, and finally uses a default path if
110-
neither is found in PATH.
121+
In this example, the function first looks for `python3` in the `PATH` environmental variable. If
122+
that executable isn't discovered, it then looks for `python`. If neither executable is discovered,
123+
it falls back to the specified default value, `/usr/bin/python3`.
111124

112125
### Example 3 - Validate multiple prerequisites
113126

@@ -126,7 +139,12 @@ resources:
126139
docker: "[tryWhich('docker')]"
127140
kubectl: "[tryWhich('kubectl')]"
128141
helm: "[tryWhich('helm')]"
129-
allFound: "[and(not(equals(tryWhich('docker'), null())), not(equals(tryWhich('kubectl'), null())), not(equals(tryWhich('helm'), null())))]"
142+
allFound: >-
143+
[and(
144+
not(equals(tryWhich('docker'), null())),
145+
not(equals(tryWhich('kubectl'), null())),
146+
not(equals(tryWhich('helm'), null()))
147+
)]
130148
```
131149

132150
```bash
@@ -156,8 +174,8 @@ not found, so `allFound` is `false`.
156174

157175
### commandName
158176

159-
The name of the executable to locate. On Windows, the function automatically checks for
160-
common executable extensions (.exe, .cmd, .bat, .ps1, etc.) if no extension is provided.
177+
The name of the executable to locate. On Windows, it automatically checks for common executable
178+
extensions, like `.exe`, `.cmd`, and `.bat`, if no extension is provided.
161179

162180
```yaml
163181
Type: string
@@ -176,20 +194,22 @@ Type: string or null
176194

177195
## Error conditions
178196

179-
The function returns `null` instead of generating errors when the executable is not found.
180-
It will return an error only if:
197+
The function returns `null` instead of generating errors when the executable isn't found.
181198

182-
- **Not a string**: The input is not a string (e.g., number, array, object, null)
199+
The function only returns an error when the input isn't a string.
183200

184201
## Notes
185202

186-
- The function searches the PATH environment variable in the same order as the operating system
187-
- On Windows, common executable extensions are automatically checked (.exe, .cmd, .bat, .ps1, etc.)
188-
- Returns `null` (not an error) when the executable is not found
189-
- The returned path is always absolute
190-
- Use with [`if()`][00] or [`coalesce()`][01] for conditional logic based on tool availability
191-
- The search is case-insensitive on Windows and case-sensitive on Unix-like systems
192-
- Symbolic links are resolved to their target paths
203+
- The function searches the `PATH` environment variable in the same order as the operating system.
204+
- On Windows, the function automatically checks for the executable with common extensions, like
205+
`.exe`, `.cmd`, and `.bat`, when the input string doesn't define an extension. For example, if
206+
the input is `dsc`, the function would return `dsc.exe` if available in `PATH`.
207+
- The function returns `null` when the executable isn't found instead of raising an error.
208+
- The function always returns the absolute path to a discovered executable.
209+
- Use with [`if()`][00] or [`coalesce()`][01] for conditional logic based on tool availability.
210+
- The function searches for the executable case-insensitively on Windows and case-sensitively on
211+
other platforms.
212+
- The function resolves symbolic links to their target paths.
193213

194214
## Related functions
195215

0 commit comments

Comments
 (0)