@koda-sl/baker-cli 0.311.0 → 0.313.0-dev.64ea8cd98
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 +1 -1
- package/dist/{chunk-WONWYE7B.js → chunk-PY7R67NE.js} +4 -4
- package/dist/chunk-PY7R67NE.js.map +1 -0
- package/dist/cli.js +306 -83
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-WONWYE7B.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-PY7R67NE.js";
|
|
71
71
|
import {
|
|
72
72
|
csvOrJson,
|
|
73
73
|
daysAgoIso,
|
|
@@ -5503,6 +5503,71 @@ var FLOW_OAUTH_SIDE_EFFECT_TYPES = [
|
|
|
5503
5503
|
function isFlowOauthSideEffect(type) {
|
|
5504
5504
|
return FLOW_OAUTH_SIDE_EFFECT_TYPES.includes(type);
|
|
5505
5505
|
}
|
|
5506
|
+
function parseEmailRecipients(raw) {
|
|
5507
|
+
const to = [];
|
|
5508
|
+
const invalid = [];
|
|
5509
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5510
|
+
for (const token of tokenizeRecipients(raw)) {
|
|
5511
|
+
const address = addressOf(token);
|
|
5512
|
+
if (address === null) {
|
|
5513
|
+
invalid.push(token);
|
|
5514
|
+
continue;
|
|
5515
|
+
}
|
|
5516
|
+
const key = address.toLowerCase();
|
|
5517
|
+
if (seen.has(key)) {
|
|
5518
|
+
continue;
|
|
5519
|
+
}
|
|
5520
|
+
seen.add(key);
|
|
5521
|
+
to.push(token);
|
|
5522
|
+
}
|
|
5523
|
+
return { to, invalid };
|
|
5524
|
+
}
|
|
5525
|
+
function looksLikeUnresolvedVariable(raw) {
|
|
5526
|
+
return /\{\{[\s\S]*?\}\}/.test(raw);
|
|
5527
|
+
}
|
|
5528
|
+
var BARE_ADDRESS = /^[^\s@<>,;"]+@[^\s@<>,;"]+\.[^\s@<>,;"]{2,}$/;
|
|
5529
|
+
var NAMED_ADDRESS = /^[^<>]*<([^<>\s]+)>$/;
|
|
5530
|
+
function addressOf(token) {
|
|
5531
|
+
if (BARE_ADDRESS.test(token)) {
|
|
5532
|
+
return token;
|
|
5533
|
+
}
|
|
5534
|
+
const named = NAMED_ADDRESS.exec(token)?.[1];
|
|
5535
|
+
return named !== void 0 && BARE_ADDRESS.test(named) ? named : null;
|
|
5536
|
+
}
|
|
5537
|
+
function tokenizeRecipients(raw) {
|
|
5538
|
+
const tokens = [];
|
|
5539
|
+
for (const fragment of splitOnSeparators(raw)) {
|
|
5540
|
+
const trimmed = fragment.trim();
|
|
5541
|
+
if (trimmed === "") {
|
|
5542
|
+
continue;
|
|
5543
|
+
}
|
|
5544
|
+
const bracketed = trimmed.includes("<") || trimmed.includes('"');
|
|
5545
|
+
tokens.push(...bracketed ? [trimmed] : trimmed.split(/\s+/));
|
|
5546
|
+
}
|
|
5547
|
+
return tokens;
|
|
5548
|
+
}
|
|
5549
|
+
function splitOnSeparators(raw) {
|
|
5550
|
+
const fragments = [];
|
|
5551
|
+
let current = "";
|
|
5552
|
+
let inQuotes = false;
|
|
5553
|
+
let inAngles = false;
|
|
5554
|
+
for (const char of raw) {
|
|
5555
|
+
if (char === '"') {
|
|
5556
|
+
inQuotes = !inQuotes;
|
|
5557
|
+
} else if (!inQuotes && char === "<") {
|
|
5558
|
+
inAngles = true;
|
|
5559
|
+
} else if (!inQuotes && char === ">") {
|
|
5560
|
+
inAngles = false;
|
|
5561
|
+
} else if (!inQuotes && !inAngles && (char === "," || char === ";" || char === "\n" || char === "\r")) {
|
|
5562
|
+
fragments.push(current);
|
|
5563
|
+
current = "";
|
|
5564
|
+
continue;
|
|
5565
|
+
}
|
|
5566
|
+
current += char;
|
|
5567
|
+
}
|
|
5568
|
+
fragments.push(current);
|
|
5569
|
+
return fragments;
|
|
5570
|
+
}
|
|
5506
5571
|
var FLOW_RESOURCE_NODE_TYPES = [
|
|
5507
5572
|
"calendly",
|
|
5508
5573
|
"savvycal",
|
|
@@ -10684,14 +10749,14 @@ function collectionLine(collection) {
|
|
|
10684
10749
|
}
|
|
10685
10750
|
function accountsInTree(nodes) {
|
|
10686
10751
|
const accounts = /* @__PURE__ */ new Set();
|
|
10687
|
-
const
|
|
10752
|
+
const walk = (node) => {
|
|
10688
10753
|
accounts.add(node.customerId);
|
|
10689
10754
|
for (const child of node.children) {
|
|
10690
|
-
|
|
10755
|
+
walk(child);
|
|
10691
10756
|
}
|
|
10692
10757
|
};
|
|
10693
10758
|
for (const node of nodes) {
|
|
10694
|
-
|
|
10759
|
+
walk(node);
|
|
10695
10760
|
}
|
|
10696
10761
|
return accounts;
|
|
10697
10762
|
}
|
|
@@ -21318,14 +21383,14 @@ function collectionLine2(collection) {
|
|
|
21318
21383
|
}
|
|
21319
21384
|
function accountsInTree2(nodes) {
|
|
21320
21385
|
const accounts = /* @__PURE__ */ new Set();
|
|
21321
|
-
const
|
|
21386
|
+
const walk = (node) => {
|
|
21322
21387
|
accounts.add(node.accountId);
|
|
21323
21388
|
for (const child of node.children) {
|
|
21324
|
-
|
|
21389
|
+
walk(child);
|
|
21325
21390
|
}
|
|
21326
21391
|
};
|
|
21327
21392
|
for (const node of nodes) {
|
|
21328
|
-
|
|
21393
|
+
walk(node);
|
|
21329
21394
|
}
|
|
21330
21395
|
return accounts;
|
|
21331
21396
|
}
|
|
@@ -26930,14 +26995,14 @@ function collectionLine3(collection) {
|
|
|
26930
26995
|
}
|
|
26931
26996
|
function accountsInTree3(nodes) {
|
|
26932
26997
|
const accounts = /* @__PURE__ */ new Set();
|
|
26933
|
-
const
|
|
26998
|
+
const walk = (node) => {
|
|
26934
26999
|
accounts.add(node.accountId);
|
|
26935
27000
|
for (const child of node.children) {
|
|
26936
|
-
|
|
27001
|
+
walk(child);
|
|
26937
27002
|
}
|
|
26938
27003
|
};
|
|
26939
27004
|
for (const node of nodes) {
|
|
26940
|
-
|
|
27005
|
+
walk(node);
|
|
26941
27006
|
}
|
|
26942
27007
|
return accounts;
|
|
26943
27008
|
}
|
|
@@ -28755,6 +28820,55 @@ Full guides: __tooling__/docs/tools/baker/ads-<platform>.md (google|meta|linkedi
|
|
|
28755
28820
|
// src/commands/analytics/index.ts
|
|
28756
28821
|
import { readFileSync as readFileSync12 } from "fs";
|
|
28757
28822
|
|
|
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
|
+
|
|
28758
28872
|
// ../api/src/event-ingest/arrivals.ts
|
|
28759
28873
|
import { z as z33 } from "zod";
|
|
28760
28874
|
|
|
@@ -29934,56 +30048,14 @@ function mergeStoredWithCounts(stored, reported) {
|
|
|
29934
30048
|
}
|
|
29935
30049
|
|
|
29936
30050
|
// src/commands/analytics/flowConversionKeys.ts
|
|
29937
|
-
function walk(node, acc = []) {
|
|
29938
|
-
if (!node || typeof node !== "object") return acc;
|
|
29939
|
-
const record = node;
|
|
29940
|
-
acc.push(record);
|
|
29941
|
-
if (Array.isArray(record.children)) for (const child of record.children) walk(child, acc);
|
|
29942
|
-
return acc;
|
|
29943
|
-
}
|
|
29944
|
-
function flowConversionCandidates(tree, slug) {
|
|
29945
|
-
const primary = [];
|
|
29946
|
-
const secondary = [];
|
|
29947
|
-
for (const node of walk(tree)) {
|
|
29948
|
-
const id = typeof node.id === "string" ? node.id : null;
|
|
29949
|
-
if (!id) continue;
|
|
29950
|
-
const triggers = flowNodeTriggers(node.nodeData);
|
|
29951
|
-
for (const triggerId of triggers.available) {
|
|
29952
|
-
const candidate = {
|
|
29953
|
-
eventKey: formEventKey(slug, id, triggerId),
|
|
29954
|
-
nodeId: id,
|
|
29955
|
-
nodeName: typeof node.name === "string" ? node.name : id,
|
|
29956
|
-
nodeType: triggers.type,
|
|
29957
|
-
triggerId,
|
|
29958
|
-
isCompletion: triggers.completion === triggerId
|
|
29959
|
-
};
|
|
29960
|
-
(candidate.isCompletion ? primary : secondary).push(candidate);
|
|
29961
|
-
}
|
|
29962
|
-
}
|
|
29963
|
-
return [
|
|
29964
|
-
...primary,
|
|
29965
|
-
...secondary,
|
|
29966
|
-
{
|
|
29967
|
-
eventKey: `submit:${slug}`,
|
|
29968
|
-
nodeId: null,
|
|
29969
|
-
nodeName: "the Form ran out of steps",
|
|
29970
|
-
nodeType: null,
|
|
29971
|
-
triggerId: null,
|
|
29972
|
-
// A Form reaching its last node is as primary as an outcome gets for a
|
|
29973
|
-
// Form with no widget in it — but it never fires on one that ends in a
|
|
29974
|
-
// booking widget or a redirect, so it does not lead the list.
|
|
29975
|
-
isCompletion: false
|
|
29976
|
-
}
|
|
29977
|
-
];
|
|
29978
|
-
}
|
|
29979
30051
|
function formKeyRefusal(eventKey, tree, slug) {
|
|
29980
30052
|
const parsed = parseEventKey(eventKey);
|
|
29981
30053
|
if (!parsed || parsed.family !== "form" || parsed.flowSlug !== slug) return null;
|
|
29982
|
-
const node =
|
|
30054
|
+
const node = flowNodes(tree).find((candidate) => candidate.id === parsed.nodeId);
|
|
29983
30055
|
if (!node) {
|
|
29984
30056
|
return {
|
|
29985
30057
|
message: `"${slug}" has no step with id "${parsed.nodeId}", so this key would be stored and count zero forever.`,
|
|
29986
|
-
fix: `Steps in this Form: ${
|
|
30058
|
+
fix: `Steps in this Form: ${flowNodes(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.`
|
|
29987
30059
|
};
|
|
29988
30060
|
}
|
|
29989
30061
|
const triggers = flowNodeTriggers(node.nodeData);
|
|
@@ -30014,8 +30086,7 @@ function flowConversionHints(slug, rows, noConversionReason) {
|
|
|
30014
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.`
|
|
30015
30087
|
];
|
|
30016
30088
|
}
|
|
30017
|
-
const
|
|
30018
|
-
const suggestion = deepestFirst.find((row) => row.isCompletion && row.nodeType !== "text") ?? deepestFirst.find((row) => row.isCompletion) ?? rows[rows.length - 1];
|
|
30089
|
+
const suggestion = suggestedEnding(rows);
|
|
30019
30090
|
return [
|
|
30020
30091
|
`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.`,
|
|
30021
30092
|
...suggestion ? [
|
|
@@ -30026,7 +30097,7 @@ function flowConversionHints(slug, rows, noConversionReason) {
|
|
|
30026
30097
|
}
|
|
30027
30098
|
function flowCoverage(forms, definitions) {
|
|
30028
30099
|
return forms.map(({ slug, tree }) => {
|
|
30029
|
-
const rows = joinFlowConversions(
|
|
30100
|
+
const rows = joinFlowConversions(flowEventKeys(tree, slug), definitions);
|
|
30030
30101
|
const declared = tree?.noConversion?.reason;
|
|
30031
30102
|
const seen = /* @__PURE__ */ new Set();
|
|
30032
30103
|
return {
|
|
@@ -32044,7 +32115,7 @@ function readFlowConversions2(slug, definitions) {
|
|
|
32044
32115
|
return {
|
|
32045
32116
|
slug,
|
|
32046
32117
|
noConversionReason: reason,
|
|
32047
|
-
endings: joinFlowConversions(
|
|
32118
|
+
endings: joinFlowConversions(flowEventKeys(tree, slug), definitions)
|
|
32048
32119
|
};
|
|
32049
32120
|
}
|
|
32050
32121
|
function conversionsEnvelope(args4, definitions, candidates) {
|
|
@@ -46816,6 +46887,19 @@ function fillNulledArrays(target, prefix, path48) {
|
|
|
46816
46887
|
return [{ path: path48, change: `\`${prefix}${key}: null\` \u2192 \`[]\`` }];
|
|
46817
46888
|
});
|
|
46818
46889
|
}
|
|
46890
|
+
function tidyEmailRecipients(sideEffect, path48) {
|
|
46891
|
+
if (sideEffect.type !== "email") return [];
|
|
46892
|
+
const config = sideEffect.encryptedConfig;
|
|
46893
|
+
if (!config || typeof config !== "object" || Array.isArray(config)) return [];
|
|
46894
|
+
const raw = config.email;
|
|
46895
|
+
if (typeof raw !== "string" || looksLikeUnresolvedVariable(raw)) return [];
|
|
46896
|
+
const { to, invalid } = parseEmailRecipients(raw);
|
|
46897
|
+
if (invalid.length > 0 || to.length === 0) return [];
|
|
46898
|
+
const tidied = to.join(", ");
|
|
46899
|
+
if (tidied === raw) return [];
|
|
46900
|
+
config.email = tidied;
|
|
46901
|
+
return [{ path: path48, change: "tidied the recipient list's spacing and separators" }];
|
|
46902
|
+
}
|
|
46819
46903
|
function sideEffectsOf(node) {
|
|
46820
46904
|
if (!Array.isArray(node.sideEffects)) return [];
|
|
46821
46905
|
return node.sideEffects.filter(
|
|
@@ -46829,7 +46913,7 @@ function normalizeSideEffect(sideEffect, where) {
|
|
|
46829
46913
|
if (!target || typeof target !== "object") return [];
|
|
46830
46914
|
return fillNulledArrays(target, owner ? `${owner}.` : "", path48);
|
|
46831
46915
|
});
|
|
46832
|
-
return [...dropUnsetOptionals(sideEffect, path48), ...arrays];
|
|
46916
|
+
return [...dropUnsetOptionals(sideEffect, path48), ...arrays, ...tidyEmailRecipients(sideEffect, path48)];
|
|
46833
46917
|
}
|
|
46834
46918
|
function normalizeFlowTree(tree) {
|
|
46835
46919
|
const changes = [];
|
|
@@ -47148,8 +47232,54 @@ Full guide: __tooling__/docs/tools/baker/flows.md`
|
|
|
47148
47232
|
});
|
|
47149
47233
|
|
|
47150
47234
|
// src/commands/funnel/index.ts
|
|
47235
|
+
import { readFileSync as readFileSync15 } from "fs";
|
|
47151
47236
|
import { defineCommand as defineCommand129 } from "citty";
|
|
47152
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
|
+
|
|
47153
47283
|
// ../api/src/funnel/vocabulary.ts
|
|
47154
47284
|
var FUNNEL_STEP_CLASSES = [
|
|
47155
47285
|
/** Saw the offer: a landing opened, an ad clicked through. */
|
|
@@ -47442,6 +47572,18 @@ var funnelRequestSchema = z44.object({
|
|
|
47442
47572
|
step: funnelStepSchema.optional(),
|
|
47443
47573
|
/** One step taken out by key; whatever came after it moves up to whatever came before it. */
|
|
47444
47574
|
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(),
|
|
47445
47587
|
/** One of the ready-made graphs, instead of stating steps. */
|
|
47446
47588
|
preset: z44.enum(FUNNEL_VERTICALS).optional(),
|
|
47447
47589
|
/** Also return the suggestion library and the presets. */
|
|
@@ -47519,7 +47661,30 @@ var funnelResponseSchema = z44.object({
|
|
|
47519
47661
|
events: z44.number(),
|
|
47520
47662
|
sessions: z44.number(),
|
|
47521
47663
|
/** The name it is counted under as a page conversion, when the company counts it. Informational. */
|
|
47522
|
-
countedAs: z44.string().optional()
|
|
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()
|
|
47523
47688
|
})
|
|
47524
47689
|
),
|
|
47525
47690
|
/** The company's sources: a system of theirs that posts events to Baker, by the event name it raises. */
|
|
@@ -47575,9 +47740,15 @@ function parseFunnelArgs(raw) {
|
|
|
47575
47740
|
const step = parseStep(raw.step);
|
|
47576
47741
|
const removeStep = parseRemoveStep(raw["remove-step"] ?? raw.removeStep);
|
|
47577
47742
|
const preset = parsePreset(raw.preset);
|
|
47578
|
-
const
|
|
47743
|
+
const addTrigger = parseWayIn(raw["add-trigger"] ?? raw.addTrigger, raw.event, "--add-trigger");
|
|
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;
|
|
47579
47748
|
if (doors > 1) {
|
|
47580
|
-
throw new FunnelArgsError(
|
|
47749
|
+
throw new FunnelArgsError(
|
|
47750
|
+
"Give one of --steps, --step, --remove-step, --preset, --add-trigger or --remove-trigger, not two."
|
|
47751
|
+
);
|
|
47581
47752
|
}
|
|
47582
47753
|
const days = raw.days === void 0 ? void 0 : Number(raw.days);
|
|
47583
47754
|
if (days !== void 0 && (!Number.isInteger(days) || days <= 0 || days > 400)) {
|
|
@@ -47588,6 +47759,8 @@ function parseFunnelArgs(raw) {
|
|
|
47588
47759
|
...step === void 0 ? {} : { step },
|
|
47589
47760
|
...removeStep === void 0 ? {} : { removeStep },
|
|
47590
47761
|
...preset === void 0 ? {} : { preset },
|
|
47762
|
+
...addTrigger === void 0 ? {} : { addTrigger },
|
|
47763
|
+
...removeTrigger === void 0 ? {} : { removeTrigger },
|
|
47591
47764
|
templates: raw.templates === true,
|
|
47592
47765
|
moments: raw.moments === true,
|
|
47593
47766
|
...days === void 0 ? {} : { days }
|
|
@@ -47599,6 +47772,8 @@ function funnelWrite(args4) {
|
|
|
47599
47772
|
...args4.step === void 0 ? {} : { step: args4.step },
|
|
47600
47773
|
...args4.removeStep === void 0 ? {} : { removeStep: args4.removeStep },
|
|
47601
47774
|
...args4.preset === void 0 ? {} : { preset: args4.preset },
|
|
47775
|
+
...args4.addTrigger === void 0 ? {} : { addTrigger: args4.addTrigger },
|
|
47776
|
+
...args4.removeTrigger === void 0 ? {} : { removeTrigger: args4.removeTrigger },
|
|
47602
47777
|
...args4.templates ? { templates: true } : {},
|
|
47603
47778
|
...args4.moments ? { moments: true } : {},
|
|
47604
47779
|
...args4.days === void 0 ? {} : { days: args4.days }
|
|
@@ -47708,6 +47883,26 @@ function parsePreset(raw) {
|
|
|
47708
47883
|
}
|
|
47709
47884
|
return raw;
|
|
47710
47885
|
}
|
|
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
|
+
}
|
|
47711
47906
|
|
|
47712
47907
|
// src/commands/funnel/index.ts
|
|
47713
47908
|
var args3 = {
|
|
@@ -47721,6 +47916,21 @@ var args3 = {
|
|
|
47721
47916
|
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"}]}\'',
|
|
47722
47917
|
required: false
|
|
47723
47918
|
},
|
|
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
|
+
},
|
|
47724
47934
|
"remove-step": {
|
|
47725
47935
|
type: "string",
|
|
47726
47936
|
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`",
|
|
@@ -47733,7 +47943,7 @@ var args3 = {
|
|
|
47733
47943
|
},
|
|
47734
47944
|
moments: {
|
|
47735
47945
|
type: "boolean",
|
|
47736
|
-
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
|
|
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; PLUS **one row per Form in this workspace \u2014 its OUTCOME** \u2014 at zero, with `outcome: true`, `seen: false` and the `step` it happens on, so a Form built minutes ago is pickable with nothing set up first. It is the booking on a Form that books, the submit on a Form that submits, and it is the same ending `baker analytics conversions` recommends counting, so the step and the conversion land on the same event. One row and not all seven a Form raises: the rest are rarely what a step wants, and `baker analytics conversions --flow <slug>` lists every ending of one Form when they are before anybody has filled it in), `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. A Form's events need NOTHING set up first \u2014 no Source, no conversion: a Baker page raises them by itself",
|
|
47737
47947
|
required: false
|
|
47738
47948
|
},
|
|
47739
47949
|
days: {
|
|
@@ -47755,17 +47965,20 @@ registerSchema({
|
|
|
47755
47965
|
var funnelCommand2 = defineCommand129({
|
|
47756
47966
|
meta: {
|
|
47757
47967
|
name: "funnel",
|
|
47758
|
-
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
|
|
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, plus each Form\'s own outcome at zero). **To make an event count on a step \u2014 the usual job \u2014 use `--add-trigger <step> --event <key>`:** it adds that one way in and touches nothing else about the step. `--step \'<json>\'` is for adding or renaming a STEP; it replaces the step with that key, so it means restating its `after` and every trigger it keeps, and one left out is gone. 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.'
|
|
47759
47969
|
},
|
|
47760
47970
|
args: args3,
|
|
47761
47971
|
run: async ({ args: raw }) => {
|
|
47762
47972
|
try {
|
|
47763
47973
|
const parsed = parseFunnelArgs(raw);
|
|
47764
47974
|
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)];
|
|
47765
47978
|
writeJsonEnvelope({
|
|
47766
47979
|
ok: true,
|
|
47767
|
-
data
|
|
47768
|
-
...
|
|
47980
|
+
data,
|
|
47981
|
+
...hints2.length > 0 ? { hints: hints2 } : {}
|
|
47769
47982
|
});
|
|
47770
47983
|
} catch (err) {
|
|
47771
47984
|
handleError4(err);
|
|
@@ -47790,6 +48003,16 @@ function handleError4(err) {
|
|
|
47790
48003
|
});
|
|
47791
48004
|
process.exit(1);
|
|
47792
48005
|
}
|
|
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
|
+
}
|
|
47793
48016
|
|
|
47794
48017
|
// src/commands/ga4/index.ts
|
|
47795
48018
|
import { defineCommand as defineCommand136 } from "citty";
|
|
@@ -47919,7 +48142,7 @@ Examples:
|
|
|
47919
48142
|
import { defineCommand as defineCommand131 } from "citty";
|
|
47920
48143
|
|
|
47921
48144
|
// src/commands/ga4/shared.ts
|
|
47922
|
-
import { readFileSync as
|
|
48145
|
+
import { readFileSync as readFileSync16 } from "fs";
|
|
47923
48146
|
function failValidation3(message) {
|
|
47924
48147
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
47925
48148
|
process.exit(1);
|
|
@@ -47935,7 +48158,7 @@ function requireTarget5(args4, entity) {
|
|
|
47935
48158
|
function readJsonSource(args4, flag) {
|
|
47936
48159
|
const inline = args4[flag];
|
|
47937
48160
|
const file = args4.file;
|
|
47938
|
-
const raw = typeof file === "string" && file.length > 0 ?
|
|
48161
|
+
const raw = typeof file === "string" && file.length > 0 ? readFileSync16(file, "utf8") : typeof inline === "string" && inline.length > 0 ? inline : void 0;
|
|
47939
48162
|
if (raw === void 0) {
|
|
47940
48163
|
failValidation3(`pass --${flag} with inline JSON or --file with a path to a JSON file`);
|
|
47941
48164
|
}
|
|
@@ -48286,7 +48509,7 @@ Examples:
|
|
|
48286
48509
|
});
|
|
48287
48510
|
|
|
48288
48511
|
// src/commands/ga4/query.ts
|
|
48289
|
-
import { appendFileSync as appendFileSync2, existsSync as existsSync7, readFileSync as
|
|
48512
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync7, readFileSync as readFileSync17, writeFileSync as writeFileSync4 } from "fs";
|
|
48290
48513
|
import { resolve as resolve2 } from "path";
|
|
48291
48514
|
import { defineCommand as defineCommand134 } from "citty";
|
|
48292
48515
|
|
|
@@ -48377,7 +48600,7 @@ function writeRowsToFile2(filePath, rows, append) {
|
|
|
48377
48600
|
writeFileSync4(filePath, content, "utf-8");
|
|
48378
48601
|
}
|
|
48379
48602
|
} else if (append && existsSync7(filePath)) {
|
|
48380
|
-
const existing = JSON.parse(
|
|
48603
|
+
const existing = JSON.parse(readFileSync17(filePath, "utf-8"));
|
|
48381
48604
|
writeFileSync4(filePath, JSON.stringify([...existing, ...rows], null, 2), "utf-8");
|
|
48382
48605
|
} else {
|
|
48383
48606
|
writeFileSync4(filePath, JSON.stringify(rows, null, 2), "utf-8");
|
|
@@ -49229,7 +49452,7 @@ Full guide: __tooling__/docs/tools/baker/ga4.md`
|
|
|
49229
49452
|
import { defineCommand as defineCommand140 } from "citty";
|
|
49230
49453
|
|
|
49231
49454
|
// src/commands/gsc/query.ts
|
|
49232
|
-
import { appendFileSync as appendFileSync3, existsSync as existsSync8, readFileSync as
|
|
49455
|
+
import { appendFileSync as appendFileSync3, existsSync as existsSync8, readFileSync as readFileSync18, writeFileSync as writeFileSync5 } from "fs";
|
|
49233
49456
|
import { resolve as resolve3 } from "path";
|
|
49234
49457
|
import { defineCommand as defineCommand137 } from "citty";
|
|
49235
49458
|
|
|
@@ -49377,7 +49600,7 @@ function writeRowsToFile3(filePath, rows, append) {
|
|
|
49377
49600
|
writeFileSync5(filePath, content, "utf-8");
|
|
49378
49601
|
}
|
|
49379
49602
|
} else if (append && existsSync8(filePath)) {
|
|
49380
|
-
const existing = JSON.parse(
|
|
49603
|
+
const existing = JSON.parse(readFileSync18(filePath, "utf-8"));
|
|
49381
49604
|
writeFileSync5(filePath, JSON.stringify([...existing, ...rows], null, 2), "utf-8");
|
|
49382
49605
|
} else {
|
|
49383
49606
|
writeFileSync5(filePath, JSON.stringify(rows, null, 2), "utf-8");
|
|
@@ -56255,7 +56478,7 @@ var inPageCollectUsedCss = (selector) => {
|
|
|
56255
56478
|
}
|
|
56256
56479
|
return false;
|
|
56257
56480
|
};
|
|
56258
|
-
const
|
|
56481
|
+
const walk = (rules, sink) => {
|
|
56259
56482
|
for (const rule of Array.from(rules)) {
|
|
56260
56483
|
totalRules++;
|
|
56261
56484
|
if (rule instanceof CSSStyleRule) {
|
|
@@ -56276,7 +56499,7 @@ var inPageCollectUsedCss = (selector) => {
|
|
|
56276
56499
|
const grouping = rule instanceof CSSMediaRule || rule instanceof CSSSupportsRule || typeof CSSLayerBlockRule !== "undefined" && rule instanceof CSSLayerBlockRule || typeof CSSContainerRule !== "undefined" && rule instanceof CSSContainerRule;
|
|
56277
56500
|
if (grouping) {
|
|
56278
56501
|
const inner = [];
|
|
56279
|
-
|
|
56502
|
+
walk(rule.cssRules, inner);
|
|
56280
56503
|
if (inner.length === 0) continue;
|
|
56281
56504
|
const condition = rule.conditionText ?? "";
|
|
56282
56505
|
const prelude = rule instanceof CSSMediaRule ? `@media ${condition}` : rule.cssText.split("{")[0]?.trim();
|
|
@@ -56290,7 +56513,7 @@ ${inner.join("\n")}
|
|
|
56290
56513
|
const owner = sheet.ownerNode;
|
|
56291
56514
|
if (owner?.hasAttribute?.("data-baker-freeze")) continue;
|
|
56292
56515
|
try {
|
|
56293
|
-
|
|
56516
|
+
walk(sheet.cssRules, kept);
|
|
56294
56517
|
} catch {
|
|
56295
56518
|
if (sheet.href) unreadableHrefs.push(sheet.href);
|
|
56296
56519
|
}
|
|
@@ -56741,7 +56964,7 @@ var inPageCollectMotion = (selector) => {
|
|
|
56741
56964
|
else if (infinite) loop.push(effect);
|
|
56742
56965
|
else entrance.push(effect);
|
|
56743
56966
|
};
|
|
56744
|
-
const
|
|
56967
|
+
const walk = (rules, insideScrollTimeline) => {
|
|
56745
56968
|
for (const rule of Array.from(rules)) {
|
|
56746
56969
|
if (rule instanceof CSSKeyframesRule) {
|
|
56747
56970
|
keyframesByName.set(rule.name, rule.cssText);
|
|
@@ -56759,17 +56982,17 @@ var inPageCollectMotion = (selector) => {
|
|
|
56759
56982
|
respectsReducedMotion = true;
|
|
56760
56983
|
continue;
|
|
56761
56984
|
}
|
|
56762
|
-
|
|
56985
|
+
walk(rule.cssRules, insideScrollTimeline);
|
|
56763
56986
|
continue;
|
|
56764
56987
|
}
|
|
56765
56988
|
const grouping = rule;
|
|
56766
|
-
if (grouping.cssRules)
|
|
56989
|
+
if (grouping.cssRules) walk(grouping.cssRules, insideScrollTimeline);
|
|
56767
56990
|
}
|
|
56768
56991
|
};
|
|
56769
56992
|
for (const sheet of Array.from(document.styleSheets)) {
|
|
56770
56993
|
if (sheet.ownerNode?.hasAttribute?.("data-baker-freeze")) continue;
|
|
56771
56994
|
try {
|
|
56772
|
-
|
|
56995
|
+
walk(sheet.cssRules, false);
|
|
56773
56996
|
} catch {
|
|
56774
56997
|
}
|
|
56775
56998
|
}
|
|
@@ -62608,7 +62831,7 @@ import { defineCommand as defineCommand217 } from "citty";
|
|
|
62608
62831
|
import { defineCommand as defineCommand214 } from "citty";
|
|
62609
62832
|
|
|
62610
62833
|
// src/commands/tag-manager/shared.ts
|
|
62611
|
-
import { readFileSync as
|
|
62834
|
+
import { readFileSync as readFileSync19 } from "fs";
|
|
62612
62835
|
function failValidation5(message) {
|
|
62613
62836
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
62614
62837
|
process.exit(1);
|
|
@@ -62624,7 +62847,7 @@ function requireTarget6(args4, entity) {
|
|
|
62624
62847
|
function loadJsonArg2(args4, flag = "json") {
|
|
62625
62848
|
const inline = args4[flag];
|
|
62626
62849
|
const file = args4.file;
|
|
62627
|
-
const raw = typeof file === "string" && file.length > 0 ?
|
|
62850
|
+
const raw = typeof file === "string" && file.length > 0 ? readFileSync19(file, "utf8") : typeof inline === "string" && inline.length > 0 ? inline : void 0;
|
|
62628
62851
|
if (raw === void 0) {
|
|
62629
62852
|
failValidation5(`pass --${flag} with inline JSON or --file with a path to a JSON file`);
|
|
62630
62853
|
}
|
|
@@ -65903,7 +66126,7 @@ function refuseUnknownFlags(root, argv) {
|
|
|
65903
66126
|
}
|
|
65904
66127
|
|
|
65905
66128
|
// src/version.ts
|
|
65906
|
-
import { readFileSync as
|
|
66129
|
+
import { readFileSync as readFileSync20 } from "fs";
|
|
65907
66130
|
function packageJsonUrl() {
|
|
65908
66131
|
return new URL("../package.json", import.meta.url);
|
|
65909
66132
|
}
|
|
@@ -65915,7 +66138,7 @@ function parsePackageVersion(raw) {
|
|
|
65915
66138
|
throw new Error("Invalid CLI package.json: missing version");
|
|
65916
66139
|
}
|
|
65917
66140
|
function getCliVersion() {
|
|
65918
|
-
return parsePackageVersion(
|
|
66141
|
+
return parsePackageVersion(readFileSync20(packageJsonUrl(), "utf8"));
|
|
65919
66142
|
}
|
|
65920
66143
|
|
|
65921
66144
|
// src/cli.ts
|