@koda-sl/baker-cli 0.228.0-dev.ddddd841e → 0.231.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.
- package/README.md +29 -53
- package/dist/{chunk-CMPAHYLB.js → chunk-EKLAHWSF.js} +4 -4
- package/dist/chunk-EKLAHWSF.js.map +1 -0
- package/dist/cli.js +2263 -933
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-CMPAHYLB.js.map +0 -1
package/README.md
CHANGED
|
@@ -1151,54 +1151,6 @@ Each finding: `{id, area, check, status, severity, evidence, fix: {explanation,
|
|
|
1151
1151
|
|
|
1152
1152
|
---
|
|
1153
1153
|
|
|
1154
|
-
### First-party web analytics (`baker analytics`)
|
|
1155
|
-
|
|
1156
|
-
Baker's own measurement of the pages it publishes. No connection to set up and nothing to configure — data exists from the moment a page is published — and it is the only source that reports drop-off **per Form step**.
|
|
1157
|
-
|
|
1158
|
-
Preset-first; `overview` answers most questions in one call.
|
|
1159
|
-
|
|
1160
|
-
```bash
|
|
1161
|
-
baker analytics overview # traffic, top pages, sources, and every Form's worst step
|
|
1162
|
-
baker analytics overview --days 7
|
|
1163
|
-
baker analytics traffic --days 90 --full # full breakdowns plus the per-day trend
|
|
1164
|
-
baker analytics funnel --flow contact # which step loses people
|
|
1165
|
-
baker analytics page --path /pricing # one page in detail
|
|
1166
|
-
baker analytics triggers --flow contact # what visitors did in the Form, wired up or not
|
|
1167
|
-
baker analytics releases # traffic and conversions per published build
|
|
1168
|
-
baker analytics landings # every page side by side, with a sparkline each
|
|
1169
|
-
baker analytics landings --tag q4 # only the pages filed under one campaign tag
|
|
1170
|
-
baker analytics tags # the same numbers rolled up per campaign
|
|
1171
|
-
baker analytics events # the events the pages define for themselves
|
|
1172
|
-
baker analytics events --event video_progress --property milestone
|
|
1173
|
-
baker analytics events --steps hero_view,pricing_view,demo_click # an ordered page funnel
|
|
1174
|
-
baker analytics devices --grain viewport # which widths the page has to survive
|
|
1175
|
-
baker analytics geo --grain postal_code --country ES
|
|
1176
|
-
baker analytics bots # which crawlers fetch the site
|
|
1177
|
-
baker analytics presets # what each report answers
|
|
1178
|
-
```
|
|
1179
|
-
|
|
1180
|
-
Shared flags: `--days <n>` (default 30) or `--start-date` / `--end-date` (`YYYY-MM-DD`, end inclusive); `--full`; `--compare` to also return the preceding window of the same length; `--timezone <IANA>` and `--granularity hour|day|week|month` to shape a series. Every call reads live — there is no cache layer, so there is nothing to bypass.
|
|
1181
|
-
|
|
1182
|
-
Pass `--timezone` whenever the client is not in UTC. Day boundaries are drawn in UTC by default, which moves two hours of every Spanish evening onto the following day — not a rounding error on a day-of-week comparison, but the wrong day.
|
|
1183
|
-
|
|
1184
|
-
Reading the output:
|
|
1185
|
-
|
|
1186
|
-
- `visitors` and `sessions` are counted from explicit `visitor_new` / `session_start` events, so a session begins when the page says it did rather than when a query guesses.
|
|
1187
|
-
- `pageViews` prefers the server-side count, which ad blockers cannot suppress, so it usually exceeds what GA4 reports for the same period.
|
|
1188
|
-
- Rates are `null`, never `0`, when there is no denominator — `null` means "no data", `0` means "genuinely none".
|
|
1189
|
-
- `warnings[]` and `hints[]` carry caveats (small sample, sampled data) that belong in the answer, not in the footnotes.
|
|
1190
|
-
- `triggers[]` reports what visitors *did* inside a Form — a link click that redirects them off the site, a scheduling widget, an embedded checkout posting back — none of which produces a funnel step. `sideEffectsFired` says how many of those fires actually did something; a trigger with many fires and none is real behaviour with nothing wired to it.
|
|
1191
|
-
- `releases[]` gives one row per published build, so a change to a page can be compared before and after instead of against a date. Only events carrying a build are counted, so its `pageViews` sits below the site total for the same period.
|
|
1192
|
-
|
|
1193
|
-
- `landings[]` is one row per page with its real name and campaign tags, joined from a dimension Baker mirrors on every publish. An empty `name` means the mirror has not caught up — say "not synced yet" rather than showing the id as a title.
|
|
1194
|
-
- `trend[]` returns **every** bucket in the window, including ones with no traffic. A quiet day is a real zero rather than a missing row, so a chart cannot draw a straight line through it and imply traffic that did not happen.
|
|
1195
|
-
- `customEvents[]` covers only events a page defined for itself through `data-baker-*` attributes or `window.baker.track()`. Each row lists the property keys it carries, which is what tells you what you can break it down by.
|
|
1196
|
-
- `customFunnel[]` is **ordered**: a session counts at step N only if it produced step N after step N-1. Reordering `--steps` answers a different question.
|
|
1197
|
-
|
|
1198
|
-
Data is retained for 400 days; a window reaching further back comes back with a `BEYOND_RETENTION` warning, and the older part is missing rather than zero.
|
|
1199
|
-
|
|
1200
|
-
---
|
|
1201
|
-
|
|
1202
1154
|
### Google Analytics 4 (`baker ga4`)
|
|
1203
1155
|
|
|
1204
1156
|
GA4 commands for multi-channel audits **and** for configuring what the property measures. Playbook-aligned report presets, property health audits, free-form Data API queries, and staged Admin API writes.
|
|
@@ -2976,18 +2928,42 @@ Notes:
|
|
|
2976
2928
|
|
|
2977
2929
|
### Forms / Flows (`baker flows`)
|
|
2978
2930
|
|
|
2979
|
-
Read this workspace's Forms (flows)
|
|
2931
|
+
Read and shape this workspace's Forms (flows). Operates on the local `_data.json` files only; no secret values are ever decrypted or printed.
|
|
2980
2932
|
|
|
2981
|
-
**
|
|
2933
|
+
**A Form has two halves, split by a trust boundary.** Its *structure* — steps, conditions, side effects, field mappings — is yours, and the write subcommands below edit exactly that. Its *confidential* half — connection secrets, OAuth accounts, third-party field definitions (HubSpot, Calendly, HighLevel, SavvyCal) — is configured through the `request_flow_input` tool (`baker_ui` MCP server): the agent authors the surrounding structure and references it by `nodeId`/`sideEffectId`, and the user enters secrets, connects accounts, and picks resources in the dashboard. Those values are written (encrypted, where a secret) into the Form on the chat's branch and go live when the chat is published. Nothing any of these commands does touches a live system.
|
|
2982
2934
|
|
|
2983
2935
|
```bash
|
|
2984
|
-
baker flows list
|
|
2985
|
-
baker flows show contact
|
|
2986
|
-
baker flows show contact --full
|
|
2936
|
+
baker flows list # every Form + how many confidential fields still need setup
|
|
2937
|
+
baker flows show contact # one Form's confidential fields and their status
|
|
2938
|
+
baker flows show contact --full # include the full flow tree (secret values redacted)
|
|
2939
|
+
|
|
2940
|
+
baker flows schema # both vocabularies + the customForm field types
|
|
2941
|
+
baker flows schema node customForm # one type: skeleton, who fills what, the reference file
|
|
2942
|
+
baker flows schema side-effect googleSpreadsheet
|
|
2943
|
+
|
|
2944
|
+
baker flows add-node contact --type text --name "Thanks"
|
|
2945
|
+
baker flows add-side-effect contact --node <nodeId> --type googleSpreadsheet # triggerId comes from the step
|
|
2946
|
+
baker flows map contact --from map.json --write # a whole mapping at once — past ~3 fields, use this
|
|
2947
|
+
baker flows map contact --map A=nombre --write # one or two fields
|
|
2948
|
+
baker flows map contact --hubspot-form <guid> --from map.json --write # HubSpot: field types read off the form
|
|
2949
|
+
baker flows map contact --from map.json --replace --write # the slot becomes exactly this; use it to REMOVE a mapping
|
|
2950
|
+
baker flows normalize contact --write # repairs a nulled optional; runs pre-commit anyway
|
|
2987
2951
|
```
|
|
2988
2952
|
|
|
2989
2953
|
Notes:
|
|
2990
2954
|
|
|
2955
|
+
- **`schema` takes the kind as an argument because `hubspot` is both** — a node type (embeds a form on the page) and a side-effect type (fires a behavioural event). They are different things with one name.
|
|
2956
|
+
- **Configure the destination before you map.** `columnMapping`/`fieldMapping` describe a *specific* destination — sheet columns, a portal's field names — that only `request_flow_input` can see, and that call returns it. A mapping written first is valid JSON that ships and drops every submission; `verify` blocks the half-wired result.
|
|
2957
|
+
- **`map` reads the record shape off the side effect's type.** One property name, four record shapes: a Sheet is addressed by column letter, HubSpot by property name, Pipedrive and GoHighLevel by field key, Crmble by field id. That is why there is no `--key`, and why `--entity` and `--custom`/`--standard` are required rather than defaulted.
|
|
2958
|
+
- **A mapping is usually eight to fifteen fields, so `--from` is the main door.** It takes `{ "map": { "<destField>": "<value>" } }` from a file or stdin; `--map` flags are for one or two. Both produce identical output.
|
|
2959
|
+
- **Most CRM fields are not fed by a form field.** The value grammar is a bare form field (`nombre`), `field:Step.name` when two steps share a name, `tracking:utm_source`, `global:Name`, `code:exposed_value`, a `"literal"`, or any of those joined with `+`. Tracking names are validated against the engine's own `TRACKING_FIELD_IDS`, read out of the workspace rather than copied — attribution columns are the most common CRM mapping there is, and they were unexpressible before.
|
|
2960
|
+
- **A CRM mapping's field type is derived from the destination, never defaulted.** Every CRM record types `fieldType` as required, and it is the account's answer, not the agent's — HubSpot builds its submission key as `<objectTypeId>.<fieldType>.<fieldName>`, so a wrong type on a date property skips the `YYYY-MM-DD` coercion and the value is dropped. `--hubspot-form <formGuid>` (or `"hubspotForm"` in the mapping file) reads every property's type and object type off the form, so nothing has to state one. Where a destination cannot be read, put the type on the LEFT — `c0ffee:varchar=email` — which leaves `:` on the right for the value kinds. A mapping with no type from either route is refused, never written without one.
|
|
2961
|
+
- **`email` maps like anything else**, into `body.fields`, while `body.format` is `"json"`. A `"body"`-format email is one written message with no keys to address, and `map` refuses it rather than reshaping the body.
|
|
2962
|
+
- **Mapping twice adds; it does not start over.** Every slot merges with what is already in it, addressed by destination name — re-mapping a name overwrites it in place, a new name is appended, and a name the call did not mention is left alone. That is the default because a mapping is built in stages (configure the destination, read the real names back, map, come back for the rest), and replacing on every call turned "add the ninth field" into "delete the other eight". `--replace` (or `"replace": true` in the mapping file) writes the slot exactly as passed, and is the only way to remove a mapping. The response says how many were kept either way.
|
|
2963
|
+
- **`triggerId` is set from the step, not from the side-effect type.** A side effect runs only when its trigger is the id its own step raises: a `customForm` step raises `customForm.onFormSubmitted`, a Calendly step `calendlyEvent.eventScheduled`, a HubSpot widget `hubspotForm.onFormSubmitted`, a `text` step one of two depending on `allowNextNode`, and an `iframe` step one per declared event. A mismatch is the quietest failure in the engine — the file is valid, verify is green, and the side effect never runs — so `add-side-effect` derives it and refuses an id the step cannot raise. `--trigger` is for the non-completion moments (a HubSpot form's `onFormReady`, a Calendly page view). **A SavvyCal step raises no trigger at all**, so a side effect there is refused outright; put it on the following step, which the booking still advances to. `baker flows schema node <type>` lists a step's ids, and `baker flows show <slug>` names any side effect already wired to a moment its step never raises.
|
|
2964
|
+
- **A step's name becomes a constant, so `add-node` judges it as one.** The Form's generated code carries `export const <NAME> = "<node id>"` per step, keyed by upper-casing the name and splitting camelCase — so `contactInfo` and `Contact Info` are the same constant, and `1. Your details` or `Thanks!` are not valid ones at all. Both are refused when the step is created, where the message can name the step; left to the generator they surface as a duplicate-constant error or a syntax error in a file nobody wrote.
|
|
2965
|
+
- **`normalize` exists so authoring a Form does not require remembering an exception.** `oauthProviderId` is an optional `string`, so a `null` there fails typecheck one build later — it is repaired and staged instead of rejected.
|
|
2966
|
+
|
|
2991
2967
|
- **Secrets never travel through this CLI or the chat.** `show` reports only whether each field is configured (`[set]`/`[missing]`, `[connected]`/`[needs connection]`, selected/not selected) — never a value. Configured secrets appear only as `[configured]` ciphertext markers.
|
|
2992
2968
|
- Confidential side-effect types: `httpWebhook`, `zapier`, `crmble` (typed credentials); `pipedrive`, `googleSpreadsheet`, `hubspotForm`, `goHighlevelContact` (OAuth connection + resource); `email`. Widget node types needing a resource pick: `calendly`, `savvycal`, `hubspot`, `hubspotMeeting`, `highlevel`, `highlevelForm`.
|
|
2993
2969
|
- `request_flow_input` changes stage on the chat's branch and apply when the chat is published; discarding the chat drops them.
|
|
@@ -16,9 +16,9 @@ import {
|
|
|
16
16
|
shouldEscalate
|
|
17
17
|
} from "./chunk-DZUVUGEP.js";
|
|
18
18
|
|
|
19
|
-
//
|
|
19
|
+
// ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js
|
|
20
20
|
var require_safe_stable_stringify = __commonJS({
|
|
21
|
-
"
|
|
21
|
+
"../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js"(exports, module) {
|
|
22
22
|
"use strict";
|
|
23
23
|
var { hasOwnProperty } = Object.prototype;
|
|
24
24
|
var stringify = configure2();
|
|
@@ -1092,7 +1092,7 @@ function resolveAdaptFormats(params) {
|
|
|
1092
1092
|
return params.formats ?? [];
|
|
1093
1093
|
}
|
|
1094
1094
|
|
|
1095
|
-
//
|
|
1095
|
+
// ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/esm/wrapper.js
|
|
1096
1096
|
var import__ = __toESM(require_safe_stable_stringify(), 1);
|
|
1097
1097
|
var configure = import__.default.configure;
|
|
1098
1098
|
var wrapper_default = import__.default;
|
|
@@ -9074,4 +9074,4 @@ export {
|
|
|
9074
9074
|
defaultRegistry,
|
|
9075
9075
|
createEngineFromEnv
|
|
9076
9076
|
};
|
|
9077
|
-
//# sourceMappingURL=chunk-
|
|
9077
|
+
//# sourceMappingURL=chunk-EKLAHWSF.js.map
|