@koda-sl/baker-cli 0.409.0 → 0.410.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/dist/cli.js
CHANGED
|
@@ -97,7 +97,7 @@ import {
|
|
|
97
97
|
withoutCastName,
|
|
98
98
|
wordCount,
|
|
99
99
|
ytDlpBlockSignal
|
|
100
|
-
} from "./chunk-
|
|
100
|
+
} from "./chunk-KTMFHBN6.js";
|
|
101
101
|
import {
|
|
102
102
|
NAME_CONTAINS_ARG,
|
|
103
103
|
csvOrJson,
|
|
@@ -34492,16 +34492,16 @@ async function runChatgptRead(reference, read, hintsFor4) {
|
|
|
34492
34492
|
}
|
|
34493
34493
|
}
|
|
34494
34494
|
var TRUNCATED_HINT = "These rows are the first 2,000, not the whole account \u2014 narrow the read (--campaign-id, --ad-group-id) before counting them or concluding something is missing.";
|
|
34495
|
-
async function getChatgptList(
|
|
34496
|
-
const { data, headers } = await apiGetWithHeaders(
|
|
34495
|
+
async function getChatgptList(path58, params) {
|
|
34496
|
+
const { data, headers } = await apiGetWithHeaders(path58, params);
|
|
34497
34497
|
return { data, truncated: headers.get(CHATGPT_ADS_TRUNCATED_HEADER) === "true" };
|
|
34498
34498
|
}
|
|
34499
|
-
async function runChatgptListRead(reference,
|
|
34499
|
+
async function runChatgptListRead(reference, path58, params, hintsFor4) {
|
|
34500
34500
|
let truncated = false;
|
|
34501
34501
|
await runChatgptRead(
|
|
34502
34502
|
reference,
|
|
34503
34503
|
async () => {
|
|
34504
|
-
const read = await getChatgptList(
|
|
34504
|
+
const read = await getChatgptList(path58, params);
|
|
34505
34505
|
truncated = read.truncated;
|
|
34506
34506
|
return read.data;
|
|
34507
34507
|
},
|
|
@@ -35306,7 +35306,7 @@ var MEMBER_ARGS = {
|
|
|
35306
35306
|
},
|
|
35307
35307
|
country: { type: "string", description: "Country of phones written without a +code, e.g. ES" }
|
|
35308
35308
|
};
|
|
35309
|
-
function membersFromArgs(args8, readFile43 = (
|
|
35309
|
+
function membersFromArgs(args8, readFile43 = (path58) => readFileSync2(path58, "utf8")) {
|
|
35310
35310
|
const fromFile = typeof args8.file === "string" && args8.file ? membersFromFile(readFile43(args8.file)) : { emails: [], phones: [] };
|
|
35311
35311
|
const given = [...csvArg(args8.emails) ?? [], ...fromFile.emails];
|
|
35312
35312
|
const givenPhones = [...csvArg(args8.phones) ?? [], ...fromFile.phones];
|
|
@@ -38681,9 +38681,9 @@ var COPY_LIST_FLAG = {
|
|
|
38681
38681
|
descriptions: "--descriptions",
|
|
38682
38682
|
longHeadlines: "--long-headlines"
|
|
38683
38683
|
};
|
|
38684
|
-
function valueAt(root,
|
|
38684
|
+
function valueAt(root, path58) {
|
|
38685
38685
|
let node = root;
|
|
38686
|
-
for (const key of
|
|
38686
|
+
for (const key of path58) {
|
|
38687
38687
|
if (node === null || typeof node !== "object") return void 0;
|
|
38688
38688
|
node = node[key];
|
|
38689
38689
|
}
|
|
@@ -38916,11 +38916,11 @@ function parseKeywordEntry(raw, defaultMatch) {
|
|
|
38916
38916
|
function rawTextEntries(value2, rawArgs) {
|
|
38917
38917
|
return repeatedValues(rawArgs, "text", value2).flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
|
|
38918
38918
|
}
|
|
38919
|
-
function rawFileEntries(
|
|
38920
|
-
if (typeof
|
|
38919
|
+
function rawFileEntries(path58) {
|
|
38920
|
+
if (typeof path58 !== "string" || path58.length === 0) {
|
|
38921
38921
|
return [];
|
|
38922
38922
|
}
|
|
38923
|
-
return readFileSync4(
|
|
38923
|
+
return readFileSync4(path58, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
38924
38924
|
}
|
|
38925
38925
|
function keywordEntries(args8, rawArgs) {
|
|
38926
38926
|
const defaultMatch = typeof args8["match-type"] === "string" ? args8["match-type"].toUpperCase() : void 0;
|
|
@@ -38943,14 +38943,14 @@ function keywordEntries(args8, rawArgs) {
|
|
|
38943
38943
|
}
|
|
38944
38944
|
return entries;
|
|
38945
38945
|
}
|
|
38946
|
-
function loadJsonFileArg(
|
|
38947
|
-
if (typeof
|
|
38946
|
+
function loadJsonFileArg(path58) {
|
|
38947
|
+
if (typeof path58 !== "string" || path58.length === 0) {
|
|
38948
38948
|
return {};
|
|
38949
38949
|
}
|
|
38950
|
-
const inline =
|
|
38951
|
-
const source = inline ? "inline JSON" :
|
|
38950
|
+
const inline = path58.trimStart().startsWith("{");
|
|
38951
|
+
const source = inline ? "inline JSON" : path58;
|
|
38952
38952
|
try {
|
|
38953
|
-
const parsed = JSON.parse(inline ?
|
|
38953
|
+
const parsed = JSON.parse(inline ? path58 : readFileSync4(path58, "utf8"));
|
|
38954
38954
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
38955
38955
|
failWriteValidation2(`${source} must contain a JSON object`);
|
|
38956
38956
|
}
|
|
@@ -39087,10 +39087,10 @@ async function stageUpdate(kind, customerId, target2, payload, hints2) {
|
|
|
39087
39087
|
async function stageTarget(kind, customerId, target2, hints2) {
|
|
39088
39088
|
await stageGoogleOp({ kind, customerId, target: target2 }, hints2);
|
|
39089
39089
|
}
|
|
39090
|
-
async function draftAction(
|
|
39090
|
+
async function draftAction(path58, body, chat) {
|
|
39091
39091
|
try {
|
|
39092
39092
|
const chatId = resolveChatId(chat);
|
|
39093
|
-
const response = await apiPost(
|
|
39093
|
+
const response = await apiPost(path58, { chatId, ...body });
|
|
39094
39094
|
writeJsonEnvelope(response);
|
|
39095
39095
|
} catch (err) {
|
|
39096
39096
|
handleGoogleError(err);
|
|
@@ -41510,14 +41510,14 @@ function mappingRowProblem(row) {
|
|
|
41510
41510
|
|
|
41511
41511
|
// ../api/src/event-sources/template.ts
|
|
41512
41512
|
var MENTION = /\{\{\s*([^{}]+?)\s*\}\}/g;
|
|
41513
|
-
function mentionOf(
|
|
41514
|
-
return `{{${
|
|
41513
|
+
function mentionOf(path58) {
|
|
41514
|
+
return `{{${path58}}}`;
|
|
41515
41515
|
}
|
|
41516
41516
|
function templateMentions(template) {
|
|
41517
41517
|
const seen = [];
|
|
41518
41518
|
for (const match of template.matchAll(MENTION)) {
|
|
41519
|
-
const
|
|
41520
|
-
if (
|
|
41519
|
+
const path58 = (match[1] ?? "").trim();
|
|
41520
|
+
if (path58 !== "" && !seen.includes(path58)) seen.push(path58);
|
|
41521
41521
|
}
|
|
41522
41522
|
return seen;
|
|
41523
41523
|
}
|
|
@@ -44892,17 +44892,17 @@ function ignoredColumnHints(columns) {
|
|
|
44892
44892
|
`Ignored ${columns.length} column(s) that are not part of a conversion: ${columns.join(", ")}. A conversion carries an order id, a date, and something to match on: a click id (gclid / gbraid / wbraid), an email, a phone, or all four of givenName + familyName + country + postalCode. Optionally a value + currency, conversionCount, and eventSource (WEB / APP / IN_STORE / PHONE / OTHER). A column named just \`Name\` is ignored on purpose \u2014 Google needs the first and last name separately, so split it before re-running.`
|
|
44893
44893
|
];
|
|
44894
44894
|
}
|
|
44895
|
-
function readRowsFile(
|
|
44896
|
-
const inline =
|
|
44895
|
+
function readRowsFile(path58) {
|
|
44896
|
+
const inline = path58.trimStart().startsWith("[") || path58.trimStart().startsWith("{");
|
|
44897
44897
|
let text2;
|
|
44898
44898
|
try {
|
|
44899
|
-
text2 = inline ?
|
|
44899
|
+
text2 = inline ? path58 : readFileSync6(path58, "utf8");
|
|
44900
44900
|
} catch (err) {
|
|
44901
|
-
failWriteValidation2(`could not read ${
|
|
44901
|
+
failWriteValidation2(`could not read ${path58}: ${err instanceof Error ? err.message : String(err)}`);
|
|
44902
44902
|
}
|
|
44903
44903
|
const parsed = parseConversionRowsText(text2);
|
|
44904
44904
|
if (!parsed.ok) {
|
|
44905
|
-
failWriteValidation2(`${inline ? "the conversions passed inline" :
|
|
44905
|
+
failWriteValidation2(`${inline ? "the conversions passed inline" : path58}: ${parsed.error}`);
|
|
44906
44906
|
}
|
|
44907
44907
|
return { rows: parsed.rows, ignoredColumns: parsed.ignoredColumns };
|
|
44908
44908
|
}
|
|
@@ -46803,19 +46803,19 @@ function failWriteValidation3(message) {
|
|
|
46803
46803
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
46804
46804
|
process.exit(1);
|
|
46805
46805
|
}
|
|
46806
|
-
function loadJsonFileArg2(
|
|
46807
|
-
if (typeof
|
|
46806
|
+
function loadJsonFileArg2(path58) {
|
|
46807
|
+
if (typeof path58 !== "string" || path58.length === 0) {
|
|
46808
46808
|
return {};
|
|
46809
46809
|
}
|
|
46810
46810
|
try {
|
|
46811
|
-
const parsed = JSON.parse(readFileSync7(
|
|
46811
|
+
const parsed = JSON.parse(readFileSync7(path58, "utf8"));
|
|
46812
46812
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
46813
|
-
failWriteValidation3(`${
|
|
46813
|
+
failWriteValidation3(`${path58} must contain a JSON object`);
|
|
46814
46814
|
}
|
|
46815
46815
|
return parsed;
|
|
46816
46816
|
} catch (err) {
|
|
46817
46817
|
if (err instanceof SyntaxError) {
|
|
46818
|
-
failWriteValidation3(`${
|
|
46818
|
+
failWriteValidation3(`${path58} is not valid JSON: ${err.message}`);
|
|
46819
46819
|
}
|
|
46820
46820
|
throw err;
|
|
46821
46821
|
}
|
|
@@ -46900,15 +46900,15 @@ function parseLocaleFlag(value2) {
|
|
|
46900
46900
|
}
|
|
46901
46901
|
return { language: match[1], country: match[2].toUpperCase() };
|
|
46902
46902
|
}
|
|
46903
|
-
function loadTargetingFileArg(
|
|
46904
|
-
if (typeof
|
|
46903
|
+
function loadTargetingFileArg(path58) {
|
|
46904
|
+
if (typeof path58 !== "string" || path58.length === 0) {
|
|
46905
46905
|
return void 0;
|
|
46906
46906
|
}
|
|
46907
|
-
const parsed = loadJsonFileArg2(
|
|
46907
|
+
const parsed = loadJsonFileArg2(path58);
|
|
46908
46908
|
const criteria = parsed.targetingCriteria ?? parsed;
|
|
46909
46909
|
if (!criteria.include) {
|
|
46910
46910
|
failWriteValidation3(
|
|
46911
|
-
`${
|
|
46911
|
+
`${path58} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
|
|
46912
46912
|
);
|
|
46913
46913
|
}
|
|
46914
46914
|
return criteria;
|
|
@@ -46943,14 +46943,14 @@ function parseCsvLine(line) {
|
|
|
46943
46943
|
cells.push(current);
|
|
46944
46944
|
return cells.map((cell3) => cell3.trim());
|
|
46945
46945
|
}
|
|
46946
|
-
function parseListFileArg(
|
|
46947
|
-
if (typeof
|
|
46946
|
+
function parseListFileArg(path58, maxRows) {
|
|
46947
|
+
if (typeof path58 !== "string" || path58.length === 0) {
|
|
46948
46948
|
return void 0;
|
|
46949
46949
|
}
|
|
46950
|
-
const raw = readFileSync7(
|
|
46950
|
+
const raw = readFileSync7(path58, "utf8");
|
|
46951
46951
|
const lines = raw.split(/\r?\n/).filter((line) => line.trim().length > 0);
|
|
46952
46952
|
if (lines.length < 2) {
|
|
46953
|
-
failWriteValidation3(`${
|
|
46953
|
+
failWriteValidation3(`${path58} needs a header row and at least one data row`);
|
|
46954
46954
|
}
|
|
46955
46955
|
const columns = parseCsvLine(lines[0]).map((column) => column.trim());
|
|
46956
46956
|
const rows = [];
|
|
@@ -46969,7 +46969,7 @@ function parseListFileArg(path59, maxRows) {
|
|
|
46969
46969
|
}
|
|
46970
46970
|
}
|
|
46971
46971
|
if (rows.length > maxRows) {
|
|
46972
|
-
failWriteValidation3(`${
|
|
46972
|
+
failWriteValidation3(`${path58} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
|
|
46973
46973
|
}
|
|
46974
46974
|
return { columns, rows };
|
|
46975
46975
|
}
|
|
@@ -47065,11 +47065,11 @@ function readPositionals(args8) {
|
|
|
47065
47065
|
function splitIdList(raw) {
|
|
47066
47066
|
return raw.split(",").map((id) => id.trim()).filter(Boolean);
|
|
47067
47067
|
}
|
|
47068
|
-
function idsFileEntries(
|
|
47069
|
-
if (typeof
|
|
47068
|
+
function idsFileEntries(path58) {
|
|
47069
|
+
if (typeof path58 !== "string" || path58.length === 0) {
|
|
47070
47070
|
return [];
|
|
47071
47071
|
}
|
|
47072
|
-
return readFileSync7(
|
|
47072
|
+
return readFileSync7(path58, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).flatMap(splitIdList);
|
|
47073
47073
|
}
|
|
47074
47074
|
function requireTargets2(args8, entity) {
|
|
47075
47075
|
const positionals = readPositionals(args8);
|
|
@@ -49830,9 +49830,9 @@ import { defineCommand as defineCommand64 } from "citty";
|
|
|
49830
49830
|
function asRecord(value2) {
|
|
49831
49831
|
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2) ? value2 : void 0;
|
|
49832
49832
|
}
|
|
49833
|
-
function readPath2(row,
|
|
49833
|
+
function readPath2(row, path58) {
|
|
49834
49834
|
let current = row;
|
|
49835
|
-
for (const segment of
|
|
49835
|
+
for (const segment of path58.split(".")) {
|
|
49836
49836
|
const record = asRecord(current);
|
|
49837
49837
|
if (!record) return void 0;
|
|
49838
49838
|
current = record[segment];
|
|
@@ -49842,10 +49842,10 @@ function readPath2(row, path59) {
|
|
|
49842
49842
|
function projectFields(rows, paths) {
|
|
49843
49843
|
return rows.map((row) => {
|
|
49844
49844
|
const projected = {};
|
|
49845
|
-
for (const
|
|
49846
|
-
const value2 = readPath2(row,
|
|
49845
|
+
for (const path58 of paths) {
|
|
49846
|
+
const value2 = readPath2(row, path58);
|
|
49847
49847
|
if (value2 !== void 0) {
|
|
49848
|
-
projected[
|
|
49848
|
+
projected[path58] = value2;
|
|
49849
49849
|
}
|
|
49850
49850
|
}
|
|
49851
49851
|
return projected;
|
|
@@ -49858,16 +49858,16 @@ function shapeListRows(rows, args8, compact5) {
|
|
|
49858
49858
|
const paths = fields.split(",").map((field) => field.trim()).filter((field) => field.length > 0);
|
|
49859
49859
|
if (paths.length > 0) {
|
|
49860
49860
|
const projected = projectFields(raw, paths).map((row, i) => {
|
|
49861
|
-
const missing = paths.filter((
|
|
49861
|
+
const missing = paths.filter((path58) => row[path58] === void 0);
|
|
49862
49862
|
const source = rows[i];
|
|
49863
49863
|
if (missing.length === 0 || source === void 0) return row;
|
|
49864
49864
|
const compactRow3 = compact5.row(source);
|
|
49865
|
-
for (const
|
|
49866
|
-
if (compactRow3[
|
|
49865
|
+
for (const path58 of missing) {
|
|
49866
|
+
if (compactRow3[path58] !== void 0) row[path58] = compactRow3[path58];
|
|
49867
49867
|
}
|
|
49868
49868
|
return row;
|
|
49869
49869
|
});
|
|
49870
|
-
const unmatched = paths.filter((
|
|
49870
|
+
const unmatched = paths.filter((path58) => projected.every((row) => row[path58] === void 0));
|
|
49871
49871
|
if (projected.length === 0 || unmatched.length === 0) return { rows: projected, fields: paths };
|
|
49872
49872
|
const carried = /* @__PURE__ */ new Set([...compact5.columns, ...raw.flatMap((row) => Object.keys(row))]);
|
|
49873
49873
|
return {
|
|
@@ -51227,54 +51227,54 @@ function ruleFields(node) {
|
|
|
51227
51227
|
([key, value2]) => (key === "and" || key === "or") && Array.isArray(value2) ? value2.flatMap(ruleFields) : [key]
|
|
51228
51228
|
);
|
|
51229
51229
|
}
|
|
51230
|
-
function branchRefusal(key, value2,
|
|
51230
|
+
function branchRefusal(key, value2, path58) {
|
|
51231
51231
|
if (!Array.isArray(value2) || value2.length === 0) {
|
|
51232
|
-
return `${
|
|
51232
|
+
return `${path58}.${key} must be a non-empty array of conditions \u2014 an empty one counts every event the pixel sends`;
|
|
51233
51233
|
}
|
|
51234
51234
|
for (const [index, child] of value2.entries()) {
|
|
51235
|
-
const refusal = ruleNodeRefusal(child, `${
|
|
51235
|
+
const refusal = ruleNodeRefusal(child, `${path58}.${key}[${index}]`);
|
|
51236
51236
|
if (refusal) {
|
|
51237
51237
|
return refusal;
|
|
51238
51238
|
}
|
|
51239
51239
|
}
|
|
51240
51240
|
return void 0;
|
|
51241
51241
|
}
|
|
51242
|
-
function conditionRefusal(key, value2,
|
|
51243
|
-
return key === "and" || key === "or" ? branchRefusal(key, value2,
|
|
51242
|
+
function conditionRefusal(key, value2, path58) {
|
|
51243
|
+
return key === "and" || key === "or" ? branchRefusal(key, value2, path58) : leafRefusal(key, value2, path58);
|
|
51244
51244
|
}
|
|
51245
|
-
function ruleNodeRefusal(node,
|
|
51245
|
+
function ruleNodeRefusal(node, path58) {
|
|
51246
51246
|
if (!isRecord2(node)) {
|
|
51247
|
-
return `${
|
|
51247
|
+
return `${path58} must be an object like {"URL":{"i_contains":"/thank-you"}}`;
|
|
51248
51248
|
}
|
|
51249
51249
|
const entries = Object.entries(node);
|
|
51250
51250
|
if (entries.length === 0) {
|
|
51251
|
-
return `${
|
|
51251
|
+
return `${path58} is empty \u2014 a rule with no condition counts every event the pixel sends`;
|
|
51252
51252
|
}
|
|
51253
51253
|
if (entries.length > 1) {
|
|
51254
|
-
return `${
|
|
51254
|
+
return `${path58} names ${entries.length} conditions side by side (${entries.map(([key]) => key).join(", ")}) \u2014 Meta reads one branch or one field test per object, so combine them with {"and":[\u2026]}`;
|
|
51255
51255
|
}
|
|
51256
51256
|
for (const [key, value2] of entries) {
|
|
51257
|
-
const refusal = conditionRefusal(key, value2,
|
|
51257
|
+
const refusal = conditionRefusal(key, value2, path58);
|
|
51258
51258
|
if (refusal) {
|
|
51259
51259
|
return refusal;
|
|
51260
51260
|
}
|
|
51261
51261
|
}
|
|
51262
51262
|
return void 0;
|
|
51263
51263
|
}
|
|
51264
|
-
function leafRefusal(field, condition,
|
|
51264
|
+
function leafRefusal(field, condition, path58) {
|
|
51265
51265
|
if (!isRecord2(condition)) {
|
|
51266
|
-
return `${
|
|
51266
|
+
return `${path58}.${field} must be a test like {"i_contains":"/thank-you"}, not a bare value`;
|
|
51267
51267
|
}
|
|
51268
51268
|
const tests = Object.entries(condition);
|
|
51269
51269
|
if (tests.length === 0) {
|
|
51270
|
-
return `${
|
|
51270
|
+
return `${path58}.${field} names no test \u2014 use one of ${Object.keys(RULE_OPERATORS).join(", ")}`;
|
|
51271
51271
|
}
|
|
51272
51272
|
if (tests.length > 1) {
|
|
51273
|
-
return `${
|
|
51273
|
+
return `${path58}.${field} names ${tests.length} operators at once (${tests.map(([operator]) => operator).join(", ")}) \u2014 test a field once per condition and combine them with {"and":[\u2026]}`;
|
|
51274
51274
|
}
|
|
51275
51275
|
for (const [operator] of tests) {
|
|
51276
51276
|
if (!RULE_OPERATORS[operator]) {
|
|
51277
|
-
return `${
|
|
51277
|
+
return `${path58}.${field} uses "${operator}", which is not a Meta rule operator \u2014 use one of ${Object.keys(RULE_OPERATORS).join(", ")} (URL matching is i_contains, not contains or includes)`;
|
|
51278
51278
|
}
|
|
51279
51279
|
}
|
|
51280
51280
|
return void 0;
|
|
@@ -51990,11 +51990,11 @@ var updateStatusSchema2 = z45.enum(UPDATE_STATUSES);
|
|
|
51990
51990
|
function currencyMinimums2(currencyCode) {
|
|
51991
51991
|
return CURRENCY_MINIMUMS2[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM2;
|
|
51992
51992
|
}
|
|
51993
|
-
function validateDailyBudgetFloor(money, ctx,
|
|
51993
|
+
function validateDailyBudgetFloor(money, ctx, path58) {
|
|
51994
51994
|
if (money?.currencyCode) {
|
|
51995
51995
|
const min = currencyMinimums2(money.currencyCode).dailyBudgetMin;
|
|
51996
51996
|
if (Number(money.amount) < min) {
|
|
51997
|
-
ctx.addIssue({ code: "custom", path:
|
|
51997
|
+
ctx.addIssue({ code: "custom", path: path58, message: `below the ${min} ${money.currencyCode} daily minimum` });
|
|
51998
51998
|
}
|
|
51999
51999
|
}
|
|
52000
52000
|
}
|
|
@@ -52912,19 +52912,19 @@ function refuseDeleteByUpdate(payload, group) {
|
|
|
52912
52912
|
);
|
|
52913
52913
|
}
|
|
52914
52914
|
}
|
|
52915
|
-
function loadJsonFileArg3(
|
|
52916
|
-
if (typeof
|
|
52915
|
+
function loadJsonFileArg3(path58) {
|
|
52916
|
+
if (typeof path58 !== "string" || path58.length === 0) {
|
|
52917
52917
|
return {};
|
|
52918
52918
|
}
|
|
52919
52919
|
try {
|
|
52920
|
-
const parsed = JSON.parse(readFileSync11(
|
|
52920
|
+
const parsed = JSON.parse(readFileSync11(path58, "utf8"));
|
|
52921
52921
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
52922
|
-
failWriteValidation4(`${
|
|
52922
|
+
failWriteValidation4(`${path58} must contain a JSON object`);
|
|
52923
52923
|
}
|
|
52924
52924
|
return parsed;
|
|
52925
52925
|
} catch (err) {
|
|
52926
52926
|
if (err instanceof SyntaxError) {
|
|
52927
|
-
failWriteValidation4(`${
|
|
52927
|
+
failWriteValidation4(`${path58} is not valid JSON: ${err.message}`);
|
|
52928
52928
|
}
|
|
52929
52929
|
throw err;
|
|
52930
52930
|
}
|
|
@@ -58695,12 +58695,12 @@ function flowExists(slug) {
|
|
|
58695
58695
|
return existsSync3(join2(flowsDir(), slug, "_data.json"));
|
|
58696
58696
|
}
|
|
58697
58697
|
function readFlowTree(slug) {
|
|
58698
|
-
const
|
|
58699
|
-
if (!existsSync3(
|
|
58698
|
+
const path58 = join2(flowsDir(), slug, "_data.json");
|
|
58699
|
+
if (!existsSync3(path58)) {
|
|
58700
58700
|
failLocal(`No form "${slug}". Run "baker flows list" to see the forms in this workspace.`);
|
|
58701
58701
|
}
|
|
58702
58702
|
try {
|
|
58703
|
-
return JSON.parse(readFileSync13(
|
|
58703
|
+
return JSON.parse(readFileSync13(path58, "utf-8"));
|
|
58704
58704
|
} catch (error) {
|
|
58705
58705
|
failLocal(`Could not read form "${slug}": ${error instanceof Error ? error.message : String(error)}`);
|
|
58706
58706
|
}
|
|
@@ -59660,12 +59660,12 @@ function readPeopleFile(args8) {
|
|
|
59660
59660
|
}
|
|
59661
59661
|
function unreadablePeopleFile(args8) {
|
|
59662
59662
|
if (!args8["people-file"]) return void 0;
|
|
59663
|
-
const
|
|
59663
|
+
const path58 = String(args8["people-file"]);
|
|
59664
59664
|
try {
|
|
59665
|
-
readFileSync14(
|
|
59665
|
+
readFileSync14(path58, "utf8");
|
|
59666
59666
|
return void 0;
|
|
59667
59667
|
} catch {
|
|
59668
|
-
return `Couldn't read --people-file ${
|
|
59668
|
+
return `Couldn't read --people-file ${path58}. Check the path, or pass the people inline with --person.`;
|
|
59669
59669
|
}
|
|
59670
59670
|
}
|
|
59671
59671
|
function peopleLimitError(args8) {
|
|
@@ -60637,11 +60637,11 @@ function parseFieldArgs(argv) {
|
|
|
60637
60637
|
for (const pair of parseRepeated(argv, "--field")) {
|
|
60638
60638
|
const eq = pair.indexOf("=");
|
|
60639
60639
|
const field = eq === -1 ? pair : pair.slice(0, eq);
|
|
60640
|
-
const
|
|
60640
|
+
const path58 = eq === -1 ? "" : pair.slice(eq + 1).trim();
|
|
60641
60641
|
const problem = mappingRowProblem(field);
|
|
60642
60642
|
if (problem !== null) throw new ConversionArgsError(problem);
|
|
60643
|
-
if (
|
|
60644
|
-
mapping[field] =
|
|
60643
|
+
if (path58 === "") throw new ConversionArgsError(`--field ${field} needs a path: --field ${field}=<dotted.path>.`);
|
|
60644
|
+
mapping[field] = path58;
|
|
60645
60645
|
}
|
|
60646
60646
|
return mapping;
|
|
60647
60647
|
}
|
|
@@ -62243,11 +62243,11 @@ function unwrap(response) {
|
|
|
62243
62243
|
}
|
|
62244
62244
|
return response.data;
|
|
62245
62245
|
}
|
|
62246
|
-
async function readAvatars(
|
|
62247
|
-
return unwrap(await apiGet(
|
|
62246
|
+
async function readAvatars(path58, params) {
|
|
62247
|
+
return unwrap(await apiGet(path58, params));
|
|
62248
62248
|
}
|
|
62249
|
-
async function writeAvatars(
|
|
62250
|
-
return unwrap(await apiPost(
|
|
62249
|
+
async function writeAvatars(path58, body) {
|
|
62250
|
+
return unwrap(await apiPost(path58, body));
|
|
62251
62251
|
}
|
|
62252
62252
|
|
|
62253
62253
|
// src/commands/avatars/create.ts
|
|
@@ -63156,12 +63156,12 @@ function missingFontFiles(urls, available) {
|
|
|
63156
63156
|
function planFontAdoption(sources, families) {
|
|
63157
63157
|
const wanted = new Map(families.map((family) => [normalizeFamily(family), family]));
|
|
63158
63158
|
const byFamily = /* @__PURE__ */ new Map();
|
|
63159
|
-
for (const { path:
|
|
63160
|
-
const dir = posix.dirname(
|
|
63159
|
+
for (const { path: path58, source } of sources) {
|
|
63160
|
+
const dir = posix.dirname(path58);
|
|
63161
63161
|
for (const face of declaredFontFaces(source)) {
|
|
63162
63162
|
if (!wanted.has(face.family)) continue;
|
|
63163
63163
|
const perFile = byFamily.get(face.family) ?? /* @__PURE__ */ new Map();
|
|
63164
|
-
perFile.set(
|
|
63164
|
+
perFile.set(path58, [...perFile.get(path58) ?? [], rebaseFontFaceSrc(face.block, dir)]);
|
|
63165
63165
|
byFamily.set(face.family, perFile);
|
|
63166
63166
|
}
|
|
63167
63167
|
}
|
|
@@ -68168,8 +68168,8 @@ function relayPrompt(args8) {
|
|
|
68168
68168
|
...args8.exclusionsLast ? ["", EXCLUSIONS] : []
|
|
68169
68169
|
].join("\n");
|
|
68170
68170
|
}
|
|
68171
|
-
function ingestNode(id,
|
|
68172
|
-
return { id, type: "ingest", params: { source: "path", path:
|
|
68171
|
+
function ingestNode(id, path58, expect) {
|
|
68172
|
+
return { id, type: "ingest", params: { source: "path", path: path58, expect } };
|
|
68173
68173
|
}
|
|
68174
68174
|
function annotateBlueprintWithLabels(blueprintInput, elementsInput) {
|
|
68175
68175
|
if (!blueprintInput || typeof blueprintInput !== "object") return blueprintInput;
|
|
@@ -68424,8 +68424,7 @@ function fontLabel(font) {
|
|
|
68424
68424
|
const origin = {
|
|
68425
68425
|
brand_file: "the brand's font file",
|
|
68426
68426
|
tokens: "named in tokens.json, loaded as a web font",
|
|
68427
|
-
brand_md: "named in BRAND.md, loaded as a web font"
|
|
68428
|
-
default: "the default, since the brand names no typeface"
|
|
68427
|
+
brand_md: "named in BRAND.md, loaded as a web font"
|
|
68429
68428
|
};
|
|
68430
68429
|
const name = font.family ?? ("path" in font.slot ? font.slot.path.split("/").pop() ?? font.slot.path : "a web font");
|
|
68431
68430
|
return `${name} (${origin[font.origin]})`;
|
|
@@ -71547,7 +71546,7 @@ var rerunCommand = defineCommand132({
|
|
|
71547
71546
|
|
|
71548
71547
|
// src/commands/canvas/scaffold-static-ad.ts
|
|
71549
71548
|
import { mkdir as mkdir8, readFile as readFile24, writeFile as writeFile12 } from "fs/promises";
|
|
71550
|
-
import
|
|
71549
|
+
import path30 from "path";
|
|
71551
71550
|
import { defineCommand as defineCommand134 } from "citty";
|
|
71552
71551
|
|
|
71553
71552
|
// src/commands/canvas/creative-limit.ts
|
|
@@ -71609,7 +71608,7 @@ import path26 from "path";
|
|
|
71609
71608
|
|
|
71610
71609
|
// src/engine/scaffold/static-fonts.ts
|
|
71611
71610
|
import { marked } from "marked";
|
|
71612
|
-
var
|
|
71611
|
+
var HEADLINE_WEIGHT = 800;
|
|
71613
71612
|
var HEADLINE_WORDS = /\b(headings?|headlines?|display|titles?|h[1-3])\b/i;
|
|
71614
71613
|
var BODY_WORDS = /\b(body|paragraphs?|text|copy)\b/i;
|
|
71615
71614
|
var PROHIBITION = /\b(never|don'?t|do not|avoid|instead of|ban(?:ned)?|no)\b/i;
|
|
@@ -71713,7 +71712,7 @@ async function brandHeadlineFont(args8) {
|
|
|
71713
71712
|
if (args8.file) return fileFace(args8.file);
|
|
71714
71713
|
const named = args8.named.headline ?? args8.named.body;
|
|
71715
71714
|
if (!named) return null;
|
|
71716
|
-
const url = await args8.resolveUrl(named.family,
|
|
71715
|
+
const url = await args8.resolveUrl(named.family, HEADLINE_WEIGHT);
|
|
71717
71716
|
return url ? { slot: { url }, family: named.family, origin: named.origin } : null;
|
|
71718
71717
|
}
|
|
71719
71718
|
|
|
@@ -71886,7 +71885,6 @@ function fileExists(target2) {
|
|
|
71886
71885
|
}
|
|
71887
71886
|
|
|
71888
71887
|
// src/commands/canvas/creative-definition.ts
|
|
71889
|
-
import path28 from "path";
|
|
71890
71888
|
import { parseDocument as parseDocument2 } from "yaml";
|
|
71891
71889
|
var PLATFORM_VALUES = ["meta", "google", "linkedin", "tiktok", "youtube", "x", "other"];
|
|
71892
71890
|
var FORMAT_VALUES = ["1:1", "4:5", "9:16", "16:9", "1.91:1"];
|
|
@@ -71951,16 +71949,16 @@ function parseDefinitionSourceFields(raw) {
|
|
|
71951
71949
|
}
|
|
71952
71950
|
|
|
71953
71951
|
// src/commands/canvas/scaffold-static-ad-paths.ts
|
|
71954
|
-
import
|
|
71952
|
+
import path28 from "path";
|
|
71955
71953
|
function resolveScaffoldStaticAdPaths(rawFile, out, cwd = process.cwd(), slug) {
|
|
71956
71954
|
const file = rawFile.trim();
|
|
71957
71955
|
const imageIsUrl = /^https?:\/\//i.test(file);
|
|
71958
|
-
const imageSource = imageIsUrl ? file :
|
|
71959
|
-
const outPath = out ?
|
|
71960
|
-
const blueprintPath2 =
|
|
71961
|
-
const creativeDir = slug ?
|
|
71962
|
-
const definitionPath = creativeDir ?
|
|
71963
|
-
const referencesDir = creativeDir ?
|
|
71956
|
+
const imageSource = imageIsUrl ? file : path28.resolve(cwd, file);
|
|
71957
|
+
const outPath = out ? path28.resolve(cwd, out) : slug ? path28.join(cwd, "src", "creatives", slug, `${slug}.canvas.json`) : imageIsUrl ? path28.join(cwd, "static-ad.canvas.json") : path28.join(path28.dirname(imageSource), "static-ad.canvas.json");
|
|
71958
|
+
const blueprintPath2 = path28.join(path28.dirname(outPath), "prompt.json");
|
|
71959
|
+
const creativeDir = slug ? path28.dirname(outPath) : null;
|
|
71960
|
+
const definitionPath = creativeDir ? path28.join(creativeDir, "_definition.md") : null;
|
|
71961
|
+
const referencesDir = creativeDir ? path28.join(creativeDir, "references") : null;
|
|
71964
71962
|
return { imageIsUrl, imageSource, outPath, blueprintPath: blueprintPath2, creativeDir, definitionPath, referencesDir };
|
|
71965
71963
|
}
|
|
71966
71964
|
var SCAFFOLD_SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
|
|
@@ -71971,7 +71969,7 @@ function isValidScaffoldSlug(slug) {
|
|
|
71971
71969
|
|
|
71972
71970
|
// src/commands/canvas/sync-definition.ts
|
|
71973
71971
|
import { readdir as readdir11, readFile as readFile23, stat as stat4 } from "fs/promises";
|
|
71974
|
-
import
|
|
71972
|
+
import path29 from "path";
|
|
71975
71973
|
import { defineCommand as defineCommand133 } from "citty";
|
|
71976
71974
|
|
|
71977
71975
|
// src/commands/canvas/definition-graph.ts
|
|
@@ -72028,7 +72026,7 @@ function buildDefinitionSyncPayload(input, graph, chatId) {
|
|
|
72028
72026
|
}
|
|
72029
72027
|
async function readDefinitionSourceFields(canvasPath) {
|
|
72030
72028
|
try {
|
|
72031
|
-
return parseDefinitionSourceFields(await readFile23(
|
|
72029
|
+
return parseDefinitionSourceFields(await readFile23(path29.join(path29.dirname(canvasPath), "_definition.md"), "utf8"));
|
|
72032
72030
|
} catch {
|
|
72033
72031
|
return {};
|
|
72034
72032
|
}
|
|
@@ -72051,15 +72049,15 @@ async function syncCreativeDefinitionBestEffort(input) {
|
|
|
72051
72049
|
}
|
|
72052
72050
|
}
|
|
72053
72051
|
async function resolveCanvasPath(inputPath) {
|
|
72054
|
-
const resolved =
|
|
72052
|
+
const resolved = path29.resolve(inputPath);
|
|
72055
72053
|
let dir = resolved;
|
|
72056
72054
|
try {
|
|
72057
72055
|
if ((await stat4(resolved)).isFile()) {
|
|
72058
72056
|
if (resolved.endsWith(".canvas.json")) return resolved;
|
|
72059
|
-
dir =
|
|
72057
|
+
dir = path29.dirname(resolved);
|
|
72060
72058
|
}
|
|
72061
72059
|
} catch {
|
|
72062
|
-
dir = resolved.endsWith(".canvas.json") ?
|
|
72060
|
+
dir = resolved.endsWith(".canvas.json") ? path29.dirname(resolved) : resolved;
|
|
72063
72061
|
}
|
|
72064
72062
|
let entries;
|
|
72065
72063
|
try {
|
|
@@ -72070,7 +72068,7 @@ async function resolveCanvasPath(inputPath) {
|
|
|
72070
72068
|
const canvases = entries.filter((name) => name.endsWith(".canvas.json"));
|
|
72071
72069
|
const slug = creativeSlugFromCanvasPath(`${dir}/x/`);
|
|
72072
72070
|
const chosen = (slug ? canvases.find((name) => name === `${slug}.canvas.json`) : void 0) ?? canvases[0];
|
|
72073
|
-
return chosen ?
|
|
72071
|
+
return chosen ? path29.join(dir, chosen) : null;
|
|
72074
72072
|
}
|
|
72075
72073
|
var syncDefinitionCommand = defineCommand133({
|
|
72076
72074
|
meta: {
|
|
@@ -72246,7 +72244,7 @@ function mergeReferenceIntoBlueprint(blueprint, reference) {
|
|
|
72246
72244
|
|
|
72247
72245
|
// src/commands/canvas/scaffold-static-ad.ts
|
|
72248
72246
|
function toCanvasRelative2(canvasDir, file) {
|
|
72249
|
-
const rel =
|
|
72247
|
+
const rel = path30.relative(canvasDir, file).split(path30.sep).join("/");
|
|
72250
72248
|
return rel.startsWith(".") ? rel : `./${rel}`;
|
|
72251
72249
|
}
|
|
72252
72250
|
async function uploadSourceAsReference(source, isUrl, client) {
|
|
@@ -72559,7 +72557,7 @@ var scaffoldStaticAdCommand = defineCommand134({
|
|
|
72559
72557
|
}
|
|
72560
72558
|
const { imageIsUrl, imageSource, outPath, blueprintPath: blueprintPath2, definitionPath, referencesDir } = resolveScaffoldStaticAdPaths(sourceFile, args8.out ? String(args8.out) : void 0, process.cwd(), slug);
|
|
72561
72559
|
if (slug) await enforceNewCreativeLimit(slug, outPath);
|
|
72562
|
-
await mkdir8(
|
|
72560
|
+
await mkdir8(path30.dirname(outPath), { recursive: true });
|
|
72563
72561
|
let models;
|
|
72564
72562
|
try {
|
|
72565
72563
|
models = resolveModels(args8);
|
|
@@ -72592,7 +72590,7 @@ var scaffoldStaticAdCommand = defineCommand134({
|
|
|
72592
72590
|
const blueprint = mergeReferenceIntoBlueprint(vision.blueprint, reference);
|
|
72593
72591
|
const elements = castAvatarsOnStaticElements(vision.elements, cast.avatars);
|
|
72594
72592
|
const uncast = staticAvatarsNotCast(vision.elements, cast.handles);
|
|
72595
|
-
const canvasDir =
|
|
72593
|
+
const canvasDir = path30.dirname(outPath);
|
|
72596
72594
|
const workspaceRoot = await findBrandRoot(canvasDir) ?? process.cwd();
|
|
72597
72595
|
const kit = await readStaticBrandKit(workspaceRoot);
|
|
72598
72596
|
const annotated = annotateBlueprintWithLabels(blueprint, elements);
|
|
@@ -72640,7 +72638,7 @@ var scaffoldStaticAdCommand = defineCommand134({
|
|
|
72640
72638
|
} catch (e) {
|
|
72641
72639
|
return fail4("scaffold", e instanceof Error ? e.message : String(e));
|
|
72642
72640
|
}
|
|
72643
|
-
const validation = await validateScaffoldedStaticAd(canvas,
|
|
72641
|
+
const validation = await validateScaffoldedStaticAd(canvas, path30.dirname(outPath));
|
|
72644
72642
|
if (validation.blocking.length > 0) {
|
|
72645
72643
|
process.stderr.write(
|
|
72646
72644
|
`${JSON.stringify({ ok: false, error: { code: "validation", issues: validation.blocking } }, null, 2)}
|
|
@@ -72729,7 +72727,7 @@ var scaffoldStaticAdCommand = defineCommand134({
|
|
|
72729
72727
|
run_estimated_credits: validation.estimatedCredits
|
|
72730
72728
|
},
|
|
72731
72729
|
checklist: {
|
|
72732
|
-
edit_prompt: `Edit ${
|
|
72730
|
+
edit_prompt: `Edit ${path30.basename(blueprintPath2)} \u2014 it is the blueprint generated from your image; rewrite it into the ad you want (palette, copy, claims, subjects). It feeds the generator directly.${reference ? " Its `reference` block is the library's read of the source ad (container, layout, mechanism, offer, text blocks): keep it as the account of why the ad won, and rebuild it for our brand." : ""}`,
|
|
72733
72731
|
winning_mechanisms: report.winning_mechanisms,
|
|
72734
72732
|
rebuild_the_mechanism: "`winning_mechanisms` is WHY the source ad works. Rewrite each one for our brand in prompt.json (a rhyme stays a rhyme in our words, a before/after stays a before/after of our product); never copy the source's literal copy.",
|
|
72735
72733
|
assets_to_supply: report.elements,
|
|
@@ -72791,7 +72789,7 @@ function clientLogoMissNote(decision, domain) {
|
|
|
72791
72789
|
|
|
72792
72790
|
// src/commands/canvas/scaffold-ad.ts
|
|
72793
72791
|
import { copyFile, cp, mkdir as mkdir9, readFile as readFile26, stat as stat5, writeFile as writeFile14 } from "fs/promises";
|
|
72794
|
-
import
|
|
72792
|
+
import path32 from "path";
|
|
72795
72793
|
import { defineCommand as defineCommand135 } from "citty";
|
|
72796
72794
|
|
|
72797
72795
|
// src/engine/scaffold/ad-spec.ts
|
|
@@ -73506,7 +73504,7 @@ function injectAdBrandOverlay(indexHtml, overlayHtml, style = {}) {
|
|
|
73506
73504
|
|
|
73507
73505
|
// src/commands/canvas/composition-dims.ts
|
|
73508
73506
|
import { readFile as readFile25, writeFile as writeFile13 } from "fs/promises";
|
|
73509
|
-
import
|
|
73507
|
+
import path31 from "path";
|
|
73510
73508
|
function patchCompositionMeta(metaJson, dims) {
|
|
73511
73509
|
try {
|
|
73512
73510
|
const meta = JSON.parse(metaJson);
|
|
@@ -73521,10 +73519,10 @@ function patchCompositionHtml(html, dims) {
|
|
|
73521
73519
|
return html.replace(/(<meta\s+name="viewport"\s+content="width=)\d+(,\s*height=)\d+(")/i, `$1${dims.w}$2${dims.h}$3`).replace(/(width:\s*)\d+(px;\s*height:\s*)\d+(px;)/i, `$1${dims.w}$2${dims.h}$3`).replace(/(data-width=")\d+(")/i, `$1${dims.w}$2`).replace(/(data-height=")\d+(")/i, `$1${dims.h}$2`);
|
|
73522
73520
|
}
|
|
73523
73521
|
async function stampCompositionDims(compositionDir, dims) {
|
|
73524
|
-
const metaPath =
|
|
73522
|
+
const metaPath = path31.join(compositionDir, "meta.json");
|
|
73525
73523
|
const rawMeta = await readFile25(metaPath, "utf8");
|
|
73526
73524
|
await writeFile13(metaPath, patchCompositionMeta(rawMeta, dims), "utf8");
|
|
73527
|
-
const htmlPath =
|
|
73525
|
+
const htmlPath = path31.join(compositionDir, "index.html");
|
|
73528
73526
|
const rawHtml = await readFile25(htmlPath, "utf8");
|
|
73529
73527
|
await writeFile13(htmlPath, patchCompositionHtml(rawHtml, dims), "utf8");
|
|
73530
73528
|
}
|
|
@@ -73821,8 +73819,8 @@ var scaffoldAdCommand = defineCommand135({
|
|
|
73821
73819
|
videoModel: chosenVideoModel,
|
|
73822
73820
|
...avatarVoice ? { avatarVoice } : {}
|
|
73823
73821
|
});
|
|
73824
|
-
const slug = args8.slug ??
|
|
73825
|
-
const outPath = args8.out ?? (args8.slug ?
|
|
73822
|
+
const slug = args8.slug ?? path32.basename(specPath).replace(/\.[^.]+$/, "");
|
|
73823
|
+
const outPath = args8.out ?? (args8.slug ? path32.join("src/creatives", slug, `${slug}.canvas.json`) : path32.join(path32.dirname(specPath), `${slug}.canvas.json`));
|
|
73826
73824
|
if (args8.slug) await enforceNewCreativeLimit(slug, outPath);
|
|
73827
73825
|
let outAr;
|
|
73828
73826
|
try {
|
|
@@ -73840,28 +73838,28 @@ var scaffoldAdCommand = defineCommand135({
|
|
|
73840
73838
|
return;
|
|
73841
73839
|
}
|
|
73842
73840
|
const outDims = canvasDims(outAr);
|
|
73843
|
-
const outDir =
|
|
73841
|
+
const outDir = path32.dirname(outPath);
|
|
73844
73842
|
await mkdir9(outDir, { recursive: true });
|
|
73845
|
-
const compositionDest =
|
|
73846
|
-
const captionsDest =
|
|
73843
|
+
const compositionDest = path32.join(outDir, "video-overlay-composition");
|
|
73844
|
+
const captionsDest = path32.join(outDir, "tiktok-captions-composition");
|
|
73847
73845
|
await cp(SHIPPED_OVERLAY_COMPOSITION_DIR, compositionDest, { recursive: true });
|
|
73848
73846
|
await cp(SHIPPED_CAPTIONS_DIR, captionsDest, { recursive: true });
|
|
73849
73847
|
await stampCompositionDims(compositionDest, outDims);
|
|
73850
73848
|
await stampCompositionDims(captionsDest, outDims);
|
|
73851
|
-
const captionsIndex =
|
|
73849
|
+
const captionsIndex = path32.join(captionsDest, "index.html");
|
|
73852
73850
|
await writeFile14(captionsIndex, injectAdCaptionPlacement(await readFile26(captionsIndex, "utf-8"), outAr), "utf-8");
|
|
73853
73851
|
const face = await stageBrandDisplayFace(outDir, captionsDest);
|
|
73854
73852
|
if (face) {
|
|
73855
73853
|
await writeFile14(captionsIndex, injectAdDisplayFace(await readFile26(captionsIndex, "utf-8"), face.file), "utf-8");
|
|
73856
73854
|
}
|
|
73857
|
-
const blueprintPath2 =
|
|
73858
|
-
const blueprintStylePath =
|
|
73855
|
+
const blueprintPath2 = path32.join(outDir, "prompt.json");
|
|
73856
|
+
const blueprintStylePath = path32.join(outDir, "prompt.style.json");
|
|
73859
73857
|
await writeSceneFiles(outDir, blueprint);
|
|
73860
73858
|
await writeFile14(blueprintStylePath, renderStyleProjectionFromValue(blueprint), "utf8");
|
|
73861
|
-
await writeFile14(
|
|
73859
|
+
await writeFile14(path32.join(outDir, AD_SPEC_FILE), `${JSON.stringify(specArtifact, null, 2)}
|
|
73862
73860
|
`, "utf8");
|
|
73863
73861
|
const logoPath = noBrand ? void 0 : spec.data.brand?.logo?.trim();
|
|
73864
|
-
const transcriptPath =
|
|
73862
|
+
const transcriptPath = path32.join(outDir, "transcript.json");
|
|
73865
73863
|
if (spec.data.voiceover === false) {
|
|
73866
73864
|
await writeFile14(transcriptPath, `${JSON.stringify(staticTranscript(spec.data, chosenVideoModel), null, 2)}
|
|
73867
73865
|
`, "utf-8");
|
|
@@ -73873,10 +73871,10 @@ var scaffoldAdCommand = defineCommand135({
|
|
|
73873
73871
|
// that stops the whole canvas. The same sheet model every other scaffold uses.
|
|
73874
73872
|
sheetModel: ACTOR_SHEET_MODEL,
|
|
73875
73873
|
videoModel: chosenVideoModel,
|
|
73876
|
-
overlayCompositionPath:
|
|
73877
|
-
captionsCompositionPath:
|
|
73878
|
-
blueprintPath:
|
|
73879
|
-
blueprintStylePath:
|
|
73874
|
+
overlayCompositionPath: path32.relative(outDir, compositionDest),
|
|
73875
|
+
captionsCompositionPath: path32.relative(outDir, captionsDest),
|
|
73876
|
+
blueprintPath: path32.relative(outDir, blueprintPath2),
|
|
73877
|
+
blueprintStylePath: path32.relative(outDir, blueprintStylePath),
|
|
73880
73878
|
aspect: spec.data.format.aspect_ratio,
|
|
73881
73879
|
resolution: spec.data.format.resolution,
|
|
73882
73880
|
// A beat is one clause and one card, so the cap has to clear a whole clause.
|
|
@@ -73915,17 +73913,17 @@ var scaffoldAdCommand = defineCommand135({
|
|
|
73915
73913
|
// the stock voice this exists to avoid. It is to convert the LATER extracts onto the
|
|
73916
73914
|
// first beat of the same speaker, which keeps a voice the clip really produced.
|
|
73917
73915
|
...avatar ? { keepRenderedVoice: true } : {},
|
|
73918
|
-
...spec.data.voiceover === false ? { staticTranscriptPath:
|
|
73916
|
+
...spec.data.voiceover === false ? { staticTranscriptPath: path32.relative(outDir, transcriptPath) } : {}
|
|
73919
73917
|
};
|
|
73920
73918
|
const canvas = scaffoldVideoCanvas(blueprint, adSpecCastElements(spec.data, avatar), opts);
|
|
73921
73919
|
const renderNode5 = canvas.nodes.find((n) => n.type === "hyperframe_render");
|
|
73922
|
-
const renderedDir = renderNode5 ?
|
|
73920
|
+
const renderedDir = renderNode5 ? path32.join(outDir, String(renderNode5.params?.composition ?? "")) : null;
|
|
73923
73921
|
let staged = null;
|
|
73924
73922
|
let markIsLight = false;
|
|
73925
73923
|
if (logoPath && renderedDir) {
|
|
73926
|
-
const ext =
|
|
73924
|
+
const ext = path32.extname(logoPath) || ".png";
|
|
73927
73925
|
try {
|
|
73928
|
-
await copyFile(logoPath,
|
|
73926
|
+
await copyFile(logoPath, path32.join(renderedDir, `brand-mark${ext}`));
|
|
73929
73927
|
staged = { file: `brand-mark${ext}`, alt: spec.data.brand?.name ?? "brand" };
|
|
73930
73928
|
markIsLight = await markInkIsLight(logoPath);
|
|
73931
73929
|
} catch {
|
|
@@ -73944,12 +73942,12 @@ var scaffoldAdCommand = defineCommand135({
|
|
|
73944
73942
|
plateIsDark: plateIsDark(spec.data.brand?.palette)
|
|
73945
73943
|
}) : "";
|
|
73946
73944
|
if (overlayHtml && renderedDir) {
|
|
73947
|
-
const indexPath =
|
|
73945
|
+
const indexPath = path32.join(renderedDir, "index.html");
|
|
73948
73946
|
const html = await readFile26(indexPath, "utf-8");
|
|
73949
73947
|
await writeFile14(indexPath, injectAdBrandOverlay(html, overlayHtml, { aspect: outAr, ...face ? { face: AD_DISPLAY_FAMILY } : {} }), "utf-8");
|
|
73950
73948
|
}
|
|
73951
73949
|
await writeFile14(
|
|
73952
|
-
|
|
73950
|
+
path32.join(outDir, REBUILD_FILE),
|
|
73953
73951
|
`${JSON.stringify({ elements: adSpecCastElements(spec.data, avatar), opts }, null, 2)}
|
|
73954
73952
|
`,
|
|
73955
73953
|
"utf8"
|
|
@@ -73979,7 +73977,7 @@ var scaffoldAdCommand = defineCommand135({
|
|
|
73979
73977
|
return;
|
|
73980
73978
|
}
|
|
73981
73979
|
if (args8.slug) {
|
|
73982
|
-
const definitionPath =
|
|
73980
|
+
const definitionPath = path32.join(outDir, "_definition.md");
|
|
73983
73981
|
const definitionExists = await stat5(definitionPath).then(() => true, () => false);
|
|
73984
73982
|
if (!definitionExists) {
|
|
73985
73983
|
await writeFile14(
|
|
@@ -74097,9 +74095,9 @@ async function fetchClientLogo() {
|
|
|
74097
74095
|
if (!response.ok) return { ok: false, reason: clientLogoMissNote({ use: false, reason: "no_hits" }, domain) };
|
|
74098
74096
|
const bytes = Buffer.from(await response.arrayBuffer());
|
|
74099
74097
|
const extension = /\.(svg|png|jpg|jpeg|webp)(?:\?|$)/i.exec(decision.url)?.[1]?.toLowerCase() ?? "svg";
|
|
74100
|
-
const dir =
|
|
74098
|
+
const dir = path32.join(BRAND_DIR, "logos");
|
|
74101
74099
|
await mkdir9(dir, { recursive: true });
|
|
74102
|
-
const file =
|
|
74100
|
+
const file = path32.join(dir, `brand-mark.${extension}`);
|
|
74103
74101
|
await writeFile14(file, bytes);
|
|
74104
74102
|
return { ok: true, path: file };
|
|
74105
74103
|
} catch {
|
|
@@ -74118,14 +74116,14 @@ async function stageBrandDisplayFace(outDir, compositionDir) {
|
|
|
74118
74116
|
if (!face) return null;
|
|
74119
74117
|
try {
|
|
74120
74118
|
if ("path" in face.slot) {
|
|
74121
|
-
const file2 = `brand-face${
|
|
74122
|
-
await copyFile(face.slot.path,
|
|
74123
|
-
return { file: file2, label: `the font file \`${
|
|
74119
|
+
const file2 = `brand-face${path32.extname(face.slot.path).toLowerCase()}`;
|
|
74120
|
+
await copyFile(face.slot.path, path32.join(compositionDir, file2));
|
|
74121
|
+
return { file: file2, label: `the font file \`${path32.relative(root, face.slot.path)}\`` };
|
|
74124
74122
|
}
|
|
74125
74123
|
const { buffer } = await fetchExternalBytes(face.slot.url, { maxBytes: MAX_FONT_BYTES });
|
|
74126
74124
|
const extension = /\.(woff2|woff|ttf|otf)(?:\?|$)/i.exec(face.slot.url)?.[1]?.toLowerCase() ?? "woff2";
|
|
74127
74125
|
const file = `brand-face.${extension}`;
|
|
74128
|
-
await writeFile14(
|
|
74126
|
+
await writeFile14(path32.join(compositionDir, file), buffer);
|
|
74129
74127
|
return { file, label: `${face.family ?? "the brand's typeface"}, loaded as a web font` };
|
|
74130
74128
|
} catch {
|
|
74131
74129
|
return null;
|
|
@@ -74135,7 +74133,7 @@ async function stageBrandDisplayFace(outDir, compositionDir) {
|
|
|
74135
74133
|
// src/commands/canvas/scaffold-video.ts
|
|
74136
74134
|
import { cp as cp2, mkdir as mkdir10, readFile as readFile29, rm as rm8, writeFile as writeFile15 } from "fs/promises";
|
|
74137
74135
|
import { tmpdir as tmpdir3 } from "os";
|
|
74138
|
-
import
|
|
74136
|
+
import path34 from "path";
|
|
74139
74137
|
import { defineCommand as defineCommand136 } from "citty";
|
|
74140
74138
|
|
|
74141
74139
|
// src/engine/scaffold/lib/model-router.ts
|
|
@@ -74276,7 +74274,7 @@ async function detectSceneCutsPySceneDetect(filePath, opts = {}) {
|
|
|
74276
74274
|
|
|
74277
74275
|
// src/commands/canvas/gitignore.ts
|
|
74278
74276
|
import { appendFile, readFile as readFile28 } from "fs/promises";
|
|
74279
|
-
import
|
|
74277
|
+
import path33 from "path";
|
|
74280
74278
|
function missingGitignoreEntries(existing, entries) {
|
|
74281
74279
|
const present2 = new Set(
|
|
74282
74280
|
existing.split("\n").map((l) => l.trim().replace(/\/+$/, "")).filter((l) => l.length > 0 && !l.startsWith("#"))
|
|
@@ -74284,7 +74282,7 @@ function missingGitignoreEntries(existing, entries) {
|
|
|
74284
74282
|
return entries.filter((e) => !present2.has(e.trim().replace(/\/+$/, "")));
|
|
74285
74283
|
}
|
|
74286
74284
|
async function ensureGitignore(dir, entries) {
|
|
74287
|
-
const file =
|
|
74285
|
+
const file = path33.join(dir, ".gitignore");
|
|
74288
74286
|
let existing;
|
|
74289
74287
|
try {
|
|
74290
74288
|
existing = await readFile28(file, "utf8");
|
|
@@ -74329,7 +74327,7 @@ async function loadTranscriptBestEffort(ref2) {
|
|
|
74329
74327
|
async function stageCaptions(outDir, transcript) {
|
|
74330
74328
|
const text2 = transcript?.trim();
|
|
74331
74329
|
if (!text2 || text2 === "[]") return {};
|
|
74332
|
-
const compositionPath =
|
|
74330
|
+
const compositionPath = path34.join(outDir, "tiktok-captions-composition");
|
|
74333
74331
|
await cp2(SHIPPED_CAPTIONS_DIR, compositionPath, { recursive: true });
|
|
74334
74332
|
return { compositionPath };
|
|
74335
74333
|
}
|
|
@@ -74365,7 +74363,7 @@ var VIDEO_EXT_BY_MIME = {
|
|
|
74365
74363
|
"video/x-matroska": ".mkv"
|
|
74366
74364
|
};
|
|
74367
74365
|
function referenceVideoExt(url, contentType) {
|
|
74368
|
-
const fromPath =
|
|
74366
|
+
const fromPath = path34.extname(new URL(url).pathname).toLowerCase();
|
|
74369
74367
|
if (fromPath && fromPath.length <= 5) return fromPath;
|
|
74370
74368
|
const mime = (contentType ?? "").split(";")[0]?.trim().toLowerCase();
|
|
74371
74369
|
return mime && VIDEO_EXT_BY_MIME[mime] || ".mp4";
|
|
@@ -74391,7 +74389,7 @@ function framesModeReport(canvas, requested) {
|
|
|
74391
74389
|
return { frames_mode: mode, ...refused ? { frames_reuse_refused: refused } : {} };
|
|
74392
74390
|
}
|
|
74393
74391
|
async function materializeReferenceVideo(fileArg2) {
|
|
74394
|
-
if (!/^https?:\/\//i.test(fileArg2)) return
|
|
74392
|
+
if (!/^https?:\/\//i.test(fileArg2)) return path34.resolve(fileArg2);
|
|
74395
74393
|
let bytes;
|
|
74396
74394
|
let contentType;
|
|
74397
74395
|
try {
|
|
@@ -74403,7 +74401,7 @@ async function materializeReferenceVideo(fileArg2) {
|
|
|
74403
74401
|
throw new Error(`failed to download reference video: ${e instanceof Error ? e.message : String(e)}`);
|
|
74404
74402
|
}
|
|
74405
74403
|
if (bytes.length === 0) throw new Error("reference video download was empty");
|
|
74406
|
-
const dest =
|
|
74404
|
+
const dest = path34.join(
|
|
74407
74405
|
tmpdir3(),
|
|
74408
74406
|
`baker-ref-${sha256Hex(bytes).slice(0, 16)}${referenceVideoExt(fileArg2, contentType)}`
|
|
74409
74407
|
);
|
|
@@ -74630,12 +74628,12 @@ var scaffoldVideoCommand = defineCommand136({
|
|
|
74630
74628
|
} catch (e) {
|
|
74631
74629
|
return fail4("download", e instanceof Error ? e.message : String(e));
|
|
74632
74630
|
}
|
|
74633
|
-
const base =
|
|
74634
|
-
const outPath = args8.out ?
|
|
74631
|
+
const base = path34.basename(videoPath, path34.extname(videoPath));
|
|
74632
|
+
const outPath = args8.out ? path34.resolve(String(args8.out)) : slug ? path34.join(process.cwd(), "src", "creatives", slug, `${slug}.canvas.json`) : path34.join(path34.dirname(videoPath), `${base}.video.canvas.json`);
|
|
74635
74633
|
if (slug) await enforceNewCreativeLimit(slug, outPath);
|
|
74636
|
-
const outDir =
|
|
74637
|
-
const blueprintPath2 =
|
|
74638
|
-
const blueprintStylePath =
|
|
74634
|
+
const outDir = path34.dirname(outPath);
|
|
74635
|
+
const blueprintPath2 = path34.join(outDir, "prompt.json");
|
|
74636
|
+
const blueprintStylePath = path34.join(outDir, "prompt.style.json");
|
|
74639
74637
|
const frames = args8.frames === "reuse" ? "reuse" : "generate";
|
|
74640
74638
|
const maxScenes = args8["max-scenes"] ? Number(args8["max-scenes"]) : void 0;
|
|
74641
74639
|
if (Number.isFinite(maxScenes)) {
|
|
@@ -74704,10 +74702,10 @@ var scaffoldVideoCommand = defineCommand136({
|
|
|
74704
74702
|
`
|
|
74705
74703
|
);
|
|
74706
74704
|
}
|
|
74707
|
-
const compositionDest =
|
|
74705
|
+
const compositionDest = path34.join(outDir, "video-overlay-composition");
|
|
74708
74706
|
await cp2(SHIPPED_OVERLAY_COMPOSITION_DIR, compositionDest, { recursive: true });
|
|
74709
74707
|
await stampCompositionDims(compositionDest, outDims);
|
|
74710
|
-
const indexPath =
|
|
74708
|
+
const indexPath = path34.join(compositionDest, "index.html");
|
|
74711
74709
|
const overlayHtml = buildOverlayHtml(blueprint, { captionsActive: Boolean(transcript), videoModel });
|
|
74712
74710
|
const indexHtml = await readFile29(indexPath, "utf8");
|
|
74713
74711
|
const injected = indexHtml.replace("<!--OVERLAYS-->", () => overlayHtml);
|
|
@@ -74723,10 +74721,10 @@ var scaffoldVideoCommand = defineCommand136({
|
|
|
74723
74721
|
const opts = {
|
|
74724
74722
|
imageModel,
|
|
74725
74723
|
videoModel,
|
|
74726
|
-
overlayCompositionPath:
|
|
74727
|
-
captionsCompositionPath: captions.compositionPath ?
|
|
74728
|
-
blueprintPath:
|
|
74729
|
-
blueprintStylePath:
|
|
74724
|
+
overlayCompositionPath: path34.relative(outDir, compositionDest),
|
|
74725
|
+
captionsCompositionPath: captions.compositionPath ? path34.relative(outDir, captions.compositionPath) : void 0,
|
|
74726
|
+
blueprintPath: path34.relative(outDir, blueprintPath2),
|
|
74727
|
+
blueprintStylePath: path34.relative(outDir, blueprintStylePath),
|
|
74730
74728
|
frames,
|
|
74731
74729
|
ambient: Boolean(args8.ambient),
|
|
74732
74730
|
seamDedup: resolveSeamDedup(args8["seam-dedup"]),
|
|
@@ -74754,7 +74752,7 @@ var scaffoldVideoCommand = defineCommand136({
|
|
|
74754
74752
|
await writeFile15(outPath, `${JSON.stringify(canvas, null, 2)}
|
|
74755
74753
|
`, "utf8");
|
|
74756
74754
|
await writeFile15(
|
|
74757
|
-
|
|
74755
|
+
path34.join(outDir, REBUILD_FILE),
|
|
74758
74756
|
`${JSON.stringify({ elements, opts }, null, 2)}
|
|
74759
74757
|
`,
|
|
74760
74758
|
"utf8"
|
|
@@ -74781,7 +74779,7 @@ var scaffoldVideoCommand = defineCommand136({
|
|
|
74781
74779
|
await ensureGitignore(process.cwd(), ["canvas/", ".context/"]);
|
|
74782
74780
|
const sourceRef = videoSourceReference(blueprint, fileArg2);
|
|
74783
74781
|
if (slug) {
|
|
74784
|
-
const definitionPath =
|
|
74782
|
+
const definitionPath = path34.join(outDir, "_definition.md");
|
|
74785
74783
|
if (!await fileExists(definitionPath)) {
|
|
74786
74784
|
await writeFile15(
|
|
74787
74785
|
definitionPath,
|
|
@@ -74837,7 +74835,7 @@ var scaffoldVideoCommand = defineCommand136({
|
|
|
74837
74835
|
graph: canvas.metadata?.video?.graph_stats
|
|
74838
74836
|
},
|
|
74839
74837
|
checklist: {
|
|
74840
|
-
edit_prompt: `The blueprint is split so you edit ONE small file at a time \u2014 never a giant one. Per-scene content (a scene's dialogue, action, frame prompts, overlays) lives in \`scenes/sNN.json\` \u2014 edit the single scene you want to change. Global cast/palette/brand/copy lives in \`${
|
|
74838
|
+
edit_prompt: `The blueprint is split so you edit ONE small file at a time \u2014 never a giant one. Per-scene content (a scene's dialogue, action, frame prompts, overlays) lives in \`scenes/sNN.json\` \u2014 edit the single scene you want to change. Global cast/palette/brand/copy lives in \`${path34.basename(blueprintPath2)}\`. \`baker canvas validate\`/\`run\` re-assemble the blueprint and re-flow every edited scene back into the render (and regenerate ${path34.basename(blueprintStylePath)}, the projection each frame's target_blueprint reads) \u2014 so your scene edits reach the render automatically. Never hand-edit the inlined node prompts in the canvas or the derived ${path34.basename(blueprintStylePath)}; both are regenerated.`,
|
|
74841
74839
|
recurring_elements_to_supply: report.elements,
|
|
74842
74840
|
voices_to_confirm: report.dialogue.map((d) => ({
|
|
74843
74841
|
scene: d.scene,
|
|
@@ -74875,7 +74873,7 @@ var scaffoldVideoCommand = defineCommand136({
|
|
|
74875
74873
|
|
|
74876
74874
|
// src/commands/canvas/set-prompt.ts
|
|
74877
74875
|
import { readFile as readFile30, writeFile as writeFile16 } from "fs/promises";
|
|
74878
|
-
import
|
|
74876
|
+
import path35 from "path";
|
|
74879
74877
|
import { defineCommand as defineCommand137 } from "citty";
|
|
74880
74878
|
function setNodePrompt(canvas, nodeId, text2) {
|
|
74881
74879
|
const nodes = canvas?.nodes;
|
|
@@ -74904,7 +74902,7 @@ var SetPromptError = class extends Error {
|
|
|
74904
74902
|
}
|
|
74905
74903
|
};
|
|
74906
74904
|
async function setPromptInCanvasFile(canvasPath, nodeId, text2) {
|
|
74907
|
-
const filePath =
|
|
74905
|
+
const filePath = path35.resolve(canvasPath);
|
|
74908
74906
|
const original = await readFile30(filePath, "utf8");
|
|
74909
74907
|
let canvas;
|
|
74910
74908
|
try {
|
|
@@ -74972,7 +74970,7 @@ var setPromptCommand = defineCommand137({
|
|
|
74972
74970
|
},
|
|
74973
74971
|
async run({ args: args8 }) {
|
|
74974
74972
|
let text2;
|
|
74975
|
-
if (args8["text-file"]) text2 = await readFile30(
|
|
74973
|
+
if (args8["text-file"]) text2 = await readFile30(path35.resolve(String(args8["text-file"])), "utf8");
|
|
74976
74974
|
else if (args8.text !== void 0) text2 = String(args8.text);
|
|
74977
74975
|
else {
|
|
74978
74976
|
process.stderr.write(
|
|
@@ -75029,7 +75027,7 @@ var staleCommand = defineCommand138({
|
|
|
75029
75027
|
});
|
|
75030
75028
|
|
|
75031
75029
|
// src/commands/canvas/validate.ts
|
|
75032
|
-
import
|
|
75030
|
+
import path36 from "path";
|
|
75033
75031
|
import { defineCommand as defineCommand139 } from "citty";
|
|
75034
75032
|
var validateCommand = defineCommand139({
|
|
75035
75033
|
meta: {
|
|
@@ -75038,7 +75036,7 @@ var validateCommand = defineCommand139({
|
|
|
75038
75036
|
},
|
|
75039
75037
|
args: { file: { type: "positional", required: true, description: "Path to canvas JSON" } },
|
|
75040
75038
|
async run({ args: args8 }) {
|
|
75041
|
-
const filePath =
|
|
75039
|
+
const filePath = path36.resolve(String(args8.file));
|
|
75042
75040
|
let prepared;
|
|
75043
75041
|
try {
|
|
75044
75042
|
prepared = await prepareCanvas(filePath, { log: (line) => process.stderr.write(`${line}
|
|
@@ -75600,7 +75598,7 @@ var feedbackCommand = defineCommand144({
|
|
|
75600
75598
|
|
|
75601
75599
|
// src/commands/creatives/performance.ts
|
|
75602
75600
|
import { readFileSync as readFileSync16 } from "fs";
|
|
75603
|
-
import
|
|
75601
|
+
import path37 from "path";
|
|
75604
75602
|
import { defineCommand as defineCommand145 } from "citty";
|
|
75605
75603
|
import { parse as parseYaml2 } from "yaml";
|
|
75606
75604
|
var DESCRIPTION4 = `How each Baker creative is doing in the live Meta ads that show it: spend, impressions, CTR, CPC, results, cost per result, frequency and a fatigue verdict, next to the angle, hook, mechanism and dominant slot its definition set out to test. Video creatives add hookRate (percent of impressions that watched 3 seconds) and holdRate (percent of those that reached a ThruPlay). Use it before briefing new creatives, to learn which angle and mechanism to make next and which creatives to replace.
|
|
@@ -75653,7 +75651,7 @@ function definitionInsights(markdown) {
|
|
|
75653
75651
|
}
|
|
75654
75652
|
function readLocalDefinition(slug) {
|
|
75655
75653
|
try {
|
|
75656
|
-
return readFileSync16(
|
|
75654
|
+
return readFileSync16(path37.join(process.cwd(), "src", "creatives", slug, "_definition.md"), "utf8");
|
|
75657
75655
|
} catch {
|
|
75658
75656
|
return null;
|
|
75659
75657
|
}
|
|
@@ -76213,11 +76211,11 @@ import { defineCommand as defineCommand149 } from "citty";
|
|
|
76213
76211
|
|
|
76214
76212
|
// src/commands/experiment/composition.ts
|
|
76215
76213
|
import { readdir as readdir14, readFile as readFile34 } from "fs/promises";
|
|
76216
|
-
import
|
|
76214
|
+
import path39 from "path";
|
|
76217
76215
|
|
|
76218
76216
|
// src/commands/landing/import-graph.ts
|
|
76219
76217
|
import { readdir as readdir13, readFile as readFile33, stat as stat6 } from "fs/promises";
|
|
76220
|
-
import
|
|
76218
|
+
import path38 from "path";
|
|
76221
76219
|
var SOURCE_EXT = /\.(astro|ts|tsx|js|jsx|mjs|cjs|vue|svelte)$/;
|
|
76222
76220
|
var RESOLVE_CANDIDATES = [
|
|
76223
76221
|
"",
|
|
@@ -76250,7 +76248,7 @@ async function walkFiles(dir) {
|
|
|
76250
76248
|
}
|
|
76251
76249
|
const out = [];
|
|
76252
76250
|
for (const entry of entries) {
|
|
76253
|
-
const full =
|
|
76251
|
+
const full = path38.join(dir, entry.name);
|
|
76254
76252
|
if (entry.isDirectory()) {
|
|
76255
76253
|
if (entry.name === "node_modules" || entry.name === "dist") continue;
|
|
76256
76254
|
out.push(...await walkFiles(full));
|
|
@@ -76264,8 +76262,8 @@ async function resolveSpecifier(specifier, fromFile, root) {
|
|
|
76264
76262
|
const bare = specifier.split("?")[0] ?? "";
|
|
76265
76263
|
if (bare.includes("*")) return null;
|
|
76266
76264
|
let base;
|
|
76267
|
-
if (bare.startsWith("/")) base =
|
|
76268
|
-
else if (bare.startsWith(".")) base =
|
|
76265
|
+
if (bare.startsWith("/")) base = path38.join(root, bare.slice(1));
|
|
76266
|
+
else if (bare.startsWith(".")) base = path38.resolve(path38.dirname(fromFile), bare);
|
|
76269
76267
|
else return null;
|
|
76270
76268
|
for (const suffix of RESOLVE_CANDIDATES) {
|
|
76271
76269
|
const candidate = base + suffix;
|
|
@@ -76287,7 +76285,7 @@ async function importedFiles(text2, file, root) {
|
|
|
76287
76285
|
}
|
|
76288
76286
|
async function landingGraphFiles(root, slug) {
|
|
76289
76287
|
const seen = /* @__PURE__ */ new Set();
|
|
76290
|
-
const queue = await walkFiles(
|
|
76288
|
+
const queue = await walkFiles(path38.join(root, "src/pages", slug));
|
|
76291
76289
|
while (queue.length > 0) {
|
|
76292
76290
|
const file = queue.pop();
|
|
76293
76291
|
if (file === void 0 || seen.has(file)) continue;
|
|
@@ -76302,7 +76300,7 @@ async function landingGraphFiles(root, slug) {
|
|
|
76302
76300
|
if (!seen.has(target2)) queue.push(target2);
|
|
76303
76301
|
}
|
|
76304
76302
|
}
|
|
76305
|
-
return new Set([...seen].map((abs) =>
|
|
76303
|
+
return new Set([...seen].map((abs) => path38.relative(root, abs).split(path38.sep).join("/")));
|
|
76306
76304
|
}
|
|
76307
76305
|
|
|
76308
76306
|
// src/commands/experiment/composition.ts
|
|
@@ -76347,7 +76345,7 @@ function formsOnlyIn(these, those) {
|
|
|
76347
76345
|
}
|
|
76348
76346
|
async function knownFlows(root) {
|
|
76349
76347
|
try {
|
|
76350
|
-
const entries = await readdir14(
|
|
76348
|
+
const entries = await readdir14(path39.join(root, "src/lib/flow-engine/flows"), { withFileTypes: true });
|
|
76351
76349
|
return new Set(entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name));
|
|
76352
76350
|
} catch {
|
|
76353
76351
|
return /* @__PURE__ */ new Set();
|
|
@@ -76358,7 +76356,7 @@ async function readForms(root, slug) {
|
|
|
76358
76356
|
const [files, flows] = await Promise.all([landingGraphFiles(root, slug), knownFlows(root)]);
|
|
76359
76357
|
if (flows.size === 0) return [];
|
|
76360
76358
|
const texts = await Promise.all(
|
|
76361
|
-
[...files].filter((file) => /\.(astro|ts|tsx|js|mjs)$/.test(file)).map((file) => readFile34(
|
|
76359
|
+
[...files].filter((file) => /\.(astro|ts|tsx|js|mjs)$/.test(file)).map((file) => readFile34(path39.join(root, file), "utf8"))
|
|
76362
76360
|
);
|
|
76363
76361
|
return formsReferenced(texts, flows);
|
|
76364
76362
|
} catch {
|
|
@@ -76369,7 +76367,7 @@ async function readForms(root, slug) {
|
|
|
76369
76367
|
// src/commands/experiment/fold.ts
|
|
76370
76368
|
import { statSync } from "fs";
|
|
76371
76369
|
import { cp as cp3, mkdir as mkdir11, readdir as readdir15, readFile as readFile35, rm as rm9, stat as stat7, writeFile as writeFile17 } from "fs/promises";
|
|
76372
|
-
import
|
|
76370
|
+
import path41 from "path";
|
|
76373
76371
|
|
|
76374
76372
|
// ../api/src/experiments/variants.ts
|
|
76375
76373
|
var VARIANT_SEPARATOR = "--";
|
|
@@ -76394,21 +76392,21 @@ function nextVariantNumber(page, existingSlugs, archived) {
|
|
|
76394
76392
|
}
|
|
76395
76393
|
|
|
76396
76394
|
// src/commands/landing/repoint.ts
|
|
76397
|
-
import
|
|
76395
|
+
import path40 from "path";
|
|
76398
76396
|
var QUOTED_RELATIVE = /(['"])(\.\.?\/[^'"]*)\1/g;
|
|
76399
76397
|
function isInside3(abs, dir) {
|
|
76400
|
-
return abs === dir || abs.startsWith(dir +
|
|
76398
|
+
return abs === dir || abs.startsWith(dir + path40.sep);
|
|
76401
76399
|
}
|
|
76402
76400
|
function toSpecifier(from, to) {
|
|
76403
|
-
const rel =
|
|
76401
|
+
const rel = path40.relative(from, to).split(path40.sep).join("/");
|
|
76404
76402
|
return rel.startsWith(".") ? rel : `./${rel}`;
|
|
76405
76403
|
}
|
|
76406
76404
|
function repointSpecifier(spec, opts) {
|
|
76407
76405
|
if (!spec.startsWith(".")) return spec;
|
|
76408
|
-
const abs =
|
|
76406
|
+
const abs = path40.resolve(opts.fromDir, spec);
|
|
76409
76407
|
if (opts.forkedTargets?.has(abs)) {
|
|
76410
|
-
const withinControl =
|
|
76411
|
-
return toSpecifier(opts.toDir,
|
|
76408
|
+
const withinControl = path40.relative(opts.controlDir, abs);
|
|
76409
|
+
return toSpecifier(opts.toDir, path40.resolve(opts.variantDir, withinControl));
|
|
76412
76410
|
}
|
|
76413
76411
|
if (!isInside3(abs, opts.controlDir)) return spec;
|
|
76414
76412
|
return toSpecifier(opts.toDir, abs);
|
|
@@ -76420,9 +76418,9 @@ function repointFile(text2, opts) {
|
|
|
76420
76418
|
}
|
|
76421
76419
|
function repointMoved(text2, opts) {
|
|
76422
76420
|
return text2.replace(QUOTED_RELATIVE, (_match, quote, spec) => {
|
|
76423
|
-
const abs =
|
|
76424
|
-
const within =
|
|
76425
|
-
const target2 = within.startsWith("..") ||
|
|
76421
|
+
const abs = path40.resolve(opts.fromDir, spec);
|
|
76422
|
+
const within = path40.relative(opts.movedFrom, abs);
|
|
76423
|
+
const target2 = within.startsWith("..") || path40.isAbsolute(within) ? abs : path40.resolve(opts.movedTo, within);
|
|
76426
76424
|
return `${quote}${toSpecifier(opts.toDir, target2)}${quote}`;
|
|
76427
76425
|
});
|
|
76428
76426
|
}
|
|
@@ -76431,7 +76429,7 @@ function repointMoved(text2, opts) {
|
|
|
76431
76429
|
var ARCHIVE_ROOT = "src/_variants";
|
|
76432
76430
|
var QUOTED_RELATIVE2 = /(['"])(\.\.?\/[^'"]*)\1/g;
|
|
76433
76431
|
function posix2(p) {
|
|
76434
|
-
return p.split(
|
|
76432
|
+
return p.split(path41.sep).join("/");
|
|
76435
76433
|
}
|
|
76436
76434
|
async function isDir(p) {
|
|
76437
76435
|
try {
|
|
@@ -76450,39 +76448,39 @@ async function filesUnder(dir, prefix = "") {
|
|
|
76450
76448
|
const out = [];
|
|
76451
76449
|
for (const entry of entries) {
|
|
76452
76450
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
76453
|
-
if (entry.isDirectory()) out.push(...await filesUnder(
|
|
76451
|
+
if (entry.isDirectory()) out.push(...await filesUnder(path41.join(dir, entry.name), rel));
|
|
76454
76452
|
else out.push(rel);
|
|
76455
76453
|
}
|
|
76456
76454
|
return out.sort();
|
|
76457
76455
|
}
|
|
76458
76456
|
var TEXT_EXT = /\.(astro|ts|tsx|js|jsx|mjs|cjs|vue|svelte|md|json|css)$/;
|
|
76459
76457
|
function archiveRelPath(abs, base) {
|
|
76460
|
-
if (!abs.startsWith(base +
|
|
76461
|
-
return posix2(
|
|
76458
|
+
if (!abs.startsWith(base + path41.sep)) return null;
|
|
76459
|
+
return posix2(path41.relative(base, abs));
|
|
76462
76460
|
}
|
|
76463
76461
|
async function archiveArm(opts) {
|
|
76464
76462
|
const { root, armDir, pageDir, archiveDir, armSlug } = opts;
|
|
76465
76463
|
const targets = await archiveContents({ root, armDir, pageDir, armSlug });
|
|
76466
|
-
const archivedBySource = new Map([...targets].map(([rel, abs]) => [abs,
|
|
76464
|
+
const archivedBySource = new Map([...targets].map(([rel, abs]) => [abs, path41.join(archiveDir, rel)]));
|
|
76467
76465
|
const written = [];
|
|
76468
76466
|
for (const [rel, abs] of [...targets].sort()) {
|
|
76469
|
-
const dest =
|
|
76470
|
-
await mkdir11(
|
|
76467
|
+
const dest = path41.join(archiveDir, rel);
|
|
76468
|
+
await mkdir11(path41.dirname(dest), { recursive: true });
|
|
76471
76469
|
if (!TEXT_EXT.test(rel)) {
|
|
76472
76470
|
await cp3(abs, dest);
|
|
76473
76471
|
} else {
|
|
76474
76472
|
const text2 = await readFile35(abs, "utf8");
|
|
76475
76473
|
await writeFile17(dest, repointIntoArchive(text2, abs, dest, archivedBySource), "utf8");
|
|
76476
76474
|
}
|
|
76477
|
-
written.push(posix2(
|
|
76475
|
+
written.push(posix2(path41.relative(root, dest)));
|
|
76478
76476
|
}
|
|
76479
76477
|
return written;
|
|
76480
76478
|
}
|
|
76481
76479
|
async function archiveContents(opts) {
|
|
76482
76480
|
const { root, armDir, pageDir, armSlug } = opts;
|
|
76483
76481
|
const graph = await landingGraphFiles(root, armSlug);
|
|
76484
|
-
const reachable = new Set([...graph].map((rel) =>
|
|
76485
|
-
for (const rel of await filesUnder(armDir)) reachable.add(
|
|
76482
|
+
const reachable = new Set([...graph].map((rel) => path41.resolve(root, rel)));
|
|
76483
|
+
for (const rel of await filesUnder(armDir)) reachable.add(path41.join(armDir, rel));
|
|
76486
76484
|
const sorted = [...reachable].sort();
|
|
76487
76485
|
const targets = /* @__PURE__ */ new Map();
|
|
76488
76486
|
for (const base of [pageDir, armDir]) {
|
|
@@ -76495,14 +76493,14 @@ async function archiveContents(opts) {
|
|
|
76495
76493
|
return targets;
|
|
76496
76494
|
}
|
|
76497
76495
|
function repointIntoArchive(text2, sourceAbs, destAbs, archivedBySource) {
|
|
76498
|
-
const fromDir =
|
|
76499
|
-
const toDir =
|
|
76496
|
+
const fromDir = path41.dirname(sourceAbs);
|
|
76497
|
+
const toDir = path41.dirname(destAbs);
|
|
76500
76498
|
return text2.replace(QUOTED_RELATIVE2, (match, quote, spec, offset) => {
|
|
76501
76499
|
const [specPath, suffix] = splitSuffix(spec);
|
|
76502
|
-
const target2 =
|
|
76500
|
+
const target2 = path41.resolve(fromDir, specPath);
|
|
76503
76501
|
const resolved = resolveInArchive(target2, archivedBySource) ?? resolveOnDisk(target2, isImportPosition(text2, offset));
|
|
76504
76502
|
if (resolved === null) return match;
|
|
76505
|
-
const rel = posix2(
|
|
76503
|
+
const rel = posix2(path41.relative(toDir, resolved));
|
|
76506
76504
|
return `${quote}${rel.startsWith(".") ? rel : `./${rel}`}${suffix}${quote}`;
|
|
76507
76505
|
});
|
|
76508
76506
|
}
|
|
@@ -76536,9 +76534,9 @@ async function promoteVariantFiles(opts) {
|
|
|
76536
76534
|
const written = [];
|
|
76537
76535
|
for (const rel of await filesUnder(variantDir)) {
|
|
76538
76536
|
if (rel === "_definition.md") continue;
|
|
76539
|
-
const from =
|
|
76540
|
-
const to =
|
|
76541
|
-
await mkdir11(
|
|
76537
|
+
const from = path41.join(variantDir, rel);
|
|
76538
|
+
const to = path41.join(pageDir, rel);
|
|
76539
|
+
await mkdir11(path41.dirname(to), { recursive: true });
|
|
76542
76540
|
if (!TEXT_EXT.test(rel)) {
|
|
76543
76541
|
await cp3(from, to);
|
|
76544
76542
|
} else {
|
|
@@ -76546,15 +76544,15 @@ async function promoteVariantFiles(opts) {
|
|
|
76546
76544
|
await writeFile17(
|
|
76547
76545
|
to,
|
|
76548
76546
|
repointMoved(text2, {
|
|
76549
|
-
fromDir:
|
|
76550
|
-
toDir:
|
|
76547
|
+
fromDir: path41.dirname(from),
|
|
76548
|
+
toDir: path41.dirname(to),
|
|
76551
76549
|
movedFrom: variantDir,
|
|
76552
76550
|
movedTo: pageDir
|
|
76553
76551
|
}),
|
|
76554
76552
|
"utf8"
|
|
76555
76553
|
);
|
|
76556
76554
|
}
|
|
76557
|
-
written.push(posix2(
|
|
76555
|
+
written.push(posix2(path41.relative(root, to)));
|
|
76558
76556
|
}
|
|
76559
76557
|
return written;
|
|
76560
76558
|
}
|
|
@@ -76578,8 +76576,8 @@ function archiveRecord(target2, variantNumber) {
|
|
|
76578
76576
|
`;
|
|
76579
76577
|
}
|
|
76580
76578
|
async function foldExperiment(root, target2) {
|
|
76581
|
-
const pageDir =
|
|
76582
|
-
const variantDir =
|
|
76579
|
+
const pageDir = path41.resolve(root, "src/pages", target2.landingSlug);
|
|
76580
|
+
const variantDir = path41.resolve(root, "src/pages", target2.variantSlug);
|
|
76583
76581
|
const variantNumber = variantNumberOf(target2.variantSlug);
|
|
76584
76582
|
if (variantNumber === null) {
|
|
76585
76583
|
return {
|
|
@@ -76593,7 +76591,7 @@ async function foldExperiment(root, target2) {
|
|
|
76593
76591
|
return { error: `src/pages/${target2.variantSlug}/ is already gone \u2014 this test looks folded in already` };
|
|
76594
76592
|
}
|
|
76595
76593
|
const archiveKey = target2.landingInternalId ?? target2.landingSlug;
|
|
76596
|
-
const archiveDir =
|
|
76594
|
+
const archiveDir = path41.resolve(root, ARCHIVE_ROOT, archiveKey, String(variantNumber));
|
|
76597
76595
|
await rm9(archiveDir, { recursive: true, force: true });
|
|
76598
76596
|
await mkdir11(archiveDir, { recursive: true });
|
|
76599
76597
|
const written = await archiveArm({
|
|
@@ -76603,8 +76601,8 @@ async function foldExperiment(root, target2) {
|
|
|
76603
76601
|
archiveDir,
|
|
76604
76602
|
armSlug: target2.survivor === "variant" ? target2.landingSlug : target2.variantSlug
|
|
76605
76603
|
});
|
|
76606
|
-
await writeFile17(
|
|
76607
|
-
written.push(posix2(
|
|
76604
|
+
await writeFile17(path41.join(archiveDir, "_variant.json"), archiveRecord(target2, variantNumber), "utf8");
|
|
76605
|
+
written.push(posix2(path41.join(ARCHIVE_ROOT, archiveKey, String(variantNumber), "_variant.json")));
|
|
76608
76606
|
if (target2.survivor === "variant") {
|
|
76609
76607
|
written.push(...await promoteVariantFiles({ root, pageDir, variantDir }));
|
|
76610
76608
|
}
|
|
@@ -76612,7 +76610,7 @@ async function foldExperiment(root, target2) {
|
|
|
76612
76610
|
return {
|
|
76613
76611
|
experimentId: target2.experimentId,
|
|
76614
76612
|
page: target2.landingSlug,
|
|
76615
|
-
archivedTo: posix2(
|
|
76613
|
+
archivedTo: posix2(path41.join(ARCHIVE_ROOT, archiveKey, String(variantNumber))),
|
|
76616
76614
|
written,
|
|
76617
76615
|
removed: [`src/pages/${target2.variantSlug}`]
|
|
76618
76616
|
};
|
|
@@ -77385,10 +77383,10 @@ function parseEvidence(raw, rawArgs) {
|
|
|
77385
77383
|
|
|
77386
77384
|
// src/commands/experiment/identity.ts
|
|
77387
77385
|
import { readFile as readFile36 } from "fs/promises";
|
|
77388
|
-
import
|
|
77386
|
+
import path42 from "path";
|
|
77389
77387
|
async function readPageInternalId(root, slug) {
|
|
77390
77388
|
try {
|
|
77391
|
-
const text2 = await readFile36(
|
|
77389
|
+
const text2 = await readFile36(path42.resolve(root, "src", "pages", slug, "_definition.md"), "utf8");
|
|
77392
77390
|
return /^internalId:\s*"?([^"\s]+)"?\s*$/m.exec(text2)?.[1];
|
|
77393
77391
|
} catch {
|
|
77394
77392
|
return void 0;
|
|
@@ -77397,7 +77395,7 @@ async function readPageInternalId(root, slug) {
|
|
|
77397
77395
|
|
|
77398
77396
|
// src/commands/experiment/measurement.ts
|
|
77399
77397
|
import { readFile as readFile37 } from "fs/promises";
|
|
77400
|
-
import
|
|
77398
|
+
import path43 from "path";
|
|
77401
77399
|
function eventDeclarationsIn(source) {
|
|
77402
77400
|
const found = [];
|
|
77403
77401
|
const pattern = /\b(data-baker-(?:view|event))\s*=\s*["']([^"']+)["']/g;
|
|
@@ -77457,7 +77455,7 @@ function sectionsOf(files, slug) {
|
|
|
77457
77455
|
return files.filter((file) => file.startsWith(prefix) && !file.slice(prefix.length).startsWith("index."));
|
|
77458
77456
|
}
|
|
77459
77457
|
async function declarationsOf(root, files) {
|
|
77460
|
-
const sources = await Promise.all(files.map((file) => readFile37(
|
|
77458
|
+
const sources = await Promise.all(files.map((file) => readFile37(path43.join(root, file), "utf8").catch(() => "")));
|
|
77461
77459
|
return sources.flatMap(eventDeclarationsIn);
|
|
77462
77460
|
}
|
|
77463
77461
|
|
|
@@ -78509,10 +78507,10 @@ function parseValueExpression(raw) {
|
|
|
78509
78507
|
return parts.map(parsePart);
|
|
78510
78508
|
}
|
|
78511
78509
|
function trackingFieldIds() {
|
|
78512
|
-
const
|
|
78513
|
-
if (!existsSync9(
|
|
78510
|
+
const path58 = join4(flowsDir(), "..", "tracking.ts");
|
|
78511
|
+
if (!existsSync9(path58)) return null;
|
|
78514
78512
|
try {
|
|
78515
|
-
const source = readFileSync17(
|
|
78513
|
+
const source = readFileSync17(path58, "utf-8");
|
|
78516
78514
|
const block2 = source.match(/TRACKING_FIELD_IDS\s*=\s*\[([\s\S]*?)\]\s*as const/)?.[1];
|
|
78517
78515
|
if (!block2) return null;
|
|
78518
78516
|
const ids2 = [...block2.matchAll(/"(tracking\.[a-z0-9_]+)"/g)].map((match) => match[1]);
|
|
@@ -79094,13 +79092,13 @@ function specsFromFile(parsed) {
|
|
|
79094
79092
|
return `${destField}${type}=${entry?.value ?? ""}`;
|
|
79095
79093
|
});
|
|
79096
79094
|
}
|
|
79097
|
-
function readSpecFile(
|
|
79095
|
+
function readSpecFile(path58) {
|
|
79098
79096
|
let raw;
|
|
79099
79097
|
try {
|
|
79100
|
-
raw =
|
|
79098
|
+
raw = path58 === "-" ? readFileSync18(0, "utf-8") : readFileSync18(path58, "utf-8");
|
|
79101
79099
|
} catch (error) {
|
|
79102
79100
|
refuse(
|
|
79103
|
-
`Could not read ${
|
|
79101
|
+
`Could not read ${path58 === "-" ? "the mapping from stdin" : `"${path58}"`}: ${error instanceof Error ? error.message : String(error)}`
|
|
79104
79102
|
);
|
|
79105
79103
|
}
|
|
79106
79104
|
let parsed;
|
|
@@ -79108,7 +79106,7 @@ function readSpecFile(path59) {
|
|
|
79108
79106
|
parsed = JSON.parse(raw);
|
|
79109
79107
|
} catch (error) {
|
|
79110
79108
|
refuse(
|
|
79111
|
-
`${
|
|
79109
|
+
`${path58 === "-" ? "stdin" : `"${path58}"`} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,
|
|
79112
79110
|
'Expected { "map": { "<destField>": "<value>", \u2026 } }'
|
|
79113
79111
|
);
|
|
79114
79112
|
}
|
|
@@ -79407,21 +79405,21 @@ var ARRAY_FIELDS = [
|
|
|
79407
79405
|
"tagIds"
|
|
79408
79406
|
];
|
|
79409
79407
|
var ARRAY_OWNERS = ["", "body"];
|
|
79410
|
-
function dropUnsetOptionals(sideEffect,
|
|
79408
|
+
function dropUnsetOptionals(sideEffect, path58) {
|
|
79411
79409
|
return OPTIONAL_STRINGS.flatMap((key) => {
|
|
79412
79410
|
if (!(key in sideEffect) || sideEffect[key] !== null && sideEffect[key] !== "") return [];
|
|
79413
79411
|
delete sideEffect[key];
|
|
79414
|
-
return [{ path:
|
|
79412
|
+
return [{ path: path58, change: `dropped \`${key}\` (an optional string is absent, never null)` }];
|
|
79415
79413
|
});
|
|
79416
79414
|
}
|
|
79417
|
-
function fillNulledArrays(target2, prefix,
|
|
79415
|
+
function fillNulledArrays(target2, prefix, path58) {
|
|
79418
79416
|
return ARRAY_FIELDS.flatMap((key) => {
|
|
79419
79417
|
if (!(key in target2) || target2[key] !== null) return [];
|
|
79420
79418
|
target2[key] = [];
|
|
79421
|
-
return [{ path:
|
|
79419
|
+
return [{ path: path58, change: `\`${prefix}${key}: null\` \u2192 \`[]\`` }];
|
|
79422
79420
|
});
|
|
79423
79421
|
}
|
|
79424
|
-
function tidyEmailRecipients(sideEffect,
|
|
79422
|
+
function tidyEmailRecipients(sideEffect, path58) {
|
|
79425
79423
|
if (sideEffect.type !== "email") return [];
|
|
79426
79424
|
const config = sideEffect.encryptedConfig;
|
|
79427
79425
|
if (!config || typeof config !== "object" || Array.isArray(config)) return [];
|
|
@@ -79432,7 +79430,7 @@ function tidyEmailRecipients(sideEffect, path59) {
|
|
|
79432
79430
|
const tidied = to.join(", ");
|
|
79433
79431
|
if (tidied === raw) return [];
|
|
79434
79432
|
config.email = tidied;
|
|
79435
|
-
return [{ path:
|
|
79433
|
+
return [{ path: path58, change: "tidied the recipient list's spacing and separators" }];
|
|
79436
79434
|
}
|
|
79437
79435
|
function sideEffectsOf(node) {
|
|
79438
79436
|
if (!Array.isArray(node.sideEffects)) return [];
|
|
@@ -79441,13 +79439,13 @@ function sideEffectsOf(node) {
|
|
|
79441
79439
|
);
|
|
79442
79440
|
}
|
|
79443
79441
|
function normalizeSideEffect(sideEffect, where) {
|
|
79444
|
-
const
|
|
79442
|
+
const path58 = `${where} \u2192 ${String(sideEffect.id ?? "side effect")}`;
|
|
79445
79443
|
const arrays = ARRAY_OWNERS.flatMap((owner) => {
|
|
79446
79444
|
const target2 = owner ? sideEffect[owner] : sideEffect;
|
|
79447
79445
|
if (!target2 || typeof target2 !== "object") return [];
|
|
79448
|
-
return fillNulledArrays(target2, owner ? `${owner}.` : "",
|
|
79446
|
+
return fillNulledArrays(target2, owner ? `${owner}.` : "", path58);
|
|
79449
79447
|
});
|
|
79450
|
-
return [...dropUnsetOptionals(sideEffect,
|
|
79448
|
+
return [...dropUnsetOptionals(sideEffect, path58), ...arrays, ...tidyEmailRecipients(sideEffect, path58)];
|
|
79451
79449
|
}
|
|
79452
79450
|
function normalizeFlowTree(tree) {
|
|
79453
79451
|
const changes = [];
|
|
@@ -80839,10 +80837,10 @@ async function stageOps(ops) {
|
|
|
80839
80837
|
handleError5(err);
|
|
80840
80838
|
}
|
|
80841
80839
|
}
|
|
80842
|
-
async function draftAction2(
|
|
80840
|
+
async function draftAction2(path58, body, chat) {
|
|
80843
80841
|
const chatId = resolveChatId(chat);
|
|
80844
80842
|
try {
|
|
80845
|
-
const { data, hints: hints2 } = splitHints(await apiPost(
|
|
80843
|
+
const { data, hints: hints2 } = splitHints(await apiPost(path58, { chatId, ...body }));
|
|
80846
80844
|
writeJsonEnvelope({ ok: true, data, ...hints2.length > 0 ? { hints: hints2 } : {} });
|
|
80847
80845
|
return data;
|
|
80848
80846
|
} catch (err) {
|
|
@@ -83372,9 +83370,9 @@ async function readImageBuffer(pathOrUrl) {
|
|
|
83372
83370
|
}
|
|
83373
83371
|
return readFile38(pathOrUrl);
|
|
83374
83372
|
}
|
|
83375
|
-
async function isDirectory(
|
|
83373
|
+
async function isDirectory(path58) {
|
|
83376
83374
|
try {
|
|
83377
|
-
const s = await stat8(
|
|
83375
|
+
const s = await stat8(path58);
|
|
83378
83376
|
return s.isDirectory();
|
|
83379
83377
|
} catch {
|
|
83380
83378
|
return false;
|
|
@@ -83802,13 +83800,13 @@ function resolveDownloadPath({ baseName, extension, out, outIsDirectory: outIsDi
|
|
|
83802
83800
|
}
|
|
83803
83801
|
function disambiguate(paths) {
|
|
83804
83802
|
const taken = /* @__PURE__ */ new Set();
|
|
83805
|
-
return paths.map((
|
|
83806
|
-
if (!taken.has(
|
|
83807
|
-
taken.add(
|
|
83808
|
-
return
|
|
83803
|
+
return paths.map((path58) => {
|
|
83804
|
+
if (!taken.has(path58)) {
|
|
83805
|
+
taken.add(path58);
|
|
83806
|
+
return path58;
|
|
83809
83807
|
}
|
|
83810
|
-
const ext = extname4(
|
|
83811
|
-
const stem =
|
|
83808
|
+
const ext = extname4(path58);
|
|
83809
|
+
const stem = path58.slice(0, path58.length - ext.length);
|
|
83812
83810
|
let n = 2;
|
|
83813
83811
|
while (taken.has(`${stem}-${n}${ext}`)) n += 1;
|
|
83814
83812
|
const unique = `${stem}-${n}${ext}`;
|
|
@@ -83934,10 +83932,10 @@ async function runDownloads(plan) {
|
|
|
83934
83932
|
const paths = disambiguate(fetched.map((item) => item.path));
|
|
83935
83933
|
const downloaded = [];
|
|
83936
83934
|
for (const [index, item] of fetched.entries()) {
|
|
83937
|
-
const
|
|
83935
|
+
const path58 = paths[index] ?? item.path;
|
|
83938
83936
|
try {
|
|
83939
|
-
await atomicWrite(
|
|
83940
|
-
downloaded.push({ input: item.input, output:
|
|
83937
|
+
await atomicWrite(path58, item.buffer);
|
|
83938
|
+
downloaded.push({ input: item.input, output: path58, bytes: item.buffer.length, contentType: item.contentType });
|
|
83941
83939
|
} catch (err) {
|
|
83942
83940
|
failed.push({ input: item.input, error: failureMessage(err, "Write failed") });
|
|
83943
83941
|
}
|
|
@@ -86920,7 +86918,7 @@ import { defineCommand as defineCommand207 } from "citty";
|
|
|
86920
86918
|
|
|
86921
86919
|
// src/commands/landing/critique.ts
|
|
86922
86920
|
import { readdir as readdir17, readFile as readFile40, stat as stat10 } from "fs/promises";
|
|
86923
|
-
import
|
|
86921
|
+
import path46 from "path";
|
|
86924
86922
|
import { defineCommand as defineCommand196 } from "citty";
|
|
86925
86923
|
|
|
86926
86924
|
// src/engine/landing/lib/constants.ts
|
|
@@ -88112,13 +88110,13 @@ function describeCounts(findings) {
|
|
|
88112
88110
|
|
|
88113
88111
|
// src/commands/landing/snapshot.ts
|
|
88114
88112
|
import { mkdir as mkdir12, rename as rename2, writeFile as writeFile19 } from "fs/promises";
|
|
88115
|
-
import
|
|
88113
|
+
import path44 from "path";
|
|
88116
88114
|
var CRITIC_VERSION = "4";
|
|
88117
88115
|
function critiqueCacheDir(projectRoot) {
|
|
88118
|
-
return
|
|
88116
|
+
return path44.join(projectRoot, ".cache", "landing-critique");
|
|
88119
88117
|
}
|
|
88120
88118
|
function snapshotPath(projectRoot, slug) {
|
|
88121
|
-
return
|
|
88119
|
+
return path44.join(critiqueCacheDir(projectRoot), `${slug}.json`);
|
|
88122
88120
|
}
|
|
88123
88121
|
async function writeCritiqueSnapshot(projectRoot, snapshot) {
|
|
88124
88122
|
await mkdir12(critiqueCacheDir(projectRoot), { recursive: true });
|
|
@@ -88131,7 +88129,7 @@ async function writeCritiqueSnapshot(projectRoot, snapshot) {
|
|
|
88131
88129
|
|
|
88132
88130
|
// src/commands/landing/source-version.ts
|
|
88133
88131
|
import { readdir as readdir16, readFile as readFile39, stat as stat9 } from "fs/promises";
|
|
88134
|
-
import
|
|
88132
|
+
import path45 from "path";
|
|
88135
88133
|
var CRITIQUED_ROOTS = ["src/pages/", "src/components/"];
|
|
88136
88134
|
async function landingSourceRelPaths(root, slug) {
|
|
88137
88135
|
const files = await landingGraphFiles(root, slug);
|
|
@@ -88140,7 +88138,7 @@ async function landingSourceRelPaths(root, slug) {
|
|
|
88140
88138
|
async function readLandingSources(root, slug) {
|
|
88141
88139
|
const rel = await landingSourceRelPaths(root, slug);
|
|
88142
88140
|
const out = [];
|
|
88143
|
-
for (const r of rel) out.push({ path: r, text: await readFile39(
|
|
88141
|
+
for (const r of rel) out.push({ path: r, text: await readFile39(path45.join(root, r), "utf8") });
|
|
88144
88142
|
return out;
|
|
88145
88143
|
}
|
|
88146
88144
|
async function computeLandingSourceSha(root, slug) {
|
|
@@ -88149,7 +88147,7 @@ async function computeLandingSourceSha(root, slug) {
|
|
|
88149
88147
|
for (const r of rel) {
|
|
88150
88148
|
let bytes;
|
|
88151
88149
|
try {
|
|
88152
|
-
bytes = await readFile39(
|
|
88150
|
+
bytes = await readFile39(path45.join(root, r));
|
|
88153
88151
|
} catch {
|
|
88154
88152
|
bytes = Buffer.alloc(0);
|
|
88155
88153
|
}
|
|
@@ -88159,16 +88157,16 @@ async function computeLandingSourceSha(root, slug) {
|
|
|
88159
88157
|
}
|
|
88160
88158
|
async function computeLegacyLandingSourceSha(landingDir) {
|
|
88161
88159
|
const rel = [];
|
|
88162
|
-
if (await isFile2(
|
|
88163
|
-
for (const abs of await walkAstro(
|
|
88164
|
-
rel.push(
|
|
88160
|
+
if (await isFile2(path45.join(landingDir, "index.astro"))) rel.push("index.astro");
|
|
88161
|
+
for (const abs of await walkAstro(path45.join(landingDir, "_components"))) {
|
|
88162
|
+
rel.push(path45.relative(landingDir, abs).split(path45.sep).join("/"));
|
|
88165
88163
|
}
|
|
88166
88164
|
rel.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
88167
88165
|
const parts = [];
|
|
88168
88166
|
for (const r of rel) {
|
|
88169
88167
|
let bytes;
|
|
88170
88168
|
try {
|
|
88171
|
-
bytes = await readFile39(
|
|
88169
|
+
bytes = await readFile39(path45.join(landingDir, r));
|
|
88172
88170
|
} catch {
|
|
88173
88171
|
bytes = Buffer.alloc(0);
|
|
88174
88172
|
}
|
|
@@ -88192,7 +88190,7 @@ async function walkAstro(dir) {
|
|
|
88192
88190
|
}
|
|
88193
88191
|
const out = [];
|
|
88194
88192
|
for (const entry of entries) {
|
|
88195
|
-
const abs =
|
|
88193
|
+
const abs = path45.join(dir, entry.name);
|
|
88196
88194
|
if (entry.isDirectory()) out.push(...await walkAstro(abs));
|
|
88197
88195
|
else if (entry.isFile() && entry.name.endsWith(".astro")) out.push(abs);
|
|
88198
88196
|
}
|
|
@@ -88253,7 +88251,7 @@ var critiqueCommand2 = defineCommand196({
|
|
|
88253
88251
|
{ availableSlugs: await listLandingSlugs(projectRoot) }
|
|
88254
88252
|
);
|
|
88255
88253
|
}
|
|
88256
|
-
if (!await isDir2(
|
|
88254
|
+
if (!await isDir2(path46.resolve(projectRoot, "src", "pages", slug))) {
|
|
88257
88255
|
fail8("NOT_FOUND", `No landing at src/pages/${slug}/`, {
|
|
88258
88256
|
availableSlugs: await listLandingSlugs(projectRoot)
|
|
88259
88257
|
});
|
|
@@ -88296,7 +88294,7 @@ async function critiqueOne(projectRoot, slug, brand, competitors) {
|
|
|
88296
88294
|
const [sources, compositionSha, sourceSha] = await Promise.all([
|
|
88297
88295
|
readLandingSources(projectRoot, slug),
|
|
88298
88296
|
computeLandingSourceSha(projectRoot, slug),
|
|
88299
|
-
computeLegacyLandingSourceSha(
|
|
88297
|
+
computeLegacyLandingSourceSha(path46.resolve(projectRoot, "src", "pages", slug))
|
|
88300
88298
|
]);
|
|
88301
88299
|
const report = critiqueLanding({ slug, sources, brand, competitors });
|
|
88302
88300
|
let snapshotFailed = false;
|
|
@@ -88316,7 +88314,7 @@ async function critiqueOne(projectRoot, slug, brand, competitors) {
|
|
|
88316
88314
|
return { slug, report, snapshotFailed };
|
|
88317
88315
|
}
|
|
88318
88316
|
async function readCompetitorNames(projectRoot) {
|
|
88319
|
-
const dir =
|
|
88317
|
+
const dir = path46.join(projectRoot, "src", "content", "competitors");
|
|
88320
88318
|
let entries;
|
|
88321
88319
|
try {
|
|
88322
88320
|
entries = (await readdir17(dir)).filter((f) => f.endsWith(".md"));
|
|
@@ -88325,9 +88323,9 @@ async function readCompetitorNames(projectRoot) {
|
|
|
88325
88323
|
}
|
|
88326
88324
|
const names = [];
|
|
88327
88325
|
for (const entry of entries) {
|
|
88328
|
-
names.push(
|
|
88326
|
+
names.push(path46.basename(entry, ".md").replace(/[-_]+/g, " "));
|
|
88329
88327
|
try {
|
|
88330
|
-
const head = (await readFile40(
|
|
88328
|
+
const head = (await readFile40(path46.join(dir, entry), "utf8")).slice(0, 2e3);
|
|
88331
88329
|
const titled = /^\s*(?:title|name)\s*:\s*["']?([^"'\n]+)["']?\s*$/im.exec(head);
|
|
88332
88330
|
if (titled?.[1]) names.push(titled[1].trim());
|
|
88333
88331
|
} catch {
|
|
@@ -88337,7 +88335,7 @@ async function readCompetitorNames(projectRoot) {
|
|
|
88337
88335
|
}
|
|
88338
88336
|
async function listLandingSlugs(projectRoot) {
|
|
88339
88337
|
try {
|
|
88340
|
-
const entries = await readdir17(
|
|
88338
|
+
const entries = await readdir17(path46.join(projectRoot, "src", "pages"), { withFileTypes: true });
|
|
88341
88339
|
return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).map((e) => e.name).sort();
|
|
88342
88340
|
} catch {
|
|
88343
88341
|
return [];
|
|
@@ -88489,7 +88487,7 @@ var addCommand = defineCommand197({
|
|
|
88489
88487
|
|
|
88490
88488
|
// src/commands/landing/inspiration/code.ts
|
|
88491
88489
|
import { mkdir as mkdir13, writeFile as writeFile20 } from "fs/promises";
|
|
88492
|
-
import
|
|
88490
|
+
import path47 from "path";
|
|
88493
88491
|
import { defineCommand as defineCommand198 } from "citty";
|
|
88494
88492
|
registerSchema({
|
|
88495
88493
|
command: "landing.inspiration.code",
|
|
@@ -88512,9 +88510,9 @@ var codeCommand = defineCommand198({
|
|
|
88512
88510
|
try {
|
|
88513
88511
|
const id = args8.id;
|
|
88514
88512
|
const data = await apiGet("/api/landing-inspiration/section-code", { id });
|
|
88515
|
-
const dir =
|
|
88513
|
+
const dir = path47.join(process.cwd(), ".baker", "inspiration", id);
|
|
88516
88514
|
await mkdir13(dir, { recursive: true });
|
|
88517
|
-
const file =
|
|
88515
|
+
const file = path47.join(dir, "section.html");
|
|
88518
88516
|
await writeFile20(file, data.html);
|
|
88519
88517
|
const hints2 = [INSPIRATION_HINTS.structureNotCopy, INSPIRATION_HINTS.adapt];
|
|
88520
88518
|
const fidelity = fidelityHint(data.fidelity);
|
|
@@ -88524,7 +88522,7 @@ var codeCommand = defineCommand198({
|
|
|
88524
88522
|
ok: true,
|
|
88525
88523
|
data: {
|
|
88526
88524
|
id,
|
|
88527
|
-
file:
|
|
88525
|
+
file: path47.relative(process.cwd(), file),
|
|
88528
88526
|
bytes: data.html.length,
|
|
88529
88527
|
fidelity: data.fidelity,
|
|
88530
88528
|
reproduction_notes: data.reproductionNotes,
|
|
@@ -88956,7 +88954,7 @@ function classifyCaptureFailure(error) {
|
|
|
88956
88954
|
|
|
88957
88955
|
// src/engine/landing-library/run.ts
|
|
88958
88956
|
import { mkdir as mkdir14, writeFile as writeFile22 } from "fs/promises";
|
|
88959
|
-
import
|
|
88957
|
+
import path49 from "path";
|
|
88960
88958
|
|
|
88961
88959
|
// ../proxy/src/preflight.ts
|
|
88962
88960
|
import http from "http";
|
|
@@ -90372,9 +90370,9 @@ async function renderBundleToPng(browser, html, viewportWidth, options = {}) {
|
|
|
90372
90370
|
|
|
90373
90371
|
// src/engine/landing-library/report.ts
|
|
90374
90372
|
import { writeFile as writeFile21 } from "fs/promises";
|
|
90375
|
-
import
|
|
90373
|
+
import path48 from "path";
|
|
90376
90374
|
async function writeCaptureReport(manifest, outDir) {
|
|
90377
|
-
const file =
|
|
90375
|
+
const file = path48.join(outDir, "report.html");
|
|
90378
90376
|
await writeFile21(file, renderReport(manifest));
|
|
90379
90377
|
return file;
|
|
90380
90378
|
}
|
|
@@ -90553,32 +90551,32 @@ async function reproducePage(args8) {
|
|
|
90553
90551
|
const { browser, page, outDir, pageUrl, livePageShot } = args8;
|
|
90554
90552
|
const built = await buildSectionBundle(page, "body", pageUrl).catch(() => null);
|
|
90555
90553
|
if (!built) return { bundle: null, fidelity: null };
|
|
90556
|
-
await writeFile22(
|
|
90554
|
+
await writeFile22(path49.join(outDir, "page.html"), built.html);
|
|
90557
90555
|
const rendered = await renderBundleToPng(browser, built.html, DESKTOP_VIEWPORT.width, {
|
|
90558
90556
|
wholePage: true,
|
|
90559
90557
|
timeoutMs: 6e4
|
|
90560
90558
|
});
|
|
90561
90559
|
if (!rendered || !livePageShot) return { bundle: "page.html", fidelity: null };
|
|
90562
|
-
await writeFile22(
|
|
90560
|
+
await writeFile22(path49.join(outDir, "page-rendered.png"), rendered);
|
|
90563
90561
|
const { score, note } = await scoreFidelity(livePageShot, rendered);
|
|
90564
90562
|
return { bundle: "page.html", fidelity: score, ...note ? { fidelityNote: note } : {} };
|
|
90565
90563
|
}
|
|
90566
90564
|
async function captureOneSection(args8) {
|
|
90567
90565
|
const { browser, page, candidate, sectionsDir, outDir, pageUrl, withCode } = args8;
|
|
90568
|
-
const dir =
|
|
90566
|
+
const dir = path49.join(sectionsDir, String(candidate.index).padStart(2, "0"));
|
|
90569
90567
|
await mkdir14(dir, { recursive: true });
|
|
90570
90568
|
const desktop = await captureSection(page, candidate);
|
|
90571
|
-
if (desktop) await writeFile22(
|
|
90569
|
+
if (desktop) await writeFile22(path49.join(dir, "desktop.png"), desktop);
|
|
90572
90570
|
const visualHash = desktop ? await perceptualHash(desktop) : null;
|
|
90573
90571
|
const motion = await collectMotion(page, candidate.selector);
|
|
90574
90572
|
const built = withCode ? await buildSectionBundle(page, candidate.selector, pageUrl) : null;
|
|
90575
90573
|
let fidelity = null;
|
|
90576
90574
|
let fidelityNote;
|
|
90577
90575
|
if (built) {
|
|
90578
|
-
await writeFile22(
|
|
90576
|
+
await writeFile22(path49.join(dir, "section.html"), built.html);
|
|
90579
90577
|
const rendered = await renderBundleToPng(browser, built.html, DESKTOP_VIEWPORT.width);
|
|
90580
90578
|
if (rendered && desktop) {
|
|
90581
|
-
await writeFile22(
|
|
90579
|
+
await writeFile22(path49.join(dir, "section-rendered.png"), rendered);
|
|
90582
90580
|
const result = await scoreFidelity(desktop, rendered);
|
|
90583
90581
|
fidelity = result.score;
|
|
90584
90582
|
fidelityNote = result.note;
|
|
@@ -90586,9 +90584,9 @@ async function captureOneSection(args8) {
|
|
|
90586
90584
|
}
|
|
90587
90585
|
return {
|
|
90588
90586
|
...candidate,
|
|
90589
|
-
desktopShot: desktop ?
|
|
90587
|
+
desktopShot: desktop ? path49.relative(outDir, path49.join(dir, "desktop.png")) : null,
|
|
90590
90588
|
mobileShot: null,
|
|
90591
|
-
bundle: built ?
|
|
90589
|
+
bundle: built ? path49.relative(outDir, path49.join(dir, "section.html")) : null,
|
|
90592
90590
|
fidelity,
|
|
90593
90591
|
...fidelityNote ? { fidelityNote } : {},
|
|
90594
90592
|
...built ? { cssStats: built.stats } : {},
|
|
@@ -90607,9 +90605,9 @@ async function captureMobileShots(args8) {
|
|
|
90607
90605
|
for (const section of sections) {
|
|
90608
90606
|
const shot = await captureSectionOnMobile(mobile.page, section);
|
|
90609
90607
|
if (!shot) continue;
|
|
90610
|
-
const file =
|
|
90608
|
+
const file = path49.join(sectionsDir, String(section.index).padStart(2, "0"), "mobile.png");
|
|
90611
90609
|
await writeFile22(file, shot);
|
|
90612
|
-
section.mobileShot =
|
|
90610
|
+
section.mobileShot = path49.relative(outDir, file);
|
|
90613
90611
|
}
|
|
90614
90612
|
} finally {
|
|
90615
90613
|
await mobile.context.close();
|
|
@@ -90624,10 +90622,10 @@ async function captureMotionTakes(args8) {
|
|
|
90624
90622
|
const filmOne = async (section) => {
|
|
90625
90623
|
const take = await captureMotionTake(browser, pageUrl, section.selector).catch(() => null);
|
|
90626
90624
|
if (!take) return;
|
|
90627
|
-
const dir =
|
|
90628
|
-
const file =
|
|
90625
|
+
const dir = path49.join(sectionsDir, String(section.index).padStart(2, "0"));
|
|
90626
|
+
const file = path49.join(dir, "motion-filmstrip.png");
|
|
90629
90627
|
await writeFile22(file, take.filmstrip);
|
|
90630
|
-
section.motionFilmstrip =
|
|
90628
|
+
section.motionFilmstrip = path49.relative(outDir, file);
|
|
90631
90629
|
log(` [${section.index}] ${section.motion.summary}`);
|
|
90632
90630
|
};
|
|
90633
90631
|
const queue = [...moving];
|
|
@@ -90684,7 +90682,7 @@ async function captureAlternateViews(args8) {
|
|
|
90684
90682
|
async function reproduceWholePage(args8) {
|
|
90685
90683
|
const { browser, page, outDir, pageUrl, withCode, log } = args8;
|
|
90686
90684
|
const fullPage = await page.screenshot({ type: "png", fullPage: true }).catch(() => null);
|
|
90687
|
-
if (fullPage) await writeFile22(
|
|
90685
|
+
if (fullPage) await writeFile22(path49.join(outDir, "full-page.png"), fullPage);
|
|
90688
90686
|
if (!withCode) return { bundle: null, fidelity: null };
|
|
90689
90687
|
const reproduction = await reproducePage({ browser, page, outDir, pageUrl, livePageShot: fullPage });
|
|
90690
90688
|
log(`page reproduction: ${reproduction.fidelity === null ? "unavailable" : reproduction.fidelity.toFixed(2)}`);
|
|
@@ -90755,7 +90753,7 @@ async function openViaLadder(args8) {
|
|
|
90755
90753
|
async function scrapeLanding(options) {
|
|
90756
90754
|
const timeoutMs = options.timeoutMs ?? 45e3;
|
|
90757
90755
|
const log = options.onProgress ?? (() => void 0);
|
|
90758
|
-
const sectionsDir =
|
|
90756
|
+
const sectionsDir = path49.join(options.outDir, "sections");
|
|
90759
90757
|
const nonPublic = refuseNonPublicUrl(options.url);
|
|
90760
90758
|
if (nonPublic) {
|
|
90761
90759
|
throw new BlockedPageError({
|
|
@@ -90817,7 +90815,7 @@ async function scrapeLanding(options) {
|
|
|
90817
90815
|
security: prepared.security,
|
|
90818
90816
|
captureTier: tier
|
|
90819
90817
|
};
|
|
90820
|
-
await writeFile22(
|
|
90818
|
+
await writeFile22(path49.join(options.outDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
|
|
90821
90819
|
`);
|
|
90822
90820
|
if (options.report !== false) {
|
|
90823
90821
|
const reportPath = await writeCaptureReport(manifest, options.outDir);
|
|
@@ -90832,28 +90830,28 @@ async function scrapeLanding(options) {
|
|
|
90832
90830
|
|
|
90833
90831
|
// src/commands/landing/inspiration/captureOut.ts
|
|
90834
90832
|
import { existsSync as existsSync12 } from "fs";
|
|
90835
|
-
import
|
|
90833
|
+
import path50 from "path";
|
|
90836
90834
|
var SCRATCH_DIR = ".baker";
|
|
90837
90835
|
function isWithin(parent, target2) {
|
|
90838
|
-
const relative =
|
|
90839
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
90836
|
+
const relative = path50.relative(parent, target2);
|
|
90837
|
+
return relative === "" || !relative.startsWith("..") && !path50.isAbsolute(relative);
|
|
90840
90838
|
}
|
|
90841
90839
|
function findRepoRoot(from) {
|
|
90842
|
-
let dir =
|
|
90840
|
+
let dir = path50.resolve(from);
|
|
90843
90841
|
for (; ; ) {
|
|
90844
|
-
if (existsSync12(
|
|
90845
|
-
const parent =
|
|
90842
|
+
if (existsSync12(path50.join(dir, ".git"))) return dir;
|
|
90843
|
+
const parent = path50.dirname(dir);
|
|
90846
90844
|
if (parent === dir) return null;
|
|
90847
90845
|
dir = parent;
|
|
90848
90846
|
}
|
|
90849
90847
|
}
|
|
90850
90848
|
function checkCaptureOut(out, options) {
|
|
90851
90849
|
const { cwd, repoRoot } = options;
|
|
90852
|
-
const resolved =
|
|
90850
|
+
const resolved = path50.resolve(cwd, out);
|
|
90853
90851
|
if (repoRoot === null || !isWithin(repoRoot, resolved)) return { ok: true };
|
|
90854
|
-
const scratch =
|
|
90852
|
+
const scratch = path50.join(repoRoot, SCRATCH_DIR);
|
|
90855
90853
|
if (isWithin(scratch, resolved)) return { ok: true };
|
|
90856
|
-
const suggestion =
|
|
90854
|
+
const suggestion = path50.posix.join(SCRATCH_DIR, "teardowns", path50.basename(resolved) || "capture");
|
|
90857
90855
|
return {
|
|
90858
90856
|
ok: false,
|
|
90859
90857
|
error: {
|
|
@@ -91027,12 +91025,12 @@ var scrapeCommand = defineCommand201({
|
|
|
91027
91025
|
});
|
|
91028
91026
|
|
|
91029
91027
|
// src/commands/landing/inspiration/search.ts
|
|
91030
|
-
import
|
|
91028
|
+
import path52 from "path";
|
|
91031
91029
|
import { defineCommand as defineCommand202 } from "citty";
|
|
91032
91030
|
|
|
91033
91031
|
// src/commands/landing/inspiration/shot.ts
|
|
91034
91032
|
import { mkdir as mkdir15, writeFile as writeFile23 } from "fs/promises";
|
|
91035
|
-
import
|
|
91033
|
+
import path51 from "path";
|
|
91036
91034
|
import sharp8 from "sharp";
|
|
91037
91035
|
var READABLE_SHOT = {
|
|
91038
91036
|
maxWidth: 1440,
|
|
@@ -91058,9 +91056,9 @@ async function downloadReadableShot(url, file) {
|
|
|
91058
91056
|
const response = await fetch(url);
|
|
91059
91057
|
if (!response.ok) return null;
|
|
91060
91058
|
const shot = await toReadableShot(Buffer.from(await response.arrayBuffer()));
|
|
91061
|
-
await mkdir15(
|
|
91059
|
+
await mkdir15(path51.dirname(file), { recursive: true });
|
|
91062
91060
|
await writeFile23(file, shot);
|
|
91063
|
-
return
|
|
91061
|
+
return path51.relative(process.cwd(), file);
|
|
91064
91062
|
} catch {
|
|
91065
91063
|
return null;
|
|
91066
91064
|
}
|
|
@@ -91152,13 +91150,13 @@ function buildSearchBody(args8) {
|
|
|
91152
91150
|
return body;
|
|
91153
91151
|
}
|
|
91154
91152
|
async function downloadShots(results) {
|
|
91155
|
-
const dir =
|
|
91153
|
+
const dir = path52.join(process.cwd(), ".baker", "inspiration");
|
|
91156
91154
|
const saved = /* @__PURE__ */ new Map();
|
|
91157
91155
|
await Promise.all(
|
|
91158
91156
|
results.map(async (result) => {
|
|
91159
91157
|
const file = await downloadReadableShot(
|
|
91160
91158
|
result.desktopShotUrl,
|
|
91161
|
-
|
|
91159
|
+
path52.join(dir, `${result.id}.${READABLE_SHOT.extension}`)
|
|
91162
91160
|
);
|
|
91163
91161
|
if (file) saved.set(result.id, file);
|
|
91164
91162
|
})
|
|
@@ -91386,7 +91384,7 @@ var sequencesCommand = defineCommand203({
|
|
|
91386
91384
|
});
|
|
91387
91385
|
|
|
91388
91386
|
// src/commands/landing/inspiration/view.ts
|
|
91389
|
-
import
|
|
91387
|
+
import path53 from "path";
|
|
91390
91388
|
import { defineCommand as defineCommand204 } from "citty";
|
|
91391
91389
|
registerSchema({
|
|
91392
91390
|
command: "landing.inspiration.view",
|
|
@@ -91419,12 +91417,12 @@ var viewCommand2 = defineCommand204({
|
|
|
91419
91417
|
const id = args8.id;
|
|
91420
91418
|
const data = await apiGet("/api/landing-inspiration/section", { id });
|
|
91421
91419
|
const section = data.section;
|
|
91422
|
-
const dir =
|
|
91420
|
+
const dir = path53.join(process.cwd(), ".baker", "inspiration", id);
|
|
91423
91421
|
const ext = READABLE_SHOT.extension;
|
|
91424
91422
|
const [desktop, mobile, filmstrip] = await Promise.all([
|
|
91425
|
-
downloadReadableShot(section.desktopShotUrl,
|
|
91426
|
-
downloadReadableShot(section.mobileShotUrl,
|
|
91427
|
-
downloadReadableShot(section.motionFilmstripUrl,
|
|
91423
|
+
downloadReadableShot(section.desktopShotUrl, path53.join(dir, `desktop.${ext}`)),
|
|
91424
|
+
downloadReadableShot(section.mobileShotUrl, path53.join(dir, `mobile.${ext}`)),
|
|
91425
|
+
downloadReadableShot(section.motionFilmstripUrl, path53.join(dir, `motion-filmstrip.${ext}`))
|
|
91428
91426
|
]);
|
|
91429
91427
|
const full = args8.full;
|
|
91430
91428
|
const hints2 = [INSPIRATION_HINTS.structureNotCopy, INSPIRATION_HINTS.adapt];
|
|
@@ -91531,7 +91529,7 @@ Full guide: __tooling__/docs/tools/baker/landing.md`
|
|
|
91531
91529
|
// src/commands/landing/variant.ts
|
|
91532
91530
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
91533
91531
|
import { mkdir as mkdir16, readdir as readdir18, readFile as readFile41, stat as stat11, writeFile as writeFile24 } from "fs/promises";
|
|
91534
|
-
import
|
|
91532
|
+
import path54 from "path";
|
|
91535
91533
|
import { defineCommand as defineCommand206 } from "citty";
|
|
91536
91534
|
registerSchema({
|
|
91537
91535
|
command: "landing.variant",
|
|
@@ -91567,7 +91565,7 @@ async function readInternalId(definitionPath) {
|
|
|
91567
91565
|
async function archivedVariantNumbers(root, internalId) {
|
|
91568
91566
|
if (!internalId) return [];
|
|
91569
91567
|
try {
|
|
91570
|
-
const entries = await readdir18(
|
|
91568
|
+
const entries = await readdir18(path54.resolve(root, "src/_variants", internalId), { withFileTypes: true });
|
|
91571
91569
|
return entries.filter((entry) => entry.isDirectory()).map((entry) => Number(entry.name)).filter((n) => Number.isInteger(n) && n > 0);
|
|
91572
91570
|
} catch {
|
|
91573
91571
|
return [];
|
|
@@ -91597,7 +91595,7 @@ async function exists2(p) {
|
|
|
91597
91595
|
}
|
|
91598
91596
|
async function listLandingSlugs2(root) {
|
|
91599
91597
|
try {
|
|
91600
|
-
const entries = await readdir18(
|
|
91598
|
+
const entries = await readdir18(path54.resolve(root, "src", "pages"), { withFileTypes: true });
|
|
91601
91599
|
return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).map((e) => e.name).sort();
|
|
91602
91600
|
} catch {
|
|
91603
91601
|
return [];
|
|
@@ -91613,7 +91611,7 @@ async function listComponents(componentsDir, prefix = "") {
|
|
|
91613
91611
|
const out = [];
|
|
91614
91612
|
for (const entry of entries) {
|
|
91615
91613
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
91616
|
-
if (entry.isDirectory()) out.push(...await listComponents(
|
|
91614
|
+
if (entry.isDirectory()) out.push(...await listComponents(path54.join(componentsDir, entry.name), rel));
|
|
91617
91615
|
else if (entry.name.endsWith(".astro")) out.push(rel);
|
|
91618
91616
|
}
|
|
91619
91617
|
return out.sort();
|
|
@@ -91680,16 +91678,16 @@ async function resolveTargets(projectRoot, opts) {
|
|
|
91680
91678
|
`"${controlSlug}" is already a variant of "${variantOfSlug(controlSlug)}". Make the next variant of the page itself: \`baker landing variant ${variantOfSlug(controlSlug)}\`.`
|
|
91681
91679
|
);
|
|
91682
91680
|
}
|
|
91683
|
-
const controlDir =
|
|
91681
|
+
const controlDir = path54.resolve(projectRoot, "src", "pages", controlSlug);
|
|
91684
91682
|
if (!await isDir3(controlDir)) {
|
|
91685
91683
|
fail9("NOT_FOUND", `No page at src/pages/${controlSlug}/`, {
|
|
91686
91684
|
availableSlugs: await listLandingSlugs2(projectRoot)
|
|
91687
91685
|
});
|
|
91688
91686
|
}
|
|
91689
|
-
if (!await exists2(
|
|
91687
|
+
if (!await exists2(path54.join(controlDir, "index.astro"))) {
|
|
91690
91688
|
fail9("NOT_FOUND", `src/pages/${controlSlug}/index.astro is missing, so there is no page to make a variant of.`);
|
|
91691
91689
|
}
|
|
91692
|
-
const internalId = await readInternalId(
|
|
91690
|
+
const internalId = await readInternalId(path54.join(controlDir, "_definition.md"));
|
|
91693
91691
|
const variantSlugValue = variantSlug(
|
|
91694
91692
|
controlSlug,
|
|
91695
91693
|
nextVariantNumber(
|
|
@@ -91698,8 +91696,8 @@ async function resolveTargets(projectRoot, opts) {
|
|
|
91698
91696
|
await archivedVariantNumbers(projectRoot, internalId)
|
|
91699
91697
|
)
|
|
91700
91698
|
);
|
|
91701
|
-
const variantDir =
|
|
91702
|
-
const available = await listComponents(
|
|
91699
|
+
const variantDir = path54.resolve(projectRoot, "src", "pages", variantSlugValue);
|
|
91700
|
+
const available = await listComponents(path54.join(controlDir, "_components"));
|
|
91703
91701
|
const forks = [];
|
|
91704
91702
|
for (const name of parseForks(opts.fork, opts.rawArgs)) {
|
|
91705
91703
|
const resolved = resolveForkName(name, available);
|
|
@@ -91715,26 +91713,26 @@ async function resolveTargets(projectRoot, opts) {
|
|
|
91715
91713
|
}
|
|
91716
91714
|
async function writeVariant(opts) {
|
|
91717
91715
|
const { controlDir, variantDir, controlSlug, variantSlug: variantSlug2, forks } = opts;
|
|
91718
|
-
const forkedTargets = new Set(forks.map((f) =>
|
|
91716
|
+
const forkedTargets = new Set(forks.map((f) => path54.join(controlDir, "_components", f)));
|
|
91719
91717
|
const written = [];
|
|
91720
|
-
const indexText = await readFile41(
|
|
91718
|
+
const indexText = await readFile41(path54.join(controlDir, "index.astro"), "utf8");
|
|
91721
91719
|
await mkdir16(variantDir, { recursive: true });
|
|
91722
91720
|
await writeFile24(
|
|
91723
|
-
|
|
91721
|
+
path54.join(variantDir, "index.astro"),
|
|
91724
91722
|
repointFile(indexText, { fromDir: controlDir, toDir: variantDir, controlDir, variantDir, forkedTargets }),
|
|
91725
91723
|
"utf8"
|
|
91726
91724
|
);
|
|
91727
91725
|
written.push(`src/pages/${variantSlug2}/index.astro`);
|
|
91728
91726
|
for (const fork of forks) {
|
|
91729
|
-
const fromFile =
|
|
91730
|
-
const toFile =
|
|
91727
|
+
const fromFile = path54.join(controlDir, "_components", fork);
|
|
91728
|
+
const toFile = path54.join(variantDir, "_components", fork);
|
|
91731
91729
|
const text2 = await readFile41(fromFile, "utf8");
|
|
91732
|
-
await mkdir16(
|
|
91730
|
+
await mkdir16(path54.dirname(toFile), { recursive: true });
|
|
91733
91731
|
await writeFile24(
|
|
91734
91732
|
toFile,
|
|
91735
91733
|
repointFile(text2, {
|
|
91736
|
-
fromDir:
|
|
91737
|
-
toDir:
|
|
91734
|
+
fromDir: path54.dirname(fromFile),
|
|
91735
|
+
toDir: path54.dirname(toFile),
|
|
91738
91736
|
controlDir,
|
|
91739
91737
|
variantDir,
|
|
91740
91738
|
forkedTargets
|
|
@@ -91743,7 +91741,7 @@ async function writeVariant(opts) {
|
|
|
91743
91741
|
);
|
|
91744
91742
|
written.push(`src/pages/${variantSlug2}/_components/${fork}`);
|
|
91745
91743
|
}
|
|
91746
|
-
const controlDefinitionPath =
|
|
91744
|
+
const controlDefinitionPath = path54.join(controlDir, "_definition.md");
|
|
91747
91745
|
if (await exists2(controlDefinitionPath)) {
|
|
91748
91746
|
const definition = buildVariantDefinition(await readFile41(controlDefinitionPath, "utf8"), {
|
|
91749
91747
|
internalId: randomUUID3().replace(/-/g, "").slice(0, 8),
|
|
@@ -91753,11 +91751,11 @@ async function writeVariant(opts) {
|
|
|
91753
91751
|
...opts.because ? { because: opts.because } : {},
|
|
91754
91752
|
...opts.change ? { change: opts.change } : {}
|
|
91755
91753
|
});
|
|
91756
|
-
await writeFile24(
|
|
91754
|
+
await writeFile24(path54.join(variantDir, "_definition.md"), definition, "utf8");
|
|
91757
91755
|
written.push(`src/pages/${variantSlug2}/_definition.md`);
|
|
91758
91756
|
}
|
|
91759
|
-
await mkdir16(
|
|
91760
|
-
await writeFile24(
|
|
91757
|
+
await mkdir16(path54.join(variantDir, "_images"), { recursive: true });
|
|
91758
|
+
await writeFile24(path54.join(variantDir, "_images", ".gitkeep"), "", "utf8");
|
|
91761
91759
|
return written;
|
|
91762
91760
|
}
|
|
91763
91761
|
var variantCommand = defineCommand206({
|
|
@@ -94463,7 +94461,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
|
|
|
94463
94461
|
|
|
94464
94462
|
// src/commands/scheduled-agents/templates.ts
|
|
94465
94463
|
import { readFile as readFile42 } from "fs/promises";
|
|
94466
|
-
import
|
|
94464
|
+
import path55 from "path";
|
|
94467
94465
|
import { defineCommand as defineCommand234 } from "citty";
|
|
94468
94466
|
registerSchema({
|
|
94469
94467
|
command: "scheduled-agents.templates",
|
|
@@ -94570,7 +94568,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
|
|
|
94570
94568
|
}
|
|
94571
94569
|
if (save.length > 0) {
|
|
94572
94570
|
const briefFile = flag("brief-file");
|
|
94573
|
-
const brief2 = briefFile.length > 0 ? await readFile42(
|
|
94571
|
+
const brief2 = briefFile.length > 0 ? await readFile42(path55.resolve(briefFile), "utf8") : flag("brief");
|
|
94574
94572
|
if (brief2.trim().length === 0) {
|
|
94575
94573
|
failValidation4("--brief-file (preferred) or --brief is required: the brief is the recipe.");
|
|
94576
94574
|
}
|
|
@@ -95210,7 +95208,7 @@ function parseImageRefs(spec) {
|
|
|
95210
95208
|
}
|
|
95211
95209
|
var defaultDeps = {
|
|
95212
95210
|
ingest: (url) => apiPost("/api/images/ingest", { url, source: "uploaded" }),
|
|
95213
|
-
upload: (
|
|
95211
|
+
upload: (path58) => uploadLocalImage({ file: path58, contentType: detectImageContentType(path58), source: "uploaded" })
|
|
95214
95212
|
};
|
|
95215
95213
|
async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
|
|
95216
95214
|
const refs = parseImageRefs(spec);
|
|
@@ -95230,10 +95228,10 @@ async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
|
|
|
95230
95228
|
}
|
|
95231
95229
|
return { imageIds, added };
|
|
95232
95230
|
}
|
|
95233
|
-
function uploadFailure(
|
|
95231
|
+
function uploadFailure(path58) {
|
|
95234
95232
|
return (error) => {
|
|
95235
95233
|
if (error instanceof ApiError) throw error;
|
|
95236
|
-
throw new ApiError("VALIDATION_ERROR", `Could not read "${
|
|
95234
|
+
throw new ApiError("VALIDATION_ERROR", `Could not read "${path58}" as an image.`);
|
|
95237
95235
|
};
|
|
95238
95236
|
}
|
|
95239
95237
|
|
|
@@ -96333,10 +96331,10 @@ async function stageOp4(op) {
|
|
|
96333
96331
|
handleError8(err);
|
|
96334
96332
|
}
|
|
96335
96333
|
}
|
|
96336
|
-
async function draftAction3(
|
|
96334
|
+
async function draftAction3(path58, body, chat) {
|
|
96337
96335
|
const chatId = resolveChatId(chat);
|
|
96338
96336
|
try {
|
|
96339
|
-
const { data, hints: hints2 } = splitHints(await apiPost(
|
|
96337
|
+
const { data, hints: hints2 } = splitHints(await apiPost(path58, { chatId, ...body }));
|
|
96340
96338
|
writeJsonEnvelope({ ok: true, data, ...hints2.length > 0 ? { hints: hints2 } : {} });
|
|
96341
96339
|
return data;
|
|
96342
96340
|
} catch (err) {
|
|
@@ -97494,7 +97492,7 @@ Example: baker videos describe j571abc123 --description "Customer explaining how
|
|
|
97494
97492
|
import { constants } from "fs";
|
|
97495
97493
|
import { copyFile as copyFile2, mkdir as mkdir17, mkdtemp as mkdtemp3, rm as rm10 } from "fs/promises";
|
|
97496
97494
|
import { tmpdir as tmpdir4 } from "os";
|
|
97497
|
-
import
|
|
97495
|
+
import path56 from "path";
|
|
97498
97496
|
import { defineCommand as defineCommand260 } from "citty";
|
|
97499
97497
|
|
|
97500
97498
|
// src/commands/videos/videoPlatforms.ts
|
|
@@ -97662,8 +97660,8 @@ var fetchCommand2 = defineCommand260({
|
|
|
97662
97660
|
}
|
|
97663
97661
|
});
|
|
97664
97662
|
async function fetchVideo(args8) {
|
|
97665
|
-
const outDir =
|
|
97666
|
-
const workDir = await mkdtemp3(
|
|
97663
|
+
const outDir = path56.resolve(args8.out);
|
|
97664
|
+
const workDir = await mkdtemp3(path56.join(tmpdir4(), "videos-fetch-"));
|
|
97667
97665
|
try {
|
|
97668
97666
|
await mkdir17(outDir, { recursive: true });
|
|
97669
97667
|
const vimeoCookie = captureVimeoCookie();
|
|
@@ -97708,7 +97706,7 @@ function fileStem(info) {
|
|
|
97708
97706
|
}
|
|
97709
97707
|
async function placeInto(outDir, source, stem) {
|
|
97710
97708
|
for (let n = 1; ; n++) {
|
|
97711
|
-
const target2 =
|
|
97709
|
+
const target2 = path56.join(outDir, `${stem}${n === 1 ? "" : `-${n}`}${path56.extname(source)}`);
|
|
97712
97710
|
try {
|
|
97713
97711
|
await copyFile2(source, target2, constants.COPYFILE_EXCL);
|
|
97714
97712
|
return target2;
|
|
@@ -97795,7 +97793,7 @@ var groupCommand2 = defineCommand262({
|
|
|
97795
97793
|
// src/commands/videos/ingest.ts
|
|
97796
97794
|
import { mkdtemp as mkdtemp4, rm as rm11, stat as stat12 } from "fs/promises";
|
|
97797
97795
|
import { tmpdir as tmpdir5 } from "os";
|
|
97798
|
-
import
|
|
97796
|
+
import path57 from "path";
|
|
97799
97797
|
import { defineCommand as defineCommand263 } from "citty";
|
|
97800
97798
|
|
|
97801
97799
|
// src/lib/streamUpload.ts
|
|
@@ -98035,7 +98033,7 @@ function ingestUrl(args8) {
|
|
|
98035
98033
|
}
|
|
98036
98034
|
async function downloadThenIngest(args8, country) {
|
|
98037
98035
|
const vimeoCookie = captureVimeoCookie();
|
|
98038
|
-
const workDir = await mkdtemp4(
|
|
98036
|
+
const workDir = await mkdtemp4(path57.join(tmpdir5(), "videos-ingest-"));
|
|
98039
98037
|
try {
|
|
98040
98038
|
const probe = await probeYtDlp({ url: args8.url, country, vimeoCookie, cookieDir: workDir });
|
|
98041
98039
|
if (isAudioOnly(probe.info)) {
|
|
@@ -99073,8 +99071,8 @@ var FLAG_FOR_FIELD = {
|
|
|
99073
99071
|
first_seen_after: "--first-seen-after",
|
|
99074
99072
|
first_seen_before: "--first-seen-before"
|
|
99075
99073
|
};
|
|
99076
|
-
function flagFor(
|
|
99077
|
-
const field = String(
|
|
99074
|
+
function flagFor(path58) {
|
|
99075
|
+
const field = String(path58[0] === "hard_filters" ? path58[1] : path58[0]);
|
|
99078
99076
|
return FLAG_FOR_FIELD[field] ?? field;
|
|
99079
99077
|
}
|
|
99080
99078
|
function schemaRejection(body) {
|