@koda-sl/baker-cli 0.313.0-dev.64ea8cd98 → 0.313.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 +3 -1
- package/dist/{chunk-PY7R67NE.js → chunk-WONWYE7B.js} +4 -4
- package/dist/chunk-WONWYE7B.js.map +1 -0
- package/dist/cli.js +91 -229
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-PY7R67NE.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -67,7 +67,7 @@ import {
|
|
|
67
67
|
validateCanvasDeep,
|
|
68
68
|
withoutCastName,
|
|
69
69
|
ytDlpBlockSignal
|
|
70
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-WONWYE7B.js";
|
|
71
71
|
import {
|
|
72
72
|
csvOrJson,
|
|
73
73
|
daysAgoIso,
|
|
@@ -222,6 +222,15 @@ function compactImage(image) {
|
|
|
222
222
|
imageUrl: String(image.imageUrl ?? ""),
|
|
223
223
|
description: String(image.description ?? ""),
|
|
224
224
|
tags: Array.isArray(image.tags) ? image.tags : [],
|
|
225
|
+
// Two numbers that are not about choosing the image but about placing it.
|
|
226
|
+
// A remote <BakerImage> with no width/height makes Astro DOWNLOAD the file
|
|
227
|
+
// at build time just to measure it — one request per image per build, on a
|
|
228
|
+
// build that is otherwise offline, and a single dropped connection there
|
|
229
|
+
// fails a client's whole verify. They are cheap enough to always carry, and
|
|
230
|
+
// burying them behind --full meant the agent placing the image never had
|
|
231
|
+
// them.
|
|
232
|
+
width: typeof image.width === "number" ? image.width : null,
|
|
233
|
+
height: typeof image.height === "number" ? image.height : null,
|
|
225
234
|
// The facts that decide a pick, so choosing does not need a second call:
|
|
226
235
|
// whose brand it is, who is in it, and what text is burned in.
|
|
227
236
|
subject: typeof analysis.subject === "string" ? analysis.subject : null,
|
|
@@ -235,8 +244,6 @@ function fullImage(image) {
|
|
|
235
244
|
const compact3 = compactImage(image);
|
|
236
245
|
return {
|
|
237
246
|
...compact3,
|
|
238
|
-
width: image.width ?? null,
|
|
239
|
-
height: image.height ?? null,
|
|
240
247
|
aspectRatio: formatAspectRatio(image.aspectRatio),
|
|
241
248
|
dominantColor: image.dominantColor ?? null,
|
|
242
249
|
imagePalette: Array.isArray(image.imagePalette) ? image.imagePalette : [],
|
|
@@ -10749,14 +10756,14 @@ function collectionLine(collection) {
|
|
|
10749
10756
|
}
|
|
10750
10757
|
function accountsInTree(nodes) {
|
|
10751
10758
|
const accounts = /* @__PURE__ */ new Set();
|
|
10752
|
-
const
|
|
10759
|
+
const walk2 = (node) => {
|
|
10753
10760
|
accounts.add(node.customerId);
|
|
10754
10761
|
for (const child of node.children) {
|
|
10755
|
-
|
|
10762
|
+
walk2(child);
|
|
10756
10763
|
}
|
|
10757
10764
|
};
|
|
10758
10765
|
for (const node of nodes) {
|
|
10759
|
-
|
|
10766
|
+
walk2(node);
|
|
10760
10767
|
}
|
|
10761
10768
|
return accounts;
|
|
10762
10769
|
}
|
|
@@ -21383,14 +21390,14 @@ function collectionLine2(collection) {
|
|
|
21383
21390
|
}
|
|
21384
21391
|
function accountsInTree2(nodes) {
|
|
21385
21392
|
const accounts = /* @__PURE__ */ new Set();
|
|
21386
|
-
const
|
|
21393
|
+
const walk2 = (node) => {
|
|
21387
21394
|
accounts.add(node.accountId);
|
|
21388
21395
|
for (const child of node.children) {
|
|
21389
|
-
|
|
21396
|
+
walk2(child);
|
|
21390
21397
|
}
|
|
21391
21398
|
};
|
|
21392
21399
|
for (const node of nodes) {
|
|
21393
|
-
|
|
21400
|
+
walk2(node);
|
|
21394
21401
|
}
|
|
21395
21402
|
return accounts;
|
|
21396
21403
|
}
|
|
@@ -26995,14 +27002,14 @@ function collectionLine3(collection) {
|
|
|
26995
27002
|
}
|
|
26996
27003
|
function accountsInTree3(nodes) {
|
|
26997
27004
|
const accounts = /* @__PURE__ */ new Set();
|
|
26998
|
-
const
|
|
27005
|
+
const walk2 = (node) => {
|
|
26999
27006
|
accounts.add(node.accountId);
|
|
27000
27007
|
for (const child of node.children) {
|
|
27001
|
-
|
|
27008
|
+
walk2(child);
|
|
27002
27009
|
}
|
|
27003
27010
|
};
|
|
27004
27011
|
for (const node of nodes) {
|
|
27005
|
-
|
|
27012
|
+
walk2(node);
|
|
27006
27013
|
}
|
|
27007
27014
|
return accounts;
|
|
27008
27015
|
}
|
|
@@ -28820,55 +28827,6 @@ Full guides: __tooling__/docs/tools/baker/ads-<platform>.md (google|meta|linkedi
|
|
|
28820
28827
|
// src/commands/analytics/index.ts
|
|
28821
28828
|
import { readFileSync as readFileSync12 } from "fs";
|
|
28822
28829
|
|
|
28823
|
-
// ../api/src/analytics/flowEventKeys.ts
|
|
28824
|
-
function flowNodes(node, acc = []) {
|
|
28825
|
-
if (!node || typeof node !== "object") return acc;
|
|
28826
|
-
const record = node;
|
|
28827
|
-
acc.push(record);
|
|
28828
|
-
if (Array.isArray(record.children)) for (const child of record.children) flowNodes(child, acc);
|
|
28829
|
-
return acc;
|
|
28830
|
-
}
|
|
28831
|
-
function flowEventKeys(tree, slug) {
|
|
28832
|
-
const primary = [];
|
|
28833
|
-
const secondary = [];
|
|
28834
|
-
const nodes = flowNodes(tree).filter((node) => typeof node.id === "string" && node.id !== "");
|
|
28835
|
-
if (nodes.length === 0) return [];
|
|
28836
|
-
for (const node of nodes) {
|
|
28837
|
-
const id = node.id;
|
|
28838
|
-
const triggers = flowNodeTriggers(node.nodeData);
|
|
28839
|
-
for (const triggerId of triggers.available) {
|
|
28840
|
-
const candidate = {
|
|
28841
|
-
eventKey: formEventKey(slug, id, triggerId),
|
|
28842
|
-
nodeId: id,
|
|
28843
|
-
nodeName: typeof node.name === "string" ? node.name : id,
|
|
28844
|
-
nodeType: triggers.type,
|
|
28845
|
-
triggerId,
|
|
28846
|
-
isCompletion: triggers.completion === triggerId
|
|
28847
|
-
};
|
|
28848
|
-
(candidate.isCompletion ? primary : secondary).push(candidate);
|
|
28849
|
-
}
|
|
28850
|
-
}
|
|
28851
|
-
return [
|
|
28852
|
-
...primary,
|
|
28853
|
-
...secondary,
|
|
28854
|
-
{
|
|
28855
|
-
eventKey: `submit:${slug}`,
|
|
28856
|
-
nodeId: null,
|
|
28857
|
-
nodeName: "the Form ran out of steps",
|
|
28858
|
-
nodeType: null,
|
|
28859
|
-
triggerId: null,
|
|
28860
|
-
// A Form reaching its last node is as primary as an outcome gets for a
|
|
28861
|
-
// Form with no widget in it — but it never fires on one that ends in a
|
|
28862
|
-
// booking widget or a redirect, so it does not lead the list.
|
|
28863
|
-
isCompletion: false
|
|
28864
|
-
}
|
|
28865
|
-
];
|
|
28866
|
-
}
|
|
28867
|
-
function suggestedEnding(endings) {
|
|
28868
|
-
const deepestFirst = [...endings].reverse();
|
|
28869
|
-
return deepestFirst.find((row) => row.isCompletion && row.nodeType !== "text") ?? deepestFirst.find((row) => row.isCompletion) ?? endings[endings.length - 1] ?? null;
|
|
28870
|
-
}
|
|
28871
|
-
|
|
28872
28830
|
// ../api/src/event-ingest/arrivals.ts
|
|
28873
28831
|
import { z as z33 } from "zod";
|
|
28874
28832
|
|
|
@@ -30048,14 +30006,56 @@ function mergeStoredWithCounts(stored, reported) {
|
|
|
30048
30006
|
}
|
|
30049
30007
|
|
|
30050
30008
|
// src/commands/analytics/flowConversionKeys.ts
|
|
30009
|
+
function walk(node, acc = []) {
|
|
30010
|
+
if (!node || typeof node !== "object") return acc;
|
|
30011
|
+
const record = node;
|
|
30012
|
+
acc.push(record);
|
|
30013
|
+
if (Array.isArray(record.children)) for (const child of record.children) walk(child, acc);
|
|
30014
|
+
return acc;
|
|
30015
|
+
}
|
|
30016
|
+
function flowConversionCandidates(tree, slug) {
|
|
30017
|
+
const primary = [];
|
|
30018
|
+
const secondary = [];
|
|
30019
|
+
for (const node of walk(tree)) {
|
|
30020
|
+
const id = typeof node.id === "string" ? node.id : null;
|
|
30021
|
+
if (!id) continue;
|
|
30022
|
+
const triggers = flowNodeTriggers(node.nodeData);
|
|
30023
|
+
for (const triggerId of triggers.available) {
|
|
30024
|
+
const candidate = {
|
|
30025
|
+
eventKey: formEventKey(slug, id, triggerId),
|
|
30026
|
+
nodeId: id,
|
|
30027
|
+
nodeName: typeof node.name === "string" ? node.name : id,
|
|
30028
|
+
nodeType: triggers.type,
|
|
30029
|
+
triggerId,
|
|
30030
|
+
isCompletion: triggers.completion === triggerId
|
|
30031
|
+
};
|
|
30032
|
+
(candidate.isCompletion ? primary : secondary).push(candidate);
|
|
30033
|
+
}
|
|
30034
|
+
}
|
|
30035
|
+
return [
|
|
30036
|
+
...primary,
|
|
30037
|
+
...secondary,
|
|
30038
|
+
{
|
|
30039
|
+
eventKey: `submit:${slug}`,
|
|
30040
|
+
nodeId: null,
|
|
30041
|
+
nodeName: "the Form ran out of steps",
|
|
30042
|
+
nodeType: null,
|
|
30043
|
+
triggerId: null,
|
|
30044
|
+
// A Form reaching its last node is as primary as an outcome gets for a
|
|
30045
|
+
// Form with no widget in it — but it never fires on one that ends in a
|
|
30046
|
+
// booking widget or a redirect, so it does not lead the list.
|
|
30047
|
+
isCompletion: false
|
|
30048
|
+
}
|
|
30049
|
+
];
|
|
30050
|
+
}
|
|
30051
30051
|
function formKeyRefusal(eventKey, tree, slug) {
|
|
30052
30052
|
const parsed = parseEventKey(eventKey);
|
|
30053
30053
|
if (!parsed || parsed.family !== "form" || parsed.flowSlug !== slug) return null;
|
|
30054
|
-
const node =
|
|
30054
|
+
const node = walk(tree).find((candidate) => candidate.id === parsed.nodeId);
|
|
30055
30055
|
if (!node) {
|
|
30056
30056
|
return {
|
|
30057
30057
|
message: `"${slug}" has no step with id "${parsed.nodeId}", so this key would be stored and count zero forever.`,
|
|
30058
|
-
fix: `Steps in this Form: ${
|
|
30058
|
+
fix: `Steps in this Form: ${walk(tree).map((n) => `${String(n.id)} (${String(n.name ?? "unnamed")})`).join(", ")}. \`baker analytics conversions --flow ${slug}\` prints each one already spelled as an event key.`
|
|
30059
30059
|
};
|
|
30060
30060
|
}
|
|
30061
30061
|
const triggers = flowNodeTriggers(node.nodeData);
|
|
@@ -30086,7 +30086,8 @@ function flowConversionHints(slug, rows, noConversionReason) {
|
|
|
30086
30086
|
`Nothing here is counted, and that is on purpose: this Form declares no outcome \u2014 "${noConversionReason}". Leave it alone unless that has stopped being true.`
|
|
30087
30087
|
];
|
|
30088
30088
|
}
|
|
30089
|
-
const
|
|
30089
|
+
const deepestFirst = [...rows].reverse();
|
|
30090
|
+
const suggestion = deepestFirst.find((row) => row.isCompletion && row.nodeType !== "text") ?? deepestFirst.find((row) => row.isCompletion) ?? rows[rows.length - 1];
|
|
30090
30091
|
return [
|
|
30091
30092
|
`Nothing on "${slug}" is counted, so it converts nobody on every report however many people finish it \u2014 Baker never guesses which ending is the point of a Form.`,
|
|
30092
30093
|
...suggestion ? [
|
|
@@ -30097,7 +30098,7 @@ function flowConversionHints(slug, rows, noConversionReason) {
|
|
|
30097
30098
|
}
|
|
30098
30099
|
function flowCoverage(forms, definitions) {
|
|
30099
30100
|
return forms.map(({ slug, tree }) => {
|
|
30100
|
-
const rows = joinFlowConversions(
|
|
30101
|
+
const rows = joinFlowConversions(flowConversionCandidates(tree, slug), definitions);
|
|
30101
30102
|
const declared = tree?.noConversion?.reason;
|
|
30102
30103
|
const seen = /* @__PURE__ */ new Set();
|
|
30103
30104
|
return {
|
|
@@ -32115,7 +32116,7 @@ function readFlowConversions2(slug, definitions) {
|
|
|
32115
32116
|
return {
|
|
32116
32117
|
slug,
|
|
32117
32118
|
noConversionReason: reason,
|
|
32118
|
-
endings: joinFlowConversions(
|
|
32119
|
+
endings: joinFlowConversions(flowConversionCandidates(tree, slug), definitions)
|
|
32119
32120
|
};
|
|
32120
32121
|
}
|
|
32121
32122
|
function conversionsEnvelope(args4, definitions, candidates) {
|
|
@@ -47232,54 +47233,8 @@ Full guide: __tooling__/docs/tools/baker/flows.md`
|
|
|
47232
47233
|
});
|
|
47233
47234
|
|
|
47234
47235
|
// src/commands/funnel/index.ts
|
|
47235
|
-
import { readFileSync as readFileSync15 } from "fs";
|
|
47236
47236
|
import { defineCommand as defineCommand129 } from "citty";
|
|
47237
47237
|
|
|
47238
|
-
// src/commands/funnel/formMoments.ts
|
|
47239
|
-
var MAX_NAMED_FORMS = 8;
|
|
47240
|
-
function formMoments(events, forms) {
|
|
47241
|
-
const seen = new Set(events.map((event) => event.eventKey));
|
|
47242
|
-
const rows = [];
|
|
47243
|
-
for (const form of forms) {
|
|
47244
|
-
const outcome = suggestedEnding(flowEventKeys(form.tree, form.slug));
|
|
47245
|
-
if (outcome === null || seen.has(outcome.eventKey)) continue;
|
|
47246
|
-
seen.add(outcome.eventKey);
|
|
47247
|
-
rows.push({
|
|
47248
|
-
eventKey: outcome.eventKey,
|
|
47249
|
-
origin: "site",
|
|
47250
|
-
flowSlug: form.slug,
|
|
47251
|
-
...outcome.nodeType === null ? {} : { nodeType: outcome.nodeType },
|
|
47252
|
-
events: 0,
|
|
47253
|
-
sessions: 0,
|
|
47254
|
-
step: outcome.nodeName,
|
|
47255
|
-
seen: false,
|
|
47256
|
-
outcome: true
|
|
47257
|
-
});
|
|
47258
|
-
}
|
|
47259
|
-
return rows;
|
|
47260
|
-
}
|
|
47261
|
-
function withFormMoments(moments, forms) {
|
|
47262
|
-
return { ...moments, events: [...moments.events, ...formMoments(moments.events, forms)] };
|
|
47263
|
-
}
|
|
47264
|
-
function unplacedFormHints(steps, forms) {
|
|
47265
|
-
const onAStep = new Set(
|
|
47266
|
-
steps.flatMap((step) => (step.triggers ?? []).flatMap((trigger) => trigger.eventKey ? [trigger.eventKey] : []))
|
|
47267
|
-
);
|
|
47268
|
-
const unplaced = [];
|
|
47269
|
-
for (const form of forms) {
|
|
47270
|
-
const endings = flowEventKeys(form.tree, form.slug);
|
|
47271
|
-
if (endings.some((ending) => onAStep.has(ending.eventKey))) continue;
|
|
47272
|
-
const outcome = suggestedEnding(endings);
|
|
47273
|
-
if (outcome !== null) unplaced.push(`${form.slug} \u2192 \`${outcome.eventKey}\` ("${outcome.nodeName}")`);
|
|
47274
|
-
}
|
|
47275
|
-
if (unplaced.length === 0) return [];
|
|
47276
|
-
const shown = unplaced.slice(0, MAX_NAMED_FORMS);
|
|
47277
|
-
const rest = unplaced.length - shown.length;
|
|
47278
|
-
return [
|
|
47279
|
-
`${unplaced.length} Form(s) in this workspace reach no funnel step, so they move nobody along it however many people finish them: ${shown.join("; ")}${rest > 0 ? `; and ${rest} more` : ""}. Place one with \`baker funnel --add-trigger <step> --event <key>\`, which adds that one way in and leaves the rest of the step alone (\`baker funnel\` with no flags lists the step keys). If you also count a Form as a page conversion, count THAT SAME key, or the two numbers disagree for ever. A Form's other endings \u2014 a booking widget mid-flow, an embed's own signals \u2014 are listed by \`baker analytics conversions --flow <slug>\`.`
|
|
47280
|
-
];
|
|
47281
|
-
}
|
|
47282
|
-
|
|
47283
47238
|
// ../api/src/funnel/vocabulary.ts
|
|
47284
47239
|
var FUNNEL_STEP_CLASSES = [
|
|
47285
47240
|
/** Saw the offer: a landing opened, an ad clicked through. */
|
|
@@ -47572,18 +47527,6 @@ var funnelRequestSchema = z44.object({
|
|
|
47572
47527
|
step: funnelStepSchema.optional(),
|
|
47573
47528
|
/** One step taken out by key; whatever came after it moves up to whatever came before it. */
|
|
47574
47529
|
removeStep: z44.string().min(1).max(64).optional(),
|
|
47575
|
-
/**
|
|
47576
|
-
* ONE way in added to a step, leaving the rest of that step alone.
|
|
47577
|
-
*
|
|
47578
|
-
* `step` takes a whole step, so adding a way in through it means restating
|
|
47579
|
-
* the step's name, stage, `after[]` and every trigger it already had — and a
|
|
47580
|
-
* trigger left out of that restatement is silently removed. This is the door
|
|
47581
|
-
* for the thing that is actually being asked ("this Form's booking should
|
|
47582
|
-
* count here"), and it cannot drop anything.
|
|
47583
|
-
*/
|
|
47584
|
-
addTrigger: z44.object({ stepKey: z44.string().min(1).max(64), eventKey: z44.string().min(1).max(320) }).optional(),
|
|
47585
|
-
/** ONE way in taken off a step, by the event key it listens for. */
|
|
47586
|
-
removeTrigger: z44.object({ stepKey: z44.string().min(1).max(64), eventKey: z44.string().min(1).max(320) }).optional(),
|
|
47587
47530
|
/** One of the ready-made graphs, instead of stating steps. */
|
|
47588
47531
|
preset: z44.enum(FUNNEL_VERTICALS).optional(),
|
|
47589
47532
|
/** Also return the suggestion library and the presets. */
|
|
@@ -47661,30 +47604,7 @@ var funnelResponseSchema = z44.object({
|
|
|
47661
47604
|
events: z44.number(),
|
|
47662
47605
|
sessions: z44.number(),
|
|
47663
47606
|
/** The name it is counted under as a page conversion, when the company counts it. Informational. */
|
|
47664
|
-
countedAs: z44.string().optional()
|
|
47665
|
-
/**
|
|
47666
|
-
* The step of the Form this happens on, in the Form's own words —
|
|
47667
|
-
* never a node id. Present on a Form's ending read from the Form
|
|
47668
|
-
* itself, which is the only place the name is known.
|
|
47669
|
-
*/
|
|
47670
|
-
step: z44.string().optional(),
|
|
47671
|
-
/**
|
|
47672
|
-
* `true` on the ONE ending of a Form that is its outcome — the
|
|
47673
|
-
* booking on a Form that books, the submit on a Form that submits.
|
|
47674
|
-
* A Form raises several events and only one of them is the point;
|
|
47675
|
-
* without this the agent is handed five equal-looking keys and the
|
|
47676
|
-
* lifecycle noise a widget raises about itself sits among them.
|
|
47677
|
-
* Same rule as `baker analytics conversions` recommends, so the
|
|
47678
|
-
* conversion and the funnel step land on the same event.
|
|
47679
|
-
*/
|
|
47680
|
-
outcome: z44.boolean().optional(),
|
|
47681
|
-
/**
|
|
47682
|
-
* `false` on an ending a Form raises natively but nobody has fired
|
|
47683
|
-
* yet — derived from the Form, offered at zero, exactly as a
|
|
47684
|
-
* Source is offered before its first send. Absent means it came
|
|
47685
|
-
* from the event store and therefore happened.
|
|
47686
|
-
*/
|
|
47687
|
-
seen: z44.boolean().optional()
|
|
47607
|
+
countedAs: z44.string().optional()
|
|
47688
47608
|
})
|
|
47689
47609
|
),
|
|
47690
47610
|
/** The company's sources: a system of theirs that posts events to Baker, by the event name it raises. */
|
|
@@ -47740,15 +47660,9 @@ function parseFunnelArgs(raw) {
|
|
|
47740
47660
|
const step = parseStep(raw.step);
|
|
47741
47661
|
const removeStep = parseRemoveStep(raw["remove-step"] ?? raw.removeStep);
|
|
47742
47662
|
const preset = parsePreset(raw.preset);
|
|
47743
|
-
const
|
|
47744
|
-
const removeTrigger = parseWayIn(raw["remove-trigger"] ?? raw.removeTrigger, raw.event, "--remove-trigger");
|
|
47745
|
-
const doors = [steps, step, removeStep, preset, addTrigger, removeTrigger].filter(
|
|
47746
|
-
(door) => door !== void 0
|
|
47747
|
-
).length;
|
|
47663
|
+
const doors = [steps, step, removeStep, preset].filter((door) => door !== void 0).length;
|
|
47748
47664
|
if (doors > 1) {
|
|
47749
|
-
throw new FunnelArgsError(
|
|
47750
|
-
"Give one of --steps, --step, --remove-step, --preset, --add-trigger or --remove-trigger, not two."
|
|
47751
|
-
);
|
|
47665
|
+
throw new FunnelArgsError("Give one of --steps, --step, --remove-step or --preset, not two.");
|
|
47752
47666
|
}
|
|
47753
47667
|
const days = raw.days === void 0 ? void 0 : Number(raw.days);
|
|
47754
47668
|
if (days !== void 0 && (!Number.isInteger(days) || days <= 0 || days > 400)) {
|
|
@@ -47759,8 +47673,6 @@ function parseFunnelArgs(raw) {
|
|
|
47759
47673
|
...step === void 0 ? {} : { step },
|
|
47760
47674
|
...removeStep === void 0 ? {} : { removeStep },
|
|
47761
47675
|
...preset === void 0 ? {} : { preset },
|
|
47762
|
-
...addTrigger === void 0 ? {} : { addTrigger },
|
|
47763
|
-
...removeTrigger === void 0 ? {} : { removeTrigger },
|
|
47764
47676
|
templates: raw.templates === true,
|
|
47765
47677
|
moments: raw.moments === true,
|
|
47766
47678
|
...days === void 0 ? {} : { days }
|
|
@@ -47772,8 +47684,6 @@ function funnelWrite(args4) {
|
|
|
47772
47684
|
...args4.step === void 0 ? {} : { step: args4.step },
|
|
47773
47685
|
...args4.removeStep === void 0 ? {} : { removeStep: args4.removeStep },
|
|
47774
47686
|
...args4.preset === void 0 ? {} : { preset: args4.preset },
|
|
47775
|
-
...args4.addTrigger === void 0 ? {} : { addTrigger: args4.addTrigger },
|
|
47776
|
-
...args4.removeTrigger === void 0 ? {} : { removeTrigger: args4.removeTrigger },
|
|
47777
47687
|
...args4.templates ? { templates: true } : {},
|
|
47778
47688
|
...args4.moments ? { moments: true } : {},
|
|
47779
47689
|
...args4.days === void 0 ? {} : { days: args4.days }
|
|
@@ -47883,26 +47793,6 @@ function parsePreset(raw) {
|
|
|
47883
47793
|
}
|
|
47884
47794
|
return raw;
|
|
47885
47795
|
}
|
|
47886
|
-
function parseWayIn(stepKey, eventKey, flag) {
|
|
47887
|
-
if (stepKey === void 0) return void 0;
|
|
47888
|
-
if (typeof stepKey !== "string" || stepKey.trim() === "") {
|
|
47889
|
-
throw new FunnelArgsError(`${flag} takes the key of the step to change: \`${flag} lead\`.`);
|
|
47890
|
-
}
|
|
47891
|
-
if (typeof eventKey !== "string" || eventKey.trim() === "") {
|
|
47892
|
-
throw new FunnelArgsError(`${flag} needs --event, naming what gets somebody there.`, {
|
|
47893
|
-
action: "read_the_moments",
|
|
47894
|
-
explanation: `Run \`baker funnel --moments\` and copy an \`events[].eventKey\` \u2014 a Form's own outcome is listed there at zero before anybody has filled it in. Then: \`${flag} ${stepKey.trim()} --event "<key>"\`.`
|
|
47895
|
-
});
|
|
47896
|
-
}
|
|
47897
|
-
const key = eventKey.trim();
|
|
47898
|
-
if (flag === "--add-trigger" && parseEventKey(key) === null) {
|
|
47899
|
-
throw new FunnelArgsError(`"${key}" is not an event key, so nothing would ever reach that step through it.`, {
|
|
47900
|
-
action: "read_the_moments",
|
|
47901
|
-
explanation: "Run `baker funnel --moments` and copy an `events[].eventKey`. They look like form:<form>:<step>:<trigger>, submit:<form>, page:<name> or view:<landing>."
|
|
47902
|
-
});
|
|
47903
|
-
}
|
|
47904
|
-
return { stepKey: stepKey.trim(), eventKey: key };
|
|
47905
|
-
}
|
|
47906
47796
|
|
|
47907
47797
|
// src/commands/funnel/index.ts
|
|
47908
47798
|
var args3 = {
|
|
@@ -47916,21 +47806,6 @@ var args3 = {
|
|
|
47916
47806
|
description: 'ONE step as a JSON object, in the same shape as an entry of --steps. It is added to the funnel as it now stands, or replaces the step with the same `key`, and every other step is left exactly as it is \u2014 the door for adding or changing a stage without restating the rest. Example: --step \'{"key":"demo","displayName":"Demo held","stepClass":"engaged","after":["lead"],"triggers":[{"id":"t1","kind":"event","eventKey":"page:demo_held"}]}\'',
|
|
47917
47807
|
required: false
|
|
47918
47808
|
},
|
|
47919
|
-
"add-trigger": {
|
|
47920
|
-
type: "string",
|
|
47921
|
-
description: 'The key of ONE step to add a way in to, with `--event` naming what gets somebody there: `--add-trigger lead --event "submit:contact"`. Start here for "this Form should count as a lead" \u2014 it adds that one way in and leaves the step\'s name, stage, `after[]` and every other trigger exactly as they are. Prefer it to `--step`, which takes a WHOLE step and therefore silently removes any trigger the restatement forgets. Adding a key the step already listens for changes nothing. Take the key from `--moments`, never from memory',
|
|
47922
|
-
required: false
|
|
47923
|
-
},
|
|
47924
|
-
"remove-trigger": {
|
|
47925
|
-
type: "string",
|
|
47926
|
-
description: 'The key of ONE step to take a way in OFF, with `--event` naming which: `--remove-trigger lead --event "submit:contact"`. By event key rather than by trigger id, because the id is not something you ever saw. Everything else about the step is untouched',
|
|
47927
|
-
required: false
|
|
47928
|
-
},
|
|
47929
|
-
event: {
|
|
47930
|
-
type: "string",
|
|
47931
|
-
description: "The event key `--add-trigger` or `--remove-trigger` acts on \u2014 an `events[].eventKey` from `--moments`, never invented. A Form's own outcome is listed there at zero, marked `outcome: true`, before anybody has filled the Form in",
|
|
47932
|
-
required: false
|
|
47933
|
-
},
|
|
47934
47809
|
"remove-step": {
|
|
47935
47810
|
type: "string",
|
|
47936
47811
|
description: "The key of one step to take off the funnel. Whatever came after it moves up to whatever came before it, so the chain stays joined. The response lists it under `removed`",
|
|
@@ -47943,7 +47818,7 @@ var args3 = {
|
|
|
47943
47818
|
},
|
|
47944
47819
|
moments: {
|
|
47945
47820
|
type: "boolean",
|
|
47946
|
-
description: "Also return everything a trigger can name, so a trigger is PICKED rather than invented: `events` (every event this company's Forms, pages and systems produced in the window, with volume, the Form it belongs to, `origin` \u2014 `site` for a page or Form, `systems` for the client's own server, `both` \u2014 and `countedAs` when the company also counts it as a page conversion, which a trigger does not need
|
|
47821
|
+
description: "Also return everything a trigger can name, so a trigger is PICKED rather than invented: `events` (every event this company's Forms, pages and systems actually produced in the window, with volume, the Form it belongs to, `origin` \u2014 `site` for a page or Form, `systems` for the client's own server, `both` \u2014 and `countedAs` when the company also counts it as a page conversion, which a trigger does not need), `sources` (the client's own systems that post events to Baker, by the `page:<name>` key each raises, pickable before its first send arrives) and `landings` (its pages, by the id a `landing` trigger takes). Use this before writing any `triggers`: a key typed from memory saves, publishes and counts nobody forever",
|
|
47947
47822
|
required: false
|
|
47948
47823
|
},
|
|
47949
47824
|
days: {
|
|
@@ -47965,20 +47840,17 @@ registerSchema({
|
|
|
47965
47840
|
var funnelCommand2 = defineCommand129({
|
|
47966
47841
|
meta: {
|
|
47967
47842
|
name: "funnel",
|
|
47968
|
-
description: 'Start here: run with no flags to see the funnel this company has, with the last 30 days of PEOPLE counted beside every step \u2014 `people` reached it, `atLeast` got at least that far, `before` got as far as the step before, `share` is the ratio, and `worstStep` names where the most people are lost. Every company has one from the day it exists: Visited (any landing) \u2192 Became a lead \u2192 Became a customer, the last two with no way in until somebody gives them one. Then `--moments` for everything a trigger can name (every event the company\'s Forms, pages and systems produced, its sources, its landings,
|
|
47843
|
+
description: 'Start here: run with no flags to see the funnel this company has, with the last 30 days of PEOPLE counted beside every step \u2014 `people` reached it, `atLeast` got at least that far, `before` got as far as the step before, `share` is the ratio, and `worstStep` names where the most people are lost. Every company has one from the day it exists: Visited (any landing) \u2192 Became a lead \u2192 Became a customer, the last two with no way in until somebody gives them one. Then `--moments` for everything a trigger can name (every event the company\'s Forms, pages and systems actually produced, its sources, its landings), and `--step \'<json>\'` to add or change ONE step in the client\'s own words \u2014 it replaces the step with that key, so restate its `after` and the triggers it keeps. A step is reached by three kinds of thing and nothing else: an event by its own key (`{"id":"t1","kind":"event","eventKey":"<from moments.events or moments.sources>"}`), one landing being viewed (`{"id":"t2","kind":"landing","landingId":"<from moments.landings>"}`) or any landing (`{"id":"t3","kind":"any_landing"}`). Nothing has to be named first. Pick every trigger from `--moments`, never from memory. A step with no `triggers` advances NOBODY and reports zero forever without warning \u2014 that is what the hints keep pointing at. There is no default door: a Form is only counted where a trigger names it. Keep it true: a chat that adds a Form, a Source or an event that moves people forward places it on its step in the same chat. Each step comes back with `sends[]`, read-only: where the people who reach it are sent and what happened, read off the system events behind its ways in. A send is set on the event with `baker analytics sends`, never on a step, and once published it spends ad budget \u2014 a failed one is named in the hints. Everything here is STAGED: it becomes the company\'s funnel in one piece when the chat is published \u2014 the client sees it on the canvas in this chat and can edit it there too \u2014 and the previous version stays on file so what was already measured under it is not lost.'
|
|
47969
47844
|
},
|
|
47970
47845
|
args: args3,
|
|
47971
47846
|
run: async ({ args: raw }) => {
|
|
47972
47847
|
try {
|
|
47973
47848
|
const parsed = parseFunnelArgs(raw);
|
|
47974
47849
|
const response = await apiPost("/api/funnel", funnelWrite(parsed));
|
|
47975
|
-
const forms = workspaceForms();
|
|
47976
|
-
const data = response.data.moments === void 0 ? response.data : { ...response.data, moments: withFormMoments(response.data.moments, forms) };
|
|
47977
|
-
const hints2 = [...response.hints ?? [], ...unplacedFormHints(response.data.steps ?? [], forms)];
|
|
47978
47850
|
writeJsonEnvelope({
|
|
47979
47851
|
ok: true,
|
|
47980
|
-
data,
|
|
47981
|
-
...
|
|
47852
|
+
data: response.data,
|
|
47853
|
+
...response.hints && response.hints.length > 0 ? { hints: response.hints } : {}
|
|
47982
47854
|
});
|
|
47983
47855
|
} catch (err) {
|
|
47984
47856
|
handleError4(err);
|
|
@@ -48003,16 +47875,6 @@ function handleError4(err) {
|
|
|
48003
47875
|
});
|
|
48004
47876
|
process.exit(1);
|
|
48005
47877
|
}
|
|
48006
|
-
function workspaceForms() {
|
|
48007
|
-
const forms = [];
|
|
48008
|
-
for (const slug of listFlowSlugs()) {
|
|
48009
|
-
try {
|
|
48010
|
-
forms.push({ slug, tree: JSON.parse(readFileSync15(flowDataPath(slug), "utf-8")) });
|
|
48011
|
-
} catch {
|
|
48012
|
-
}
|
|
48013
|
-
}
|
|
48014
|
-
return forms;
|
|
48015
|
-
}
|
|
48016
47878
|
|
|
48017
47879
|
// src/commands/ga4/index.ts
|
|
48018
47880
|
import { defineCommand as defineCommand136 } from "citty";
|
|
@@ -48142,7 +48004,7 @@ Examples:
|
|
|
48142
48004
|
import { defineCommand as defineCommand131 } from "citty";
|
|
48143
48005
|
|
|
48144
48006
|
// src/commands/ga4/shared.ts
|
|
48145
|
-
import { readFileSync as
|
|
48007
|
+
import { readFileSync as readFileSync15 } from "fs";
|
|
48146
48008
|
function failValidation3(message) {
|
|
48147
48009
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
48148
48010
|
process.exit(1);
|
|
@@ -48158,7 +48020,7 @@ function requireTarget5(args4, entity) {
|
|
|
48158
48020
|
function readJsonSource(args4, flag) {
|
|
48159
48021
|
const inline = args4[flag];
|
|
48160
48022
|
const file = args4.file;
|
|
48161
|
-
const raw = typeof file === "string" && file.length > 0 ?
|
|
48023
|
+
const raw = typeof file === "string" && file.length > 0 ? readFileSync15(file, "utf8") : typeof inline === "string" && inline.length > 0 ? inline : void 0;
|
|
48162
48024
|
if (raw === void 0) {
|
|
48163
48025
|
failValidation3(`pass --${flag} with inline JSON or --file with a path to a JSON file`);
|
|
48164
48026
|
}
|
|
@@ -48509,7 +48371,7 @@ Examples:
|
|
|
48509
48371
|
});
|
|
48510
48372
|
|
|
48511
48373
|
// src/commands/ga4/query.ts
|
|
48512
|
-
import { appendFileSync as appendFileSync2, existsSync as existsSync7, readFileSync as
|
|
48374
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync7, readFileSync as readFileSync16, writeFileSync as writeFileSync4 } from "fs";
|
|
48513
48375
|
import { resolve as resolve2 } from "path";
|
|
48514
48376
|
import { defineCommand as defineCommand134 } from "citty";
|
|
48515
48377
|
|
|
@@ -48600,7 +48462,7 @@ function writeRowsToFile2(filePath, rows, append) {
|
|
|
48600
48462
|
writeFileSync4(filePath, content, "utf-8");
|
|
48601
48463
|
}
|
|
48602
48464
|
} else if (append && existsSync7(filePath)) {
|
|
48603
|
-
const existing = JSON.parse(
|
|
48465
|
+
const existing = JSON.parse(readFileSync16(filePath, "utf-8"));
|
|
48604
48466
|
writeFileSync4(filePath, JSON.stringify([...existing, ...rows], null, 2), "utf-8");
|
|
48605
48467
|
} else {
|
|
48606
48468
|
writeFileSync4(filePath, JSON.stringify(rows, null, 2), "utf-8");
|
|
@@ -49452,7 +49314,7 @@ Full guide: __tooling__/docs/tools/baker/ga4.md`
|
|
|
49452
49314
|
import { defineCommand as defineCommand140 } from "citty";
|
|
49453
49315
|
|
|
49454
49316
|
// src/commands/gsc/query.ts
|
|
49455
|
-
import { appendFileSync as appendFileSync3, existsSync as existsSync8, readFileSync as
|
|
49317
|
+
import { appendFileSync as appendFileSync3, existsSync as existsSync8, readFileSync as readFileSync17, writeFileSync as writeFileSync5 } from "fs";
|
|
49456
49318
|
import { resolve as resolve3 } from "path";
|
|
49457
49319
|
import { defineCommand as defineCommand137 } from "citty";
|
|
49458
49320
|
|
|
@@ -49600,7 +49462,7 @@ function writeRowsToFile3(filePath, rows, append) {
|
|
|
49600
49462
|
writeFileSync5(filePath, content, "utf-8");
|
|
49601
49463
|
}
|
|
49602
49464
|
} else if (append && existsSync8(filePath)) {
|
|
49603
|
-
const existing = JSON.parse(
|
|
49465
|
+
const existing = JSON.parse(readFileSync17(filePath, "utf-8"));
|
|
49604
49466
|
writeFileSync5(filePath, JSON.stringify([...existing, ...rows], null, 2), "utf-8");
|
|
49605
49467
|
} else {
|
|
49606
49468
|
writeFileSync5(filePath, JSON.stringify(rows, null, 2), "utf-8");
|
|
@@ -56478,7 +56340,7 @@ var inPageCollectUsedCss = (selector) => {
|
|
|
56478
56340
|
}
|
|
56479
56341
|
return false;
|
|
56480
56342
|
};
|
|
56481
|
-
const
|
|
56343
|
+
const walk2 = (rules, sink) => {
|
|
56482
56344
|
for (const rule of Array.from(rules)) {
|
|
56483
56345
|
totalRules++;
|
|
56484
56346
|
if (rule instanceof CSSStyleRule) {
|
|
@@ -56499,7 +56361,7 @@ var inPageCollectUsedCss = (selector) => {
|
|
|
56499
56361
|
const grouping = rule instanceof CSSMediaRule || rule instanceof CSSSupportsRule || typeof CSSLayerBlockRule !== "undefined" && rule instanceof CSSLayerBlockRule || typeof CSSContainerRule !== "undefined" && rule instanceof CSSContainerRule;
|
|
56500
56362
|
if (grouping) {
|
|
56501
56363
|
const inner = [];
|
|
56502
|
-
|
|
56364
|
+
walk2(rule.cssRules, inner);
|
|
56503
56365
|
if (inner.length === 0) continue;
|
|
56504
56366
|
const condition = rule.conditionText ?? "";
|
|
56505
56367
|
const prelude = rule instanceof CSSMediaRule ? `@media ${condition}` : rule.cssText.split("{")[0]?.trim();
|
|
@@ -56513,7 +56375,7 @@ ${inner.join("\n")}
|
|
|
56513
56375
|
const owner = sheet.ownerNode;
|
|
56514
56376
|
if (owner?.hasAttribute?.("data-baker-freeze")) continue;
|
|
56515
56377
|
try {
|
|
56516
|
-
|
|
56378
|
+
walk2(sheet.cssRules, kept);
|
|
56517
56379
|
} catch {
|
|
56518
56380
|
if (sheet.href) unreadableHrefs.push(sheet.href);
|
|
56519
56381
|
}
|
|
@@ -56964,7 +56826,7 @@ var inPageCollectMotion = (selector) => {
|
|
|
56964
56826
|
else if (infinite) loop.push(effect);
|
|
56965
56827
|
else entrance.push(effect);
|
|
56966
56828
|
};
|
|
56967
|
-
const
|
|
56829
|
+
const walk2 = (rules, insideScrollTimeline) => {
|
|
56968
56830
|
for (const rule of Array.from(rules)) {
|
|
56969
56831
|
if (rule instanceof CSSKeyframesRule) {
|
|
56970
56832
|
keyframesByName.set(rule.name, rule.cssText);
|
|
@@ -56982,17 +56844,17 @@ var inPageCollectMotion = (selector) => {
|
|
|
56982
56844
|
respectsReducedMotion = true;
|
|
56983
56845
|
continue;
|
|
56984
56846
|
}
|
|
56985
|
-
|
|
56847
|
+
walk2(rule.cssRules, insideScrollTimeline);
|
|
56986
56848
|
continue;
|
|
56987
56849
|
}
|
|
56988
56850
|
const grouping = rule;
|
|
56989
|
-
if (grouping.cssRules)
|
|
56851
|
+
if (grouping.cssRules) walk2(grouping.cssRules, insideScrollTimeline);
|
|
56990
56852
|
}
|
|
56991
56853
|
};
|
|
56992
56854
|
for (const sheet of Array.from(document.styleSheets)) {
|
|
56993
56855
|
if (sheet.ownerNode?.hasAttribute?.("data-baker-freeze")) continue;
|
|
56994
56856
|
try {
|
|
56995
|
-
|
|
56857
|
+
walk2(sheet.cssRules, false);
|
|
56996
56858
|
} catch {
|
|
56997
56859
|
}
|
|
56998
56860
|
}
|
|
@@ -62831,7 +62693,7 @@ import { defineCommand as defineCommand217 } from "citty";
|
|
|
62831
62693
|
import { defineCommand as defineCommand214 } from "citty";
|
|
62832
62694
|
|
|
62833
62695
|
// src/commands/tag-manager/shared.ts
|
|
62834
|
-
import { readFileSync as
|
|
62696
|
+
import { readFileSync as readFileSync18 } from "fs";
|
|
62835
62697
|
function failValidation5(message) {
|
|
62836
62698
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
62837
62699
|
process.exit(1);
|
|
@@ -62847,7 +62709,7 @@ function requireTarget6(args4, entity) {
|
|
|
62847
62709
|
function loadJsonArg2(args4, flag = "json") {
|
|
62848
62710
|
const inline = args4[flag];
|
|
62849
62711
|
const file = args4.file;
|
|
62850
|
-
const raw = typeof file === "string" && file.length > 0 ?
|
|
62712
|
+
const raw = typeof file === "string" && file.length > 0 ? readFileSync18(file, "utf8") : typeof inline === "string" && inline.length > 0 ? inline : void 0;
|
|
62851
62713
|
if (raw === void 0) {
|
|
62852
62714
|
failValidation5(`pass --${flag} with inline JSON or --file with a path to a JSON file`);
|
|
62853
62715
|
}
|
|
@@ -66126,7 +65988,7 @@ function refuseUnknownFlags(root, argv) {
|
|
|
66126
65988
|
}
|
|
66127
65989
|
|
|
66128
65990
|
// src/version.ts
|
|
66129
|
-
import { readFileSync as
|
|
65991
|
+
import { readFileSync as readFileSync19 } from "fs";
|
|
66130
65992
|
function packageJsonUrl() {
|
|
66131
65993
|
return new URL("../package.json", import.meta.url);
|
|
66132
65994
|
}
|
|
@@ -66138,7 +66000,7 @@ function parsePackageVersion(raw) {
|
|
|
66138
66000
|
throw new Error("Invalid CLI package.json: missing version");
|
|
66139
66001
|
}
|
|
66140
66002
|
function getCliVersion() {
|
|
66141
|
-
return parsePackageVersion(
|
|
66003
|
+
return parsePackageVersion(readFileSync19(packageJsonUrl(), "utf8"));
|
|
66142
66004
|
}
|
|
66143
66005
|
|
|
66144
66006
|
// src/cli.ts
|