PageSourceSearch

https://walkeros.io/assets/js/41e28bf7.bdc86dcc.js

js walkeros.io collected 2026-09-25 21:27:19 UTC 19,259 bytes, 104 lines download raw bytes

1"use strict";(globalThis.webpackChunk_walkeros_website=globalThis.webpackChunk_walkeros_website||[]).push([[3728],{8563(e,s,t){t.r(s),t.d(s,{assets:()=>o,contentTitle:()=>r,default:()=>p,frontMatter:()=>l,metadata:()=>n,toc:()=>d});let n=JSON.parse('{"id":"getting-started/flow/step-examples","title":"Step examples","description":"Embed input/output examples on each flow step for testing, documentation, and simulation","source":"@site/docs/getting-started/flow/step-examples.mdx","sourceDirName":"getting-started/flow","slug":"/getting-started/flow/step-examples","permalink":"/docs/getting-started/flow/step-examples","draft":false,"unlisted":false,"editUrl":"https://github.com/elbwalker/walkerOS/edit/main/website/docs/getting-started/flow/step-examples.mdx","tags":[],"version":"current","sidebarPosition":1,"frontMatter":{"title":"Step examples","description":"Embed input/output examples on each flow step for testing, documentation, and simulation","sidebar_position":1},"sidebar":"docsSidebar","previous":{"title":"Flow","permalink":"/docs/getting-started/flow/"},"next":{"title":"Contract","permalink":"/docs/getting-started/flow/contract"}}');var a=t(62540),i=t(65404);let l={title:"Step examples",description:"Embed input/output examples on each flow step for testing, documentation, and simulation",sidebar_position:1},r="Step examples",o={},d=[{value:"What are step examples",id:"what-are-step-examples",level:2},{value:"The <code>{ in, out }</code> format",id:"the--in-out--format",level:2},{value:"Command examples",id:"command-examples",level:3},{value:"Three type zones",id:"three-type-zones",level:2},{value:"Adding examples to a flow",id:"adding-examples-to-a-flow",level:2},{value:"Using examples with the CLI",id:"using-examples-with-the-cli",level:2},{value:"Simulate a single example",id:"simulate-a-single-example",level:3},{value:"Validate examples",id:"validate-examples",level:3},{value:"Cross-step validation",id:"cross-step-validation",level:3},{value:"Using examples in tests",id:"using-examples-in-tests",level:2},{value:"Package-level vs flow-level examples",id:"package-level-vs-flow-level-examples",level:2},{value:"Next steps",id:"next-steps",level:2}];function c(e){let s={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,i.R)(),...e.components},{CodeSnippet:t,Details:n}=s;return t||h("CodeSnippet",!0),n||h("Details",!0),(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(s.header,{children:(0,a.jsx)(s.h1,{id:"step-examples",children:"Step examples"})}),"\n",(0,a.jsxs)(s.p,{children:["Add ",(0,a.jsx)(s.code,{children:"examples"})," to any step in your flow config to document what it expects and produces:"]}),"\n",(0,a.jsx)(s.pre,{children:(0,a.jsx)(s.code,{className:"language-json",children:'"examples": {\n  "purchase": {\n    "in": { "name": "order complete", "data": { "id": "ORD-123", "total": 149.97 } },\n    "mapping": { "name": "purchase", "data": { "map": { "transaction_id": "data.id", "value": "data.total" } } },\n    "out": ["event", "purchase", { "transaction_id": "ORD-123", "value": 149.97 }]\n  }\n}\n'})}),"\n",(0,a.jsx)(s.p,{children:"Examples are test fixtures, documentation, and simulation data in one place. They live in your flow config, get stripped at build time, and have zero runtime impact."}),"\n",(0,a.jsx)(s.h2,{id:"what-are-step-examples",children:"What are step examples"}),"\n",(0,a.jsxs)(s.p,{children:["Every source, transformer, and destination in a walkerOS flow is a ",(0,a.jsx)(s.strong,{children:"step"}),". Each step receives input and produces output. Step examples are named ",(0,a.jsx)(s.code,{children:"{ in, out }"})," pairs that capture concrete data for each step: what goes in, what comes out."]}),"\n",(0,a.jsx)(s.p,{children:"They serve multiple purposes simultaneously:"}),"\n",(0,a.jsxs)(s.ul,{children:["\n",(0,a.jsxs)(s.li,{children:[(0,a.jsx)(s.strong,{children:"Documentation"}),": developers see real data shapes, not just type signatures"]}),"\n",(0,a.jsxs)(s.li,{children:[(0,a.jsx)(s.strong,{children:"Testing"}),": CI runs examples as regression tests via ",(0,a.jsx)(s.code,{children:"walkeros push --simulate"})]}),"\n",(0,a.jsxs)(s.li,{children:[(0,a.jsx)(s.strong,{children:"Simulation"}),": debug your pipeline before deployment"]}),"\n",(0,a.jsxs)(s.li,{children:[(0,a.jsx)(s.strong,{children:"LLM context"}),": AI tools use examples to suggest correct mappings"]}),"\n"]}),"\n",(0,a.jsxs)(s.h2,{id:"the--in-out--format",children:["The ",(0,a.jsx)(s.code,{children:"{ in, out }"})," format"]}),"\n",(0,a.jsx)(s.p,{children:"Each example has a human-readable name and two fields:"}),"\n",(0,a.jsx)(t,{code:`{
2  "examples": {
3    "page view": {
4      "in": {
5        "name": "page view",
6        "data": { "title": "Home", "path": "/" }
7      },
8      "out": ["event", "page_view", { "page_title": "Home" }]
9    },
10    "purchase": {
11      "in": {
12        "name": "order complete",
13        "data": { "id": "ORD-123", "total": 149.97, "currency": "EUR" }
14      },
15      "mapping": {
16        "name": "purchase",
17        "data": {
18          "map": {
19            "transaction_id": "data.id",
20            "value": "data.total",
21            "currency": "data.currency"
22          }
23        }
24      },
25      "out": ["event", "purchase", {
26        "transaction_id": "ORD-123",
27        "value": 149.97,
28        "currency": "EUR"
29      }]
30    }
31  }
32}`,language:"json"}),"\n",(0,a.jsxs)(s.table,{children:[(0,a.jsx)(s.thead,{children:(0,a.jsxs)(s.tr,{children:[(0,a.jsx)(s.th,{children:"Field"}),(0,a.jsx)(s.th,{children:"Type"}),(0,a.jsx)(s.th,{children:"Description"})]})}),(0,a.jsxs)(s.tbody,{children:[(0,a.jsxs)(s.tr,{children:[(0,a.jsx)(s.td,{children:(0,a.jsx)(s.code,{children:"in"})}),(0,a.jsx)(s.td,{children:"any"}),(0,a.jsx)(s.td,{children:"The data the step receives"})]}),(0,a.jsxs)(s.tr,{children:[(0,a.jsx)(s.td,{children:(0,a.jsx)(s.code,{children:"mapping"})}),(0,a.jsx)(s.td,{children:"object"}),(0,a.jsx)(s.td,{children:"The mapping rule applied to this event (destinations only)"})]}),(0,a.jsxs)(s.tr,{children:[(0,a.jsx)(s.td,{children:(0,a.jsx)(s.code,{children:"out"})}),(0,a.jsx)(s.td,{children:"any"}),(0,a.jsx)(s.td,{children:"The data the step produces"})]}),(0,a.jsxs)(s.tr,{children:[(0,a.jsx)(s.td,{children:(0,a.jsx)(s.code,{children:"out: false"})}),(0,a.jsx)(s.td,{children:(0,a.jsx)(s.code,{children:"false"})}),(0,a.jsx)(s.td,{children:"The step rejects or filters this event"})]}),(0,a.jsxs)(s.tr,{children:[(0,a.jsx)(s.td,{children:(0,a.jsx)(s.code,{children:"command"})}),(0,a.jsx)(s.td,{children:"string"}),(0,a.jsxs)(s.td,{children:["Route ",(0,a.jsx)(s.code,{children:"in"})," through a walker command instead of pushing it as an event (",(0,a.jsx)(s.code,{children:"config"}),", ",(0,a.jsx)(s.code,{children:"consent"}),", ",(0,a.jsx)(s.code,{children:"user"}),", ",(0,a.jsx)(s.code,{children:"run"}),")"]})]})]})]}),"\n",(0,a.jsxs)(s.p,{children:["For destinations, the optional ",(0,a.jsx)(s.code,{children:"mapping"})," field captures the mapping rule that transforms the walkerOS event into the vendor-specific output. This ties the example to a specific mapping configuration, so tests and simulations can register it dynamically as ",(0,a.jsx)(s.code,{children:"{ [entity]: { [action]: example.mapping } }"}),"."]}),"\n",(0,a.jsx)(s.h3,{id:"command-examples",children:"Command examples"}),"\n",(0,a.jsxs)(s.p,{children:["Some destinations need to react to walker commands (consent updates, user identification, run state) rather than events. Set the ",(0,a.jsx)(s.code,{children:"command"})," field on a step example so the test runner invokes ",(0,a.jsx)(s.code,{children:"elb('walker <command>', in)"})," instead of pushing ",(0,a.jsx)(s.code,{children:"in"})," as a regular event:"]}),"\n",(0,a.jsx)(t,{code:`{
33  "command": "consent",
34  "in": { "marketing": true, "functional": true },
35  "out": ["consent", "update", { "ad_storage": "granted", "analytics_storage": "granted" }]
36}`,language:"json"}),"\n",(0,a.jsxs)(s.p,{children:["Supported commands: `config`, `consent`, `user`, `run`. When ",(0,a.jsx)(s.code,{children:"command"})," is set, ",(0,a.jsx)(s.code,{children:"mapping"}
36)," is ignored, because commands don't flow through event mapping. See the ",(0,a.jsx)(s.a,{href:"https://github.com/elbwalker/walkerOS/blob/main/skills/walkeros-using-step-examples/SKILL.md#command-step-example",children:"walkeros-using-step-examples skill"})," for the full test-runner pattern."]}),"\n",(0,a.jsxs)(s.p,{children:["You can add as many named examples as you need. Each name becomes addressable from the CLI with ",(0,a.jsx)(s.code,{children:"--example"}),"."]}),"\n",(0,a.jsx)(s.h2,{id:"three-type-zones",children:"Three type zones"}),"\n",(0,a.jsxs)(s.p,{children:["A walkerOS flow has three distinct type zones. The shape of ",(0,a.jsx)(s.code,{children:"in"})," and ",(0,a.jsx)(s.code,{children:"out"})," depends on where the step sits:"]}),"\n",(0,a.jsx)(s.pre,{children:(0,a.jsx)(s.code,{children:"  ARBITRARY          walkerOS.Event              ARBITRARY\n \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510    \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510    \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n \u2502 Source   \u2502 \u2192  \u2502 Collector \u2192 Transform \u2502 \u2192  \u2502 Destination  \u2502\n \u2502 ingest   \u2502    \u2502 \u2192 ... \u2192 Transform    \u2502    \u2502 output       \u2502\n \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n  package-        known structure,            package-\n  specific        varying properties          specific\n"})}),"\n",(0,a.jsxs)(s.ul,{children:["\n",(0,a.jsxs)(s.li,{children:[(0,a.jsxs)(s.strong,{children:["Source ",(0,a.jsx)(s.code,{children:"in"})]}),": raw HTTP request body, DOM event, dataLayer push (package-specific)"]}),"\n",(0,a.jsxs)(s.li,{children:[(0,a.jsxs)(s.strong,{children:["Source ",(0,a.jsx)(s.code,{children:"out"})," through destination ",(0,a.jsx)(s.code,{children:"in"})]}),": ",(0,a.jsx)(s.code,{children:"walkerOS.Event"})," (known structure, varying properties)"]}),"\n",(0,a.jsxs)(s.li,{children:[(0,a.jsxs)(s.strong,{children:["Destination ",(0,a.jsx)(s.code,{children:"out"})]}),": ",(0,a.jsx)(s.code,{children:"gtag()"})," args, ",(0,a.jsx)(s.code,{children:"fbq()"})," args, HTTP POST body (vendor-specific)"]}),"\n"]}),"\n",(0,a.jsxs)(s.p,{children:["Transformers that filter events use ",(0,a.jsx)(s.code,{children:"out: false"})," to indicate rejection."]}),"\n",(0,a.jsx)(s.h2,{id:"adding-examples-to-a-flow",children:"Adding examples to a flow"}),"\n",(0,a.jsx)(s.p,{children:"Here is a complete flow config with examples on a source, transformer, and destination:"}),"\n",(0,a.jsx)(t,{code:`{
37  "version": 4,
38  "flows": {
39    "default": {
40      "config": { "platform": "server" },
41      "sources": {
42        "http": {
43          "package": "@walkeros/server-source-express",
44          "config": { "settings": { "port": 8080 } },
45          "examples": {
46            "page view": {
47              "in": {
48                "method": "POST",
49                "body": { "name": "page view", "data": { "title": "Home" } }
50              },
51              "out": { "name": "page view", "data": { "title": "Home" } }
52            }
53          }
54        }
55      },
56      "transformers": {
57        "fingerprint": {
58          "package": "@walkeros/server-transformer-fingerprint",
59          "examples": {
60            "enriched event": {
61              "in": { "name": "page view", "data": { "title": "Home" } },
62              "out": { "name": "page view", "data": { "title": "Home" } }
63            }
64          }
65        }
66      },
67      "destinations": {
68        "ga4": {
69          "package": "@walkeros/web-destination-gtag",
70          "config": {
71            "settings": { "measurementId": "G-DEMO123456" }
72          },
73          "examples": {
74            "page view": {
75              "in": { "name": "page view", "data": { "title": "Home" } },
76              "mapping": {
77                "name": "page_view",
78                "data": { "map": { "page_title": "data.title" } }
79              },
80              "out": ["event", "page_view", { "page_title": "Home" }]
81            }
82          }
83        }
84      },
85      "collector": {}
86    }
87  }
88}`,language:"json"}),"\n",(0,a.jsx)(s.p,{children:"Examples are stripped by the bundler at build time. They never appear in your production bundle."}),"\n",(0,a.jsx)(s.h2,{id:"using-examples-with-the-cli",children:"Using examples with the CLI"}),"\n",(0,a.jsx)(s.h3,{id:"simulate-a-single-example",children:"Simulate a single example"}),"\n",(0,a.jsx)(s.p,{children:"Run a named example through the pipeline:"}),"\n",(0,a.jsx)(t,{code:`# Run the "page view" example from the ga4 destination
89walkeros push flow.json --simulate destination.ga4 --event '{"name":"page view","data":{"title":"Home"}}'`,language:"bash"}),"\n",(0,a.jsxs)(s.p,{children:["The CLI feeds ",(0,a.jsx)(s.code,{children:"in"})," to the step, runs it through the pipeline, and compares the actual output against ",(0,a.jsx)(s.code,{children:"out"}),". Mismatches are reported as errors."]}),"\n",(0,a.jsx)(s.h3,{id:"validate-examples",children:"Validate examples"}),"\n",(0,a.jsx)(s.p,{children:"Check that examples match expected shapes without running the full pipeline:"}),"\n",(0,a.jsx)(t,{code:"walkeros validate flow.json",language:"bash"}),"\n",(0,a.jsx)(s.h3,{id:"cross-step-validation",children:"Cross-step validation"}),"\n",(0,a.jsxs)(s.p,{children:["Cross-step example validation is included automatically when validating a flow. It verifies that connected steps (source \u2192 transformer \u2192 destination) have structurally compatible ",(0,a.jsx)(s.code,{children:"out"}),"/",(0,a.jsx)(s.code,{children:"in"})," pairs:"]}),"\n",(0,a.jsx)(t,{code:"walkeros validate flow.json",language:"bash"}),"\n",(0,a.jsx)(s.p,{children:"Cross-step validation checks that:"}),"\n",(0,a.jsxs)(s.ul,{children:["\n",(0,a.jsxs)(s.li,{children:["Source ",(0,a.jsx)(s.code,{children:"out"}
89)," types match transformer ",(0,a.jsx)(s.code,{children:"in"})," types"]}),"\n",(0,a.jsxs)(s.li,{children:["Transformer ",(0,a.jsx)(s.code,{children:"out"})," types match destination ",(0,a.jsx)(s.code,{children:"in"})," types"]}),"\n",(0,a.jsx)(s.li,{children:"Steps without examples produce warnings"}),"\n",(0,a.jsx)(s.li,{children:"Contract compliance when contracts are defined"}),"\n"]}),"\n",(0,a.jsx)(s.h2,{id:"using-examples-in-tests",children:"Using examples in tests"}),"\n",(0,a.jsx)(s.p,{children:"Extract examples from your flow config and use them as test fixtures:"}),"\n",(0,a.jsx)(t,{code:`import { readFileSync } from 'fs';
90import { push } from '@walkeros/web-destination-gtag';
91
92const flow = JSON.parse(readFileSync('flow.json', 'utf-8'));
93const ga4Examples = flow.flows.default.destinations.ga4.examples;
94
95const cases = Object.entries(ga4Examples).map(
96  ([name, ex]) => [name, ex.in, ex.out]
97);
98
99it.each(cases)('ga4 destination: %s', (name, input, expected) => {
100  const result = push(input);
101  expect(result).toEqual(expected);
102});`,language:"typescript"}),"\n",(0,a.jsx)(s.p,{children:"This pattern means your flow config is the single source of truth for both documentation and tests."}),"\n",(0,a.jsx)(s.h2,{id:"package-level-vs-flow-level-examples",children:"Package-level vs flow-level examples"}),"\n",(0,a.jsx)(s.p,{children:"Examples exist at two levels:"}),"\n",(0,a.jsxs)(s.table,{children:[(0,a.jsx)(s.thead,{children:(0,a.jsxs)(s.tr,{children:[(0,a.jsx)(s.th,{children:"Level"}),(0,a.jsx)(s.th,{children:"Where"}),(0,a.jsx)(s.th,{children:"Purpose"})]})}),(0,a.jsxs)(s.tbody,{children:[(0,a.jsxs)(s.tr,{children:[(0,a.jsx)(s.td,{children:(0,a.jsx)(s.strong,{children:"Package"})}),(0,a.jsxs)(s.td,{children:[(0,a.jsx)(s.code,{children:"walkerOS.json"})," in the npm package (via ",(0,a.jsx)(s.code,{children:"dev.ts"}),")"]}),(0,a.jsx)(s.td,{children:"Generic examples showing what the package handles"})]}),(0,a.jsxs)(s.tr,{children:[(0,a.jsx)(s.td,{children:(0,a.jsx)(s.strong,{children:"Flow"})}),(0,a.jsxs)(s.td,{children:["Inline on step references in ",(0,a.jsx)(s.code,{children:"flow.json"})]}),(0,a.jsx)(s.td,{children:"Specific examples for your actual data and mappings"})]})]})]}),"\n",(0,a.jsxs)(s.p,{children:[(0,a.jsx)(s.strong,{children:"Package examples"})," are generic and ship with the npm package. They show the package's capabilities with sample data. The CLI and MCP tools discover them from CDN."]}),"\n",(0,a.jsxs)(s.p,{children:[(0,a.jsx)(s.strong,{children:"Flow examples"})," are specific to your setup. They use your real event names, your actual data properties, and your configured mappings. They override or complement package examples."]}),"\n",(0,a.jsxs)(n,{children:[(0,a.jsx)("summary",{children:"How packages ship examples"}),(0,a.jsxs)(s.p,{children:["Packages export examples through the ",(0,a.jsx)(s.code,{children:"dev.ts"})," convention:"]}),(0,a.jsx)(t,{code:`// src/dev.ts
103export * as schemas from './schemas';
104export * as examples from './examples';`,language:"typescript"}),(0,a.jsxs)(s.p,{children:["These are included in the package's ",(0,a.jsx)(s.code,{children:"walkerOS.json"})," metadata and discoverable via CDN, following the same ",(0,a.jsx)(s.code,{children:"{ in, out }"})," format used in flow configs."]})]}),"\n",(0,a.jsx)(s.h2,{id:"next-steps",children:"Next steps"}),"\n",(0,a.jsxs)(s.ul,{children:["\n",(0,a.jsxs)(s.li,{children:[(0,a.jsx)(s.strong,{children:(0,a.jsx)(s.a,{href:"/docs/apps/cli",children:"CLI"})}),": Bundle and simulate flows with examples"]}),"\n",(0,a.jsxs)(s.li,{children:[(0,a.jsx)(s.strong,{children:(0,a.jsx)(s.a,{href:"/docs/getting-started/flow",children:"Flow"})}),": Learn the full flow configuration format"]}),"\n",(0,a.jsxs)(s.li,{children:[(0,a.jsx)(s.strong,{children:(0,a.jsx)(s.a,{href:"/docs/mapping",children:"Mapping"})}),": Transform events between steps"]}),"\n",(0,a.jsxs)(s.li,{children:[(0,a.jsx)(s.strong,{children:(0,a.jsx)(s.a,{href:"/docs/getting-started/event-model",children:"Event model"})}),": Understand the walkerOS event structure"]}),"\n"]})]})}function p(e={}){let{wrapper:s}={...(0,i.R)(),...e.components};return s?(0,a.jsx)(s,{...e,children:(0,a.jsx)(c,{...e})}):c(e)}function h(e,s){throw Error("Expected "+(s?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}},65404(e,s,t){t.d(s,{R:()=>l,x:()=>r});var n=t(63696);let a={},i=n.createContext(a);function l(e){let s=n.useContext(i);return n.useMemo(function(){return"function"==typeof e?e(s):{...s,...e}},[s,e])}function r(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:l(e.components),n.createElement(i.Provider,{value:s},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.