Skip to content

Commit ff60829

Browse files
fix(SOL-422): map fields with action-level fieldConfigs
- fieldConfigs replaces inline map_fields fields; map_fields/typecast take dataSource only - expressions relative to each record, no step prefix - drop schema inference troubleshooting entry - lower() replaces unsupported .toLowerCase() in enum matching Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent b680d2f commit ff60829

2 files changed

Lines changed: 92 additions & 114 deletions

File tree

‎plugins/integrations/stackone-unified-connectors/skills/stackone-unified-connectors/SKILL.md‎

Lines changed: 43 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -72,30 +72,28 @@ stepFunction:
7272
version: '2' # REQUIRED - omitting causes empty results
7373
```
7474

75-
### 4. Use Inline Fields in map_fields Parameters
75+
### 4. Define Fields in Action-Level fieldConfigs
7676

77-
Pass `fields` directly in `map_fields` step parameters rather than action-level `fieldConfigs`. This avoids schema inference issues that cause build failures.
77+
Declare the field mapping once in the action's `fieldConfigs`. The `map_fields` and `typecast` steps then take only a `dataSource` and apply those `fieldConfigs`.
7878

7979
```yaml
80-
# RECOMMENDED - Inline fields
81-
- stepId: map_data
82-
stepFunction:
83-
functionName: map_fields
84-
version: '2'
85-
parameters:
86-
fields:
87-
- targetFieldKey: email
88-
expression: $.email # Direct reference, NO step prefix
89-
type: string
90-
dataSource: $.steps.get_data.output.data
80+
fieldConfigs:
81+
- targetFieldKey: email
82+
expression: $.email # Relative to each record, NO step prefix
83+
type: string
84+
85+
steps:
86+
- stepId: map_data
87+
stepFunction:
88+
functionName: map_fields
89+
version: '2'
90+
parameters:
91+
dataSource: $.steps.get_data.output.data
9192
```
9293

93-
### 5. Expression Context Depends on Location
94+
### 5. Expressions Are Relative to Each Record
9495

95-
| Location | Expression Format | Example |
96-
|----------|------------------|---------|
97-
| Inline in `parameters.fields` | Direct field reference | `$.email`, `$.work.department` |
98-
| Action-level `fieldConfigs` | Step ID prefix required | `$.get_employees.email` |
96+
`fieldConfigs` expressions are evaluated against each record of the `map_fields` `dataSource`, so reference the record's fields directly: `$.email`, `$.work.department`. Do not prefix them with a step ID.
9997

10098
### 6. Never Suggest User-Side Mapping
10199

@@ -190,52 +188,44 @@ See `references/scope-patterns.md` for detailed patterns.
190188

191189
### Step 5: Map Fields to Schema
192190

193-
Use inline fields in map_fields parameters:
191+
Declare the mapping in action-level `fieldConfigs`, then run `map_fields` and `typecast` over the data:
194192

195193
```yaml
194+
fieldConfigs:
195+
- targetFieldKey: id
196+
expression: $.id
197+
type: string
198+
- targetFieldKey: email
199+
expression: $.email
200+
type: string
201+
- targetFieldKey: department
202+
expression: $.work.department # Nested field
203+
type: string
204+
- targetFieldKey: status
205+
expression: $.status
206+
type: enum
207+
enumMapper:
208+
matcher:
209+
- matchExpression: '{{$.status == "Active"}}'
210+
value: active
211+
- matchExpression: '{{$.status == "Inactive"}}'
212+
value: inactive
213+
- matchExpression: '{{$.status == null}}'
214+
value: unknown
215+
196216
steps:
197217
- stepId: map_data
198218
stepFunction:
199219
functionName: map_fields
200220
version: '2'
201221
parameters:
202-
fields:
203-
- targetFieldKey: id
204-
expression: $.id
205-
type: string
206-
- targetFieldKey: email
207-
expression: $.email
208-
type: string
209-
- targetFieldKey: department
210-
expression: $.work.department # Nested field
211-
type: string
212-
- targetFieldKey: status
213-
expression: $.status
214-
type: enum
215-
enumMapper:
216-
matcher:
217-
- matchExpression: '{{$.status == "Active"}}'
218-
value: active
219-
- matchExpression: '{{$.status == "Inactive"}}'
220-
value: inactive
221-
- matchExpression: '{{$.status == null}}'
222-
value: unknown
223222
dataSource: $.steps.get_data.output.data
224223
225224
- stepId: typecast_data
226225
stepFunction:
227226
functionName: typecast
228227
version: '2'
229228
parameters:
230-
fields:
231-
- targetFieldKey: id
232-
type: string
233-
- targetFieldKey: email
234-
type: string
235-
- targetFieldKey: department
236-
type: string
237-
- targetFieldKey: status
238-
type: enum
239229
dataSource: $.steps.map_data.output.data
240230
241231
result:
@@ -333,7 +323,7 @@ Actions:
333323
3. **If no skill**: Ask for schema, recommend creating `unified-hris-schema` skill for consistency across HRIS providers
334324
4. Research BambooHR endpoints: `/v1/employees`, `/v1/employees/directory`, custom reports
335325
5. Present options with trade-offs (field coverage, scopes, deprecation)
336-
6. After user selects, implement map_fields with inline fields using schema from skill
326+
6. After user selects, declare `fieldConfigs` using schema from skill and add map_fields and typecast steps
337327
7. Configure pagination with cursor support
338328
8. Test with `--debug`, verify field names match schema
339329
9. Document coverage
@@ -360,7 +350,7 @@ User says: "My unified connector returns provider field names instead of my sche
360350
Actions:
361351
1. Check if `targetFieldKey` uses YOUR schema names (not provider names)
362352
2. Verify `version: '2'` is specified on map_fields and typecast
363-
3. Check expression context - inline fields should NOT have step prefix
353+
3. Check expression context - `fieldConfigs` expressions should NOT have a step prefix
364354
4. Run with `--debug` to see raw response structure
365355
5. Verify dataSource path is correct
366356

@@ -387,20 +377,16 @@ Result: Working pagination with correct cursor handling.
387377

388378
### Mapping produces empty results
389379
**Cause**: Missing `version: '2'` or wrong expression context.
390-
**Fix**: Add `version: '2'` to map_fields and typecast. For inline fields, use direct references (`$.email`) without step prefix.
380+
**Fix**: Add `version: '2'` to map_fields and typecast. In `fieldConfigs`, use direct references (`$.email`) without step prefix.
391381

392382
### Enum values not translating
393383
**Cause**: `matchExpression` doesn't match provider values (case-sensitive).
394-
**Fix**: Check exact provider values with `--debug`. Use `.toLowerCase()` for case-insensitive matching. Always include null/unknown fallback.
384+
**Fix**: Check exact provider values with `--debug`. Use the `lower()` function for case-insensitive matching (e.g. `'{{lower($.status) == "active"}}'`). Always include null/unknown fallback.
395385

396386
### Pagination returns same records
397387
**Cause**: Cursor not being sent or extracted correctly.
398388
**Fix**: Verify `iterator.key` matches API's expected parameter name. Check `nextKey` path against raw response. Verify `iterator.in` is correct (query/body/headers).
399389

400-
### Build fails with schema inference errors
401-
**Cause**: Action-level `fieldConfigs` triggering unwanted schema inference.
402-
**Fix**: Use inline fields in `map_fields` parameters instead of action-level `fieldConfigs`.
403-
404390
### Dynamic inputs resolve to undefined
405391
**Cause**: Using `paginated_request` which doesn't handle `$.inputs.*` well.
406392
**Fix**: Use standard `request` function with dual-condition pattern for defaults.

‎plugins/integrations/stackone-unified-connectors/skills/stackone-unified-connectors/references/field-mapping-patterns.md‎

Lines changed: 49 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -13,34 +13,36 @@
1313
| `enum` | Constrained values | status (requires enumMapper) |
1414
| `object` | Nested structure | work_location |
1515

16-
## Inline Fields (Recommended Approach)
16+
## Action-Level fieldConfigs
1717

18-
Define fields directly in `map_fields` step parameters:
18+
Define fields in the action's `fieldConfigs`. The `map_fields` step takes only a `dataSource` and applies them:
1919

2020
```yaml
21-
- stepId: map_data
22-
stepFunction:
23-
functionName: map_fields
24-
version: '2'
25-
parameters:
26-
fields:
27-
- targetFieldKey: email
28-
expression: $.email # Direct reference, NO step prefix
29-
type: string
30-
- targetFieldKey: department
31-
expression: $.work.department # Nested field reference
32-
type: string
33-
dataSource: $.steps.get_data.output.data
21+
fieldConfigs:
22+
- targetFieldKey: email
23+
expression: $.email # Relative to each record, NO step prefix
24+
type: string
25+
- targetFieldKey: department
26+
expression: $.work.department # Nested field reference
27+
type: string
28+
29+
steps:
30+
- stepId: map_data
31+
stepFunction:
32+
functionName: map_fields
33+
version: '2'
34+
parameters:
35+
dataSource: $.steps.get_data.output.data
3436
```
3537
36-
**Why inline?** Action-level `fieldConfigs` can trigger schema inference that adds unwanted properties, causing build failures.
38+
The field snippets below are entries in `fieldConfigs`.
3739

3840
## Enum Mapping
3941

4042
### Basic Enum
4143

4244
```yaml
43-
fields:
45+
fieldConfigs:
4446
- targetFieldKey: status
4547
expression: $.status
4648
type: enum
@@ -59,7 +61,7 @@ fields:
5961
```yaml
6062
enumMapper:
6163
matcher:
62-
- matchExpression: '{{($.status || "").toLowerCase() == "active"}}'
64+
- matchExpression: '{{lower($.status) == "active"}}'
6365
value: active
6466
```
6567

@@ -101,7 +103,7 @@ enumMapper:
101103
### Simple Nested Field
102104

103105
```yaml
104-
fields:
106+
fieldConfigs:
105107
- targetFieldKey: city
106108
expression: $.location.city
107109
type: string
@@ -119,7 +121,7 @@ Provider returns:
119121

120122
Your schema is flat:
121123
```yaml
122-
fields:
124+
fieldConfigs:
123125
- targetFieldKey: department
124126
expression: $.work.department
125127
type: string
@@ -133,7 +135,7 @@ fields:
133135
### Simple Array
134136

135137
```yaml
136-
fields:
138+
fieldConfigs:
137139
- targetFieldKey: email_addresses
138140
expression: $.emails[*]
139141
type: string
@@ -143,7 +145,7 @@ fields:
143145
### JEXL Array Operations
144146

145147
```yaml
146-
fields:
148+
fieldConfigs:
147149
- targetFieldKey: export_formats
148150
expression: '{{keys(exportLinks)}}'
149151
type: string
@@ -155,7 +157,7 @@ fields:
155157
### Fallback Values
156158

157159
```yaml
158-
fields:
160+
fieldConfigs:
159161
- targetFieldKey: file_format
160162
expression: '{{$.fullFileExtension || $.mimeType}}'
161163
type: string
@@ -164,7 +166,7 @@ fields:
164166
### Conditional Logic
165167

166168
```yaml
167-
fields:
169+
fieldConfigs:
168170
- targetFieldKey: default_format
169171
expression: '{{exportLinks ? (keys(exportLinks)[0] || "application/pdf") : $.mimeType}}'
170172
type: string
@@ -173,7 +175,7 @@ fields:
173175
### Boolean Check
174176

175177
```yaml
176-
fields:
178+
fieldConfigs:
177179
- targetFieldKey: is_exportable
178180
expression: '{{$.exportLinks != null}}'
179181
type: boolean
@@ -184,6 +186,20 @@ fields:
184186
Mapping HiBob employee data:
185187

186188
```yaml
189+
fieldConfigs:
190+
- targetFieldKey: email
191+
expression: $.email
192+
type: string
193+
- targetFieldKey: employee_id
194+
expression: $.id
195+
type: string
196+
- targetFieldKey: department
197+
expression: $.work.department
198+
type: string
199+
- targetFieldKey: job_title
200+
expression: $.work.title
201+
type: string
202+
187203
steps:
188204
- stepId: get_employees
189205
stepFunction:
@@ -211,35 +227,13 @@ steps:
211227
functionName: map_fields
212228
version: '2'
213229
parameters:
214-
fields:
215-
- targetFieldKey: email
216-
expression: $.email
217-
type: string
218-
- targetFieldKey: employee_id
219-
expression: $.id
220-
type: string
221-
- targetFieldKey: department
222-
expression: $.work.department
223-
type: string
224-
- targetFieldKey: job_title
225-
expression: $.work.title
226-
type: string
227230
dataSource: $.steps.get_employees.output.data
228231
229232
- stepId: typecast_data
230233
stepFunction:
231234
functionName: typecast
232235
version: '2'
233236
parameters:
234-
fields:
235-
- targetFieldKey: email
236-
type: string
237-
- targetFieldKey: employee_id
238-
type: string
239-
- targetFieldKey: department
240-
type: string
241-
- targetFieldKey: job_title
242-
type: string
243237
dataSource: $.steps.map_data.output.data
244238
245239
result:
@@ -251,15 +245,13 @@ result:
251245
### Wrong Expression Context
252246

253247
```yaml
254-
# WRONG - Using step prefix in inline fields
255-
parameters:
256-
fields:
257-
- expression: $.get_employees.email # Don't use step prefix!
248+
# WRONG - Using step prefix in fieldConfigs
249+
fieldConfigs:
250+
- expression: $.get_employees.email # Don't use step prefix!
258251
259252
# CORRECT - Direct field reference
260-
parameters:
261-
fields:
262-
- expression: $.email
253+
fieldConfigs:
254+
- expression: $.email
263255
```
264256

265257
### Missing Version
@@ -289,9 +281,9 @@ stepFunction:
289281

290282
## Validation Checklist
291283

292-
- [ ] Using inline `fields` in map_fields parameters
293-
- [ ] Expressions use correct context (no step prefix for inline)
284+
- [ ] All schema fields declared in action-level `fieldConfigs`
285+
- [ ] Expressions use correct context (no step prefix in `fieldConfigs`)
294286
- [ ] `version: '2'` specified for map_fields and typecast
295287
- [ ] All `targetFieldKey` values match YOUR schema
296288
- [ ] All enum fields have `enumMapper` with null handler
297-
- [ ] typecast step includes all mapped fields
289+
- [ ] typecast step runs on the map_fields output

0 commit comments

Comments
 (0)