@koda-sl/baker-cli 0.191.0 → 0.192.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
|
@@ -47,7 +47,7 @@ import {
|
|
|
47
47
|
toModelSafeImage,
|
|
48
48
|
ulid,
|
|
49
49
|
validateCanvasDeep
|
|
50
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-ISZWNERZ.js";
|
|
51
51
|
import {
|
|
52
52
|
csvOrJson,
|
|
53
53
|
daysAgoIso,
|
|
@@ -11142,7 +11142,7 @@ var assetsUpdateCommand = defineCommand30({
|
|
|
11142
11142
|
var assetsCommand = defineCommand30({
|
|
11143
11143
|
meta: {
|
|
11144
11144
|
name: "assets",
|
|
11145
|
-
description: "Stage asset create/update + asset-link attach/detach (via --file). For a high-performance Search campaign add \u22654 sitelinks, \u22653 callouts,
|
|
11145
|
+
description: "Stage asset create/update + asset-link attach/detach (via --file). For a high-performance Search campaign add \u22654 sitelinks, \u22653 callouts, \u22651 structured snippet, and \u22653 image assets per campaign. Build the images with the creative-canvas-ads flow (platform preset `google_search`) \u2014 product or team in action, never stock, and never a logo on a plain background."
|
|
11146
11146
|
},
|
|
11147
11147
|
subCommands: {
|
|
11148
11148
|
create: fileCreateCommand(
|
|
@@ -35559,20 +35559,29 @@ async function captureMobileShots(args) {
|
|
|
35559
35559
|
await mobile.context.close();
|
|
35560
35560
|
}
|
|
35561
35561
|
}
|
|
35562
|
+
var MOTION_CONCURRENCY = 3;
|
|
35562
35563
|
async function captureMotionTakes(args) {
|
|
35563
35564
|
const { browser, sections, sectionsDir, outDir, pageUrl, log } = args;
|
|
35564
35565
|
const moving = sections.filter((section) => isWorthFilming(section.motion));
|
|
35565
35566
|
if (moving.length === 0) return;
|
|
35566
35567
|
log(`filming ${moving.length} moving sections`);
|
|
35567
|
-
|
|
35568
|
-
const take = await captureMotionTake(browser, pageUrl, section.selector);
|
|
35569
|
-
if (!take)
|
|
35568
|
+
const filmOne = async (section) => {
|
|
35569
|
+
const take = await captureMotionTake(browser, pageUrl, section.selector).catch(() => null);
|
|
35570
|
+
if (!take) return;
|
|
35570
35571
|
const dir = path31.join(sectionsDir, String(section.index).padStart(2, "0"));
|
|
35571
35572
|
const file = path31.join(dir, "motion-filmstrip.png");
|
|
35572
35573
|
await writeFile15(file, take.filmstrip);
|
|
35573
35574
|
section.motionFilmstrip = path31.relative(outDir, file);
|
|
35574
35575
|
log(` [${section.index}] ${section.motion.summary}`);
|
|
35575
|
-
}
|
|
35576
|
+
};
|
|
35577
|
+
const queue = [...moving];
|
|
35578
|
+
await Promise.all(
|
|
35579
|
+
Array.from({ length: Math.min(MOTION_CONCURRENCY, queue.length) }, async () => {
|
|
35580
|
+
for (let next = queue.shift(); next; next = queue.shift()) {
|
|
35581
|
+
await filmOne(next);
|
|
35582
|
+
}
|
|
35583
|
+
})
|
|
35584
|
+
);
|
|
35576
35585
|
}
|
|
35577
35586
|
async function scrapeLanding(options) {
|
|
35578
35587
|
const timeoutMs = options.timeoutMs ?? 45e3;
|
|
@@ -35666,6 +35675,54 @@ async function scrapeLanding(options) {
|
|
|
35666
35675
|
}
|
|
35667
35676
|
}
|
|
35668
35677
|
|
|
35678
|
+
// src/engine/landing-library/unreachable.ts
|
|
35679
|
+
var NET_ERROR_REASONS = [
|
|
35680
|
+
{
|
|
35681
|
+
prefixes: ["ERR_NAME_NOT_RESOLVED", "ERR_NAME_RESOLUTION_FAILED"],
|
|
35682
|
+
message: "We couldn't find this site \u2014 check the address is spelled right."
|
|
35683
|
+
},
|
|
35684
|
+
{
|
|
35685
|
+
prefixes: ["ERR_SSL_", "ERR_CERT_", "ERR_TLS_", "ERR_BAD_SSL_"],
|
|
35686
|
+
message: "This site's secure connection is broken, so no browser can open it \u2014 including ours. That's a fault on their side, not something you can fix here."
|
|
35687
|
+
},
|
|
35688
|
+
{
|
|
35689
|
+
prefixes: ["ERR_TOO_MANY_REDIRECTS"],
|
|
35690
|
+
message: "This site kept redirecting us and never settled on a page."
|
|
35691
|
+
},
|
|
35692
|
+
{
|
|
35693
|
+
prefixes: ["ERR_BLOCKED_BY_", "ERR_ACCESS_DENIED"],
|
|
35694
|
+
message: "This site refused our visit, so we couldn't read the page."
|
|
35695
|
+
},
|
|
35696
|
+
{
|
|
35697
|
+
prefixes: [
|
|
35698
|
+
"ERR_CONNECTION_",
|
|
35699
|
+
"ERR_ADDRESS_UNREACHABLE",
|
|
35700
|
+
"ERR_EMPTY_RESPONSE",
|
|
35701
|
+
"ERR_NETWORK_CHANGED",
|
|
35702
|
+
"ERR_INTERNET_DISCONNECTED",
|
|
35703
|
+
"ERR_TIMED_OUT"
|
|
35704
|
+
],
|
|
35705
|
+
message: "This site didn't respond, so we couldn't read the page. It may be down \u2014 try again later."
|
|
35706
|
+
}
|
|
35707
|
+
];
|
|
35708
|
+
var GENERIC_UNREACHABLE = "We couldn't open this site, so there was no page to study.";
|
|
35709
|
+
var TOO_SLOW = "This site took too long to load, so we stopped waiting. Try again later.";
|
|
35710
|
+
function describeUnreachableSite(error) {
|
|
35711
|
+
const raw = error instanceof Error ? error.message : typeof error === "string" ? error : "";
|
|
35712
|
+
if (!raw) return null;
|
|
35713
|
+
const netError = /net::(ERR_[A-Z0-9_]+)/.exec(raw)?.[1];
|
|
35714
|
+
if (netError) {
|
|
35715
|
+
const reason = NET_ERROR_REASONS.find(
|
|
35716
|
+
(candidate) => candidate.prefixes.some((prefix) => netError.startsWith(prefix))
|
|
35717
|
+
);
|
|
35718
|
+
return { code: "SITE_UNREACHABLE", message: reason?.message ?? GENERIC_UNREACHABLE };
|
|
35719
|
+
}
|
|
35720
|
+
if (/Timeout \d+ms exceeded/.test(raw) || raw.includes("page.goto: Timeout")) {
|
|
35721
|
+
return { code: "SITE_UNREACHABLE", message: TOO_SLOW };
|
|
35722
|
+
}
|
|
35723
|
+
return null;
|
|
35724
|
+
}
|
|
35725
|
+
|
|
35669
35726
|
// src/commands/landing/inspiration/scrape.ts
|
|
35670
35727
|
async function recordCapture(manifest, outDir) {
|
|
35671
35728
|
const consultedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -35701,7 +35758,7 @@ registerSchema({
|
|
|
35701
35758
|
},
|
|
35702
35759
|
motion: {
|
|
35703
35760
|
type: "boolean",
|
|
35704
|
-
description: "Film sections that move. `--no-motion` to skip \u2014
|
|
35761
|
+
description: "Film sections that move. `--no-motion` to skip \u2014 the single biggest lever on runtime",
|
|
35705
35762
|
required: false
|
|
35706
35763
|
},
|
|
35707
35764
|
report: { type: "boolean", description: "Write report.html. `--no-report` to skip", required: false }
|
|
@@ -35773,6 +35830,11 @@ var scrapeCommand = defineCommand147({
|
|
|
35773
35830
|
writeJson({ ok: false, error: { code: error.code, message: error.message } });
|
|
35774
35831
|
process.exit(1);
|
|
35775
35832
|
}
|
|
35833
|
+
const unreachable = describeUnreachableSite(error);
|
|
35834
|
+
if (unreachable) {
|
|
35835
|
+
writeJson({ ok: false, error: { code: unreachable.code, message: unreachable.message } });
|
|
35836
|
+
process.exit(1);
|
|
35837
|
+
}
|
|
35776
35838
|
reportError(error);
|
|
35777
35839
|
}
|
|
35778
35840
|
}
|