@walkeros/cli 4.9.0-next-1793116456867 → 4.9.0

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.
@@ -54,17 +54,19 @@ walkeros push examples/flow-complete.json --flow web \
54
54
  --event '{"name":"page view","data":{"title":"Home"}}' \
55
55
  --consent '{"functional":true}' --simulate destination.ga4
56
56
 
57
- # The server flow needs GCP_SA, FINGERPRINT_SALT and EMAIL_SALT set (see the
58
- # setup in flow-complete.md) and a request context for its fingerprint step
57
+ # The server flow needs GCP_SA, FINGERPRINT_SALT, EMAIL_SALT and
58
+ # META_ACCESS_TOKEN set (see the setup in flow-complete.md) and a request
59
+ # context for its fingerprint step
59
60
  walkeros push examples/flow-complete.json --flow server \
60
61
  --event '{"name":"page view","data":{"title":"Home"}}' \
61
62
  --ingest '{"ip":"203.0.113.7","userAgent":"Mozilla/5.0"}' \
62
63
  --simulate destination.pubsub
63
64
  ```
64
65
 
65
- Without `GCP_SA` a server simulation stops with
66
- `required secret "GCP_SA" is not set`; without `--ingest` the fingerprint step
67
- drops the event and Pub/Sub records `no calls`.
66
+ Without one of these four secrets a server simulation stops, for example with
67
+ `required secret "META_ACCESS_TOKEN" is not set`, whichever step you simulate;
68
+ without `--ingest` the fingerprint step drops the event and Pub/Sub records
69
+ `no calls`.
68
70
 
69
71
  ---
70
72
 
@@ -14,8 +14,8 @@ folder's absolute path (always for `runneros start`, which runs inside the
14
14
  artifact folder). From any other directory the lookup finds no file and the user
15
15
  gets no `ltv` or `segment`, without an error. A server flow simulation also
16
16
  needs the variables the setup in `flow-complete.md` exports (`GCP_SA`,
17
- `FINGERPRINT_SALT`, `EMAIL_SALT`).
17
+ `FINGERPRINT_SALT`, `EMAIL_SALT`, `META_ACCESS_TOKEN`).
18
18
 
19
19
  In production the store is swapped for a real one, e.g.
20
- `@walkeros/server-store-sheets` or a GCS store; the `loadUser` step does not
21
- change.
20
+ `@walkeros/server-store-sheets`, a GCS store, or `@walkeros/server-store-api`
21
+ for your CRM's API; the `loadUser` step does not change.
@@ -241,25 +241,25 @@
241
241
  "bundle": {
242
242
  "packages": {
243
243
  "@walkeros/collector": {
244
- "version": "4.9.0-next-1793116456867"
244
+ "version": "4.9.0"
245
245
  },
246
246
  "@walkeros/web-source-cmp-usercentrics": {
247
- "version": "4.9.0-next-1793116456867"
247
+ "version": "4.9.0"
248
248
  },
249
249
  "@walkeros/web-source-session": {
250
- "version": "4.9.0-next-1793116456867"
250
+ "version": "4.9.0"
251
251
  },
252
252
  "@walkeros/web-source-datalayer": {
253
- "version": "4.9.0-next-1793116456867"
253
+ "version": "4.9.0"
254
254
  },
255
255
  "@walkeros/web-source-browser": {
256
- "version": "4.9.0-next-1793116456867"
256
+ "version": "4.9.0"
257
257
  },
258
258
  "@walkeros/web-destination-gtag": {
259
- "version": "4.9.0-next-1793116456867"
259
+ "version": "4.9.0"
260
260
  },
261
261
  "@walkeros/web-destination-api": {
262
- "version": "4.9.0-next-1793116456867"
262
+ "version": "4.9.0"
263
263
  }
264
264
  },
265
265
  "env": {
@@ -1778,40 +1778,40 @@
1778
1778
  "bundle": {
1779
1779
  "packages": {
1780
1780
  "@walkeros/collector": {
1781
- "version": "4.9.0-next-1793116456867"
1781
+ "version": "4.9.0"
1782
1782
  },
1783
1783
  "@walkeros/server-source-express": {
1784
- "version": "4.9.0-next-1793116456867"
1784
+ "version": "4.9.0"
1785
1785
  },
1786
1786
  "@walkeros/transformer-ga4": {
1787
- "version": "4.9.0-next-1793116456867"
1787
+ "version": "4.9.0"
1788
1788
  },
1789
1789
  "@walkeros/transformer-validate": {
1790
- "version": "4.9.0-next-1793116456867"
1790
+ "version": "4.9.0"
1791
1791
  },
1792
1792
  "@walkeros/server-transformer-bot": {
1793
- "version": "4.9.0-next-1793116456867"
1793
+ "version": "4.9.0"
1794
1794
  },
1795
1795
  "@walkeros/server-transformer-fingerprint": {
1796
- "version": "4.9.0-next-1793116456867"
1796
+ "version": "4.9.0"
1797
1797
  },
1798
1798
  "@walkeros/server-transformer-file": {
1799
- "version": "4.9.0-next-1793116456867"
1799
+ "version": "4.9.0"
1800
1800
  },
1801
1801
  "@walkeros/server-store-fs": {
1802
- "version": "4.9.0-next-1793116456867"
1802
+ "version": "4.9.0"
1803
1803
  },
1804
1804
  "@walkeros/server-destination-gcp": {
1805
- "version": "4.9.0-next-1793116456867"
1805
+ "version": "4.9.0"
1806
1806
  },
1807
1807
  "@walkeros/server-destination-meta": {
1808
- "version": "4.9.0-next-1793116456867"
1808
+ "version": "4.9.0"
1809
1809
  },
1810
1810
  "@walkeros/server-destination-piwikpro": {
1811
- "version": "4.9.0-next-1793116456867"
1811
+ "version": "4.9.0"
1812
1812
  },
1813
1813
  "@walkeros/server-destination-datamanager": {
1814
- "version": "4.9.0-next-1793116456867"
1814
+ "version": "4.9.0"
1815
1815
  }
1816
1816
  }
1817
1817
  }
@@ -1881,6 +1881,10 @@
1881
1881
  {
1882
1882
  "path": "/walker.js",
1883
1883
  "methods": ["GET"]
1884
+ },
1885
+ {
1886
+ "path": "/demo/products/:id",
1887
+ "methods": ["GET"]
1884
1888
  }
1885
1889
  ],
1886
1890
  "cors": {
@@ -1942,6 +1946,14 @@
1942
1946
  "value": "/g/collect"
1943
1947
  },
1944
1948
  "stop": true
1949
+ },
1950
+ {
1951
+ "match": {
1952
+ "key": "ingest.path",
1953
+ "operator": "prefix",
1954
+ "value": "/demo/products/"
1955
+ },
1956
+ "next": "productApi"
1945
1957
  }
1946
1958
  ]
1947
1959
  },
@@ -2412,6 +2424,7 @@
2412
2424
  },
2413
2425
  "config": {
2414
2426
  "settings": {
2427
+ "prefix": "/",
2415
2428
  "headers": {
2416
2429
  "Cache-Control": "public, max-age=300",
2417
2430
  "Cross-Origin-Resource-Policy": "same-site"
@@ -2422,6 +2435,23 @@
2422
2435
  "stop": true
2423
2436
  }
2424
2437
  },
2438
+ "productApi": {
2439
+ "package": "@walkeros/server-transformer-file",
2440
+ "env": {
2441
+ "store": "$store.assets"
2442
+ },
2443
+ "config": {
2444
+ "settings": {
2445
+ "prefix": "/demo/",
2446
+ "headers": {
2447
+ "Content-Type": "application/json; charset=utf-8"
2448
+ }
2449
+ }
2450
+ },
2451
+ "next": {
2452
+ "stop": true
2453
+ }
2454
+ },
2425
2455
  "dedup": {
2426
2456
  "cache": {
2427
2457
  "stop": true,
@@ -2558,7 +2588,7 @@
2558
2588
  "package": "@walkeros/server-transformer-fingerprint",
2559
2589
  "config": {
2560
2590
  "settings": {
2561
- "salt": "$env.FINGERPRINT_SALT",
2591
+ "salt": "$secret.FINGERPRINT_SALT",
2562
2592
  "length": 16,
2563
2593
  "site": ["event.source.url", "ingest.origin"]
2564
2594
  }
@@ -4042,7 +4072,7 @@
4042
4072
  "package": "@walkeros/server-transformer-fingerprint",
4043
4073
  "config": {
4044
4074
  "settings": {
4045
- "salt": "$env.EMAIL_SALT",
4075
+ "salt": "$secret.EMAIL_SALT",
4046
4076
  "rotate": "none",
4047
4077
  "output": "user.email",
4048
4078
  "fields": [
@@ -4304,7 +4334,7 @@
4304
4334
  },
4305
4335
  "settings": {
4306
4336
  "pixelId": "$env.META_PIXEL_ID:1234567890",
4307
- "accessToken": "$env.META_ACCESS_TOKEN",
4337
+ "accessToken": "$secret.META_ACCESS_TOKEN",
4308
4338
  "action_source": "website",
4309
4339
  "user_data": {
4310
4340
  "em": {
@@ -4852,13 +4882,13 @@
4852
4882
  "bundle": {
4853
4883
  "packages": {
4854
4884
  "@walkeros/collector": {
4855
- "version": "4.9.0-next-1793116456867"
4885
+ "version": "4.9.0"
4856
4886
  },
4857
4887
  "@walkeros/server-source-gcp": {
4858
- "version": "4.9.0-next-1793116456867"
4888
+ "version": "4.9.0"
4859
4889
  },
4860
4890
  "@walkeros/server-destination-gcp": {
4861
- "version": "4.9.0-next-1793116456867"
4891
+ "version": "4.9.0"
4862
4892
  }
4863
4893
  }
4864
4894
  }
@@ -20,9 +20,9 @@ things.
20
20
  `.env` file. Run this once in the repo root before the server lines: `GCP_SA`
21
21
  holds a service account JSON (a throwaway key is enough for simulation: every
22
22
  Google client runs on its mock), `FINGERPRINT_SALT`, `EMAIL_SALT` and
23
- `META_ACCESS_TOKEN` have no defaults on purpose, and `CUSTOMERS_DIR` points
24
- the customers store at the demo data. Every other value is `$env.NAME:default`
25
- and works out of the box.
23
+ `META_ACCESS_TOKEN` are secrets (`$secret.`) with no defaults, and
24
+ `CUSTOMERS_DIR` points the customers store at the demo data. Every other value
25
+ is `$env.NAME:default` and works out of the box.
26
26
 
27
27
  ```bash
28
28
  export CUSTOMERS_DIR="$PWD/packages/cli/examples/customers"
@@ -39,8 +39,8 @@ web usercentrics, session, dataLayer, browser
39
39
  -> collector.next: opt-out stop, pageGroup
40
40
  -> ga4 (to Google, main property) gtm (dataLayer) collect (to server)
41
41
 
42
- server express /collect /g/collect /walker.js
43
- before: one [ G-SUBSITE hit -> ga4Decode -> ga4Consent | *.js -> file (stop) | other /g/collect (stop) ]
42
+ server express /collect /g/collect /walker.js /demo/products/:id
43
+ before: one [ G-SUBSITE hit -> ga4Decode -> ga4Consent | *.js -> file (stop) | other /g/collect (stop) | /demo/products/ -> productApi (stop) ]
44
44
  next: opt-out stop, dedup
45
45
  -> collector.next: fingerprint, bot, not impression -> enrich [ loadUser, sessionSave, sessionLoad, validate ]
46
46
  -> pubsub (every event, email pseudonymized)
@@ -104,7 +104,8 @@ walkeros push packages/cli/examples/flow-complete.json -f web -e '{"name":"page
104
104
  - `datalayer-source` at `/flows/web/sources/dataLayer`: The dataLayer source
105
105
  reads the pushes the shop already makes, so nothing on the page changes.
106
106
  - `source-require` at `/flows/web/sources/dataLayer/config/require`: require
107
- holds the source until consent and session are known.
107
+ holds back the entries already in the dataLayer until consent and session
108
+ are known; new pushes are captured from the start.
108
109
  - `source-mapping` at `/flows/web/sources/dataLayer/config/mapping`: Source
109
110
  mapping renames dataLayer add_to_cart to product add and picks its fields.
110
111
  - `browser-source` at `/flows/web/sources/browser`: The browser source reads
@@ -123,8 +124,9 @@ walkeros push packages/cli/examples/flow-complete.json -f web -e '{"name":"page
123
124
  flows reach it with $flow.
124
125
  - `config-settings` at `/flows/web/config/settings`: Platform settings:
125
126
  windowCollector names the global collector instance.
126
- - `require: ["consent", "session"]` on the dataLayer source means nothing is
127
- read before the banner decision and the session are known.
127
+ - `require: ["consent", "session"]` on the dataLayer source holds back the
128
+ entries already in the dataLayer until the banner decision and the session are
129
+ known. New pushes are captured at once.
128
130
  - The browser source is `primary`: its `elb` is the one the page calls.
129
131
  - Usercentrics and session examples are shown in the browser (their simulation
130
132
  in jsdom is still waiting), the dataLayer and browser examples simulate.
@@ -138,13 +140,14 @@ walkeros push packages/cli/examples/flow-complete.json -f web -e '{"name":"page
138
140
  ## server-entry: A first-party endpoint, and a GA4 migration path
139
141
 
140
142
  - **Purpose:** one express source answers the browser (`/collect`), GA4 hits of
141
- a sub-site (`/g/collect`) and script requests (`/walker.js`).
143
+ a sub-site (`/g/collect`), script requests (`/walker.js`) and product lookups
144
+ (`/demo/products/:id`).
142
145
  - **Features:**
143
146
  - `server-url` at `/flows/server/config/url`: The full collect endpoint, local
144
147
  by default, SERVER_URL in production.
145
148
  - `express-paths` at `/flows/server/sources/express/config/settings/paths`:
146
149
  One route per job, each with its own methods: /collect, /g/collect,
147
- /walker.js.
150
+ /walker.js, /demo/products/:id.
148
151
  - `express-cors` at `/flows/server/sources/express/config/settings/cors`: CORS
149
152
  response headers for the shop origin; express adds X-Content-Type-Options
150
153
  itself.
@@ -476,9 +479,9 @@ walkeros push packages/cli/examples/flow-complete.json -f server -e events/order
476
479
  - `ref-var-inline` at
477
480
  `/flows/warehouse/sources/pubsub/config/setup/deadLetterPolicy/deadLetterTopic`:
478
481
  Inside a longer string $var is replaced in place, here in a full topic name.
479
- - `ref-env` at `/flows/server/transformers/fingerprint/config/settings/salt`:
480
- $env without a default must be set: a secret salt never gets a public
481
- default.
482
+ - `ref-env` at `/flows/web/collector/custom/environment`: $env without a
483
+ default must be set: this web flow declares ENVIRONMENT in
484
+ config.bundle.env, so the build never misses it.
482
485
  - `ref-env-default` at `/variables/gcp/project`: $env.NAME:default works out
483
486
  of the box and takes the environment value when set.
484
487
  - `ref-secret` at `/flows/server/destinations/pubsub/config/credentials`:
@@ -495,11 +498,13 @@ walkeros push packages/cli/examples/flow-complete.json -f server -e events/order
495
498
  - `ref-store` at `/flows/server/transformers/file/env/store`: $store.assets
496
499
  injects a store into a step.
497
500
  - `bundle-env` at `/flows/web/config/bundle/env`: Web $env is resolved at
498
- build time from this declared set, so every build is the same.
501
+ build time: a local walkeros bundle reads the shell environment with this
502
+ declared set on top.
499
503
  - **Kinds:** `$var` (whole, deep, inline), `$env.NAME` and `$env.NAME:default`,
500
504
  `$secret`, `$flow`, `$code:`, `$contract`, `$store`.
501
- - **Secrets:** `$secret` is used only for `GCP_SA`, on the server and in the
502
- warehouse; web flows reject `$secret`.
505
+ - **Secrets:** `$secret` holds `GCP_SA` (server and warehouse) and, on the
506
+ server, `FINGERPRINT_SALT`, `EMAIL_SALT` and `META_ACCESS_TOKEN`; web flows
507
+ reject `$secret`.
503
508
  - **CLI:** `runneros` reads a private env file:
504
509
 
505
510
  ```bash
@@ -736,6 +741,15 @@ walkeros push packages/cli/examples/flow-complete.json -f server -e '{"name":"pa
736
741
  first party from the server flow.
737
742
  - `file-headers` at `/flows/server/transformers/file/config/settings/headers`:
738
743
  Default response headers for served files: caching and resource policy.
744
+ - `file-prefix` at `/flows/server/transformers/file/config/settings/prefix`:
745
+ prefix / makes the step own every script request: a missing walker.js
746
+ answers 404 instead of the tracking pixel.
747
+ - `products-case` at `/flows/server/sources/express/before/one/3`: The last
748
+ case sends product lookups (/demo/products/<id>) to productApi.
749
+ - `product-api` at `/flows/server/transformers/productApi`: A lookup route:
750
+ GET /demo/products/<id> answers the product as JSON from the assets store
751
+ (prefix /demo/ is stripped to the key products/<id>; headers sets the JSON
752
+ Content-Type), 404 for an unknown id, and never becomes an event.
739
753
  - `gclid-to-ads` at
740
754
  `/flows/server/destinations/datamanager/config/mapping/order/complete/data/map/gclid`:
741
755
  The gclid saved at session start reaches Google Ads with the purchase.
@@ -748,12 +762,27 @@ walkeros push packages/cli/examples/flow-complete.json -f server -e '{"name":"pa
748
762
  (`packages/cli/examples/customers`, one JSON record per customer id), outside
749
763
  root `include`, so no customer data ships in a bundle. `basePath` is relative
750
764
  to the working directory, so `CUSTOMERS_DIR` holds it as an absolute path (the
751
- setup block at the top exports it). In production a Sheets or GCS store takes
752
- its place; `loadUser` does not change.
765
+ setup block at the top exports it). In production a Sheets or GCS store, or
766
+ `@walkeros/server-store-api` for your CRM's API, takes its place; `loadUser`
767
+ does not change.
753
768
  - **walker.js first party:** the `file` transformer answers `GET /walker.js`
754
769
  from the `assets` store with `settings.headers` (`Cache-Control`,
755
770
  `Cross-Origin-Resource-Policy`) and ends with `next: { stop: true }`. Express
756
- `settings.cors` adds the CORS headers.
771
+ `settings.cors` adds the CORS headers. With `prefix: "/"` the step owns every
772
+ script request: a missing `walker.js` answers 404 with
773
+ `Cache-Control: no-store` instead of the tracking pixel.
774
+ - **A lookup route:** `productApi` is a second `file` step on the same `assets`
775
+ store. `GET /demo/products/SKU-1` answers 200 with the product as JSON
776
+ (`shared/products/SKU-1`; `settings.headers` sets the JSON `Content-Type`,
777
+ since the step serves bytes as stored), an unknown id answers 404 with
778
+ `Cache-Control: no-store`, and `next: { stop: true }` keeps every lookup from
779
+ becoming an event. A failing store read answers 503 and is logged at ERROR.
780
+
781
+ ```bash
782
+ curl -i http://localhost:8080/demo/products/SKU-1
783
+ curl -i http://localhost:8080/demo/products/SKU-9
784
+ ```
785
+
757
786
  - **Why `X-Content-Type-Options: nosniff` is not in the file:** express sets it
758
787
  on every response itself.
759
788
  - The `file` example is proven over HTTP in the integration test; its simulation
@@ -18,7 +18,9 @@
18
18
  "platform": "server",
19
19
  "bundle": {
20
20
  "packages": {
21
- "@walkeros/collector": {}
21
+ "@walkeros/collector": {
22
+ "version": "latest"
23
+ }
22
24
  }
23
25
  }
24
26
  }
@@ -970,7 +970,7 @@ declare const teaching: {
970
970
  pointer: string;
971
971
  chapter: "references";
972
972
  level: "intermediate";
973
- useCases: "cookieless-id"[];
973
+ useCases: never[];
974
974
  note: string;
975
975
  docs: {
976
976
  page: string;
@@ -1700,6 +1700,30 @@ declare const teaching: {
1700
1700
  page: string;
1701
1701
  }[];
1702
1702
  };
1703
+ 'file-prefix': {
1704
+ pointer: string;
1705
+ chapter: "state-stores";
1706
+ level: "intermediate";
1707
+ useCases: "script-serving"[];
1708
+ note: string;
1709
+ docs: never[];
1710
+ };
1711
+ 'products-case': {
1712
+ pointer: string;
1713
+ chapter: "state-stores";
1714
+ level: "intermediate";
1715
+ useCases: never[];
1716
+ note: string;
1717
+ docs: never[];
1718
+ };
1719
+ 'product-api': {
1720
+ pointer: string;
1721
+ chapter: "state-stores";
1722
+ level: "intermediate";
1723
+ useCases: never[];
1724
+ note: string;
1725
+ docs: never[];
1726
+ };
1703
1727
  'gclid-to-ads': {
1704
1728
  pointer: string;
1705
1729
  chapter: "state-stores";