# Args Configuration

Args map action inputs to the parameters sent to the provider's API. They live inside the step function, under `parameters.args`.

**Key distinction**: `inputs` define what StackOne accepts from the caller. `args` define what gets sent to the provider.

## Args Schema

```yaml
args:
  - name: parameterName        # Parameter name as provider expects it (required)
    value: $.inputs.fieldName  # JSONPath to input value (required)
    in: body                   # Location: query | body | headers (required)
    condition: '{{...}}'       # Conditional inclusion for optional params (optional)
    spread: true               # Spread object/array directly into body (optional)
    arrayFormat: comma         # Array serialization format for query params (optional)
```

## Fields Reference

### Required Fields

| Field | Notes |
| :--- | :--- |
| `name` | Parameter name as the provider API expects it |
| `value` | JSONPath expression — e.g. `$.inputs.field`, `$.credentials.apiKey` |
| `in` | `query`, `body`, or `headers` |

### Optional Fields

| Field | Notes |
| :--- | :--- |
| `condition` | Use `'{{present(inputs.field)}}'` for all optional parameters |
| `spread` | `true` — passes value directly into body as-is. Use for objects (spreads fields) or arrays (sends array directly). **`in: body` only** |
| `arrayFormat` | `repeat`, `brackets`, `comma`, or `stringify` — controls array serialization in query strings. **`in: query` only** |

### `arrayFormat` Values

| Value | URL result |
| :--- | :--- |
| _(not set)_ | `?ids[0]=a&ids[1]=b&ids[2]=c` |
| `repeat` | `?ids=a&ids=b&ids=c` |
| `brackets` | `?ids[]=a&ids[]=b&ids[]=c` |
| `comma` | `?ids=a,b,c` |
| `stringify` | `?ids=["a","b","c"]` |

## Input `in` → Args Placement

Every input must be wired into the step function at the correct location:

| Input `in` | Where it goes in args |
| :--- | :--- |
| `query` | `args` entry with `in: query` |
| `body` | `args` entry with `in: body` |
| `header` | `args` entry with `in: headers` |
| `path` | Interpolated into `url` via `${inputs.field}` — **not** in args |

## Examples

### Required vs Optional Args

```yaml
args:
  # Required — no condition
  - name: email
    value: $.inputs.email
    in: body

  # Optional — always add condition
  - name: phone
    value: $.inputs.phone
    in: body
    condition: '{{present(inputs.phone)}}'

  # Optional query param
  - name: limit
    value: $.inputs.limit
    in: query
    condition: '{{present(inputs.limit)}}'
```

### Credential Args (API Key in Header)

```yaml
args:
  # Non-Bearer API key header — always include condition
  - name: X-API-Key
    value: $.credentials.apiKey
    in: headers
    condition: '{{present(credentials.apiKey)}}'
```

### Hyphenated Header Keys

Hyphenated names require bracket notation in both `value` and `condition`:

```yaml
args:
  - name: if-match
    value: $.inputs['if-match']
    in: headers
    condition: '{{present(inputs["if-match"])}}'
```

### Special-Character Query Param Names

For OData or APIs using `$filter`, `$top`, `$expand` — wrap the name in a JEXL expression:

```yaml
args:
  - name: '{{"$filter"}}'
    value: $.inputs.filter
    in: query
    condition: '{{present(inputs.filter)}}'

  - name: '{{"$top"}}'
    value: $.inputs.top
    in: query
    condition: '{{present(inputs.top)}}'
```

### Array Query Params

```yaml
args:
  # Comma-separated: ?tags=a,b,c
  - name: tags
    value: $.inputs.tags
    in: query
    arrayFormat: comma
    condition: '{{present(inputs.tags)}}'

  # Repeated: ?ids=a&ids=b&ids=c
  - name: ids
    value: $.inputs.ids
    in: query
    arrayFormat: repeat
    condition: '{{present(inputs.ids)}}'

  # Stringified: ?stage=["applied","rejected"]
  - name: stage
    value: $.inputs.stage
    in: query
    arrayFormat: stringify
    condition: '{{present(inputs.stage)}}'
```

### Spread — Object into Body

Use `spread: true` when the provider expects the object's fields merged directly into the body:

```yaml
args:
  - name: metadata
    value: $.inputs.metadata
    in: body
    spread: true
    condition: '{{present(inputs.metadata)}}'
```

### Spread — Array Directly into Body

Use when the provider expects a raw JSON array `[{...}, {...}]` instead of `{"key": [...]}`:

```yaml
args:
  - name: items
    value: $.inputs.items
    in: body
    spread: true
    condition: '{{present(inputs.items)}}'
```

### Nested Object Array (Top-Level Only)

For `type: object, array: true` inputs — add only the top-level field; nested properties are included automatically:

```yaml
args:
  - name: answers        # top-level only — nested properties included automatically
    value: $.inputs.answers
    in: body
    condition: '{{present(inputs.answers)}}'
```

## Mapping Inputs to Args — Patterns

### Simple (required body field)

```yaml
# Input
- name: email
  type: string
  in: body
  required: true

# Arg
- name: email
  value: $.inputs.email
  in: body
```

### Optional query param

```yaml
# Input
- name: limit
  type: number
  in: query
  required: false

# Arg
- name: limit
  value: $.inputs.limit
  in: query
  condition: '{{present(inputs.limit)}}'
```

### Path param — goes in URL, not args

```yaml
# Input
- name: userId
  type: string
  in: path
  required: true

# Step URL (no arg entry needed)
url: /users/${inputs.userId}
```

### Enum field

```yaml
# Input
- name: status
  type: enum
  in: query
  required: false
  oneOf:
    values:
      - active
      - inactive

# Arg
- name: status
  value: $.inputs.status
  in: query
  condition: '{{present(inputs.status)}}'
```

## Critical Rules

### MUST DO:
- ✅ Use JSONPath for `value`: `$.inputs.fieldName`
- ✅ Add `condition: '{{present(inputs.field)}}'` for ALL optional params
- ✅ Use `arrayFormat` for query string arrays
- ✅ Use `spread: true` for raw array or object bodies
- ✅ Use bracket notation for hyphenated param names
- ✅ Wire ALL inputs into args (complete coverage)
- ✅ Credential args must always have a `condition` check

### MUST NOT:
- ❌ Use JEXL for `value` (use JSONPath)
- ❌ Skip `condition` for optional parameters
- ❌ Put path params in args (use URL interpolation instead)
- ❌ Use `spread: true` with `in: query`
- ❌ Use `arrayFormat` with `in: body`
- ❌ Leave any input unwired
