# Transformation YAML Reference


> Complete YAML reference for transformation and transformation-library resources managed with Rudder CLI.



This guide provides a complete YAML reference for managing transformation resources using Rudder CLI.

## Overview

You can define transformation resources in YAML files anywhere inside your CLI project directory. Rudder CLI scans the project recursively and processes valid resource files.

Supported resource kinds for this workflow:

- `transformation`
- `transformation-library`

## Transformation resource

Use `kind: transformation` to define a transformation.

### `spec` properties

| Property | Type | <div>Description</div> |
| :----| :-----| :------|
| `id` <br/> Required | String | Unique project ID for the transformation. |
| `name` <br/> Required | String | Human-readable name. Must be non-empty. |
| `language` <br/> Required | String | Transformation language. Allowed values: `javascript`, `python`. |
| `description` | String | Optional description. |
| `code` | String | Inline transformation code containing valid syntax for the selected language. Mutually exclusive with `file`. |
| `file` | String | Path to transformation code file. Note that: <br /><br /><ul><li>The referenced file must exist and be readable.</li><li>Relative paths are resolved from the YAML spec's parent directory.</li></ul>**Warning:** One of `code` or `file` is required. |
| `tests` | Array | Optional list of local test suites. These tests are used only by [`rudder-cli transformations test`](https://www.rudderstack.com/docs/rudder-cli/transformations-walkthrough/#6-test-transformations-locally) and are not synced to workspace state during [`rudder-cli apply`](https://www.rudderstack.com/docs/rudder-cli/transformations-walkthrough/#7-apply-changes). |

### `tests` properties

| Property | Type | <div>Description</div> |
| :----| :-----| :------|
| `name` <br/> Required | String | Test suite name. Must be non-empty and can contain only letters, numbers, spaces, `_`, `-`, and `/`. |
| `input` | String | Directory with JSON input payload files. Relative paths resolve from the spec directory. If omitted, default is `./input`. |
| `output` | String | Directory with expected output JSON files. Relative paths resolve from the spec directory. If omitted, default is `./output`. |

**Info**

Rudder CLI tests the transformation using default RudderStack events if:

- `spec.tests` is not configured, or
- No input JSON files are found in the specified `input` path

### Validation rules

<div class="vr-explorer vr-explorer--filtered" data-vr-explorer data-vr-instance="1">
<div class="vr-explorer__toolbar">
<div class="vr-explorer__toolbar-row">
<div class="vr-explorer__search-wrap">
<label class="vr-explorer__search-label" for="vr-rules-search-1">Search rules</label>
<input id="vr-rules-search-1" class="vr-explorer__search" type="search" placeholder="Search rules…" data-vr-search autocomplete="off">
</div>
<div class="vr-explorer__spec-wrap">
Spec version
<div class="vr-explorer__spec-toggle">
<button type="button" class="vr-explorer__spec-btn is-active" data-vr-spec="v1">v1</button>
<button type="button" class="vr-explorer__spec-btn" data-vr-spec="legacy">v0.1</button>
</div>
</div>
</div>
<div class="vr-explorer__toolbar-row vr-explorer__toolbar-row--filters">
<div class="vr-explorer__phase">
Filter by phase
<button type="button" class="vr-explorer__phase-btn is-active" data-vr-phase="all">All</button>
<button type="button" class="vr-explorer__phase-btn" data-vr-phase="syntactic">Syntactic</button>
<button type="button" class="vr-explorer__phase-btn" data-vr-phase="semantic">Semantic</button>
</div>
<p class="vr-explorer__count" data-vr-count data-vr-total="5">Showing <strong>5</strong> of 5 rules</p>
</div>
</div>
<div class="vr-explorer__rules"><div class="vr-rule" id="vr-rule-1-project-duplicate-urn-v1" data-vr-rule data-phase="syntactic" data-spec-version="v1" data-section="filtered-1" data-search="project/duplicate-urn urns must be unique across the project syntactic">
<div class="vr-rule__head">
<h4 class="vr-rule__title">URNs must be unique across the project</h4>
<div class="vr-rule__meta">
syntactic
error</div>
<p class="vr-rule__id">Rule ID: <code>project/duplicate-urn</code></p>
</div><div class="vr-examples vr-examples--full-border">
<h4 class="vr-examples__heading">Examples</h4><nav>
<div class="nav nav-tabs vr-examples__tabs">
<a class="nav-item nav-link active vr-examples__tab vr-examples__tab--valid" id="nav-vr-tab-vr-rule-1-project-duplicate-urn-v1-valid" data-toggle="tab" href="#vr-tab-vr-rule-1-project-duplicate-urn-v1-valid">

✓
Valid

</a>
<a class="nav-item nav-link vr-examples__tab vr-examples__tab--invalid" id="nav-vr-tab-vr-rule-1-project-duplicate-urn-v1-invalid" data-toggle="tab" href="#vr-tab-vr-rule-1-project-duplicate-urn-v1-invalid">

✕
Invalid

</a>
</div>
</nav>
<div class="tab-content vr-examples__panels" id="nav-tab-content-vr-tab-vr-rule-1-project-duplicate-urn-v1">
<div class="tab-pane fade show active vr-examples__panel vr-examples__panel--valid" id="vr-tab-vr-rule-1-project-duplicate-urn-v1-valid"><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Distinct URNs across files</h4><p class="vr-example__desc">Each spec declares a different resource, so URNs do not collide.</p><div class="rs-code">
<div class="rs-code__head">
a.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: events
metadata:
  name: events-a
spec:
  events:
    - id: order_completed
      name: Order Completed</code></pre></div>
</div><div class="rs-code">
<div class="rs-code__head">
b.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: events
metadata:
  name: events-b
spec:
  events:
    - id: cart_viewed
      name: Cart Viewed</code></pre></div>
</div></div></div>
<div class="tab-pane fade vr-examples__panel vr-examples__panel--invalid" id="vr-tab-vr-rule-1-project-duplicate-urn-v1-invalid"><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Same URN declared in two files</h4><p class="vr-example__desc">Both files declare the same event ID, which resolves to one URN. The rule flags each occurrence.</p><div class="rs-code">
<div class="rs-code__head">
a.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: events
metadata:
  name: events-a
spec:
  events:
    - id: order_completed
      name: Order Completed</code></pre></div>
</div><div class="rs-code">
<div class="rs-code__head">
b.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: events
metadata:
  name: events-b
spec:
  events:
    - id: order_completed
      name: Order Completed (duplicate)</code></pre></div>
</div><div class="vr-diagnostics">
<div class="vr-diagnostics__label">Diagnostics</div>
<ul class="vr-diagnostics__list"><li class="vr-diagnostics__item">
a.yaml
<code class="vr-diagnostics__ref">/spec/events/0/id</code>
duplicate URN &#39;event:order_completed&#39;
</li><li class="vr-diagnostics__item">
b.yaml
<code class="vr-diagnostics__ref">/spec/events/0/id</code>
duplicate URN &#39;event:order_completed&#39;
</li></ul>
</div></div></div>
</div></div></div>
<div class="vr-rule" id="vr-rule-1-project-manifest-inline-conflict-v1" data-vr-rule data-phase="syntactic" data-spec-version="v1" data-section="filtered-1" data-search="project/manifest-inline-conflict a (workspace_id, urn) must not be defined in both an import-manifest and inline metadata.import with differing remote_ids syntactic">
<div class="vr-rule__head">
<h4 class="vr-rule__title">A (workspace_id, urn) must not be defined in both an import-manifest and inline metadata.import with differing remote_ids</h4>
<div class="vr-rule__meta">
syntactic
error</div>
<p class="vr-rule__id">Rule ID: <code>project/manifest-inline-conflict</code></p>
</div><div class="vr-examples vr-examples--full-border">
<h4 class="vr-examples__heading">Examples</h4><nav>
<div class="nav nav-tabs vr-examples__tabs">
<a class="nav-item nav-link active vr-examples__tab vr-examples__tab--valid" id="nav-vr-tab-vr-rule-1-project-manifest-inline-conflict-v1-valid" data-toggle="tab" href="#vr-tab-vr-rule-1-project-manifest-inline-conflict-v1-valid">

✓
Valid

</a>
<a class="nav-item nav-link vr-examples__tab vr-examples__tab--invalid" id="nav-vr-tab-vr-rule-1-project-manifest-inline-conflict-v1-invalid" data-toggle="tab" href="#vr-tab-vr-rule-1-project-manifest-inline-conflict-v1-invalid">

✕
Invalid (2 examples)

</a>
</div>
</nav>
<div class="tab-content vr-examples__panels" id="nav-tab-content-vr-tab-vr-rule-1-project-manifest-inline-conflict-v1">
<div class="tab-pane fade show active vr-examples__panel vr-examples__panel--valid" id="vr-tab-vr-rule-1-project-manifest-inline-conflict-v1-valid"><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Manifest and inline metadata import distinct resources</h4><p class="vr-example__desc">One resource is imported via the manifest, a different one via inline metadata. No URN appears in both, so the project is valid.</p><div class="rs-code">
<div class="rs-code__head">
events.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: events
metadata:
  name: events
  import:
    workspaces:
      - workspace_id: &#34;ws-1&#34;
        resources:
          - urn: &#34;event:cart_viewed&#34;
            remote_id: &#34;remote_b&#34;
spec:
  events:
    - id: order_completed
      name: Order Completed
    - id: cart_viewed
      name: Cart Viewed</code></pre></div>
</div><div class="rs-code">
<div class="rs-code__head">
import-manifest.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: import-manifest
metadata:
  name: import-manifest
spec:
  workspaces:
    - workspace_id: &#34;ws-1&#34;
      resources:
        - urn: &#34;event:order_completed&#34;
          remote_id: &#34;remote_a&#34;</code></pre></div>
</div></div></div>
<div class="tab-pane fade vr-examples__panel vr-examples__panel--invalid" id="vr-tab-vr-rule-1-project-manifest-inline-conflict-v1-invalid"><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Same URN imported by both a manifest and inline metadata</h4><p class="vr-example__desc">The URN event:order_completed is declared in both the manifest and an inline metadata.import block — an ambiguous double import. The rule flags both locations; remove one.</p><div class="rs-code">
<div class="rs-code__head">
events.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: events
metadata:
  name: events
  import:
    workspaces:
      - workspace_id: &#34;ws-1&#34;
        resources:
          - urn: &#34;event:order_completed&#34;
            remote_id: &#34;remote_b&#34;
spec:
  events:
    - id: order_completed
      name: Order Completed</code></pre></div>
</div><div class="rs-code">
<div class="rs-code__head">
import-manifest.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: import-manifest
metadata:
  name: import-manifest
spec:
  workspaces:
    - workspace_id: &#34;ws-1&#34;
      resources:
        - urn: &#34;event:order_completed&#34;
          remote_id: &#34;remote_a&#34;</code></pre></div>
</div><div class="vr-diagnostics">
<div class="vr-diagnostics__label">Diagnostics</div>
<ul class="vr-diagnostics__list"><li class="vr-diagnostics__item">
import-manifest.yaml
<code class="vr-diagnostics__ref">/spec/workspaces/0/resources/0/urn</code>
URN &#39;event:order_completed&#39; is defined in both an import-manifest and inline metadata
</li><li class="vr-diagnostics__item">
events.yaml
<code class="vr-diagnostics__ref">/metadata/import/workspaces/0/resources/0/urn</code>
URN &#39;event:order_completed&#39; is defined in both an import-manifest and inline metadata
</li></ul>
</div></div><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Manifest URN overlaps a legacy rudder/0.1 inline local_id import</h4><p class="vr-example__desc">The events spec uses the legacy rudder/0.1 format, whose inline imports reference resources by local_id &#43; remote_id. The local_id order_completed resolves to the URN event:order_completed — the same URN the manifest imports. Legacy specs are still subject to the conflict rule, so both locations are flagged; remove the inline metadata entry.</p><div class="rs-code">
<div class="rs-code__head">
events.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/0.1
kind: events
metadata:
  name: events
  import:
    workspaces:
      - workspace_id: &#34;ws-1&#34;
        resources:
          - local_id: order_completed
            remote_id: &#34;remote_b&#34;
spec:
  events:
    - id: order_completed
      name: Order Completed</code></pre></div>
</div><div class="rs-code">
<div class="rs-code__head">
import-manifest.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: import-manifest
metadata:
  name: import-manifest
spec:
  workspaces:
    - workspace_id: &#34;ws-1&#34;
      resources:
        - urn: &#34;event:order_completed&#34;
          remote_id: &#34;remote_a&#34;</code></pre></div>
</div><div class="vr-diagnostics">
<div class="vr-diagnostics__label">Diagnostics</div>
<ul class="vr-diagnostics__list"><li class="vr-diagnostics__item">
import-manifest.yaml
<code class="vr-diagnostics__ref">/spec/workspaces/0/resources/0/urn</code>
URN &#39;event:order_completed&#39; is defined in both an import-manifest and inline metadata
</li><li class="vr-diagnostics__item">
events.yaml
<code class="vr-diagnostics__ref">/metadata/import/workspaces/0/resources/0/urn</code>
URN &#39;event:order_completed&#39; is defined in both an import-manifest and inline metadata
</li></ul>
</div></div></div>
</div></div></div>
<div class="vr-rule" id="vr-rule-1-project-metadata-syntax-valid-v1" data-vr-rule data-phase="syntactic" data-spec-version="v1" data-section="filtered-1" data-search="project/metadata-syntax-valid metadata syntax must be valid syntactic">
<div class="vr-rule__head">
<h4 class="vr-rule__title">Metadata syntax must be valid</h4>
<div class="vr-rule__meta">
syntactic
error</div>
<p class="vr-rule__id">Rule ID: <code>project/metadata-syntax-valid</code></p>
</div><div class="vr-examples vr-examples--full-border">
<h4 class="vr-examples__heading">Examples</h4><nav>
<div class="nav nav-tabs vr-examples__tabs">
<a class="nav-item nav-link active vr-examples__tab vr-examples__tab--valid" id="nav-vr-tab-vr-rule-1-project-metadata-syntax-valid-v1-valid" data-toggle="tab" href="#vr-tab-vr-rule-1-project-metadata-syntax-valid-v1-valid">

✓
Valid (2 examples)

</a>
<a class="nav-item nav-link vr-examples__tab vr-examples__tab--invalid" id="nav-vr-tab-vr-rule-1-project-metadata-syntax-valid-v1-invalid" data-toggle="tab" href="#vr-tab-vr-rule-1-project-metadata-syntax-valid-v1-invalid">

✕
Invalid (2 examples)

</a>
</div>
</nav>
<div class="tab-content vr-examples__panels" id="nav-tab-content-vr-tab-vr-rule-1-project-metadata-syntax-valid-v1">
<div class="tab-pane fade show active vr-examples__panel vr-examples__panel--valid" id="vr-tab-vr-rule-1-project-metadata-syntax-valid-v1-valid"><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Metadata with only the required name</h4><p class="vr-example__desc">Minimal valid metadata: a name only.</p><div class="rs-code">
<div class="rs-code__head">
spec.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: events
metadata:
  name: my-events
spec:
  events: []</code></pre></div>
</div></div><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Metadata with a well-formed import block</h4><p class="vr-example__desc">An import block where each workspace declares workspace_id and each resource references a URN in the spec body.</p><div class="rs-code">
<div class="rs-code__head">
spec.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: events
metadata:
  name: my-events
  import:
    workspaces:
      - workspace_id: ws-123
        resources:
          - urn: &#34;event:order_completed&#34;
            remote_id: ev-remote-456
spec:
  events:
    - id: order_completed
      name: Order Completed</code></pre></div>
</div></div></div>
<div class="tab-pane fade vr-examples__panel vr-examples__panel--invalid" id="vr-tab-vr-rule-1-project-metadata-syntax-valid-v1-invalid"><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Metadata missing required name</h4><p class="vr-example__desc">Every spec metadata block must declare a name.</p><div class="rs-code">
<div class="rs-code__head">
spec.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: events
metadata:
  import:
    workspaces:
      - workspace_id: ws-123
spec:
  events: []</code></pre></div>
</div><div class="vr-diagnostics">
<div class="vr-diagnostics__label">Diagnostics</div>
<ul class="vr-diagnostics__list"><li class="vr-diagnostics__item">
spec.yaml
<code class="vr-diagnostics__ref">/metadata/name</code>
&#39;name&#39; is required
</li></ul>
</div></div><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Import workspace missing required workspace_id</h4><p class="vr-example__desc">Each import workspace entry must declare a workspace_id.</p><div class="rs-code">
<div class="rs-code__head">
spec.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: events
metadata:
  name: my-events
  import:
    workspaces:
      - resources:
          - urn: &#34;event:order_completed&#34;
            remote_id: ev-remote-456
spec:
  events:
    - id: order_completed
      name: Order Completed</code></pre></div>
</div><div class="vr-diagnostics">
<div class="vr-diagnostics__label">Diagnostics</div>
<ul class="vr-diagnostics__list"><li class="vr-diagnostics__item">
spec.yaml
<code class="vr-diagnostics__ref">/metadata/import/workspaces/0/workspace_id</code>
&#39;workspace_id&#39; is required
</li></ul>
</div></div></div>
</div></div></div>
<div class="vr-rule" id="vr-rule-1-transformations-transformation-semantic-valid-v1" data-vr-rule data-phase="semantic" data-spec-version="v1" data-section="filtered-1" data-search="transformations/transformation/semantic-valid transformation imports must resolve to existing transformation libraries semantic">
<div class="vr-rule__head">
<h4 class="vr-rule__title">Transformation imports must resolve to existing transformation libraries</h4>
<div class="vr-rule__meta">
semantic
error</div>
<p class="vr-rule__id">Rule ID: <code>transformations/transformation/semantic-valid</code></p>
</div><div class="vr-examples vr-examples--full-border">
<h4 class="vr-examples__heading">Examples</h4><nav>
<div class="nav nav-tabs vr-examples__tabs">
<a class="nav-item nav-link active vr-examples__tab vr-examples__tab--valid" id="nav-vr-tab-vr-rule-1-transformations-transformation-semantic-valid-v1-valid" data-toggle="tab" href="#vr-tab-vr-rule-1-transformations-transformation-semantic-valid-v1-valid">

✓
Valid

</a>
<a class="nav-item nav-link vr-examples__tab vr-examples__tab--invalid" id="nav-vr-tab-vr-rule-1-transformations-transformation-semantic-valid-v1-invalid" data-toggle="tab" href="#vr-tab-vr-rule-1-transformations-transformation-semantic-valid-v1-invalid">

✕
Invalid

</a>
</div>
</nav>
<div class="tab-content vr-examples__panels" id="nav-tab-content-vr-tab-vr-rule-1-transformations-transformation-semantic-valid-v1">
<div class="tab-pane fade show active vr-examples__panel vr-examples__panel--valid" id="vr-tab-vr-rule-1-transformations-transformation-semantic-valid-v1-valid"><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Transformation without library imports is valid</h4><div class="rs-code">
<div class="rs-code__head">
spec.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: transformation
metadata:
  name: my-transformations
spec:
  transformations:
    - id: my-transformation
      name: My Transformation
      language: javascript
      code: |
        export function transformEvent(event, metadata) {
          event.properties.processed = true;
          return event;
        }        </code></pre></div>
</div></div></div>
<div class="tab-pane fade vr-examples__panel vr-examples__panel--invalid" id="vr-tab-vr-rule-1-transformations-transformation-semantic-valid-v1-invalid"><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Transformation imports a missing library</h4><div class="rs-code">
<div class="rs-code__head">
spec.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: transformation
metadata:
  name: my-transformations
spec:
  transformations:
    - id: my-transformation
      name: My Transformation
      language: javascript
      code: |
        import mathUtils from &#39;mathUtils&#39;;
        export function transformEvent(event, metadata) {
          event.properties.value = mathUtils.round(event.properties.value);
          return event;
        }        </code></pre></div>
</div><div class="vr-diagnostics">
<div class="vr-diagnostics__label">Diagnostics</div>
<ul class="vr-diagnostics__list"><li class="vr-diagnostics__item">
spec.yaml
<code class="vr-diagnostics__ref">/code</code>
&#39;mathUtils&#39; imported library not found
</li></ul>
</div></div></div>
</div></div></div>
<div class="vr-rule" id="vr-rule-1-transformations-transformation-spec-syntax-valid-v1" data-vr-rule data-phase="syntactic" data-spec-version="v1" data-section="filtered-1" data-search="transformations/transformation/spec-syntax-valid transformation spec syntax must be valid syntactic">
<div class="vr-rule__head">
<h4 class="vr-rule__title">Transformation spec syntax must be valid</h4>
<div class="vr-rule__meta">
syntactic
error</div>
<p class="vr-rule__id">Rule ID: <code>transformations/transformation/spec-syntax-valid</code></p>
</div><div class="vr-examples vr-examples--full-border">
<h4 class="vr-examples__heading">Examples</h4><nav>
<div class="nav nav-tabs vr-examples__tabs">
<a class="nav-item nav-link active vr-examples__tab vr-examples__tab--valid" id="nav-vr-tab-vr-rule-1-transformations-transformation-spec-syntax-valid-v1-valid" data-toggle="tab" href="#vr-tab-vr-rule-1-transformations-transformation-spec-syntax-valid-v1-valid">

✓
Valid

</a>
<a class="nav-item nav-link vr-examples__tab vr-examples__tab--invalid" id="nav-vr-tab-vr-rule-1-transformations-transformation-spec-syntax-valid-v1-invalid" data-toggle="tab" href="#vr-tab-vr-rule-1-transformations-transformation-spec-syntax-valid-v1-invalid">

✕
Invalid (4 examples)

</a>
</div>
</nav>
<div class="tab-content vr-examples__panels" id="nav-tab-content-vr-tab-vr-rule-1-transformations-transformation-spec-syntax-valid-v1">
<div class="tab-pane fade show active vr-examples__panel vr-examples__panel--valid" id="vr-tab-vr-rule-1-transformations-transformation-spec-syntax-valid-v1-valid"><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Valid transformation spec with inline JavaScript</h4><div class="rs-code">
<div class="rs-code__head">
spec.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: transformation
metadata:
  name: my-transformations
spec:
  transformations:
    - id: my-transformation
      name: My Transformation
      description: Enriches events with additional metadata
      language: javascript
      code: |
        export function transformEvent(event, metadata) {
          event.properties.enriched = true;
          return event;
        }        </code></pre></div>
</div></div></div>
<div class="tab-pane fade vr-examples__panel vr-examples__panel--invalid" id="vr-tab-vr-rule-1-transformations-transformation-spec-syntax-valid-v1-invalid"><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Transformation spec missing required id</h4><div class="rs-code">
<div class="rs-code__head">
spec.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: transformation
metadata:
  name: my-transformations
spec:
  transformations:
    - name: My Transformation
      language: javascript
      code: |
        export function transformEvent(event, metadata) {
          return event;
        }        </code></pre></div>
</div><div class="vr-diagnostics">
<div class="vr-diagnostics__label">Diagnostics</div>
<ul class="vr-diagnostics__list"><li class="vr-diagnostics__item">
spec.yaml
<code class="vr-diagnostics__ref">/id</code>
&#39;id&#39; is required
</li></ul>
</div></div><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Transformation spec missing the required language</h4><div class="rs-code">
<div class="rs-code__head">
spec.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: transformation
metadata:
  name: my-transformations
spec:
  transformations:
    - id: my-transformation
      name: My Transformation
      code: |
        export function transformEvent(event, metadata) {
          return event;
        }        </code></pre></div>
</div><div class="vr-diagnostics">
<div class="vr-diagnostics__label">Diagnostics</div>
<ul class="vr-diagnostics__list"><li class="vr-diagnostics__item">
spec.yaml
<code class="vr-diagnostics__ref">/language</code>
&#39;language&#39; is required
</li></ul>
</div></div><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Transformation spec defined with an unsupported language</h4><div class="rs-code">
<div class="rs-code__head">
spec.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: transformation
metadata:
  name: my-transformations
spec:
  transformations:
    - id: my-transformation
      name: My Transformation
      language: ruby
      code: |
        def transform_event(event, metadata)
          event
        end        </code></pre></div>
</div><div class="vr-diagnostics">
<div class="vr-diagnostics__label">Diagnostics</div>
<ul class="vr-diagnostics__list"><li class="vr-diagnostics__item">
spec.yaml
<code class="vr-diagnostics__ref">/language</code>
&#39;language&#39; must be one of [javascript python]
</li></ul>
</div></div><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Transformation spec missing code and file</h4><div class="rs-code">
<div class="rs-code__head">
spec.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: transformation
metadata:
  name: my-transformations
spec:
  transformations:
    - id: my-transformation
      name: My Transformation
      language: javascript</code></pre></div>
</div><div class="vr-diagnostics">
<div class="vr-diagnostics__label">Diagnostics</div>
<ul class="vr-diagnostics__list"><li class="vr-diagnostics__item">
spec.yaml
<code class="vr-diagnostics__ref">/code</code>
&#39;code&#39; is required when &#39;file&#39; is not specified
</li></ul>
</div></div></div>
</div></div></div>
</div>
</div>

## Transformation library resource

Use `kind: transformation-library` to define a reusable transformation library.

### `spec` properties

| Property | Type | <div>Description</div> |
| :----| :-----| :------|
| `id` <br/> Required | String | Unique project ID for the library. |
| `name` <br/> Required | String | Human-readable name — must be non-empty. |
| `description` | String | Optional description. |
| `language` <br/> Required | String | Library language. Allowed values are `javascript` and `python`. |
| `code` | String | Inline library code containing valid syntax for the selected language. Mutually exclusive with `file`. |
| `file` | String | Path to library code file. Note that: <br /><br /><ul><li>The referenced file must exist and be readable.</li><li>Relative paths are resolved from the YAML spec's parent directory.</li></ul>**Warning:** One of `code` or `file` is required. |
| `import_name` <br/> Required | String | Handle used when importing the library in transformation code — must be camelCase of `name`. <br /><br />**Warning:** Validation fails if `import_name` does not match the camelCase form of `name`. |

### Library validation rules

<div class="vr-explorer vr-explorer--filtered" data-vr-explorer data-vr-instance="1">
<div class="vr-explorer__toolbar">
<div class="vr-explorer__toolbar-row">
<div class="vr-explorer__search-wrap">
<label class="vr-explorer__search-label" for="vr-rules-search-1">Search rules</label>
<input id="vr-rules-search-1" class="vr-explorer__search" type="search" placeholder="Search rules…" data-vr-search autocomplete="off">
</div>
<div class="vr-explorer__spec-wrap">
Spec version
<div class="vr-explorer__spec-toggle">
<button type="button" class="vr-explorer__spec-btn is-active" data-vr-spec="v1">v1</button>
<button type="button" class="vr-explorer__spec-btn" data-vr-spec="legacy">v0.1</button>
</div>
</div>
</div>
<div class="vr-explorer__toolbar-row vr-explorer__toolbar-row--filters">
<div class="vr-explorer__phase">
Filter by phase
<button type="button" class="vr-explorer__phase-btn is-active" data-vr-phase="all">All</button>
<button type="button" class="vr-explorer__phase-btn" data-vr-phase="syntactic">Syntactic</button>
<button type="button" class="vr-explorer__phase-btn" data-vr-phase="semantic">Semantic</button>
</div>
<p class="vr-explorer__count" data-vr-count data-vr-total="5">Showing <strong>5</strong> of 5 rules</p>
</div>
</div>
<div class="vr-explorer__rules"><div class="vr-rule" id="vr-rule-1-project-duplicate-urn-v1" data-vr-rule data-phase="syntactic" data-spec-version="v1" data-section="filtered-1" data-search="project/duplicate-urn urns must be unique across the project syntactic">
<div class="vr-rule__head">
<h4 class="vr-rule__title">URNs must be unique across the project</h4>
<div class="vr-rule__meta">
syntactic
error</div>
<p class="vr-rule__id">Rule ID: <code>project/duplicate-urn</code></p>
</div><div class="vr-examples vr-examples--full-border">
<h4 class="vr-examples__heading">Examples</h4><nav>
<div class="nav nav-tabs vr-examples__tabs">
<a class="nav-item nav-link active vr-examples__tab vr-examples__tab--valid" id="nav-vr-tab-vr-rule-1-project-duplicate-urn-v1-valid" data-toggle="tab" href="#vr-tab-vr-rule-1-project-duplicate-urn-v1-valid">

✓
Valid

</a>
<a class="nav-item nav-link vr-examples__tab vr-examples__tab--invalid" id="nav-vr-tab-vr-rule-1-project-duplicate-urn-v1-invalid" data-toggle="tab" href="#vr-tab-vr-rule-1-project-duplicate-urn-v1-invalid">

✕
Invalid

</a>
</div>
</nav>
<div class="tab-content vr-examples__panels" id="nav-tab-content-vr-tab-vr-rule-1-project-duplicate-urn-v1">
<div class="tab-pane fade show active vr-examples__panel vr-examples__panel--valid" id="vr-tab-vr-rule-1-project-duplicate-urn-v1-valid"><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Distinct URNs across files</h4><p class="vr-example__desc">Each spec declares a different resource, so URNs do not collide.</p><div class="rs-code">
<div class="rs-code__head">
a.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: events
metadata:
  name: events-a
spec:
  events:
    - id: order_completed
      name: Order Completed</code></pre></div>
</div><div class="rs-code">
<div class="rs-code__head">
b.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: events
metadata:
  name: events-b
spec:
  events:
    - id: cart_viewed
      name: Cart Viewed</code></pre></div>
</div></div></div>
<div class="tab-pane fade vr-examples__panel vr-examples__panel--invalid" id="vr-tab-vr-rule-1-project-duplicate-urn-v1-invalid"><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Same URN declared in two files</h4><p class="vr-example__desc">Both files declare the same event ID, which resolves to one URN. The rule flags each occurrence.</p><div class="rs-code">
<div class="rs-code__head">
a.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: events
metadata:
  name: events-a
spec:
  events:
    - id: order_completed
      name: Order Completed</code></pre></div>
</div><div class="rs-code">
<div class="rs-code__head">
b.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: events
metadata:
  name: events-b
spec:
  events:
    - id: order_completed
      name: Order Completed (duplicate)</code></pre></div>
</div><div class="vr-diagnostics">
<div class="vr-diagnostics__label">Diagnostics</div>
<ul class="vr-diagnostics__list"><li class="vr-diagnostics__item">
a.yaml
<code class="vr-diagnostics__ref">/spec/events/0/id</code>
duplicate URN &#39;event:order_completed&#39;
</li><li class="vr-diagnostics__item">
b.yaml
<code class="vr-diagnostics__ref">/spec/events/0/id</code>
duplicate URN &#39;event:order_completed&#39;
</li></ul>
</div></div></div>
</div></div></div>
<div class="vr-rule" id="vr-rule-1-project-manifest-inline-conflict-v1" data-vr-rule data-phase="syntactic" data-spec-version="v1" data-section="filtered-1" data-search="project/manifest-inline-conflict a (workspace_id, urn) must not be defined in both an import-manifest and inline metadata.import with differing remote_ids syntactic">
<div class="vr-rule__head">
<h4 class="vr-rule__title">A (workspace_id, urn) must not be defined in both an import-manifest and inline metadata.import with differing remote_ids</h4>
<div class="vr-rule__meta">
syntactic
error</div>
<p class="vr-rule__id">Rule ID: <code>project/manifest-inline-conflict</code></p>
</div><div class="vr-examples vr-examples--full-border">
<h4 class="vr-examples__heading">Examples</h4><nav>
<div class="nav nav-tabs vr-examples__tabs">
<a class="nav-item nav-link active vr-examples__tab vr-examples__tab--valid" id="nav-vr-tab-vr-rule-1-project-manifest-inline-conflict-v1-valid" data-toggle="tab" href="#vr-tab-vr-rule-1-project-manifest-inline-conflict-v1-valid">

✓
Valid

</a>
<a class="nav-item nav-link vr-examples__tab vr-examples__tab--invalid" id="nav-vr-tab-vr-rule-1-project-manifest-inline-conflict-v1-invalid" data-toggle="tab" href="#vr-tab-vr-rule-1-project-manifest-inline-conflict-v1-invalid">

✕
Invalid (2 examples)

</a>
</div>
</nav>
<div class="tab-content vr-examples__panels" id="nav-tab-content-vr-tab-vr-rule-1-project-manifest-inline-conflict-v1">
<div class="tab-pane fade show active vr-examples__panel vr-examples__panel--valid" id="vr-tab-vr-rule-1-project-manifest-inline-conflict-v1-valid"><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Manifest and inline metadata import distinct resources</h4><p class="vr-example__desc">One resource is imported via the manifest, a different one via inline metadata. No URN appears in both, so the project is valid.</p><div class="rs-code">
<div class="rs-code__head">
events.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: events
metadata:
  name: events
  import:
    workspaces:
      - workspace_id: &#34;ws-1&#34;
        resources:
          - urn: &#34;event:cart_viewed&#34;
            remote_id: &#34;remote_b&#34;
spec:
  events:
    - id: order_completed
      name: Order Completed
    - id: cart_viewed
      name: Cart Viewed</code></pre></div>
</div><div class="rs-code">
<div class="rs-code__head">
import-manifest.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: import-manifest
metadata:
  name: import-manifest
spec:
  workspaces:
    - workspace_id: &#34;ws-1&#34;
      resources:
        - urn: &#34;event:order_completed&#34;
          remote_id: &#34;remote_a&#34;</code></pre></div>
</div></div></div>
<div class="tab-pane fade vr-examples__panel vr-examples__panel--invalid" id="vr-tab-vr-rule-1-project-manifest-inline-conflict-v1-invalid"><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Same URN imported by both a manifest and inline metadata</h4><p class="vr-example__desc">The URN event:order_completed is declared in both the manifest and an inline metadata.import block — an ambiguous double import. The rule flags both locations; remove one.</p><div class="rs-code">
<div class="rs-code__head">
events.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: events
metadata:
  name: events
  import:
    workspaces:
      - workspace_id: &#34;ws-1&#34;
        resources:
          - urn: &#34;event:order_completed&#34;
            remote_id: &#34;remote_b&#34;
spec:
  events:
    - id: order_completed
      name: Order Completed</code></pre></div>
</div><div class="rs-code">
<div class="rs-code__head">
import-manifest.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: import-manifest
metadata:
  name: import-manifest
spec:
  workspaces:
    - workspace_id: &#34;ws-1&#34;
      resources:
        - urn: &#34;event:order_completed&#34;
          remote_id: &#34;remote_a&#34;</code></pre></div>
</div><div class="vr-diagnostics">
<div class="vr-diagnostics__label">Diagnostics</div>
<ul class="vr-diagnostics__list"><li class="vr-diagnostics__item">
import-manifest.yaml
<code class="vr-diagnostics__ref">/spec/workspaces/0/resources/0/urn</code>
URN &#39;event:order_completed&#39; is defined in both an import-manifest and inline metadata
</li><li class="vr-diagnostics__item">
events.yaml
<code class="vr-diagnostics__ref">/metadata/import/workspaces/0/resources/0/urn</code>
URN &#39;event:order_completed&#39; is defined in both an import-manifest and inline metadata
</li></ul>
</div></div><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Manifest URN overlaps a legacy rudder/0.1 inline local_id import</h4><p class="vr-example__desc">The events spec uses the legacy rudder/0.1 format, whose inline imports reference resources by local_id &#43; remote_id. The local_id order_completed resolves to the URN event:order_completed — the same URN the manifest imports. Legacy specs are still subject to the conflict rule, so both locations are flagged; remove the inline metadata entry.</p><div class="rs-code">
<div class="rs-code__head">
events.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/0.1
kind: events
metadata:
  name: events
  import:
    workspaces:
      - workspace_id: &#34;ws-1&#34;
        resources:
          - local_id: order_completed
            remote_id: &#34;remote_b&#34;
spec:
  events:
    - id: order_completed
      name: Order Completed</code></pre></div>
</div><div class="rs-code">
<div class="rs-code__head">
import-manifest.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: import-manifest
metadata:
  name: import-manifest
spec:
  workspaces:
    - workspace_id: &#34;ws-1&#34;
      resources:
        - urn: &#34;event:order_completed&#34;
          remote_id: &#34;remote_a&#34;</code></pre></div>
</div><div class="vr-diagnostics">
<div class="vr-diagnostics__label">Diagnostics</div>
<ul class="vr-diagnostics__list"><li class="vr-diagnostics__item">
import-manifest.yaml
<code class="vr-diagnostics__ref">/spec/workspaces/0/resources/0/urn</code>
URN &#39;event:order_completed&#39; is defined in both an import-manifest and inline metadata
</li><li class="vr-diagnostics__item">
events.yaml
<code class="vr-diagnostics__ref">/metadata/import/workspaces/0/resources/0/urn</code>
URN &#39;event:order_completed&#39; is defined in both an import-manifest and inline metadata
</li></ul>
</div></div></div>
</div></div></div>
<div class="vr-rule" id="vr-rule-1-project-metadata-syntax-valid-v1" data-vr-rule data-phase="syntactic" data-spec-version="v1" data-section="filtered-1" data-search="project/metadata-syntax-valid metadata syntax must be valid syntactic">
<div class="vr-rule__head">
<h4 class="vr-rule__title">Metadata syntax must be valid</h4>
<div class="vr-rule__meta">
syntactic
error</div>
<p class="vr-rule__id">Rule ID: <code>project/metadata-syntax-valid</code></p>
</div><div class="vr-examples vr-examples--full-border">
<h4 class="vr-examples__heading">Examples</h4><nav>
<div class="nav nav-tabs vr-examples__tabs">
<a class="nav-item nav-link active vr-examples__tab vr-examples__tab--valid" id="nav-vr-tab-vr-rule-1-project-metadata-syntax-valid-v1-valid" data-toggle="tab" href="#vr-tab-vr-rule-1-project-metadata-syntax-valid-v1-valid">

✓
Valid (2 examples)

</a>
<a class="nav-item nav-link vr-examples__tab vr-examples__tab--invalid" id="nav-vr-tab-vr-rule-1-project-metadata-syntax-valid-v1-invalid" data-toggle="tab" href="#vr-tab-vr-rule-1-project-metadata-syntax-valid-v1-invalid">

✕
Invalid (2 examples)

</a>
</div>
</nav>
<div class="tab-content vr-examples__panels" id="nav-tab-content-vr-tab-vr-rule-1-project-metadata-syntax-valid-v1">
<div class="tab-pane fade show active vr-examples__panel vr-examples__panel--valid" id="vr-tab-vr-rule-1-project-metadata-syntax-valid-v1-valid"><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Metadata with only the required name</h4><p class="vr-example__desc">Minimal valid metadata: a name only.</p><div class="rs-code">
<div class="rs-code__head">
spec.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: events
metadata:
  name: my-events
spec:
  events: []</code></pre></div>
</div></div><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Metadata with a well-formed import block</h4><p class="vr-example__desc">An import block where each workspace declares workspace_id and each resource references a URN in the spec body.</p><div class="rs-code">
<div class="rs-code__head">
spec.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: events
metadata:
  name: my-events
  import:
    workspaces:
      - workspace_id: ws-123
        resources:
          - urn: &#34;event:order_completed&#34;
            remote_id: ev-remote-456
spec:
  events:
    - id: order_completed
      name: Order Completed</code></pre></div>
</div></div></div>
<div class="tab-pane fade vr-examples__panel vr-examples__panel--invalid" id="vr-tab-vr-rule-1-project-metadata-syntax-valid-v1-invalid"><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Metadata missing required name</h4><p class="vr-example__desc">Every spec metadata block must declare a name.</p><div class="rs-code">
<div class="rs-code__head">
spec.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: events
metadata:
  import:
    workspaces:
      - workspace_id: ws-123
spec:
  events: []</code></pre></div>
</div><div class="vr-diagnostics">
<div class="vr-diagnostics__label">Diagnostics</div>
<ul class="vr-diagnostics__list"><li class="vr-diagnostics__item">
spec.yaml
<code class="vr-diagnostics__ref">/metadata/name</code>
&#39;name&#39; is required
</li></ul>
</div></div><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Import workspace missing required workspace_id</h4><p class="vr-example__desc">Each import workspace entry must declare a workspace_id.</p><div class="rs-code">
<div class="rs-code__head">
spec.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: events
metadata:
  name: my-events
  import:
    workspaces:
      - resources:
          - urn: &#34;event:order_completed&#34;
            remote_id: ev-remote-456
spec:
  events:
    - id: order_completed
      name: Order Completed</code></pre></div>
</div><div class="vr-diagnostics">
<div class="vr-diagnostics__label">Diagnostics</div>
<ul class="vr-diagnostics__list"><li class="vr-diagnostics__item">
spec.yaml
<code class="vr-diagnostics__ref">/metadata/import/workspaces/0/workspace_id</code>
&#39;workspace_id&#39; is required
</li></ul>
</div></div></div>
</div></div></div>
<div class="vr-rule" id="vr-rule-1-transformations-transformation-library-semantic-valid-v1" data-vr-rule data-phase="semantic" data-spec-version="v1" data-section="filtered-1" data-search="transformations/transformation-library/semantic-valid transformation library must be semantically valid semantic">
<div class="vr-rule__head">
<h4 class="vr-rule__title">Transformation library must be semantically valid</h4>
<div class="vr-rule__meta">
semantic
error</div>
<p class="vr-rule__id">Rule ID: <code>transformations/transformation-library/semantic-valid</code></p>
</div><div class="vr-examples vr-examples--full-border">
<h4 class="vr-examples__heading">Examples</h4><nav>
<div class="nav nav-tabs vr-examples__tabs">
<a class="nav-item nav-link active vr-examples__tab vr-examples__tab--valid" id="nav-vr-tab-vr-rule-1-transformations-transformation-library-semantic-valid-v1-valid" data-toggle="tab" href="#vr-tab-vr-rule-1-transformations-transformation-library-semantic-valid-v1-valid">

✓
Valid

</a>
<a class="nav-item nav-link vr-examples__tab vr-examples__tab--invalid" id="nav-vr-tab-vr-rule-1-transformations-transformation-library-semantic-valid-v1-invalid" data-toggle="tab" href="#vr-tab-vr-rule-1-transformations-transformation-library-semantic-valid-v1-invalid">

✕
Invalid

</a>
</div>
</nav>
<div class="tab-content vr-examples__panels" id="nav-tab-content-vr-tab-vr-rule-1-transformations-transformation-library-semantic-valid-v1">
<div class="tab-pane fade show active vr-examples__panel vr-examples__panel--valid" id="vr-tab-vr-rule-1-transformations-transformation-library-semantic-valid-v1-valid"><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Transformation library with unique import_name</h4><div class="rs-code">
<div class="rs-code__head">
spec.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: transformation-library
metadata:
  name: my-libraries
spec:
  libraries:
    - id: math-utils
      name: Math Utils
      import_name: mathUtils
      language: javascript
      code: |
        export function round(value) {
          return Math.round(value);
        }        </code></pre></div>
</div></div></div>
<div class="tab-pane fade vr-examples__panel vr-examples__panel--invalid" id="vr-tab-vr-rule-1-transformations-transformation-library-semantic-valid-v1-invalid"><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Duplicate transformation library import_name</h4><div class="rs-code">
<div class="rs-code__head">
spec.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: transformation-library
metadata:
  name: my-libraries
spec:
  libraries:
    - id: math-utils
      name: Math Utils
      import_name: mathUtils
      language: javascript
      code: |
        export function round(value) {
          return Math.round(value);
        }        
    - id: math-helpers
      name: Math Helpers
      import_name: mathUtils
      language: javascript
      code: |
        export function ceil(value) {
          return Math.ceil(value);
        }        </code></pre></div>
</div><div class="vr-diagnostics">
<div class="vr-diagnostics__label">Diagnostics</div>
<ul class="vr-diagnostics__list"><li class="vr-diagnostics__item">
spec.yaml
<code class="vr-diagnostics__ref">/import_name</code>
import_name &#39;mathUtils&#39; is duplicate
</li></ul>
</div></div></div>
</div></div></div>
<div class="vr-rule" id="vr-rule-1-transformations-transformation-library-spec-syntax-valid-v1" data-vr-rule data-phase="syntactic" data-spec-version="v1" data-section="filtered-1" data-search="transformations/transformation-library/spec-syntax-valid transformation library spec syntax must be valid syntactic">
<div class="vr-rule__head">
<h4 class="vr-rule__title">Transformation library spec syntax must be valid</h4>
<div class="vr-rule__meta">
syntactic
error</div>
<p class="vr-rule__id">Rule ID: <code>transformations/transformation-library/spec-syntax-valid</code></p>
</div><div class="vr-examples vr-examples--full-border">
<h4 class="vr-examples__heading">Examples</h4><nav>
<div class="nav nav-tabs vr-examples__tabs">
<a class="nav-item nav-link active vr-examples__tab vr-examples__tab--valid" id="nav-vr-tab-vr-rule-1-transformations-transformation-library-spec-syntax-valid-v1-valid" data-toggle="tab" href="#vr-tab-vr-rule-1-transformations-transformation-library-spec-syntax-valid-v1-valid">

✓
Valid

</a>
<a class="nav-item nav-link vr-examples__tab vr-examples__tab--invalid" id="nav-vr-tab-vr-rule-1-transformations-transformation-library-spec-syntax-valid-v1-invalid" data-toggle="tab" href="#vr-tab-vr-rule-1-transformations-transformation-library-spec-syntax-valid-v1-invalid">

✕
Invalid (4 examples)

</a>
</div>
</nav>
<div class="tab-content vr-examples__panels" id="nav-tab-content-vr-tab-vr-rule-1-transformations-transformation-library-spec-syntax-valid-v1">
<div class="tab-pane fade show active vr-examples__panel vr-examples__panel--valid" id="vr-tab-vr-rule-1-transformations-transformation-library-spec-syntax-valid-v1-valid"><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Valid transformation library spec with inline JavaScript</h4><div class="rs-code">
<div class="rs-code__head">
spec.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: transformation-library
metadata:
  name: my-libraries
spec:
  libraries:
    - id: math-utils
      name: Math Utils
      import_name: mathUtils
      description: Utility functions for math operations
      language: javascript
      code: |
        export function round(value) {
          return Math.round(value);
        }        </code></pre></div>
</div></div></div>
<div class="tab-pane fade vr-examples__panel vr-examples__panel--invalid" id="vr-tab-vr-rule-1-transformations-transformation-library-spec-syntax-valid-v1-invalid"><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Transformation library spec missing required id</h4><div class="rs-code">
<div class="rs-code__head">
spec.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: transformation-library
metadata:
  name: my-libraries
spec:
  libraries:
    - name: Math Utils
      import_name: mathUtils
      language: javascript
      code: |
        export function round(value) {
          return Math.round(value);
        }        </code></pre></div>
</div><div class="vr-diagnostics">
<div class="vr-diagnostics__label">Diagnostics</div>
<ul class="vr-diagnostics__list"><li class="vr-diagnostics__item">
spec.yaml
<code class="vr-diagnostics__ref">/id</code>
&#39;id&#39; is required
</li></ul>
</div></div><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Transformation library spec missing required import_name</h4><div class="rs-code">
<div class="rs-code__head">
spec.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: transformation-library
metadata:
  name: my-libraries
spec:
  libraries:
    - id: math-utils
      name: Math Utils
      language: javascript
      code: |
        export function round(value) {
          return Math.round(value);
        }        </code></pre></div>
</div><div class="vr-diagnostics">
<div class="vr-diagnostics__label">Diagnostics</div>
<ul class="vr-diagnostics__list"><li class="vr-diagnostics__item">
spec.yaml
<code class="vr-diagnostics__ref">/import_name</code>
&#39;import_name&#39; is required
</li></ul>
</div></div><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Transformation library import_name is not camelCase of name</h4><div class="rs-code">
<div class="rs-code__head">
spec.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: transformation-library
metadata:
  name: my-libraries
spec:
  libraries:
    - id: math-utils
      name: Math Utils
      import_name: MathUtils
      language: javascript
      code: |
        export function round(value) {
          return Math.round(value);
        }        </code></pre></div>
</div><div class="vr-diagnostics">
<div class="vr-diagnostics__label">Diagnostics</div>
<ul class="vr-diagnostics__list"><li class="vr-diagnostics__item">
spec.yaml
<code class="vr-diagnostics__ref">/import_name</code>
&#39;import_name&#39; must be camelCase of &#39;name&#39;
</li></ul>
</div></div><div class="vr-example__item">
<h4 class="vr-examples__heading vr-examples__heading--example">Transformation library spec with unsupported language</h4><div class="rs-code">
<div class="rs-code__head">
spec.yaml
yaml
<button class="rs-code__copy" type="button">

Copy
</button>
</div>
<div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: transformation-library
metadata:
  name: my-libraries
spec:
  libraries:
    - id: math-utils
      name: Math Utils
      import_name: mathUtils
      language: ruby
      code: |
        def round(value)
          value.round
        end        </code></pre></div>
</div><div class="vr-diagnostics">
<div class="vr-diagnostics__label">Diagnostics</div>
<ul class="vr-diagnostics__list"><li class="vr-diagnostics__item">
spec.yaml
<code class="vr-diagnostics__ref">/language</code>
&#39;language&#39; must be one of [javascript python]
</li></ul>
</div></div></div>
</div></div></div>
</div>
</div>

## Testing framework

Rudder CLI includes a rich built-in testing framework for validating transformations and transformation libraries locally.

### Structure

The testing framework uses input and output directories to run test cases:

- All files in the `input` directory are treated as test inputs
- Corresponding files in the `output` directory are used as expected outputs for comparison against the actual transformation results

**Warning:** Input and output file names must match for accurate testing and comparison.

For each test case, the framework sends the input event through the transformation and compares the actual output against the expected output.

### Test modes

The testing framework supports two modes:

| Mode | Description |
| :---- | :------ |
| Default | Displays minimal details about test results. |
| `--verbose` | Displays more context around differences, including three lines above and below each code diff. |

### Test result classification

Each input file represents a separate test case. Rudder CLI classifies transformation test results into the following categories:

| Result | Description |
| :---- | :------ |
| Passed | The actual output matches the expected output. If the expected output is missing, then a successful execution is considered as passed. |
| Execution error | The transformation code encountered an error during execution. |
| Output mismatch error | The actual output doesn't match the expected output. |

**Info:** Transformation library tests focus specifically on syntax validation.

## See more

- See [Manage Transformations Using Rudder CLI](https://www.rudderstack.com/docs/rudder-cli/manage-transformations/) for feature overview 
- See [Transformations Quickstart](https://www.rudderstack.com/docs/rudder-cli/transformations-walkthrough/) for a complete end-to-end example
