@koda-sl/baker-cli 0.239.0 → 0.241.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/cli.js +166 -103
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -9763,11 +9763,11 @@ function rawTextEntries(value) {
|
|
|
9763
9763
|
const values = Array.isArray(value) ? value : typeof value === "string" ? [value] : [];
|
|
9764
9764
|
return values.filter((v) => typeof v === "string").flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
|
|
9765
9765
|
}
|
|
9766
|
-
function rawFileEntries(
|
|
9767
|
-
if (typeof
|
|
9766
|
+
function rawFileEntries(path40) {
|
|
9767
|
+
if (typeof path40 !== "string" || path40.length === 0) {
|
|
9768
9768
|
return [];
|
|
9769
9769
|
}
|
|
9770
|
-
return readFileSync2(
|
|
9770
|
+
return readFileSync2(path40, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
9771
9771
|
}
|
|
9772
9772
|
function keywordEntries(args) {
|
|
9773
9773
|
const defaultMatch = typeof args["match-type"] === "string" ? args["match-type"].toUpperCase() : void 0;
|
|
@@ -9790,19 +9790,19 @@ function keywordEntries(args) {
|
|
|
9790
9790
|
}
|
|
9791
9791
|
return entries;
|
|
9792
9792
|
}
|
|
9793
|
-
function loadJsonFileArg(
|
|
9794
|
-
if (typeof
|
|
9793
|
+
function loadJsonFileArg(path40) {
|
|
9794
|
+
if (typeof path40 !== "string" || path40.length === 0) {
|
|
9795
9795
|
return {};
|
|
9796
9796
|
}
|
|
9797
9797
|
try {
|
|
9798
|
-
const parsed = JSON.parse(readFileSync2(
|
|
9798
|
+
const parsed = JSON.parse(readFileSync2(path40, "utf8"));
|
|
9799
9799
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
9800
|
-
failWriteValidation(`${
|
|
9800
|
+
failWriteValidation(`${path40} must contain a JSON object`);
|
|
9801
9801
|
}
|
|
9802
9802
|
return parsed;
|
|
9803
9803
|
} catch (err) {
|
|
9804
9804
|
if (err instanceof SyntaxError) {
|
|
9805
|
-
failWriteValidation(`${
|
|
9805
|
+
failWriteValidation(`${path40} is not valid JSON: ${err.message}`);
|
|
9806
9806
|
}
|
|
9807
9807
|
throw err;
|
|
9808
9808
|
}
|
|
@@ -9932,10 +9932,10 @@ async function stageUpdate(kind, customerId, target, payload, hints) {
|
|
|
9932
9932
|
async function stageTarget(kind, customerId, target, hints) {
|
|
9933
9933
|
await stageGoogleOp({ kind, customerId, target }, hints);
|
|
9934
9934
|
}
|
|
9935
|
-
async function draftAction(
|
|
9935
|
+
async function draftAction(path40, body, chat) {
|
|
9936
9936
|
try {
|
|
9937
9937
|
const chatId = resolveChatId(chat);
|
|
9938
|
-
const response = await apiPost(
|
|
9938
|
+
const response = await apiPost(path40, { chatId, ...body });
|
|
9939
9939
|
writeJsonEnvelope(response);
|
|
9940
9940
|
} catch (err) {
|
|
9941
9941
|
handleGoogleError(err);
|
|
@@ -14869,19 +14869,19 @@ function failWriteValidation2(message) {
|
|
|
14869
14869
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
14870
14870
|
process.exit(1);
|
|
14871
14871
|
}
|
|
14872
|
-
function loadJsonFileArg2(
|
|
14873
|
-
if (typeof
|
|
14872
|
+
function loadJsonFileArg2(path40) {
|
|
14873
|
+
if (typeof path40 !== "string" || path40.length === 0) {
|
|
14874
14874
|
return {};
|
|
14875
14875
|
}
|
|
14876
14876
|
try {
|
|
14877
|
-
const parsed = JSON.parse(readFileSync4(
|
|
14877
|
+
const parsed = JSON.parse(readFileSync4(path40, "utf8"));
|
|
14878
14878
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
14879
|
-
failWriteValidation2(`${
|
|
14879
|
+
failWriteValidation2(`${path40} must contain a JSON object`);
|
|
14880
14880
|
}
|
|
14881
14881
|
return parsed;
|
|
14882
14882
|
} catch (err) {
|
|
14883
14883
|
if (err instanceof SyntaxError) {
|
|
14884
|
-
failWriteValidation2(`${
|
|
14884
|
+
failWriteValidation2(`${path40} is not valid JSON: ${err.message}`);
|
|
14885
14885
|
}
|
|
14886
14886
|
throw err;
|
|
14887
14887
|
}
|
|
@@ -14966,15 +14966,15 @@ function parseLocaleFlag(value) {
|
|
|
14966
14966
|
}
|
|
14967
14967
|
return { language: match[1], country: match[2].toUpperCase() };
|
|
14968
14968
|
}
|
|
14969
|
-
function loadTargetingFileArg(
|
|
14970
|
-
if (typeof
|
|
14969
|
+
function loadTargetingFileArg(path40) {
|
|
14970
|
+
if (typeof path40 !== "string" || path40.length === 0) {
|
|
14971
14971
|
return void 0;
|
|
14972
14972
|
}
|
|
14973
|
-
const parsed = loadJsonFileArg2(
|
|
14973
|
+
const parsed = loadJsonFileArg2(path40);
|
|
14974
14974
|
const criteria = parsed.targetingCriteria ?? parsed;
|
|
14975
14975
|
if (!criteria.include) {
|
|
14976
14976
|
failWriteValidation2(
|
|
14977
|
-
`${
|
|
14977
|
+
`${path40} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
|
|
14978
14978
|
);
|
|
14979
14979
|
}
|
|
14980
14980
|
return criteria;
|
|
@@ -15009,14 +15009,14 @@ function parseCsvLine(line) {
|
|
|
15009
15009
|
cells.push(current);
|
|
15010
15010
|
return cells.map((cell2) => cell2.trim());
|
|
15011
15011
|
}
|
|
15012
|
-
function parseListFileArg(
|
|
15013
|
-
if (typeof
|
|
15012
|
+
function parseListFileArg(path40, maxRows) {
|
|
15013
|
+
if (typeof path40 !== "string" || path40.length === 0) {
|
|
15014
15014
|
return void 0;
|
|
15015
15015
|
}
|
|
15016
|
-
const raw = readFileSync4(
|
|
15016
|
+
const raw = readFileSync4(path40, "utf8");
|
|
15017
15017
|
const lines = raw.split(/\r?\n/).filter((line) => line.trim().length > 0);
|
|
15018
15018
|
if (lines.length < 2) {
|
|
15019
|
-
failWriteValidation2(`${
|
|
15019
|
+
failWriteValidation2(`${path40} needs a header row and at least one data row`);
|
|
15020
15020
|
}
|
|
15021
15021
|
const columns = parseCsvLine(lines[0]).map((column) => column.trim());
|
|
15022
15022
|
const rows = [];
|
|
@@ -15035,7 +15035,7 @@ function parseListFileArg(path39, maxRows) {
|
|
|
15035
15035
|
}
|
|
15036
15036
|
}
|
|
15037
15037
|
if (rows.length > maxRows) {
|
|
15038
|
-
failWriteValidation2(`${
|
|
15038
|
+
failWriteValidation2(`${path40} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
|
|
15039
15039
|
}
|
|
15040
15040
|
return { columns, rows };
|
|
15041
15041
|
}
|
|
@@ -15131,11 +15131,11 @@ function readPositionals(args) {
|
|
|
15131
15131
|
function splitIdList(raw) {
|
|
15132
15132
|
return raw.split(",").map((id) => id.trim()).filter(Boolean);
|
|
15133
15133
|
}
|
|
15134
|
-
function idsFileEntries(
|
|
15135
|
-
if (typeof
|
|
15134
|
+
function idsFileEntries(path40) {
|
|
15135
|
+
if (typeof path40 !== "string" || path40.length === 0) {
|
|
15136
15136
|
return [];
|
|
15137
15137
|
}
|
|
15138
|
-
return readFileSync4(
|
|
15138
|
+
return readFileSync4(path40, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).flatMap(splitIdList);
|
|
15139
15139
|
}
|
|
15140
15140
|
function requireTargets(args, entity) {
|
|
15141
15141
|
const positionals = readPositionals(args);
|
|
@@ -17756,9 +17756,9 @@ function compactRow(row) {
|
|
|
17756
17756
|
...destination.postUrn ? { postUrn: destination.postUrn } : {}
|
|
17757
17757
|
};
|
|
17758
17758
|
}
|
|
17759
|
-
function readPath(row,
|
|
17759
|
+
function readPath(row, path40) {
|
|
17760
17760
|
let current = row;
|
|
17761
|
-
for (const segment of
|
|
17761
|
+
for (const segment of path40.split(".")) {
|
|
17762
17762
|
const record = asRecord2(current);
|
|
17763
17763
|
if (!record) return void 0;
|
|
17764
17764
|
current = record[segment];
|
|
@@ -17768,10 +17768,10 @@ function readPath(row, path39) {
|
|
|
17768
17768
|
function projectFields(rows, paths) {
|
|
17769
17769
|
return rows.map((row) => {
|
|
17770
17770
|
const projected = {};
|
|
17771
|
-
for (const
|
|
17772
|
-
const value = readPath(row,
|
|
17771
|
+
for (const path40 of paths) {
|
|
17772
|
+
const value = readPath(row, path40);
|
|
17773
17773
|
if (value !== void 0) {
|
|
17774
|
-
projected[
|
|
17774
|
+
projected[path40] = value;
|
|
17775
17775
|
}
|
|
17776
17776
|
}
|
|
17777
17777
|
return projected;
|
|
@@ -19071,11 +19071,11 @@ var updateStatusSchema = z25.enum(UPDATE_STATUSES);
|
|
|
19071
19071
|
function currencyMinimums2(currencyCode) {
|
|
19072
19072
|
return CURRENCY_MINIMUMS2[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM2;
|
|
19073
19073
|
}
|
|
19074
|
-
function validateDailyBudgetFloor(money, ctx,
|
|
19074
|
+
function validateDailyBudgetFloor(money, ctx, path40) {
|
|
19075
19075
|
if (money?.currencyCode) {
|
|
19076
19076
|
const min = currencyMinimums2(money.currencyCode).dailyBudgetMin;
|
|
19077
19077
|
if (Number(money.amount) < min) {
|
|
19078
|
-
ctx.addIssue({ code: "custom", path:
|
|
19078
|
+
ctx.addIssue({ code: "custom", path: path40, message: `below the ${min} ${money.currencyCode} daily minimum` });
|
|
19079
19079
|
}
|
|
19080
19080
|
}
|
|
19081
19081
|
}
|
|
@@ -19159,6 +19159,13 @@ var campaignCreateSchema3 = z25.object({
|
|
|
19159
19159
|
dailyBudget: moneySchema2.optional(),
|
|
19160
19160
|
lifetimeBudget: moneySchema2.optional(),
|
|
19161
19161
|
spendCap: moneySchema2.optional(),
|
|
19162
|
+
/**
|
|
19163
|
+
* Ad-set budget sharing: lets ad sets lend up to 20% of their budget to each
|
|
19164
|
+
* other. Meta requires an explicit true/false on any campaign that carries no
|
|
19165
|
+
* campaign budget (subcode 4834011); Baker sends false unless asked, because
|
|
19166
|
+
* turning it on moves real spend between ad sets nobody asked to move.
|
|
19167
|
+
*/
|
|
19168
|
+
adSetBudgetSharing: z25.boolean().optional(),
|
|
19162
19169
|
start_time: z25.number().int().positive().optional(),
|
|
19163
19170
|
stop_time: z25.number().int().positive().optional()
|
|
19164
19171
|
}).superRefine((p, ctx) => {
|
|
@@ -19737,19 +19744,19 @@ function failWriteValidation3(message) {
|
|
|
19737
19744
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
19738
19745
|
process.exit(1);
|
|
19739
19746
|
}
|
|
19740
|
-
function loadJsonFileArg3(
|
|
19741
|
-
if (typeof
|
|
19747
|
+
function loadJsonFileArg3(path40) {
|
|
19748
|
+
if (typeof path40 !== "string" || path40.length === 0) {
|
|
19742
19749
|
return {};
|
|
19743
19750
|
}
|
|
19744
19751
|
try {
|
|
19745
|
-
const parsed = JSON.parse(readFileSync8(
|
|
19752
|
+
const parsed = JSON.parse(readFileSync8(path40, "utf8"));
|
|
19746
19753
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
19747
|
-
failWriteValidation3(`${
|
|
19754
|
+
failWriteValidation3(`${path40} must contain a JSON object`);
|
|
19748
19755
|
}
|
|
19749
19756
|
return parsed;
|
|
19750
19757
|
} catch (err) {
|
|
19751
19758
|
if (err instanceof SyntaxError) {
|
|
19752
|
-
failWriteValidation3(`${
|
|
19759
|
+
failWriteValidation3(`${path40} is not valid JSON: ${err.message}`);
|
|
19753
19760
|
}
|
|
19754
19761
|
throw err;
|
|
19755
19762
|
}
|
|
@@ -19871,6 +19878,7 @@ function campaignPayloadFromFlags2(args) {
|
|
|
19871
19878
|
dailyBudget: parseMoneyFlag2(args["daily-budget"], args.currency, "--daily-budget"),
|
|
19872
19879
|
lifetimeBudget: parseMoneyFlag2(args["lifetime-budget"], args.currency, "--lifetime-budget"),
|
|
19873
19880
|
spendCap: parseMoneyFlag2(args["spend-cap"], args.currency, "--spend-cap"),
|
|
19881
|
+
adSetBudgetSharing: args["adset-budget-sharing"] === void 0 ? void 0 : Boolean(args["adset-budget-sharing"]),
|
|
19874
19882
|
start_time: parseDateFlag2(args.start, "--start"),
|
|
19875
19883
|
stop_time: parseDateFlag2(args.stop, "--stop")
|
|
19876
19884
|
};
|
|
@@ -19904,6 +19912,10 @@ Example: baker ads meta campaigns create --name "Q3 Prospecting" --objective OUT
|
|
|
19904
19912
|
"special-ad-categories": { type: "string", description: "CSV: NONE|HOUSING|EMPLOYMENT|CREDIT|\u2026 (default NONE)" },
|
|
19905
19913
|
"special-ad-category-country": { type: "string", description: "CSV of 2-letter country codes" },
|
|
19906
19914
|
"buying-type": { type: "string", description: "AUCTION|RESERVED (default AUCTION)" },
|
|
19915
|
+
"adset-budget-sharing": {
|
|
19916
|
+
type: "boolean",
|
|
19917
|
+
description: "Let ad sets lend up to 20% of their budget to each other (off unless set; ignored with a campaign budget)"
|
|
19918
|
+
},
|
|
19907
19919
|
...campaignBudgetArgs,
|
|
19908
19920
|
file: { type: "string", description: "JSON file with the full payload; flags override file keys" }
|
|
19909
19921
|
},
|
|
@@ -20055,6 +20067,7 @@ function creativePayloadFromFlags(args) {
|
|
|
20055
20067
|
imageRef: args["image-ref"],
|
|
20056
20068
|
videoId: args["video-id"],
|
|
20057
20069
|
videoRef: args["video-ref"],
|
|
20070
|
+
thumbnailHash: args["thumbnail-hash"],
|
|
20058
20071
|
url_tags: args["url-tags"],
|
|
20059
20072
|
enhancements
|
|
20060
20073
|
};
|
|
@@ -20089,6 +20102,10 @@ Example: baker ads meta creatives create --page 555 --message "Save now" --link
|
|
|
20089
20102
|
"image-ref": { type: "string", description: "meta_temp_* ref of a staged media upload" },
|
|
20090
20103
|
"video-id": { type: "string", description: "Meta video id (already uploaded)" },
|
|
20091
20104
|
"video-ref": { type: "string", description: "meta_temp_* ref of a staged video upload" },
|
|
20105
|
+
"thumbnail-hash": {
|
|
20106
|
+
type: "string",
|
|
20107
|
+
description: "Cover image hash for a video ad (Meta's own cover is used when omitted)"
|
|
20108
|
+
},
|
|
20092
20109
|
"url-tags": { type: "string", description: "URL tracking params (utm_source=fb&\u2026)" },
|
|
20093
20110
|
"standard-enhancements": { type: "string", description: "Advantage+ Creative standard enhancements on|off" },
|
|
20094
20111
|
file: { type: "string", description: "JSON file with the full creative payload (carousel cards / dynamic assets)" }
|
|
@@ -24327,11 +24344,11 @@ function unwrap(response) {
|
|
|
24327
24344
|
}
|
|
24328
24345
|
return response.data;
|
|
24329
24346
|
}
|
|
24330
|
-
async function readAvatars(
|
|
24331
|
-
return unwrap(await apiGet(
|
|
24347
|
+
async function readAvatars(path40, params) {
|
|
24348
|
+
return unwrap(await apiGet(path40, params));
|
|
24332
24349
|
}
|
|
24333
|
-
async function writeAvatars(
|
|
24334
|
-
return unwrap(await apiPost(
|
|
24350
|
+
async function writeAvatars(path40, body) {
|
|
24351
|
+
return unwrap(await apiPost(path40, body));
|
|
24335
24352
|
}
|
|
24336
24353
|
|
|
24337
24354
|
// src/commands/avatars/create.ts
|
|
@@ -25165,12 +25182,12 @@ function missingFontFiles(urls, available) {
|
|
|
25165
25182
|
function planFontAdoption(sources, families) {
|
|
25166
25183
|
const wanted = new Map(families.map((family) => [normalizeFamily(family), family]));
|
|
25167
25184
|
const byFamily = /* @__PURE__ */ new Map();
|
|
25168
|
-
for (const { path:
|
|
25169
|
-
const dir = posix.dirname(
|
|
25185
|
+
for (const { path: path40, source } of sources) {
|
|
25186
|
+
const dir = posix.dirname(path40);
|
|
25170
25187
|
for (const face of declaredFontFaces(source)) {
|
|
25171
25188
|
if (!wanted.has(face.family)) continue;
|
|
25172
25189
|
const perFile = byFamily.get(face.family) ?? /* @__PURE__ */ new Map();
|
|
25173
|
-
perFile.set(
|
|
25190
|
+
perFile.set(path40, [...perFile.get(path40) ?? [], rebaseFontFaceSrc(face.block, dir)]);
|
|
25174
25191
|
byFamily.set(face.family, perFile);
|
|
25175
25192
|
}
|
|
25176
25193
|
}
|
|
@@ -33365,12 +33382,12 @@ function collectSideEffects(tree) {
|
|
|
33365
33382
|
);
|
|
33366
33383
|
}
|
|
33367
33384
|
function readFlowTree(slug) {
|
|
33368
|
-
const
|
|
33369
|
-
if (!existsSync5(
|
|
33385
|
+
const path40 = join3(flowsDir(), slug, "_data.json");
|
|
33386
|
+
if (!existsSync5(path40)) {
|
|
33370
33387
|
failLocal(`No form "${slug}". Run "baker flows list" to see the forms in this workspace.`);
|
|
33371
33388
|
}
|
|
33372
33389
|
try {
|
|
33373
|
-
return JSON.parse(readFileSync9(
|
|
33390
|
+
return JSON.parse(readFileSync9(path40, "utf-8"));
|
|
33374
33391
|
} catch (error) {
|
|
33375
33392
|
failLocal(`Could not read form "${slug}": ${error instanceof Error ? error.message : String(error)}`);
|
|
33376
33393
|
}
|
|
@@ -33762,10 +33779,10 @@ function parseValueExpression(raw) {
|
|
|
33762
33779
|
return parts.map(parsePart);
|
|
33763
33780
|
}
|
|
33764
33781
|
function trackingFieldIds() {
|
|
33765
|
-
const
|
|
33766
|
-
if (!existsSync6(
|
|
33782
|
+
const path40 = join4(flowsDir(), "..", "tracking.ts");
|
|
33783
|
+
if (!existsSync6(path40)) return null;
|
|
33767
33784
|
try {
|
|
33768
|
-
const source = readFileSync10(
|
|
33785
|
+
const source = readFileSync10(path40, "utf-8");
|
|
33769
33786
|
const block2 = source.match(/TRACKING_FIELD_IDS\s*=\s*\[([\s\S]*?)\]\s*as const/)?.[1];
|
|
33770
33787
|
if (!block2) return null;
|
|
33771
33788
|
const ids = [...block2.matchAll(/"(tracking\.[a-z0-9_]+)"/g)].map((match) => match[1]);
|
|
@@ -34317,13 +34334,13 @@ function specsFromFile(parsed) {
|
|
|
34317
34334
|
return `${destField}${type}=${entry?.value ?? ""}`;
|
|
34318
34335
|
});
|
|
34319
34336
|
}
|
|
34320
|
-
function readSpecFile(
|
|
34337
|
+
function readSpecFile(path40) {
|
|
34321
34338
|
let raw;
|
|
34322
34339
|
try {
|
|
34323
|
-
raw =
|
|
34340
|
+
raw = path40 === "-" ? readFileSync11(0, "utf-8") : readFileSync11(path40, "utf-8");
|
|
34324
34341
|
} catch (error) {
|
|
34325
34342
|
refuse(
|
|
34326
|
-
`Could not read ${
|
|
34343
|
+
`Could not read ${path40 === "-" ? "the mapping from stdin" : `"${path40}"`}: ${error instanceof Error ? error.message : String(error)}`
|
|
34327
34344
|
);
|
|
34328
34345
|
}
|
|
34329
34346
|
let parsed;
|
|
@@ -34331,7 +34348,7 @@ function readSpecFile(path39) {
|
|
|
34331
34348
|
parsed = JSON.parse(raw);
|
|
34332
34349
|
} catch (error) {
|
|
34333
34350
|
refuse(
|
|
34334
|
-
`${
|
|
34351
|
+
`${path40 === "-" ? "stdin" : `"${path40}"`} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,
|
|
34335
34352
|
'Expected { "map": { "<destField>": "<value>", \u2026 } }'
|
|
34336
34353
|
);
|
|
34337
34354
|
}
|
|
@@ -34585,18 +34602,18 @@ var ARRAY_FIELDS = [
|
|
|
34585
34602
|
"tagIds"
|
|
34586
34603
|
];
|
|
34587
34604
|
var ARRAY_OWNERS = ["", "body"];
|
|
34588
|
-
function dropUnsetOptionals(sideEffect,
|
|
34605
|
+
function dropUnsetOptionals(sideEffect, path40) {
|
|
34589
34606
|
return OPTIONAL_STRINGS.flatMap((key) => {
|
|
34590
34607
|
if (!(key in sideEffect) || sideEffect[key] !== null && sideEffect[key] !== "") return [];
|
|
34591
34608
|
delete sideEffect[key];
|
|
34592
|
-
return [{ path:
|
|
34609
|
+
return [{ path: path40, change: `dropped \`${key}\` (an optional string is absent, never null)` }];
|
|
34593
34610
|
});
|
|
34594
34611
|
}
|
|
34595
|
-
function fillNulledArrays(target, prefix,
|
|
34612
|
+
function fillNulledArrays(target, prefix, path40) {
|
|
34596
34613
|
return ARRAY_FIELDS.flatMap((key) => {
|
|
34597
34614
|
if (!(key in target) || target[key] !== null) return [];
|
|
34598
34615
|
target[key] = [];
|
|
34599
|
-
return [{ path:
|
|
34616
|
+
return [{ path: path40, change: `\`${prefix}${key}: null\` \u2192 \`[]\`` }];
|
|
34600
34617
|
});
|
|
34601
34618
|
}
|
|
34602
34619
|
function sideEffectsOf(node) {
|
|
@@ -34606,13 +34623,13 @@ function sideEffectsOf(node) {
|
|
|
34606
34623
|
);
|
|
34607
34624
|
}
|
|
34608
34625
|
function normalizeSideEffect(sideEffect, where) {
|
|
34609
|
-
const
|
|
34626
|
+
const path40 = `${where} \u2192 ${String(sideEffect.id ?? "side effect")}`;
|
|
34610
34627
|
const arrays = ARRAY_OWNERS.flatMap((owner) => {
|
|
34611
34628
|
const target = owner ? sideEffect[owner] : sideEffect;
|
|
34612
34629
|
if (!target || typeof target !== "object") return [];
|
|
34613
|
-
return fillNulledArrays(target, owner ? `${owner}.` : "",
|
|
34630
|
+
return fillNulledArrays(target, owner ? `${owner}.` : "", path40);
|
|
34614
34631
|
});
|
|
34615
|
-
return [...dropUnsetOptionals(sideEffect,
|
|
34632
|
+
return [...dropUnsetOptionals(sideEffect, path40), ...arrays];
|
|
34616
34633
|
}
|
|
34617
34634
|
function normalizeFlowTree(tree) {
|
|
34618
34635
|
const changes = [];
|
|
@@ -35150,10 +35167,10 @@ async function stageOps(ops) {
|
|
|
35150
35167
|
handleError2(err);
|
|
35151
35168
|
}
|
|
35152
35169
|
}
|
|
35153
|
-
async function draftAction2(
|
|
35170
|
+
async function draftAction2(path40, body, chat) {
|
|
35154
35171
|
const chatId = resolveChatId(chat);
|
|
35155
35172
|
try {
|
|
35156
|
-
const data = await apiPost(
|
|
35173
|
+
const data = await apiPost(path40, { chatId, ...body });
|
|
35157
35174
|
writeJsonEnvelope({ ok: true, data });
|
|
35158
35175
|
return data;
|
|
35159
35176
|
} catch (err) {
|
|
@@ -37585,9 +37602,9 @@ async function readImageBuffer(pathOrUrl) {
|
|
|
37585
37602
|
}
|
|
37586
37603
|
return readFile20(pathOrUrl);
|
|
37587
37604
|
}
|
|
37588
|
-
async function isDirectory(
|
|
37605
|
+
async function isDirectory(path40) {
|
|
37589
37606
|
try {
|
|
37590
|
-
const s = await stat4(
|
|
37607
|
+
const s = await stat4(path40);
|
|
37591
37608
|
return s.isDirectory();
|
|
37592
37609
|
} catch {
|
|
37593
37610
|
return false;
|
|
@@ -37889,13 +37906,13 @@ function resolveDownloadPath({ baseName, extension, out, outIsDirectory: outIsDi
|
|
|
37889
37906
|
}
|
|
37890
37907
|
function disambiguate(paths) {
|
|
37891
37908
|
const taken = /* @__PURE__ */ new Set();
|
|
37892
|
-
return paths.map((
|
|
37893
|
-
if (!taken.has(
|
|
37894
|
-
taken.add(
|
|
37895
|
-
return
|
|
37909
|
+
return paths.map((path40) => {
|
|
37910
|
+
if (!taken.has(path40)) {
|
|
37911
|
+
taken.add(path40);
|
|
37912
|
+
return path40;
|
|
37896
37913
|
}
|
|
37897
|
-
const ext = extname3(
|
|
37898
|
-
const stem =
|
|
37914
|
+
const ext = extname3(path40);
|
|
37915
|
+
const stem = path40.slice(0, path40.length - ext.length);
|
|
37899
37916
|
let n = 2;
|
|
37900
37917
|
while (taken.has(`${stem}-${n}${ext}`)) n += 1;
|
|
37901
37918
|
const unique = `${stem}-${n}${ext}`;
|
|
@@ -38022,10 +38039,10 @@ async function runDownloads(plan) {
|
|
|
38022
38039
|
const paths = disambiguate(fetched.map((item) => item.path));
|
|
38023
38040
|
const downloaded = [];
|
|
38024
38041
|
for (const [index, item] of fetched.entries()) {
|
|
38025
|
-
const
|
|
38042
|
+
const path40 = paths[index] ?? item.path;
|
|
38026
38043
|
try {
|
|
38027
|
-
await atomicWrite(
|
|
38028
|
-
downloaded.push({ input: item.input, output:
|
|
38044
|
+
await atomicWrite(path40, item.buffer);
|
|
38045
|
+
downloaded.push({ input: item.input, output: path40, bytes: item.buffer.length, contentType: item.contentType });
|
|
38029
38046
|
} catch (err) {
|
|
38030
38047
|
failed.push({ input: item.input, error: failureMessage(err, "Write failed") });
|
|
38031
38048
|
}
|
|
@@ -42706,7 +42723,7 @@ var pageCommand2 = defineCommand160({
|
|
|
42706
42723
|
|
|
42707
42724
|
// src/commands/landing/inspiration/scrape.ts
|
|
42708
42725
|
import { readFile as readFile23 } from "fs/promises";
|
|
42709
|
-
import
|
|
42726
|
+
import path34 from "path";
|
|
42710
42727
|
import { defineCommand as defineCommand161 } from "citty";
|
|
42711
42728
|
|
|
42712
42729
|
// src/engine/landing/lib/capturedReferences.ts
|
|
@@ -44773,6 +44790,44 @@ async function scrapeLanding(options) {
|
|
|
44773
44790
|
}
|
|
44774
44791
|
}
|
|
44775
44792
|
|
|
44793
|
+
// src/commands/landing/inspiration/captureOut.ts
|
|
44794
|
+
import { existsSync as existsSync9 } from "fs";
|
|
44795
|
+
import path33 from "path";
|
|
44796
|
+
var SCRATCH_DIR = ".baker";
|
|
44797
|
+
function isWithin(parent, target) {
|
|
44798
|
+
const relative = path33.relative(parent, target);
|
|
44799
|
+
return relative === "" || !relative.startsWith("..") && !path33.isAbsolute(relative);
|
|
44800
|
+
}
|
|
44801
|
+
function findRepoRoot(from) {
|
|
44802
|
+
let dir = path33.resolve(from);
|
|
44803
|
+
for (; ; ) {
|
|
44804
|
+
if (existsSync9(path33.join(dir, ".git"))) return dir;
|
|
44805
|
+
const parent = path33.dirname(dir);
|
|
44806
|
+
if (parent === dir) return null;
|
|
44807
|
+
dir = parent;
|
|
44808
|
+
}
|
|
44809
|
+
}
|
|
44810
|
+
function checkCaptureOut(out, options) {
|
|
44811
|
+
const { cwd, repoRoot } = options;
|
|
44812
|
+
const resolved = path33.resolve(cwd, out);
|
|
44813
|
+
if (repoRoot === null || !isWithin(repoRoot, resolved)) return { ok: true };
|
|
44814
|
+
const scratch = path33.join(repoRoot, SCRATCH_DIR);
|
|
44815
|
+
if (isWithin(scratch, resolved)) return { ok: true };
|
|
44816
|
+
const suggestion = path33.posix.join(SCRATCH_DIR, "teardowns", path33.basename(resolved) || "capture");
|
|
44817
|
+
return {
|
|
44818
|
+
ok: false,
|
|
44819
|
+
error: {
|
|
44820
|
+
code: "CAPTURE_OUT_NOT_SCRATCH",
|
|
44821
|
+
message: `A capture has to be written to ${SCRATCH_DIR}/ inside this workspace. It is reference material for this turn, and anywhere else it becomes a permanent part of the client's files.`,
|
|
44822
|
+
fix: {
|
|
44823
|
+
action: "retry_with_changes",
|
|
44824
|
+
explanation: `Re-run with --out ${suggestion}.`
|
|
44825
|
+
},
|
|
44826
|
+
retryable: false
|
|
44827
|
+
}
|
|
44828
|
+
};
|
|
44829
|
+
}
|
|
44830
|
+
|
|
44776
44831
|
// src/commands/landing/inspiration/scrape.ts
|
|
44777
44832
|
var RETRYABLE_FAILURES = /* @__PURE__ */ new Set([
|
|
44778
44833
|
"SITE_TOO_SLOW",
|
|
@@ -44787,7 +44842,7 @@ async function recordCapture(manifest, outDir) {
|
|
|
44787
44842
|
for (const section of manifest.sections) {
|
|
44788
44843
|
if (!section.bundle) continue;
|
|
44789
44844
|
try {
|
|
44790
|
-
const markup = await readFile23(
|
|
44845
|
+
const markup = await readFile23(path34.join(outDir, section.bundle), "utf8");
|
|
44791
44846
|
const copyStrings = capturedCopyStrings(markup);
|
|
44792
44847
|
if (copyStrings.length === 0) continue;
|
|
44793
44848
|
references.push({
|
|
@@ -44833,7 +44888,7 @@ registerSchema({
|
|
|
44833
44888
|
description: "Start here when the user points at a specific page and wants it now: capture one landing page into a directory of section screenshots, standalone HTML bundles, a whole-page reproduction and motion filmstrips. Returns when the capture is done, unlike `add`. Read the screenshots. Also records every captured section for the originality check.",
|
|
44834
44889
|
args: {
|
|
44835
44890
|
url: { type: "string", description: "Page to capture", required: true },
|
|
44836
|
-
out: { type: "string", description: "Output directory", required: true },
|
|
44891
|
+
out: { type: "string", description: "Output directory under .baker/", required: true },
|
|
44837
44892
|
mobile: { type: "boolean", description: "Phone-viewport pass. `--no-mobile` to skip", required: false },
|
|
44838
44893
|
code: {
|
|
44839
44894
|
type: "boolean",
|
|
@@ -44855,7 +44910,7 @@ var scrapeCommand = defineCommand161({
|
|
|
44855
44910
|
},
|
|
44856
44911
|
args: {
|
|
44857
44912
|
url: { type: "positional", description: "Page to capture", required: true },
|
|
44858
|
-
out: { type: "string", description: "Output directory", required: true },
|
|
44913
|
+
out: { type: "string", description: "Output directory, under .baker/", required: true },
|
|
44859
44914
|
mobile: {
|
|
44860
44915
|
type: "boolean",
|
|
44861
44916
|
description: "Phone-viewport pass (--no-mobile to skip)",
|
|
@@ -44872,6 +44927,14 @@ var scrapeCommand = defineCommand161({
|
|
|
44872
44927
|
report: { type: "boolean", description: "Write report.html (--no-report to skip)", required: false, default: true }
|
|
44873
44928
|
},
|
|
44874
44929
|
run: async ({ args }) => {
|
|
44930
|
+
const location2 = checkCaptureOut(args.out, {
|
|
44931
|
+
cwd: process.cwd(),
|
|
44932
|
+
repoRoot: findRepoRoot(process.cwd())
|
|
44933
|
+
});
|
|
44934
|
+
if (!location2.ok) {
|
|
44935
|
+
writeJson({ ok: false, error: location2.error });
|
|
44936
|
+
process.exit(1);
|
|
44937
|
+
}
|
|
44875
44938
|
try {
|
|
44876
44939
|
const manifest = await scrapeLanding({
|
|
44877
44940
|
url: args.url,
|
|
@@ -44949,12 +45012,12 @@ var scrapeCommand = defineCommand161({
|
|
|
44949
45012
|
});
|
|
44950
45013
|
|
|
44951
45014
|
// src/commands/landing/inspiration/search.ts
|
|
44952
|
-
import
|
|
45015
|
+
import path36 from "path";
|
|
44953
45016
|
import { defineCommand as defineCommand162 } from "citty";
|
|
44954
45017
|
|
|
44955
45018
|
// src/commands/landing/inspiration/shot.ts
|
|
44956
45019
|
import { mkdir as mkdir12, writeFile as writeFile17 } from "fs/promises";
|
|
44957
|
-
import
|
|
45020
|
+
import path35 from "path";
|
|
44958
45021
|
import sharp6 from "sharp";
|
|
44959
45022
|
var READABLE_SHOT = {
|
|
44960
45023
|
maxWidth: 1440,
|
|
@@ -44980,9 +45043,9 @@ async function downloadReadableShot(url, file) {
|
|
|
44980
45043
|
const response = await fetch(url);
|
|
44981
45044
|
if (!response.ok) return null;
|
|
44982
45045
|
const shot = await toReadableShot(Buffer.from(await response.arrayBuffer()));
|
|
44983
|
-
await mkdir12(
|
|
45046
|
+
await mkdir12(path35.dirname(file), { recursive: true });
|
|
44984
45047
|
await writeFile17(file, shot);
|
|
44985
|
-
return
|
|
45048
|
+
return path35.relative(process.cwd(), file);
|
|
44986
45049
|
} catch {
|
|
44987
45050
|
return null;
|
|
44988
45051
|
}
|
|
@@ -45074,13 +45137,13 @@ function buildSearchBody(args) {
|
|
|
45074
45137
|
return body;
|
|
45075
45138
|
}
|
|
45076
45139
|
async function downloadShots(results) {
|
|
45077
|
-
const dir =
|
|
45140
|
+
const dir = path36.join(process.cwd(), ".baker", "inspiration");
|
|
45078
45141
|
const saved = /* @__PURE__ */ new Map();
|
|
45079
45142
|
await Promise.all(
|
|
45080
45143
|
results.map(async (result) => {
|
|
45081
45144
|
const file = await downloadReadableShot(
|
|
45082
45145
|
result.desktopShotUrl,
|
|
45083
|
-
|
|
45146
|
+
path36.join(dir, `${result.id}.${READABLE_SHOT.extension}`)
|
|
45084
45147
|
);
|
|
45085
45148
|
if (file) saved.set(result.id, file);
|
|
45086
45149
|
})
|
|
@@ -45308,7 +45371,7 @@ var sequencesCommand = defineCommand163({
|
|
|
45308
45371
|
});
|
|
45309
45372
|
|
|
45310
45373
|
// src/commands/landing/inspiration/view.ts
|
|
45311
|
-
import
|
|
45374
|
+
import path37 from "path";
|
|
45312
45375
|
import { defineCommand as defineCommand164 } from "citty";
|
|
45313
45376
|
registerSchema({
|
|
45314
45377
|
command: "landing.inspiration.view",
|
|
@@ -45341,12 +45404,12 @@ var viewCommand2 = defineCommand164({
|
|
|
45341
45404
|
const id = args.id;
|
|
45342
45405
|
const data = await apiGet("/api/landing-inspiration/section", { id });
|
|
45343
45406
|
const section = data.section;
|
|
45344
|
-
const dir =
|
|
45407
|
+
const dir = path37.join(process.cwd(), ".baker", "inspiration", id);
|
|
45345
45408
|
const ext = READABLE_SHOT.extension;
|
|
45346
45409
|
const [desktop, mobile, filmstrip] = await Promise.all([
|
|
45347
|
-
downloadReadableShot(section.desktopShotUrl,
|
|
45348
|
-
downloadReadableShot(section.mobileShotUrl,
|
|
45349
|
-
downloadReadableShot(section.motionFilmstripUrl,
|
|
45410
|
+
downloadReadableShot(section.desktopShotUrl, path37.join(dir, `desktop.${ext}`)),
|
|
45411
|
+
downloadReadableShot(section.mobileShotUrl, path37.join(dir, `mobile.${ext}`)),
|
|
45412
|
+
downloadReadableShot(section.motionFilmstripUrl, path37.join(dir, `motion-filmstrip.${ext}`))
|
|
45350
45413
|
]);
|
|
45351
45414
|
const full = args.full;
|
|
45352
45415
|
const hints = [INSPIRATION_HINTS.structureNotCopy, INSPIRATION_HINTS.adapt];
|
|
@@ -47196,7 +47259,7 @@ var listCommand15 = defineCommand183({
|
|
|
47196
47259
|
|
|
47197
47260
|
// src/commands/scheduled-actions/templates.ts
|
|
47198
47261
|
import { readFile as readFile24 } from "fs/promises";
|
|
47199
|
-
import
|
|
47262
|
+
import path38 from "path";
|
|
47200
47263
|
import { defineCommand as defineCommand184 } from "citty";
|
|
47201
47264
|
registerSchema({
|
|
47202
47265
|
command: "scheduled-actions.templates",
|
|
@@ -47299,7 +47362,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-actions.md`
|
|
|
47299
47362
|
}
|
|
47300
47363
|
if (save.length > 0) {
|
|
47301
47364
|
const briefFile = flag("brief-file");
|
|
47302
|
-
const brief = briefFile.length > 0 ? await readFile24(
|
|
47365
|
+
const brief = briefFile.length > 0 ? await readFile24(path38.resolve(briefFile), "utf8") : flag("brief");
|
|
47303
47366
|
if (brief.trim().length === 0) {
|
|
47304
47367
|
failValidation4("--brief-file (preferred) or --brief is required: the brief is the recipe.");
|
|
47305
47368
|
}
|
|
@@ -47770,7 +47833,7 @@ function parseImageRefs(spec) {
|
|
|
47770
47833
|
}
|
|
47771
47834
|
var defaultDeps = {
|
|
47772
47835
|
ingest: (url) => apiPost("/api/images/ingest", { url, source: "uploaded" }),
|
|
47773
|
-
upload: (
|
|
47836
|
+
upload: (path40) => uploadLocalImage({ file: path40, contentType: detectImageContentType(path40), source: "uploaded" })
|
|
47774
47837
|
};
|
|
47775
47838
|
async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
|
|
47776
47839
|
const refs = parseImageRefs(spec);
|
|
@@ -47790,10 +47853,10 @@ async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
|
|
|
47790
47853
|
}
|
|
47791
47854
|
return { imageIds, added };
|
|
47792
47855
|
}
|
|
47793
|
-
function uploadFailure(
|
|
47856
|
+
function uploadFailure(path40) {
|
|
47794
47857
|
return (error) => {
|
|
47795
47858
|
if (error instanceof ApiError) throw error;
|
|
47796
|
-
throw new ApiError("VALIDATION_ERROR", `Could not read "${
|
|
47859
|
+
throw new ApiError("VALIDATION_ERROR", `Could not read "${path40}" as an image.`);
|
|
47797
47860
|
};
|
|
47798
47861
|
}
|
|
47799
47862
|
|
|
@@ -48855,10 +48918,10 @@ async function stageOp4(op) {
|
|
|
48855
48918
|
handleError5(err);
|
|
48856
48919
|
}
|
|
48857
48920
|
}
|
|
48858
|
-
async function draftAction3(
|
|
48921
|
+
async function draftAction3(path40, body, chat) {
|
|
48859
48922
|
const chatId = resolveChatId(chat);
|
|
48860
48923
|
try {
|
|
48861
|
-
const data = await apiPost(
|
|
48924
|
+
const data = await apiPost(path40, { chatId, ...body });
|
|
48862
48925
|
writeJsonEnvelope({ ok: true, data });
|
|
48863
48926
|
return data;
|
|
48864
48927
|
} catch (err) {
|
|
@@ -49965,7 +50028,7 @@ var groupCommand2 = defineCommand209({
|
|
|
49965
50028
|
// src/commands/videos/ingest.ts
|
|
49966
50029
|
import { mkdtemp as mkdtemp2, rm as rm7, stat as stat7 } from "fs/promises";
|
|
49967
50030
|
import { tmpdir as tmpdir3 } from "os";
|
|
49968
|
-
import
|
|
50031
|
+
import path39 from "path";
|
|
49969
50032
|
import { defineCommand as defineCommand210 } from "citty";
|
|
49970
50033
|
|
|
49971
50034
|
// src/lib/streamUpload.ts
|
|
@@ -50316,7 +50379,7 @@ function ingestUrl(args) {
|
|
|
50316
50379
|
}
|
|
50317
50380
|
async function downloadThenIngest(args, country) {
|
|
50318
50381
|
const vimeoCookie = captureVimeoCookie();
|
|
50319
|
-
const workDir = await mkdtemp2(
|
|
50382
|
+
const workDir = await mkdtemp2(path39.join(tmpdir3(), "videos-ingest-"));
|
|
50320
50383
|
try {
|
|
50321
50384
|
const probe = await probeYtDlp({ url: args.url, country, vimeoCookie, cookieDir: workDir });
|
|
50322
50385
|
if (isAudioOnly(probe.info)) {
|
|
@@ -51936,7 +51999,7 @@ function unknownFlagEnvelope(unknown, commandPath, suggestion) {
|
|
|
51936
51999
|
};
|
|
51937
52000
|
}
|
|
51938
52001
|
function commandPathOf(root, argv) {
|
|
51939
|
-
const
|
|
52002
|
+
const path40 = [];
|
|
51940
52003
|
let command = root;
|
|
51941
52004
|
for (const token of argv) {
|
|
51942
52005
|
if (token === "--" || token.startsWith("-")) {
|
|
@@ -51947,10 +52010,10 @@ function commandPathOf(root, argv) {
|
|
|
51947
52010
|
if (next === void 0 || typeof next !== "object") {
|
|
51948
52011
|
break;
|
|
51949
52012
|
}
|
|
51950
|
-
|
|
52013
|
+
path40.push(token);
|
|
51951
52014
|
command = next;
|
|
51952
52015
|
}
|
|
51953
|
-
return
|
|
52016
|
+
return path40.join(" ");
|
|
51954
52017
|
}
|
|
51955
52018
|
function refuseUnknownFlags(root, argv) {
|
|
51956
52019
|
const unknown = findUnknownFlags(root, argv);
|