@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-OWDTSPY4.js";
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, and \u22651 structured snippet per campaign."
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
- for (const section of moving) {
35568
- const take = await captureMotionTake(browser, pageUrl, section.selector);
35569
- if (!take) continue;
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 roughly halves runtime",
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
  }