@walkeros/cli 0.8.0 → 1.0.1-next-1768820936934
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/README.md +37 -17
- package/dist/examples/README.md +33 -0
- package/dist/examples/flow-complete.json +571 -0
- package/dist/examples/flow-complete.md +247 -0
- package/dist/index.d.ts +2 -10
- package/dist/index.js +45 -44
- package/dist/index.js.map +1 -1
- package/examples/README.md +33 -0
- package/examples/flow-complete.json +571 -0
- package/examples/flow-complete.md +247 -0
- package/package.json +3 -3
- package/dist/walker.js +0 -1
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
# flow-complete.json - Comprehensive walkerOS Flow Example
|
|
2
|
+
|
|
3
|
+
This example demonstrates **ALL JSON-compatible walkerOS features** with
|
|
4
|
+
real-world patterns. It contains two named flows (`web` and `server`) showing a
|
|
5
|
+
complete event tracking architecture.
|
|
6
|
+
|
|
7
|
+
## Architecture
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
11
|
+
│ WEB FLOW │
|
|
12
|
+
│ │
|
|
13
|
+
│ Browser Source ─┐ │
|
|
14
|
+
│ DataLayer Source ──▶ [Validator] ──▶ Collector ──▶ GA4 Destination │
|
|
15
|
+
│ Demo Source ────┘ └──▶ API Destination │
|
|
16
|
+
│ │ │
|
|
17
|
+
└──────────────────────────────────────────────────────────────│──────────────┘
|
|
18
|
+
▼
|
|
19
|
+
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
20
|
+
│ SERVER FLOW │
|
|
21
|
+
│ │
|
|
22
|
+
│ HTTP Request ──▶ Express Source ──▶ Collector ──▶ [Fingerprint] ──────┐ │
|
|
23
|
+
│ │ [Validator] │ │
|
|
24
|
+
│ │ ▼ │
|
|
25
|
+
│ └── ingest: IP, user-agent ────────▶ Meta Destination
|
|
26
|
+
│ language, referer Demo Destination│
|
|
27
|
+
└─────────────────────────────────────────────────────────────────────────────┘
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Quick Start
|
|
31
|
+
|
|
32
|
+
### Run Web Flow
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
cd walkerOS
|
|
36
|
+
npx walkeros serve packages/cli/examples/flow-complete.json --flow web
|
|
37
|
+
# Open http://localhost:3000 - demo events fire automatically
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Run Server Flow
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
cd walkerOS
|
|
44
|
+
npx walkeros run packages/cli/examples/flow-complete.json --flow server
|
|
45
|
+
|
|
46
|
+
# Test health
|
|
47
|
+
curl http://localhost:8080/health
|
|
48
|
+
|
|
49
|
+
# Send test event
|
|
50
|
+
curl -X POST http://localhost:8080/collect \
|
|
51
|
+
-H "Content-Type: application/json" \
|
|
52
|
+
-d '{
|
|
53
|
+
"name": "order complete",
|
|
54
|
+
"data": {"id": "ORD-999", "total": 99.99, "currency": "EUR"},
|
|
55
|
+
"user": {"email": "test@example.com", "id": "U-123"},
|
|
56
|
+
"nested": [{"entity": "product", "data": {"id": "P1", "name": "Item", "price": 99.99, "quantity": 1}}]
|
|
57
|
+
}'
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Run Both (Full Pipeline)
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# Terminal 1: Start server
|
|
64
|
+
npx walkeros run packages/cli/examples/flow-complete.json --flow server
|
|
65
|
+
|
|
66
|
+
# Terminal 2: Start web (sends to server via API destination)
|
|
67
|
+
npx walkeros serve packages/cli/examples/flow-complete.json --flow web
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Feature Inventory
|
|
73
|
+
|
|
74
|
+
### Features Used (51)
|
|
75
|
+
|
|
76
|
+
#### Mapping - Value Extraction
|
|
77
|
+
|
|
78
|
+
| Feature | Location | Example |
|
|
79
|
+
| ----------------- | ----------------- | ------------------------------------------------------------ |
|
|
80
|
+
| Key extraction | GA4 page_view | `"page_title": "data.title"` |
|
|
81
|
+
| Static value | Meta ViewContent | `"content_type": { "value": "product" }` |
|
|
82
|
+
| Key with fallback | GA4 add_to_cart | `{ "key": "data.currency", "value": "$variables.currency" }` |
|
|
83
|
+
| Nested key (deep) | dataLayer mapping | `"items.0.item_id"` |
|
|
84
|
+
|
|
85
|
+
#### Mapping - Structure
|
|
86
|
+
|
|
87
|
+
| Feature | Location | Example |
|
|
88
|
+
| --------------------- | ------------------ | ----------------------------------------------------------- |
|
|
89
|
+
| Map (object) | GA4 purchase | `"data": { "map": { ... } }` |
|
|
90
|
+
| Loop with "nested" | GA4 purchase items | `{ "loop": ["nested", { "map": {...} }] }` |
|
|
91
|
+
| Loop with "this" | GA4 add_to_cart | `{ "loop": ["this", { "map": {...} }] }` |
|
|
92
|
+
| Set (single value) | Meta ViewContent | `"content_ids": { "set": ["data.id"] }` |
|
|
93
|
+
| Set (multiple values) | Meta settings | `"external_id": { "set": ["user.device", "user.session"] }` |
|
|
94
|
+
| Direct passthrough | Meta PageView | `"data": "data"` |
|
|
95
|
+
|
|
96
|
+
#### Mapping - Control
|
|
97
|
+
|
|
98
|
+
| Feature | Location | Example |
|
|
99
|
+
| -------------------- | ------------------- | ----------------------------------------------------------- |
|
|
100
|
+
| Consent-gated field | API destination | `{ "key": "user.email", "consent": { "marketing": true } }` |
|
|
101
|
+
| Ignore rule | GA4/API test events | `{ "ignore": true }` |
|
|
102
|
+
| Wildcard action (\*) | GA4 test, Meta | `"test": { "*": { "ignore": true } }` |
|
|
103
|
+
| Wildcard entity (\*) | Meta click handler | `"*": { "click": { "name": "CustomEvent" } }` |
|
|
104
|
+
|
|
105
|
+
#### Definitions & Variables
|
|
106
|
+
|
|
107
|
+
| Feature | Location | Example |
|
|
108
|
+
| -------------------- | ------------------ | -------------------------------------------- |
|
|
109
|
+
| Root-level variables | Root | `"currency": "EUR"` |
|
|
110
|
+
| Flow-level variables | server.variables | `"metaPixelId": "${META_PIXEL_ID:...}"` |
|
|
111
|
+
| Environment variable | Variables | `"${GA4_MEASUREMENT_ID:G-DEMO123456}"` |
|
|
112
|
+
| Env with default | Variables | `"${API_URL:http://localhost:8080/collect}"` |
|
|
113
|
+
| $variables reference | GA4 settings | `"$variables.ga4MeasurementId"` |
|
|
114
|
+
| Definition (complex) | Root definitions | `"ga4ItemsLoop": { "loop": [...] }` |
|
|
115
|
+
| $ref reference | GA4 purchase items | `{ "$ref": "#/definitions/ga4ItemsLoop" }` |
|
|
116
|
+
|
|
117
|
+
#### Sources
|
|
118
|
+
|
|
119
|
+
| Feature | Location | Example |
|
|
120
|
+
| -------------------- | --------- | ------------------------------------- |
|
|
121
|
+
| Primary source | browser | `"primary": true` |
|
|
122
|
+
| Multiple sources | web flow | browser + dataLayer + demo |
|
|
123
|
+
| Source-level mapping | dataLayer | `"mapping": { "add_to_cart": {...} }` |
|
|
124
|
+
| Pre-collector chain | dataLayer | `"next": "dataLayerValidator"` |
|
|
125
|
+
| Demo source events | demo | Pre-configured test events |
|
|
126
|
+
|
|
127
|
+
#### Transformers
|
|
128
|
+
|
|
129
|
+
| Feature | Location | Example |
|
|
130
|
+
| ----------------------- | ------------------ | ---------------------------------- |
|
|
131
|
+
| Validator transformer | dataLayerValidator | JSON Schema validation |
|
|
132
|
+
| Fingerprint transformer | server | Hash context fields to `user.hash` |
|
|
133
|
+
| Transformer chaining | server | `"next": "serverValidator"` |
|
|
134
|
+
| Post-collector chain | Meta | `"before": "fingerprint"` |
|
|
135
|
+
| Contract validation | serverValidator | Entity/action schemas |
|
|
136
|
+
| Format option | serverValidator | `"format": true` |
|
|
137
|
+
|
|
138
|
+
#### Destinations
|
|
139
|
+
|
|
140
|
+
| Feature | Location | Example |
|
|
141
|
+
| --------------------- | ---------------- | ---------------------------------- |
|
|
142
|
+
| Destination consent | GA4 | `"consent": { "marketing": true }` |
|
|
143
|
+
| Destination mapping | All destinations | Entity/action to vendor events |
|
|
144
|
+
| Multiple destinations | Both flows | GA4 + API, Meta + Demo |
|
|
145
|
+
| Batch option | API | `"batch": 5` |
|
|
146
|
+
|
|
147
|
+
#### Collector
|
|
148
|
+
|
|
149
|
+
| Feature | Location | Example |
|
|
150
|
+
| ----------------- | --------------- | --------------------------------------- |
|
|
151
|
+
| Tagging | Both collectors | `"tagging": 1` |
|
|
152
|
+
| Consent defaults | Both collectors | `"consent": { "functional": true }` |
|
|
153
|
+
| Globals | Both collectors | `"environment": "demo"` |
|
|
154
|
+
| Custom properties | web collector | `"custom": { "campaign": "flow-demo" }` |
|
|
155
|
+
| User defaults | web collector | `"user": { "id": "anonymous" }` |
|
|
156
|
+
|
|
157
|
+
#### Server-Specific
|
|
158
|
+
|
|
159
|
+
| Feature | Location | Example |
|
|
160
|
+
| -------------------- | ----------- | ----------------------------------------------- |
|
|
161
|
+
| Ingest metadata | http source | `"context.ip": "ip"` |
|
|
162
|
+
| Language header | ingest | `"context.language": "headers.accept-language"` |
|
|
163
|
+
| Policy | Meta | Pre-processing field transformation |
|
|
164
|
+
| Policy consent-gated | Meta | `"user_data.em"` with consent |
|
|
165
|
+
| Policy nested map | Meta | `"custom_data.request_meta": { "map": {...} }` |
|
|
166
|
+
|
|
167
|
+
#### Browser Source
|
|
168
|
+
|
|
169
|
+
| Feature | Location | Example |
|
|
170
|
+
| --------------- | -------- | ---------------------------------- |
|
|
171
|
+
| Prefix | browser | `"prefix": "data-elb"` |
|
|
172
|
+
| Auto pageview | browser | `"pageview": true` |
|
|
173
|
+
| Session consent | browser | `"session": { "consent": {...} }` |
|
|
174
|
+
| ELB binding | browser | `"elb": "elb"`, `"elbLayer": true` |
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
### Features NOT Used (15)
|
|
179
|
+
|
|
180
|
+
#### Requires JavaScript (7)
|
|
181
|
+
|
|
182
|
+
These features cannot be used in pure JSON configurations:
|
|
183
|
+
|
|
184
|
+
| Feature | Reason |
|
|
185
|
+
| --------------------------- | ----------------------------- |
|
|
186
|
+
| `fn:` function | Requires JavaScript callback |
|
|
187
|
+
| `condition:` | Requires JavaScript predicate |
|
|
188
|
+
| Conditional mapping (array) | Requires condition functions |
|
|
189
|
+
| Custom transformer code | Requires JavaScript |
|
|
190
|
+
| Custom source code | Requires JavaScript |
|
|
191
|
+
| Custom destination code | Requires JavaScript |
|
|
192
|
+
| Event handler callbacks | Requires JavaScript |
|
|
193
|
+
|
|
194
|
+
#### Omitted for Clarity (8)
|
|
195
|
+
|
|
196
|
+
These features could be added but were omitted to keep the example focused:
|
|
197
|
+
|
|
198
|
+
| Feature | Why Omitted |
|
|
199
|
+
| ------------------------- | ----------------------------- |
|
|
200
|
+
| Multiple named flows (3+) | Two flows sufficient for demo |
|
|
201
|
+
| Queue config | Advanced batching scenario |
|
|
202
|
+
| Retry config | Advanced error handling |
|
|
203
|
+
| Custom fetch options | API destination advanced |
|
|
204
|
+
| Dynamic routing | Requires condition logic |
|
|
205
|
+
| Transform before send | Covered by policy |
|
|
206
|
+
| Custom headers in API | Would add complexity |
|
|
207
|
+
| Multiple validators | One per flow sufficient |
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Data Flow Examples
|
|
212
|
+
|
|
213
|
+
### Order Complete (Server Flow)
|
|
214
|
+
|
|
215
|
+
1. **Ingest**: Request metadata extracted (IP, user-agent, referer) to
|
|
216
|
+
`context.*`
|
|
217
|
+
2. **Policy**: Pre-processes event:
|
|
218
|
+
- `user_data.em` from `user.email` (only if marketing consent)
|
|
219
|
+
- `user_data.external_id` from `user.id`
|
|
220
|
+
- `custom_data.server_processed` = `true`
|
|
221
|
+
- `custom_data.request_meta` = `{ ip, ua }` from context
|
|
222
|
+
3. **Fingerprint**: Hashes context fields to `user.hash`
|
|
223
|
+
4. **Validator**: Checks products have `data.id`
|
|
224
|
+
5. **Mapping**: Transforms to Meta format:
|
|
225
|
+
- `"name": "Purchase"`
|
|
226
|
+
- `value`, `currency`, `order_id` extracted
|
|
227
|
+
- `contents` via `$ref` to definition loop
|
|
228
|
+
|
|
229
|
+
### Product Add (Web Flow)
|
|
230
|
+
|
|
231
|
+
1. **DataLayer Source**: Captures `add_to_cart` event
|
|
232
|
+
2. **Source Mapping**: Transforms to `product add` with walkerOS structure
|
|
233
|
+
3. **Validator**: Checks `id` and `name` present
|
|
234
|
+
4. **Collector**: Adds globals, consent, user data
|
|
235
|
+
5. **GA4 Mapping**: Transforms to `add_to_cart` with items array
|
|
236
|
+
6. **API Destination**: Batches and sends to server (if batch size reached)
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## Environment Variables
|
|
241
|
+
|
|
242
|
+
| Variable | Default | Description |
|
|
243
|
+
| -------------------- | ------------------------------- | -------------------------- |
|
|
244
|
+
| `GA4_MEASUREMENT_ID` | `G-DEMO123456` | Google Analytics 4 ID |
|
|
245
|
+
| `API_URL` | `http://localhost:8080/collect` | Server collection endpoint |
|
|
246
|
+
| `META_PIXEL_ID` | `123456789012345` | Meta Pixel ID |
|
|
247
|
+
| `META_ACCESS_TOKEN` | `demo_token` | Meta Conversions API token |
|
package/dist/index.d.ts
CHANGED
|
@@ -160,11 +160,6 @@ interface GlobalOptions {
|
|
|
160
160
|
* @default false
|
|
161
161
|
*/
|
|
162
162
|
silent?: boolean;
|
|
163
|
-
/**
|
|
164
|
-
* Preview command without executing
|
|
165
|
-
* @default false
|
|
166
|
-
*/
|
|
167
|
-
dryRun?: boolean;
|
|
168
163
|
}
|
|
169
164
|
|
|
170
165
|
interface BundleStats {
|
|
@@ -185,9 +180,8 @@ interface BundleCommandOptions {
|
|
|
185
180
|
json?: boolean;
|
|
186
181
|
cache?: boolean;
|
|
187
182
|
verbose?: boolean;
|
|
188
|
-
dryRun?: boolean;
|
|
189
183
|
silent?: boolean;
|
|
190
|
-
dockerfile?: boolean;
|
|
184
|
+
dockerfile?: boolean | string;
|
|
191
185
|
}
|
|
192
186
|
declare function bundleCommand(options: BundleCommandOptions): Promise<void>;
|
|
193
187
|
/**
|
|
@@ -247,9 +241,9 @@ interface ApiCall {
|
|
|
247
241
|
interface SimulateCommandOptions {
|
|
248
242
|
config: string;
|
|
249
243
|
event?: string;
|
|
244
|
+
flow?: string;
|
|
250
245
|
json?: boolean;
|
|
251
246
|
verbose?: boolean;
|
|
252
|
-
dryRun?: boolean;
|
|
253
247
|
silent?: boolean;
|
|
254
248
|
platform?: 'web' | 'server';
|
|
255
249
|
}
|
|
@@ -352,8 +346,6 @@ interface RunCommandOptions {
|
|
|
352
346
|
json?: boolean;
|
|
353
347
|
/** Verbose logging */
|
|
354
348
|
verbose?: boolean;
|
|
355
|
-
/** Dry-run mode */
|
|
356
|
-
dryRun?: boolean;
|
|
357
349
|
/** Suppress output */
|
|
358
350
|
silent?: boolean;
|
|
359
351
|
}
|
package/dist/index.js
CHANGED
|
@@ -30,6 +30,7 @@ var VERSION = JSON.parse(findPackageJson()).version;
|
|
|
30
30
|
// src/commands/bundle/index.ts
|
|
31
31
|
import path9 from "path";
|
|
32
32
|
import fs8 from "fs-extra";
|
|
33
|
+
import { getPlatform as getPlatform2 } from "@walkeros/core";
|
|
33
34
|
|
|
34
35
|
// src/core/logger.ts
|
|
35
36
|
import chalk from "chalk";
|
|
@@ -1335,10 +1336,6 @@ async function bundleCommand(options) {
|
|
|
1335
1336
|
const timer = createTimer();
|
|
1336
1337
|
timer.start();
|
|
1337
1338
|
const logger2 = createCommandLogger(options);
|
|
1338
|
-
if (options.dryRun) {
|
|
1339
|
-
logger2.log(`[DRY-RUN] Would execute bundle with config: ${options.config}`);
|
|
1340
|
-
return;
|
|
1341
|
-
}
|
|
1342
1339
|
try {
|
|
1343
1340
|
if (options.flow && options.all) {
|
|
1344
1341
|
throw new Error("Cannot use both --flow and --all flags together");
|
|
@@ -1385,11 +1382,12 @@ async function bundleCommand(options) {
|
|
|
1385
1382
|
displayStats(stats, logger2);
|
|
1386
1383
|
}
|
|
1387
1384
|
if (options.dockerfile && !options.all) {
|
|
1388
|
-
const
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1385
|
+
const platform = getPlatform2(flowConfig);
|
|
1386
|
+
if (platform) {
|
|
1387
|
+
const outputDir = path9.dirname(buildOptions.output);
|
|
1388
|
+
const customFile = typeof options.dockerfile === "string" ? options.dockerfile : void 0;
|
|
1389
|
+
await generateDockerfile(outputDir, platform, logger2, customFile);
|
|
1390
|
+
}
|
|
1393
1391
|
}
|
|
1394
1392
|
} catch (error) {
|
|
1395
1393
|
const errorMessage = getErrorMessage(error);
|
|
@@ -1473,26 +1471,34 @@ async function bundle(configOrPath, options = {}) {
|
|
|
1473
1471
|
options.stats ?? false
|
|
1474
1472
|
);
|
|
1475
1473
|
}
|
|
1476
|
-
async function generateDockerfile(
|
|
1477
|
-
const
|
|
1474
|
+
async function generateDockerfile(outputDir, platform, logger2, customFile) {
|
|
1475
|
+
const destPath = path9.join(outputDir, "Dockerfile");
|
|
1476
|
+
if (customFile && await fs8.pathExists(customFile)) {
|
|
1477
|
+
await fs8.copy(customFile, destPath);
|
|
1478
|
+
logger2.log(`Dockerfile: ${destPath} (copied from ${customFile})`);
|
|
1479
|
+
return;
|
|
1480
|
+
}
|
|
1481
|
+
const isWeb = platform === "web";
|
|
1482
|
+
const bundleFile = isWeb ? "walker.js" : "bundle.mjs";
|
|
1483
|
+
const mode = isWeb ? "serve" : "collect";
|
|
1478
1484
|
const dockerfile = `# Generated by walkeros CLI
|
|
1479
1485
|
FROM walkeros/flow:latest
|
|
1480
1486
|
|
|
1481
|
-
COPY ${
|
|
1487
|
+
COPY ${bundleFile} /app/flow/${bundleFile}
|
|
1482
1488
|
|
|
1483
|
-
ENV MODE
|
|
1484
|
-
ENV BUNDLE=/app/flow
|
|
1489
|
+
ENV MODE=${mode}
|
|
1490
|
+
ENV BUNDLE=/app/flow/${bundleFile}
|
|
1485
1491
|
|
|
1486
1492
|
EXPOSE 8080
|
|
1487
1493
|
`;
|
|
1488
|
-
await fs8.writeFile(
|
|
1489
|
-
logger2.log(`Dockerfile: ${
|
|
1494
|
+
await fs8.writeFile(destPath, dockerfile);
|
|
1495
|
+
logger2.log(`Dockerfile: ${destPath}`);
|
|
1490
1496
|
}
|
|
1491
1497
|
|
|
1492
1498
|
// src/commands/simulate/simulator.ts
|
|
1493
1499
|
import path10 from "path";
|
|
1494
1500
|
import fs10 from "fs-extra";
|
|
1495
|
-
import { getPlatform as
|
|
1501
|
+
import { getPlatform as getPlatform3 } from "@walkeros/core";
|
|
1496
1502
|
|
|
1497
1503
|
// src/commands/simulate/tracker.ts
|
|
1498
1504
|
var CallTracker = class {
|
|
@@ -1804,6 +1810,7 @@ async function simulateCore(inputPath, event, options = {}) {
|
|
|
1804
1810
|
try {
|
|
1805
1811
|
logger2.debug(`Simulating event: ${JSON.stringify(event)}`);
|
|
1806
1812
|
const result = await executeSimulation(event, inputPath, options.platform, {
|
|
1813
|
+
flow: options.flow,
|
|
1807
1814
|
logger: logger2,
|
|
1808
1815
|
verbose: options.verbose
|
|
1809
1816
|
});
|
|
@@ -1851,7 +1858,8 @@ async function executeSimulation(event, inputPath, platformOverride, options = {
|
|
|
1851
1858
|
typedEvent,
|
|
1852
1859
|
tempDir,
|
|
1853
1860
|
startTime,
|
|
1854
|
-
collectorLoggerConfig
|
|
1861
|
+
collectorLoggerConfig,
|
|
1862
|
+
options.flow
|
|
1855
1863
|
);
|
|
1856
1864
|
} else {
|
|
1857
1865
|
return await executeBundleSimulation(
|
|
@@ -1877,9 +1885,11 @@ async function executeSimulation(event, inputPath, platformOverride, options = {
|
|
|
1877
1885
|
}
|
|
1878
1886
|
}
|
|
1879
1887
|
}
|
|
1880
|
-
async function executeConfigSimulation(_content, configPath, typedEvent, tempDir, startTime, loggerConfig2) {
|
|
1881
|
-
const { flowConfig, buildOptions } = await loadFlowConfig(configPath
|
|
1882
|
-
|
|
1888
|
+
async function executeConfigSimulation(_content, configPath, typedEvent, tempDir, startTime, loggerConfig2, flowName) {
|
|
1889
|
+
const { flowConfig, buildOptions } = await loadFlowConfig(configPath, {
|
|
1890
|
+
flowName
|
|
1891
|
+
});
|
|
1892
|
+
const platform = getPlatform3(flowConfig);
|
|
1883
1893
|
const tracker = new CallTracker();
|
|
1884
1894
|
const tempOutput = path10.join(
|
|
1885
1895
|
tempDir,
|
|
@@ -1979,18 +1989,13 @@ async function executeBundleSimulation(bundleContent, platform, typedEvent, temp
|
|
|
1979
1989
|
// src/commands/simulate/index.ts
|
|
1980
1990
|
async function simulateCommand(options) {
|
|
1981
1991
|
const logger2 = createCommandLogger(options);
|
|
1982
|
-
if (options.dryRun) {
|
|
1983
|
-
logger2.log(
|
|
1984
|
-
`[DRY-RUN] Would execute simulate with config: ${options.config}`
|
|
1985
|
-
);
|
|
1986
|
-
return;
|
|
1987
|
-
}
|
|
1988
1992
|
const startTime = Date.now();
|
|
1989
1993
|
try {
|
|
1990
1994
|
const event = await loadJsonFromSource(options.event, {
|
|
1991
1995
|
name: "event"
|
|
1992
1996
|
});
|
|
1993
1997
|
const result = await simulateCore(options.config, event, {
|
|
1998
|
+
flow: options.flow,
|
|
1994
1999
|
json: options.json,
|
|
1995
2000
|
verbose: options.verbose,
|
|
1996
2001
|
silent: options.silent
|
|
@@ -2041,7 +2046,7 @@ import path11 from "path";
|
|
|
2041
2046
|
import { JSDOM as JSDOM2, VirtualConsole as VirtualConsole2 } from "jsdom";
|
|
2042
2047
|
import fs11 from "fs-extra";
|
|
2043
2048
|
import {
|
|
2044
|
-
getPlatform as
|
|
2049
|
+
getPlatform as getPlatform4
|
|
2045
2050
|
} from "@walkeros/core";
|
|
2046
2051
|
import { schemas as schemas2 } from "@walkeros/core/dev";
|
|
2047
2052
|
async function pushCommand(options) {
|
|
@@ -2153,7 +2158,7 @@ async function executeConfigPush(options, validatedEvent, logger2, setTempDir) {
|
|
|
2153
2158
|
flowName: options.flow,
|
|
2154
2159
|
logger: logger2
|
|
2155
2160
|
});
|
|
2156
|
-
const platform =
|
|
2161
|
+
const platform = getPlatform4(flowConfig);
|
|
2157
2162
|
logger2.debug("Bundling flow configuration");
|
|
2158
2163
|
const configDir = buildOptions.configDir || process.cwd();
|
|
2159
2164
|
const tempDir = path11.join(
|
|
@@ -2587,10 +2592,6 @@ async function runCommand(mode, options) {
|
|
|
2587
2592
|
logger2.debug("Bundle ready");
|
|
2588
2593
|
}
|
|
2589
2594
|
}
|
|
2590
|
-
if (options.dryRun) {
|
|
2591
|
-
logger2.log(`[DRY-RUN] Would execute locally: run ${mode}`);
|
|
2592
|
-
return;
|
|
2593
|
-
}
|
|
2594
2595
|
const modeLabel = mode === "collect" ? "Collector" : "Server";
|
|
2595
2596
|
logger2.log(`Starting ${modeLabel}...`);
|
|
2596
2597
|
await executeRunLocal(mode, flowPath, {
|
|
@@ -2712,7 +2713,10 @@ program.hook("preAction", (thisCommand, actionCommand) => {
|
|
|
2712
2713
|
console.log(`${chalk2.hex("#01b5e2")("walkerOS")} v${VERSION}`);
|
|
2713
2714
|
}
|
|
2714
2715
|
});
|
|
2715
|
-
program.command("bundle [file]").description("Bundle NPM packages with custom code").option("
|
|
2716
|
+
program.command("bundle [file]").description("Bundle NPM packages with custom code").option("--flow <name>", "flow name for multi-flow configs").option("--all", "build all flows for multi-flow configs").option("--stats", "show bundle statistics").option("--json", "output as JSON (implies --stats)").option("--no-cache", "disable package caching").option("-v, --verbose", "verbose output").option("-s, --silent", "suppress output").option(
|
|
2717
|
+
"--dockerfile [file]",
|
|
2718
|
+
"generate Dockerfile (or copy custom file) to dist/"
|
|
2719
|
+
).action(async (file, options) => {
|
|
2716
2720
|
await bundleCommand({
|
|
2717
2721
|
config: file || "bundle.config.json",
|
|
2718
2722
|
flow: options.flow,
|
|
@@ -2721,29 +2725,28 @@ program.command("bundle [file]").description("Bundle NPM packages with custom co
|
|
|
2721
2725
|
json: options.json,
|
|
2722
2726
|
cache: options.cache,
|
|
2723
2727
|
verbose: options.verbose,
|
|
2724
|
-
dryRun: options.dryRun,
|
|
2725
2728
|
silent: options.silent,
|
|
2726
2729
|
dockerfile: options.dockerfile
|
|
2727
2730
|
});
|
|
2728
2731
|
});
|
|
2729
2732
|
program.command("simulate [file]").description("Simulate event processing and capture API calls").option(
|
|
2730
2733
|
"-e, --event <source>",
|
|
2731
|
-
"
|
|
2732
|
-
).option("-p, --platform <platform>", "
|
|
2734
|
+
"event to simulate (JSON string, file path, or URL)"
|
|
2735
|
+
).option("--flow <name>", "flow name for multi-flow configs").option("-p, --platform <platform>", "platform override (web or server)").option("--json", "output as JSON").option("-v, --verbose", "verbose output").option("-s, --silent", "suppress output").action(async (file, options) => {
|
|
2733
2736
|
await simulateCommand({
|
|
2734
2737
|
config: file || "bundle.config.json",
|
|
2735
2738
|
event: options.event,
|
|
2739
|
+
flow: options.flow,
|
|
2736
2740
|
platform: options.platform,
|
|
2737
2741
|
json: options.json,
|
|
2738
2742
|
verbose: options.verbose,
|
|
2739
|
-
dryRun: options.dryRun,
|
|
2740
2743
|
silent: options.silent
|
|
2741
2744
|
});
|
|
2742
2745
|
});
|
|
2743
2746
|
program.command("push [file]").description("Push an event through the flow with real API execution").requiredOption(
|
|
2744
2747
|
"-e, --event <source>",
|
|
2745
|
-
"
|
|
2746
|
-
).option("--flow <name>", "
|
|
2748
|
+
"event to push (JSON string, file path, or URL)"
|
|
2749
|
+
).option("--flow <name>", "flow name for multi-flow configs").option("-p, --platform <platform>", "platform override (web or server)").option("--json", "output as JSON").option("-v, --verbose", "verbose output").option("-s, --silent", "suppress output").action(async (file, options) => {
|
|
2747
2750
|
await pushCommand({
|
|
2748
2751
|
config: file || "bundle.config.json",
|
|
2749
2752
|
event: options.event,
|
|
@@ -2757,20 +2760,19 @@ program.command("push [file]").description("Push an event through the flow with
|
|
|
2757
2760
|
var runCmd = program.command("run").description("Run walkerOS flows in collect or serve mode");
|
|
2758
2761
|
runCmd.command("collect [file]").description(
|
|
2759
2762
|
"Run collector mode (event collection endpoint). Defaults to server-collect.mjs if no file specified."
|
|
2760
|
-
).option("-p, --port <number>", "
|
|
2763
|
+
).option("-p, --port <number>", "port to listen on (default: 8080)", parseInt).option("-h, --host <address>", "host address (default: 0.0.0.0)").option("--json", "output as JSON").option("-v, --verbose", "verbose output").option("-s, --silent", "suppress output").action(async (file, options) => {
|
|
2761
2764
|
await runCommand("collect", {
|
|
2762
2765
|
config: file || "server-collect.mjs",
|
|
2763
2766
|
port: options.port,
|
|
2764
2767
|
host: options.host,
|
|
2765
2768
|
json: options.json,
|
|
2766
2769
|
verbose: options.verbose,
|
|
2767
|
-
dryRun: options.dryRun,
|
|
2768
2770
|
silent: options.silent
|
|
2769
2771
|
});
|
|
2770
2772
|
});
|
|
2771
2773
|
runCmd.command("serve [file]").description(
|
|
2772
2774
|
"Run serve mode (single-file server for browser bundles). Defaults to baked-in web-serve.js if no file specified."
|
|
2773
|
-
).option("-p, --port <number>", "
|
|
2775
|
+
).option("-p, --port <number>", "port to listen on (default: 8080)", parseInt).option("-h, --host <address>", "host address (default: 0.0.0.0)").option("--name <filename>", "filename in URL (default: walker.js)").option("--path <directory>", "URL directory path (e.g., libs/v1)").option("--json", "output as JSON").option("-v, --verbose", "verbose output").option("-s, --silent", "suppress output").action(async (file, options) => {
|
|
2774
2776
|
await runCommand("serve", {
|
|
2775
2777
|
config: file || "web-serve.js",
|
|
2776
2778
|
port: options.port,
|
|
@@ -2779,7 +2781,6 @@ runCmd.command("serve [file]").description(
|
|
|
2779
2781
|
servePath: options.path,
|
|
2780
2782
|
json: options.json,
|
|
2781
2783
|
verbose: options.verbose,
|
|
2782
|
-
dryRun: options.dryRun,
|
|
2783
2784
|
silent: options.silent
|
|
2784
2785
|
});
|
|
2785
2786
|
});
|