happo 6.3.6 → 6.4.1

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.
Files changed (57) hide show
  1. package/dist/cli/cancelJob-ROJDWYPD.js +10 -0
  2. package/dist/cli/{chunk-2F4ONKOX.js → chunk-F4CUEMIS.js} +3 -3
  3. package/dist/cli/{chunk-VOPCZYUD.js → chunk-FZHTC4L5.js} +2 -2
  4. package/dist/cli/{chunk-VOPCZYUD.js.map → chunk-FZHTC4L5.js.map} +1 -1
  5. package/dist/cli/{chunk-4FHG27V2.js → chunk-JAUTKTZY.js} +4 -4
  6. package/dist/cli/chunk-JAUTKTZY.js.map +7 -0
  7. package/dist/cli/{chunk-QIVIGY3K.js → chunk-JQ5JKJGY.js} +2 -2
  8. package/dist/cli/{chunk-GBORF5SP.js → chunk-NAK4M3PS.js} +2 -2
  9. package/dist/cli/{chunk-B4NWDBAN.js → chunk-XM2DXDSO.js} +2 -2
  10. package/dist/cli/chunk-XM2DXDSO.js.map +7 -0
  11. package/dist/cli/createAsyncComparison-37KSA6M4.js +10 -0
  12. package/dist/cli/{createAsyncReport-MZGC4WYR.js → createAsyncReport-XKNIFAJB.js} +4 -4
  13. package/dist/cli/{getFlakes-OZICV3BM.js → getFlakes-KRJUAUHV.js} +4 -4
  14. package/dist/cli/main.js +11 -11
  15. package/dist/cli/package-S5HBIHRL.js +7 -0
  16. package/dist/cli/{prepareSnapRequests-6BOXFGHI.js → prepareSnapRequests-EXILTRP4.js} +112 -70
  17. package/dist/cli/prepareSnapRequests-EXILTRP4.js.map +7 -0
  18. package/dist/cli/startJob-KT7MPC4H.js +10 -0
  19. package/dist/cli/{wrapper-UNP6YKH6.js → wrapper-KRUJ2F4T.js} +7 -7
  20. package/dist/config/RemoteBrowserTarget.d.ts +8 -2
  21. package/dist/config/RemoteBrowserTarget.d.ts.map +1 -1
  22. package/dist/config/index.d.ts +5 -1
  23. package/dist/config/index.d.ts.map +1 -1
  24. package/dist/config/index.js.map +2 -2
  25. package/dist/cypress/task.js +19 -10
  26. package/dist/cypress/task.js.map +2 -2
  27. package/dist/network/fetchWithRetry.d.ts +1 -1
  28. package/dist/network/fetchWithRetry.d.ts.map +1 -1
  29. package/dist/network/makeHappoAPIRequest.d.ts +1 -1
  30. package/dist/network/makeHappoAPIRequest.d.ts.map +1 -1
  31. package/dist/network/prepareSnapRequests.d.ts.map +1 -1
  32. package/dist/playwright/index.js +19 -10
  33. package/dist/playwright/index.js.map +2 -2
  34. package/dist/storybook/getStorybookStoryCount.d.ts +7 -0
  35. package/dist/storybook/getStorybookStoryCount.d.ts.map +1 -0
  36. package/dist/storybook/index.d.ts +5 -1
  37. package/dist/storybook/index.d.ts.map +1 -1
  38. package/dist/storybook/index.js +56 -35
  39. package/dist/storybook/index.js.map +4 -4
  40. package/package.json +1 -1
  41. package/dist/cli/cancelJob-LQPQPD5I.js +0 -10
  42. package/dist/cli/chunk-4FHG27V2.js.map +0 -7
  43. package/dist/cli/chunk-B4NWDBAN.js.map +0 -7
  44. package/dist/cli/createAsyncComparison-5ZQY53AW.js +0 -10
  45. package/dist/cli/package-FRXI4E4G.js +0 -7
  46. package/dist/cli/prepareSnapRequests-6BOXFGHI.js.map +0 -7
  47. package/dist/cli/startJob-GASMCYIM.js +0 -10
  48. /package/dist/cli/{cancelJob-LQPQPD5I.js.map → cancelJob-ROJDWYPD.js.map} +0 -0
  49. /package/dist/cli/{chunk-2F4ONKOX.js.map → chunk-F4CUEMIS.js.map} +0 -0
  50. /package/dist/cli/{chunk-QIVIGY3K.js.map → chunk-JQ5JKJGY.js.map} +0 -0
  51. /package/dist/cli/{chunk-GBORF5SP.js.map → chunk-NAK4M3PS.js.map} +0 -0
  52. /package/dist/cli/{createAsyncComparison-5ZQY53AW.js.map → createAsyncComparison-37KSA6M4.js.map} +0 -0
  53. /package/dist/cli/{createAsyncReport-MZGC4WYR.js.map → createAsyncReport-XKNIFAJB.js.map} +0 -0
  54. /package/dist/cli/{getFlakes-OZICV3BM.js.map → getFlakes-KRJUAUHV.js.map} +0 -0
  55. /package/dist/cli/{package-FRXI4E4G.js.map → package-S5HBIHRL.js.map} +0 -0
  56. /package/dist/cli/{startJob-GASMCYIM.js.map → startJob-KT7MPC4H.js.map} +0 -0
  57. /package/dist/cli/{wrapper-UNP6YKH6.js.map → wrapper-KRUJ2F4T.js.map} +0 -0
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  makeHappoAPIRequest
3
- } from "./chunk-B4NWDBAN.js";
4
- import "./chunk-4FHG27V2.js";
5
- import "./chunk-VOPCZYUD.js";
3
+ } from "./chunk-XM2DXDSO.js";
4
+ import "./chunk-JAUTKTZY.js";
5
+ import "./chunk-FZHTC4L5.js";
6
6
 
7
7
  // src/network/prepareSnapRequests.ts
8
- import fs5 from "node:fs";
9
- import path5 from "node:path";
8
+ import fs6 from "node:fs";
9
+ import path6 from "node:path";
10
10
 
11
11
  // src/utils/createHash.ts
12
12
  import crypto from "node:crypto";
@@ -16,6 +16,12 @@ function createHash(data) {
16
16
 
17
17
  // src/config/RemoteBrowserTarget.ts
18
18
  var VIEWPORT_PATTERN = /^([0-9]+)x([0-9]+)$/;
19
+ function computeDefaultChunks(estimatedSnapCount) {
20
+ if (!Number.isFinite(estimatedSnapCount) || estimatedSnapCount <= 0) {
21
+ return 1;
22
+ }
23
+ return Math.min(20, Math.ceil(estimatedSnapCount / 100));
24
+ }
19
25
  function getPageSlices(pages, chunks) {
20
26
  const result = [];
21
27
  const pagesPerChunk = Math.ceil(pages.length / chunks);
@@ -38,7 +44,7 @@ var RemoteBrowserTarget = class {
38
44
  otherOptions;
39
45
  constructor(browserName, {
40
46
  viewport = "1024x768",
41
- chunks = 1,
47
+ chunks,
42
48
  maxHeight,
43
49
  ...otherOptions
44
50
  }) {
@@ -65,7 +71,8 @@ var RemoteBrowserTarget = class {
65
71
  staticPackage,
66
72
  snapPayloads,
67
73
  pages,
68
- targetName
74
+ targetName,
75
+ estimatedSnapsCount
69
76
  }, config) {
70
77
  const boundMakeRequest = async ({
71
78
  slice,
@@ -121,22 +128,24 @@ var RemoteBrowserTarget = class {
121
128
  };
122
129
  const requestIds = [];
123
130
  if (staticPackage) {
124
- for (let i = 0; i < this.chunks; i += 1) {
131
+ const effectiveChunks = this.chunks ?? Math.max(1, computeDefaultChunks(estimatedSnapsCount ?? 0));
132
+ for (let i = 0; i < effectiveChunks; i += 1) {
125
133
  const requestId = await boundMakeRequest({
126
- chunk: { index: i, total: this.chunks }
134
+ chunk: effectiveChunks > 1 ? { index: i, total: effectiveChunks } : void 0
127
135
  });
128
136
  requestIds.push(requestId);
129
137
  }
130
138
  } else if (pages) {
131
- for (const pageSlice of getPageSlices(pages, this.chunks)) {
139
+ for (const pageSlice of getPageSlices(pages, this.chunks ?? 1)) {
132
140
  const requestId = await boundMakeRequest({
133
141
  pageSlice
134
142
  });
135
143
  requestIds.push(requestId);
136
144
  }
137
145
  } else {
138
- const snapsPerChunk = Math.ceil((snapPayloads?.length ?? 0) / this.chunks);
139
- for (let i = 0; i < this.chunks; i += 1) {
146
+ const effectiveChunks = this.chunks ?? 1;
147
+ const snapsPerChunk = Math.ceil((snapPayloads?.length ?? 0) / effectiveChunks);
148
+ for (let i = 0; i < effectiveChunks; i += 1) {
140
149
  const slice = snapPayloads?.slice(
141
150
  i * snapsPerChunk,
142
151
  i * snapsPerChunk + snapsPerChunk
@@ -153,8 +162,8 @@ var RemoteBrowserTarget = class {
153
162
 
154
163
  // src/storybook/index.ts
155
164
  import { spawn } from "node:child_process";
156
- import fs3 from "node:fs";
157
- import path3 from "node:path";
165
+ import fs4 from "node:fs";
166
+ import path4 from "node:path";
158
167
 
159
168
  // src/storybook/getStorybookBuildCommandParts.ts
160
169
  import fs from "node:fs";
@@ -191,11 +200,27 @@ function getStorybookBuildCommandParts(packageJsonPath = path.join(process.cwd()
191
200
  return ["storybook", "build"];
192
201
  }
193
202
 
194
- // src/storybook/getStorybookVersionFromPackageJson.ts
203
+ // src/storybook/getStorybookStoryCount.ts
195
204
  import fs2 from "node:fs";
196
205
  import path2 from "node:path";
197
- function getStorybookVersionFromPackageJson(packageJsonPath = path2.join(process.cwd(), "package.json")) {
198
- const data = fs2.readFileSync(packageJsonPath, "utf8");
206
+ async function getStorybookStoryCount(packageDir) {
207
+ const indexPath = path2.join(packageDir, "index.json");
208
+ try {
209
+ const content = await fs2.promises.readFile(indexPath, "utf8");
210
+ const data = JSON.parse(content);
211
+ const entries = data.entries ?? data.stories ?? {};
212
+ return Object.values(entries).filter((e) => e.type === "story").length;
213
+ } catch (error) {
214
+ console.warn("Failed to get estimated snaps count from Storybook:", error);
215
+ return void 0;
216
+ }
217
+ }
218
+
219
+ // src/storybook/getStorybookVersionFromPackageJson.ts
220
+ import fs3 from "node:fs";
221
+ import path3 from "node:path";
222
+ function getStorybookVersionFromPackageJson(packageJsonPath = path3.join(process.cwd(), "package.json")) {
223
+ const data = fs3.readFileSync(packageJsonPath, "utf8");
199
224
  const packageJson = JSON.parse(data);
200
225
  const combinedDependencies = {
201
226
  ...packageJson.dependencies,
@@ -237,35 +262,35 @@ function resolveBuildCommandParts() {
237
262
  }
238
263
  return getStorybookBuildCommandParts();
239
264
  }
240
- function buildStorybook({
265
+ async function buildStorybook({
241
266
  configDir,
242
267
  staticDir,
243
268
  outputDir
244
269
  }) {
270
+ await fs4.promises.rm(outputDir, { recursive: true, force: true });
271
+ const buildCommandParts = resolveBuildCommandParts();
272
+ if (!buildCommandParts[0]) {
273
+ throw new Error("Failed to resolve build command parts");
274
+ }
275
+ const params = [
276
+ ...buildCommandParts,
277
+ "--output-dir",
278
+ outputDir,
279
+ "--config-dir",
280
+ configDir
281
+ ];
282
+ if (staticDir) {
283
+ params.push("--static-dir", staticDir);
284
+ }
285
+ let binary = fs4.existsSync("yarn.lock") ? "yarn" : "npx";
286
+ if (buildCommandParts[0].includes("node_modules")) {
287
+ binary = buildCommandParts[0];
288
+ params.shift();
289
+ }
290
+ if (HAPPO_DEBUG2) {
291
+ console.log(`[happo] Using build command \`${binary} ${params.join(" ")}\``);
292
+ }
245
293
  return new Promise((resolve, reject) => {
246
- fs3.rmSync(outputDir, { recursive: true, force: true });
247
- const buildCommandParts = resolveBuildCommandParts();
248
- if (!buildCommandParts[0]) {
249
- throw new Error("Failed to resolve build command parts");
250
- }
251
- const params = [
252
- ...buildCommandParts,
253
- "--output-dir",
254
- outputDir,
255
- "--config-dir",
256
- configDir
257
- ];
258
- if (staticDir) {
259
- params.push("--static-dir", staticDir);
260
- }
261
- let binary = fs3.existsSync("yarn.lock") ? "yarn" : "npx";
262
- if (buildCommandParts[0].includes("node_modules")) {
263
- binary = buildCommandParts[0];
264
- params.shift();
265
- }
266
- if (HAPPO_DEBUG2) {
267
- console.log(`[happo] Using build command \`${binary} ${params.join(" ")}\``);
268
- }
269
294
  const spawned = spawn(binary, params, {
270
295
  stdio: "inherit",
271
296
  shell: process.platform == "win32"
@@ -273,7 +298,7 @@ function buildStorybook({
273
298
  spawned.on("exit", (code) => {
274
299
  if (code === 0) {
275
300
  try {
276
- fs3.unlinkSync(path3.join(outputDir, "project.json"));
301
+ fs4.unlinkSync(path4.join(outputDir, "project.json"));
277
302
  } catch (error) {
278
303
  console.warn(
279
304
  `Ignoring error when attempting to remove project.json: ${error}`
@@ -296,8 +321,8 @@ async function buildStorybookPackage({
296
321
  if (!usePrebuiltPackage) {
297
322
  await buildStorybook({ configDir, staticDir, outputDir });
298
323
  }
299
- const iframePath = path3.join(outputDir, "iframe.html");
300
- if (!fs3.existsSync(iframePath)) {
324
+ const iframePath = path4.join(outputDir, "iframe.html");
325
+ if (!fs4.existsSync(iframePath)) {
301
326
  throw new Error(
302
327
  "Failed to build static storybook package (missing iframe.html)"
303
328
  );
@@ -305,8 +330,8 @@ async function buildStorybookPackage({
305
330
  try {
306
331
  const skipped = typeof skip === "function" ? await skip() : Array.isArray(skip) ? skip : [];
307
332
  assertSkippedIsSkipItems(skipped);
308
- const iframeContent = fs3.readFileSync(iframePath, "utf8");
309
- fs3.writeFileSync(
333
+ const iframeContent = await fs4.promises.readFile(iframePath, "utf8");
334
+ await fs4.promises.writeFile(
310
335
  iframePath,
311
336
  iframeContent.replace(
312
337
  "<head>",
@@ -319,7 +344,12 @@ async function buildStorybookPackage({
319
344
  `
320
345
  )
321
346
  );
322
- return outputDir;
347
+ const estimatedSnapsCount = await getStorybookStoryCount(outputDir);
348
+ const result = { packageDir: outputDir };
349
+ if (estimatedSnapsCount != null) {
350
+ result.estimatedSnapsCount = estimatedSnapsCount;
351
+ }
352
+ return result;
323
353
  } catch (e) {
324
354
  console.error(e);
325
355
  throw e;
@@ -327,8 +357,8 @@ async function buildStorybookPackage({
327
357
  }
328
358
 
329
359
  // src/utils/deterministicArchive.ts
330
- import fs4 from "node:fs";
331
- import path4 from "node:path";
360
+ import fs5 from "node:fs";
361
+ import path5 from "node:path";
332
362
  import { zip } from "fflate";
333
363
 
334
364
  // src/utils/validateArchive.ts
@@ -359,19 +389,19 @@ function validateArchive(totalBytes, entries) {
359
389
  // src/utils/deterministicArchive.ts
360
390
  var FILE_CREATION_DATE = new Date(2019, 1, 8, 13, 31, 55);
361
391
  async function resolveFilesRecursiveForDir(dirOrFile) {
362
- const resolvedDirOrFile = path4.resolve(dirOrFile);
363
- const isDir = (await fs4.promises.lstat(resolvedDirOrFile)).isDirectory();
392
+ const resolvedDirOrFile = path5.resolve(dirOrFile);
393
+ const isDir = (await fs5.promises.lstat(resolvedDirOrFile)).isDirectory();
364
394
  if (isDir) {
365
395
  const fileEntries = [];
366
- for await (const fileType of fs4.promises.glob("**/*", {
396
+ for await (const fileType of fs5.promises.glob("**/*", {
367
397
  cwd: resolvedDirOrFile,
368
398
  withFileTypes: true
369
399
  })) {
370
400
  if (fileType.isFile()) {
371
401
  const fullPath = `${fileType.parentPath}/${fileType.name}`;
372
402
  fileEntries.push({
373
- name: path4.relative(resolvedDirOrFile, fullPath),
374
- stream: fs4.createReadStream(fullPath)
403
+ name: path5.relative(resolvedDirOrFile, fullPath),
404
+ stream: fs5.createReadStream(fullPath)
375
405
  });
376
406
  }
377
407
  }
@@ -379,8 +409,8 @@ async function resolveFilesRecursiveForDir(dirOrFile) {
379
409
  }
380
410
  return [
381
411
  {
382
- name: path4.relative(process.cwd(), resolvedDirOrFile),
383
- stream: fs4.createReadStream(resolvedDirOrFile)
412
+ name: path5.relative(process.cwd(), resolvedDirOrFile),
413
+ stream: fs5.createReadStream(resolvedDirOrFile)
384
414
  }
385
415
  ];
386
416
  }
@@ -632,9 +662,9 @@ async function uploadAssets(buffer, options, config) {
632
662
  }
633
663
 
634
664
  // src/network/prepareSnapRequests.ts
635
- async function fileExists(path6) {
665
+ async function fileExists(path7) {
636
666
  try {
637
- await fs5.promises.stat(path6);
667
+ await fs6.promises.stat(path7);
638
668
  return true;
639
669
  } catch (error) {
640
670
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -644,7 +674,7 @@ async function fileExists(path6) {
644
674
  }
645
675
  }
646
676
  async function createIframeHTML(rootDir, entryPoint, logger) {
647
- const iframePath = path5.join(rootDir, "iframe.html");
677
+ const iframePath = path6.join(rootDir, "iframe.html");
648
678
  if (await fileExists(iframePath)) {
649
679
  logger.info(`Using existing iframe.html at '${iframePath}'`);
650
680
  return;
@@ -660,14 +690,18 @@ async function createIframeHTML(rootDir, entryPoint, logger) {
660
690
  <script src="${entryPoint}"></script>
661
691
  </body>
662
692
  </html>`;
663
- await fs5.promises.mkdir(rootDir, { recursive: true });
664
- await fs5.promises.writeFile(iframePath, iframeContent);
693
+ await fs6.promises.mkdir(rootDir, { recursive: true });
694
+ await fs6.promises.writeFile(iframePath, iframeContent);
665
695
  }
666
696
  async function buildPackage({ integration }, logger) {
667
697
  if (integration.type === "custom") {
668
- const { rootDir, entryPoint } = await integration.build();
698
+ const { rootDir, entryPoint, estimatedSnapsCount } = await integration.build();
669
699
  await createIframeHTML(rootDir, entryPoint, logger);
670
- return rootDir;
700
+ const result = { packageDir: rootDir };
701
+ if (estimatedSnapsCount != null) {
702
+ result.estimatedSnapsCount = estimatedSnapsCount;
703
+ }
704
+ return result;
671
705
  }
672
706
  if (integration.type === "storybook") {
673
707
  return await buildStorybookPackage(integration);
@@ -675,7 +709,7 @@ async function buildPackage({ integration }, logger) {
675
709
  throw new Error(`Unsupported integration type: ${integration.type}`);
676
710
  }
677
711
  async function validatePackage(packageDir) {
678
- const iframePath = path5.join(packageDir, "iframe.html");
712
+ const iframePath = path6.join(packageDir, "iframe.html");
679
713
  if (!await fileExists(iframePath)) {
680
714
  throw new Error(
681
715
  `Could not find iframe.html in static package at '${iframePath}'`
@@ -683,10 +717,10 @@ async function validatePackage(packageDir) {
683
717
  }
684
718
  }
685
719
  async function preparePackage(config, logger) {
686
- const packageDir = await buildPackage(config, logger);
720
+ const { packageDir, estimatedSnapsCount } = await buildPackage(config, logger);
687
721
  await validatePackage(packageDir);
688
722
  const { buffer, hash } = await deterministicArchive([packageDir]);
689
- return await uploadAssets(
723
+ const packagePath = await uploadAssets(
690
724
  buffer,
691
725
  {
692
726
  hash,
@@ -694,10 +728,15 @@ async function preparePackage(config, logger) {
694
728
  },
695
729
  config
696
730
  );
731
+ const result = { packagePath };
732
+ if (estimatedSnapsCount != null) {
733
+ result.estimatedSnapsCount = estimatedSnapsCount;
734
+ }
735
+ return result;
697
736
  }
698
737
  async function prepareSnapRequests(config) {
699
738
  const logger = new Logger();
700
- const packagePath = config.integration.type === "pages" ? null : await preparePackage(config, logger);
739
+ const prepareResult = config.integration.type === "pages" ? null : await preparePackage(config, logger);
701
740
  const targetNames = Object.keys(config.targets);
702
741
  const tl = targetNames.length;
703
742
  logger.info(
@@ -718,8 +757,11 @@ async function prepareSnapRequests(config) {
718
757
  const targetParams = {
719
758
  targetName: name
720
759
  };
721
- if (packagePath) {
722
- targetParams.staticPackage = packagePath;
760
+ if (prepareResult) {
761
+ targetParams.staticPackage = prepareResult.packagePath;
762
+ if (prepareResult.estimatedSnapsCount != null) {
763
+ targetParams.estimatedSnapsCount = prepareResult.estimatedSnapsCount;
764
+ }
723
765
  }
724
766
  if (config.integration.type === "pages") {
725
767
  targetParams.pages = config.integration.pages;
@@ -737,4 +779,4 @@ async function prepareSnapRequests(config) {
737
779
  export {
738
780
  prepareSnapRequests as default
739
781
  };
740
- //# sourceMappingURL=prepareSnapRequests-6BOXFGHI.js.map
782
+ //# sourceMappingURL=prepareSnapRequests-EXILTRP4.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/network/prepareSnapRequests.ts", "../../src/utils/createHash.ts", "../../src/config/RemoteBrowserTarget.ts", "../../src/storybook/index.ts", "../../src/storybook/getStorybookBuildCommandParts.ts", "../../src/storybook/getStorybookStoryCount.ts", "../../src/storybook/getStorybookVersionFromPackageJson.ts", "../../src/utils/deterministicArchive.ts", "../../src/utils/validateArchive.ts", "../../src/utils/Logger.ts", "../../src/network/uploadAssets.ts"],
4
+ "sourcesContent": ["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport type { ConfigWithDefaults } from '../config/index.ts';\nimport RemoteBrowserTarget, {\n type ExecuteParams,\n} from '../config/RemoteBrowserTarget.ts';\nimport buildStorybookPackage from '../storybook/index.ts';\nimport deterministicArchive from '../utils/deterministicArchive.ts';\nimport Logger, { logTag } from '../utils/Logger.ts';\nimport uploadAssets from './uploadAssets.ts';\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await fs.promises.stat(path);\n return true;\n } catch (error) {\n if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {\n return false;\n }\n\n throw error;\n }\n}\n\nasync function createIframeHTML(\n rootDir: string,\n entryPoint: string,\n logger: Logger,\n): Promise<void> {\n const iframePath = path.join(rootDir, 'iframe.html');\n\n if (await fileExists(iframePath)) {\n logger.info(`Using existing iframe.html at '${iframePath}'`);\n return;\n }\n\n const iframeContent = `<!DOCTYPE html>\n<html lang=\"en\" dir=\"ltr\">\n <head>\n <title>Happo</title>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n </head>\n <body>\n <script src=\"${entryPoint}\"></script>\n </body>\n</html>`;\n\n await fs.promises.mkdir(rootDir, { recursive: true });\n await fs.promises.writeFile(iframePath, iframeContent);\n}\n\ninterface BuildPackageResult {\n packageDir: string;\n estimatedSnapsCount?: number;\n}\n\nasync function buildPackage(\n { integration }: ConfigWithDefaults,\n logger: Logger,\n): Promise<BuildPackageResult> {\n if (integration.type === 'custom') {\n const { rootDir, entryPoint, estimatedSnapsCount } = await integration.build();\n await createIframeHTML(rootDir, entryPoint, logger);\n\n const result: BuildPackageResult = { packageDir: rootDir };\n if (estimatedSnapsCount != null) {\n result.estimatedSnapsCount = estimatedSnapsCount;\n }\n return result;\n }\n\n if (integration.type === 'storybook') {\n return await buildStorybookPackage(integration);\n }\n\n throw new Error(`Unsupported integration type: ${integration.type}`);\n}\n\nasync function validatePackage(packageDir: string): Promise<void> {\n const iframePath = path.join(packageDir, 'iframe.html');\n\n if (!(await fileExists(iframePath))) {\n throw new Error(\n `Could not find iframe.html in static package at '${iframePath}'`,\n );\n }\n}\n\ninterface PreparePackageResult {\n packagePath: string;\n estimatedSnapsCount?: number;\n}\n\nasync function preparePackage(\n config: ConfigWithDefaults,\n logger: Logger,\n): Promise<PreparePackageResult> {\n const { packageDir, estimatedSnapsCount } = await buildPackage(config, logger);\n\n await validatePackage(packageDir);\n\n const { buffer, hash } = await deterministicArchive([packageDir]);\n const packagePath = await uploadAssets(\n buffer,\n {\n hash,\n logger,\n },\n config,\n );\n\n const result: PreparePackageResult = { packagePath };\n if (estimatedSnapsCount != null) {\n result.estimatedSnapsCount = estimatedSnapsCount;\n }\n return result;\n}\n\nexport default async function prepareSnapRequests(\n config: ConfigWithDefaults,\n): Promise<Array<number>> {\n const logger = new Logger();\n const prepareResult =\n config.integration.type === 'pages'\n ? null\n : await preparePackage(config, logger);\n\n const targetNames = Object.keys(config.targets);\n const tl = targetNames.length;\n logger.info(\n `${logTag(config.project)}Generating screenshots in ${tl} target${\n tl > 1 ? 's' : ''\n }...`,\n );\n const outerStartTime = Date.now();\n const results: Array<number> = [];\n await Promise.all(\n targetNames.map(async (name) => {\n const startTime = Date.now();\n\n if (!config.targets[name]) {\n throw new Error(`Target ${name} not found in config`);\n }\n\n const target = new RemoteBrowserTarget(\n config.targets[name].type,\n config.targets[name],\n );\n\n const targetParams: ExecuteParams = {\n targetName: name,\n };\n\n if (prepareResult) {\n targetParams.staticPackage = prepareResult.packagePath;\n\n if (prepareResult.estimatedSnapsCount != null) {\n targetParams.estimatedSnapsCount = prepareResult.estimatedSnapsCount;\n }\n }\n\n if (config.integration.type === 'pages') {\n targetParams.pages = config.integration.pages;\n }\n\n const snapRequestIds = await target.execute(targetParams, config);\n logger.start(` - ${logTag(config.project)}${name}`, { startTime });\n logger.success();\n results.push(...snapRequestIds);\n }),\n );\n logger.start(undefined, { startTime: outerStartTime });\n logger.success();\n return results;\n}\n", "import crypto from 'node:crypto';\n\n/**\n * Creates an MD5 hash of the input data\n * @param data - The data to hash (string, Buffer, or TypedArray)\n * @returns The MD5 hash as a hexadecimal string\n */\nexport default function createHash(\n data: string | Buffer | NodeJS.TypedArray,\n): string {\n return crypto.createHash('md5').update(data).digest('hex');\n}\n", "import makeHappoAPIRequest from '../network/makeHappoAPIRequest.ts';\nimport createHash from '../utils/createHash.ts';\nimport type {\n BrowserType,\n ConfigWithDefaults,\n Page,\n TargetWithDefaults,\n} from './index.ts';\n\nconst VIEWPORT_PATTERN = /^([0-9]+)x([0-9]+)$/;\n\n/**\n * Compute the number of chunks to use based on an estimated snapshot count.\n *\n * Aims for roughly 100 items per chunk, capped at 20. Returns 1 for\n * non-positive or non-finite inputs.\n */\nfunction computeDefaultChunks(estimatedSnapCount: number): number {\n if (!Number.isFinite(estimatedSnapCount) || estimatedSnapCount <= 0) {\n return 1;\n }\n\n return Math.min(20, Math.ceil(estimatedSnapCount / 100));\n}\n\n/**\n * PageSlice is an array of pages with the extra extendsSha property.\n */\ninterface PageSlice extends Array<Page> {\n extendsSha?: string;\n}\n\ninterface Chunk {\n index: number;\n total: number;\n}\n\ninterface BoundMakeRequestParams {\n slice?: Array<unknown> | undefined;\n chunk?: Chunk | undefined;\n pageSlice?: PageSlice | undefined;\n}\n\nexport interface CSSBlock {\n id: string;\n conditional: boolean;\n css: string;\n}\n\nexport interface ExecuteParams {\n globalCSS?: string | Array<CSSBlock>;\n\n /** Path to the assets package */\n assetsPackage?: string;\n\n /** Path to the static package */\n staticPackage?: string;\n\n snapPayloads?: Array<unknown>;\n pages?: Array<Page>;\n targetName?: string;\n\n /**\n * Total number of snapshots in the package. When provided for staticPackage\n * requests without explicit chunks, used to automatically determine the\n * optimal number of parallel chunks.\n */\n estimatedSnapsCount?: number;\n}\n\nfunction getPageSlices(pages: Array<Page>, chunks: number): Array<PageSlice> {\n const result: Array<PageSlice> = [];\n\n // First, split the raw pages into chunks\n const pagesPerChunk = Math.ceil(pages.length / chunks);\n for (let i = 0; i < chunks; i += 1) {\n const pageSlice = pages.slice(\n i * pagesPerChunk,\n i * pagesPerChunk + pagesPerChunk,\n );\n\n if (pageSlice.length > 0) {\n result.push(pageSlice);\n }\n }\n return result;\n}\n\nexport default class RemoteBrowserTarget {\n public readonly chunks: number | undefined;\n public readonly browserName: BrowserType;\n public readonly viewport: string;\n public readonly maxHeight: number | undefined;\n public readonly otherOptions: Record<string, unknown>;\n\n constructor(\n browserName: BrowserType,\n {\n viewport = '1024x768',\n chunks,\n maxHeight,\n ...otherOptions\n }: TargetWithDefaults,\n ) {\n if (!browserName) {\n throw new Error(\n `Invalid browser type: \"${browserName}\". Make sure the \"type\" field in your target configuration is set to a valid browser type.`,\n );\n }\n\n const viewportMatch = viewport.match(VIEWPORT_PATTERN);\n if (!viewportMatch) {\n throw new Error(\n `Invalid viewport \"${viewport}\". Here's an example of a valid one: \"1024x768\".`,\n );\n }\n\n this.chunks = chunks;\n this.browserName = browserName;\n this.viewport = viewport;\n this.maxHeight = maxHeight ?? undefined;\n this.otherOptions = otherOptions;\n }\n\n async execute(\n {\n globalCSS,\n assetsPackage,\n staticPackage,\n snapPayloads,\n pages,\n targetName,\n estimatedSnapsCount,\n }: ExecuteParams,\n config: ConfigWithDefaults,\n ): Promise<Array<number>> {\n const boundMakeRequest = async ({\n slice,\n chunk,\n pageSlice,\n }: BoundMakeRequestParams): Promise<number> => {\n const payloadString = JSON.stringify({\n viewport: this.viewport,\n maxHeight: this.maxHeight,\n ...this.otherOptions,\n globalCSS,\n snapPayloads: slice,\n chunk,\n staticPackage,\n assetsPackage,\n pages: pageSlice,\n extendsSha: pageSlice ? pageSlice.extendsSha : undefined,\n });\n\n const payloadHash = createHash(\n payloadString + (pageSlice ? Math.random() : ''),\n );\n\n const formData: Record<string, string | number | File | undefined> = {\n type:\n pageSlice && pageSlice.extendsSha\n ? 'extends-report'\n : `browser-${this.browserName}`,\n targetName,\n payloadHash,\n payload: new File([payloadString], 'payload.json', {\n type: 'application/json',\n }),\n };\n\n if (pageSlice && pageSlice.extendsSha) {\n formData.extendsSha = pageSlice.extendsSha;\n }\n\n const requestResult = await makeHappoAPIRequest(\n {\n path: `/api/snap-requests?payloadHash=${payloadHash}`,\n method: 'POST',\n json: true,\n formData,\n },\n config,\n { retryCount: 5 },\n );\n\n if (!requestResult) {\n throw new Error('No requestResult');\n }\n\n if (!('requestId' in requestResult)) {\n throw new Error('No requestId in requestResult');\n }\n\n if (typeof requestResult.requestId !== 'number') {\n throw new TypeError('requestId is not a number');\n }\n\n return requestResult.requestId;\n };\n\n const requestIds: Array<number> = [];\n\n if (staticPackage) {\n const effectiveChunks =\n this.chunks ?? Math.max(1, computeDefaultChunks(estimatedSnapsCount ?? 0));\n for (let i = 0; i < effectiveChunks; i += 1) {\n // We `await` here inside the loop to avoid POSTing all payloads to the\n // server at the same time (thus reducing load a little).\n const requestId = await boundMakeRequest({\n chunk:\n effectiveChunks > 1 ? { index: i, total: effectiveChunks } : undefined,\n });\n requestIds.push(requestId);\n }\n } else if (pages) {\n for (const pageSlice of getPageSlices(pages, this.chunks ?? 1)) {\n // We `await` here inside the loop to avoid POSTing all payloads to the\n // server at the same time (thus reducing load a little).\n const requestId = await boundMakeRequest({\n pageSlice,\n });\n requestIds.push(requestId);\n }\n } else {\n const effectiveChunks = this.chunks ?? 1;\n const snapsPerChunk = Math.ceil((snapPayloads?.length ?? 0) / effectiveChunks);\n for (let i = 0; i < effectiveChunks; i += 1) {\n const slice = snapPayloads?.slice(\n i * snapsPerChunk,\n i * snapsPerChunk + snapsPerChunk,\n );\n\n // We `await` here inside the loop to avoid POSTing all payloads to the\n // server at the same time (thus reducing load a little).\n const requestId = await boundMakeRequest({\n slice,\n });\n requestIds.push(requestId);\n }\n }\n\n return requestIds;\n }\n}\n", "import { spawn } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nimport type { StorybookIntegration } from '../config/index.ts';\nimport getStorybookBuildCommandParts from './getStorybookBuildCommandParts.ts';\nimport getStorybookStoryCount from './getStorybookStoryCount.ts';\nimport getStorybookVersionFromPackageJson from './getStorybookVersionFromPackageJson.ts';\nimport type { SkipItems } from './isomorphic/types.ts';\n\nconst { HAPPO_DEBUG } = process.env;\n\nfunction assertSkippedIsSkipItems(skipped: unknown): asserts skipped is SkipItems {\n if (!Array.isArray(skipped)) {\n throw new TypeError(`The \\`skip\\` option didn't provide an array`);\n }\n\n if (skipped.some((item) => !item.component || !item.variant)) {\n throw new Error(\n `Each item provided by the \\`skip\\` option needs a \\`component\\` and a \\`variant\\` property`,\n );\n }\n}\n\nfunction resolveBuildCommandParts() {\n const version = getStorybookVersionFromPackageJson();\n\n if (version < 9) {\n throw new Error(\n `Storybook v${version} is not supported. Please update storybook to v9 or later.`,\n );\n }\n\n return getStorybookBuildCommandParts();\n}\n\nasync function buildStorybook({\n configDir,\n staticDir,\n outputDir,\n}: {\n configDir: string;\n staticDir?: string | undefined;\n outputDir: string;\n}): Promise<void> {\n await fs.promises.rm(outputDir, { recursive: true, force: true });\n\n const buildCommandParts = resolveBuildCommandParts();\n\n if (!buildCommandParts[0]) {\n throw new Error('Failed to resolve build command parts');\n }\n\n const params = [\n ...buildCommandParts,\n '--output-dir',\n outputDir,\n '--config-dir',\n configDir,\n ];\n\n if (staticDir) {\n params.push('--static-dir', staticDir);\n }\n\n let binary = fs.existsSync('yarn.lock') ? 'yarn' : 'npx';\n\n if (buildCommandParts[0].includes('node_modules')) {\n binary = buildCommandParts[0];\n params.shift(); // remove binary from params\n }\n\n if (HAPPO_DEBUG) {\n console.log(`[happo] Using build command \\`${binary} ${params.join(' ')}\\``);\n }\n\n return new Promise((resolve, reject) => {\n const spawned = spawn(binary, params, {\n stdio: 'inherit',\n shell: process.platform == 'win32',\n });\n\n spawned.on('exit', (code) => {\n if (code === 0) {\n try {\n fs.unlinkSync(path.join(outputDir, 'project.json'));\n } catch (error) {\n console.warn(\n `Ignoring error when attempting to remove project.json: ${error}`,\n );\n }\n resolve();\n } else {\n reject(new Error('Failed to build static storybook package'));\n }\n });\n });\n}\n\nexport interface BuildStorybookPackageResult {\n packageDir: string;\n estimatedSnapsCount?: number;\n}\n\nexport default async function buildStorybookPackage({\n configDir = '.storybook',\n staticDir,\n outputDir = '.out',\n usePrebuiltPackage = false,\n skip,\n}: Omit<StorybookIntegration, 'type'>): Promise<BuildStorybookPackageResult> {\n if (!usePrebuiltPackage) {\n await buildStorybook({ configDir, staticDir, outputDir });\n }\n\n const iframePath = path.join(outputDir, 'iframe.html');\n if (!fs.existsSync(iframePath)) {\n throw new Error(\n 'Failed to build static storybook package (missing iframe.html)',\n );\n }\n\n try {\n const skipped =\n typeof skip === 'function' ? await skip() : Array.isArray(skip) ? skip : [];\n\n assertSkippedIsSkipItems(skipped);\n\n const iframeContent = await fs.promises.readFile(iframePath, 'utf8');\n\n await fs.promises.writeFile(\n iframePath,\n iframeContent.replace(\n '<head>',\n `<head>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <script type=\"text/javascript\">window.__IS_HAPPO_RUN = true;</script>\n <script type=\"text/javascript\">window.happoSkipped = ${JSON.stringify(\n skipped,\n )};</script>\n `,\n ),\n );\n\n const estimatedSnapsCount = await getStorybookStoryCount(outputDir);\n\n const result: BuildStorybookPackageResult = { packageDir: outputDir };\n if (estimatedSnapsCount != null) {\n result.estimatedSnapsCount = estimatedSnapsCount;\n }\n return result;\n } catch (e) {\n console.error(e);\n throw e;\n }\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\n\nconst { HAPPO_DEBUG } = process.env;\n\nexport default function getStorybookBuildCommandParts(\n packageJsonPath: string = path.join(process.cwd(), 'package.json'),\n): [string, string] {\n try {\n const data = fs.readFileSync(packageJsonPath, 'utf8');\n const packageJson = JSON.parse(data);\n\n if (packageJson.scripts.storybook) {\n if (HAPPO_DEBUG) {\n console.log(\n '[happo] Found `storybook` script in package.json. Will attempt to use binary found at `node_modules/.bin/storybook` instead',\n );\n }\n\n const pathToStorybookCommand = path.join(\n process.cwd(),\n 'node_modules',\n '.bin',\n 'storybook',\n );\n\n if (fs.existsSync(pathToStorybookCommand)) {\n return [pathToStorybookCommand, 'build'];\n }\n }\n } catch (e) {\n if (HAPPO_DEBUG) {\n console.log(\n '[happo] Caught error when resolving Storybook build command parts. Will use default.',\n e,\n );\n }\n }\n\n return ['storybook', 'build'];\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\n\ninterface StorybookIndexEntry {\n type: string;\n}\n\ninterface StorybookIndex {\n entries?: Record<string, StorybookIndexEntry>;\n stories?: Record<string, StorybookIndexEntry>;\n}\n\n/**\n * Reads the storybook index.json from the given package directory and returns\n * the total number of story entries (excluding docs and other non-story types).\n * Returns undefined if the file cannot be read or parsed.\n */\nexport default async function getStorybookStoryCount(\n packageDir: string,\n): Promise<number | undefined> {\n const indexPath = path.join(packageDir, 'index.json');\n try {\n const content = await fs.promises.readFile(indexPath, 'utf8');\n const data = JSON.parse(content) as StorybookIndex;\n const entries = data.entries ?? data.stories ?? {};\n return Object.values(entries).filter((e) => e.type === 'story').length;\n } catch (error) {\n console.warn('Failed to get estimated snaps count from Storybook:', error);\n return undefined;\n }\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\n\nexport default function getStorybookVersionFromPackageJson(\n packageJsonPath: string = path.join(process.cwd(), 'package.json'),\n): number {\n const data = fs.readFileSync(packageJsonPath, 'utf8');\n const packageJson = JSON.parse(data);\n\n const combinedDependencies = {\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n };\n\n const storybookPackage = [\n 'storybook',\n '@storybook/react',\n '@storybook/angular',\n '@storybook/vue',\n ].find((pkg) => combinedDependencies[pkg]);\n\n if (storybookPackage) {\n const storybookVersion = combinedDependencies[storybookPackage];\n const majorVersion = Number.parseInt(storybookVersion.match(/\\d+/)[0], 10);\n return majorVersion;\n } else {\n throw new Error('Storybook is not listed as a dependency in package.json');\n }\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport { Readable } from 'node:stream';\n\nimport type { Zippable } from 'fflate';\nimport { zip } from 'fflate';\n\nimport createHash from './createHash.ts';\nimport validateArchive from './validateArchive.ts';\n\n// We're setting the creation date to the same for all files so that the zip\n// packages created for the same content ends up having the same fingerprint.\n// https://github.com/101arrowz/fflate/issues/219#issuecomment-2333945868\nconst FILE_CREATION_DATE = new Date(2019, 1, 8, 13, 31, 55);\n\n// Type definitions\ninterface FileEntry {\n name: string;\n stream: fs.ReadStream;\n}\n\nexport interface ArchiveContentEntry {\n name: string;\n content: string | Buffer | fs.ReadStream | Readable;\n}\n\ninterface ArchiveResult {\n buffer: Buffer<ArrayBuffer>;\n hash: string;\n}\n\ninterface ArchiveEntry {\n name: string;\n size: number;\n}\n\n/**\n * Resolves all files in a directory and all of its subdirectories\n *\n * @param dirOrFile - The directory or file path to resolve\n * @returns Promise resolving to an array of file entries\n */\nasync function resolveFilesRecursiveForDir(\n dirOrFile: string,\n): Promise<Array<FileEntry>> {\n const resolvedDirOrFile = path.resolve(dirOrFile);\n const isDir = (await fs.promises.lstat(resolvedDirOrFile)).isDirectory();\n\n if (isDir) {\n const fileEntries: Array<FileEntry> = [];\n\n for await (const fileType of fs.promises.glob('**/*', {\n cwd: resolvedDirOrFile,\n withFileTypes: true,\n })) {\n // Check if it's a file (not a directory)\n if (fileType.isFile()) {\n const fullPath = `${fileType.parentPath}/${fileType.name}`;\n\n fileEntries.push({\n name: path.relative(resolvedDirOrFile, fullPath),\n stream: fs.createReadStream(fullPath),\n });\n }\n }\n\n return fileEntries;\n }\n\n return [\n {\n name: path.relative(process.cwd(), resolvedDirOrFile),\n stream: fs.createReadStream(resolvedDirOrFile),\n },\n ];\n}\n\n/**\n * Resolves all files in all directories recursively\n *\n * @param dirsAndFiles - Variable number of directory and file paths\n * @returns Promise resolving to a flattened array of file entries\n */\nasync function resolveFilesRecursive(\n ...dirsAndFiles: Array<string>\n): Promise<Array<FileEntry>> {\n const files = await Promise.all(\n dirsAndFiles.map((dirOrFile) => resolveFilesRecursiveForDir(dirOrFile)),\n );\n\n return files.flat();\n}\n\n/**\n * Converts a stream to a Uint8Array\n */\nasync function streamToUint8Array(\n stream: fs.ReadStream | Readable,\n): Promise<Uint8Array> {\n const chunks: Array<Uint8Array> = [];\n for await (const chunk of stream) {\n chunks.push(chunk instanceof Uint8Array ? chunk : new Uint8Array(chunk));\n }\n const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const result = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n result.set(chunk, offset);\n offset += chunk.length;\n }\n return result;\n}\n\n/**\n * Converts content to Uint8Array\n */\nasync function contentToUint8Array(\n content: string | Buffer | fs.ReadStream | Readable,\n): Promise<Uint8Array> {\n if (typeof content === 'string') {\n return new TextEncoder().encode(content);\n }\n if (Buffer.isBuffer(content)) {\n return new Uint8Array(content);\n }\n return streamToUint8Array(content);\n}\n\n/**\n * Creates a deterministic archive of the given files\n *\n * @param dirsAndFiles - Array of directory and file paths to include\n * @param contentToArchive - Array of content entries to include in the archive\n * @returns Promise resolving to archive result with buffer and hash\n */\nexport default async function deterministicArchive(\n dirsAndFiles: Array<string>,\n contentToArchive: Array<ArchiveContentEntry> = [],\n): Promise<ArchiveResult> {\n const uniqueDirsAndFiles = Array.from(new Set(dirsAndFiles));\n\n // Sort by name to make the output deterministic\n // Use simple string comparison instead of localeCompare for cross-platform determinism\n const filesToArchiveSorted = (\n await resolveFilesRecursive(...uniqueDirsAndFiles)\n ).toSorted((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));\n\n const contentToArchiveSorted = contentToArchive.toSorted((a, b) =>\n a.name < b.name ? -1 : a.name > b.name ? 1 : 0,\n );\n\n const seenFiles = new Set<string>();\n const entries: Array<ArchiveEntry> = [];\n\n // Collect all entries with their data first\n interface EntryData {\n name: string;\n data: Uint8Array;\n }\n\n const entryDataList: Array<EntryData> = [];\n\n // Process files from disk\n for (const file of filesToArchiveSorted) {\n if (!seenFiles.has(file.name)) {\n const data = await streamToUint8Array(file.stream);\n entryDataList.push({ name: file.name, data });\n entries.push({ name: file.name, size: data.length });\n seenFiles.add(file.name);\n }\n }\n\n // Process in-memory content\n // Extract basename to match archiver's behavior with prefix: '' for content entries\n for (const file of contentToArchiveSorted) {\n if (!seenFiles.has(file.name)) {\n const data = await contentToUint8Array(file.content);\n entryDataList.push({ name: file.name, data });\n entries.push({ name: file.name, size: data.length });\n seenFiles.add(file.name);\n }\n }\n\n // Sort all entries by name to ensure deterministic order\n // Use simple string comparison instead of localeCompare for cross-platform determinism\n entryDataList.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));\n\n // Build zipData object in sorted order to ensure deterministic zip creation\n const zipData: Zippable = {};\n for (const entry of entryDataList) {\n zipData[entry.name] = [\n entry.data,\n {\n mtime: FILE_CREATION_DATE,\n level: 6,\n },\n ];\n }\n\n const zipBuffer = await new Promise<Uint8Array>((resolve, reject) => {\n zip(zipData, { level: 6 }, (err, data) => {\n if (err) {\n reject(err);\n } else {\n resolve(data);\n }\n });\n });\n const buffer = Buffer.from(zipBuffer);\n validateArchive(buffer.length, entries);\n const hash = createHash(buffer);\n\n return { buffer, hash };\n}\n", "/**\n * Validates that the archive was created successfully\n * @param totalBytes - The total bytes in the archive\n * @param entries - Array of archive entries\n */\nexport default function validateArchive(\n totalBytes: number,\n entries: Array<{ name: string; size: number }>,\n): void {\n const totalMegaBytes = Math.round(totalBytes / 1024 / 1024);\n\n if (totalMegaBytes < 30) {\n return;\n }\n\n const messageBits = [\n `Package size is ${totalMegaBytes} MB (${totalBytes} bytes), maximum is 60 MB.`,\n \"Here are the largest 20 files in the archive. Consider removing ones that aren't necessary.\",\n ];\n\n const fileSizes = entries.map((entry) => ({\n name: entry.name,\n size: entry.size || 0,\n }));\n\n for (const file of fileSizes.toSorted((a, b) => b.size - a.size).slice(0, 20)) {\n messageBits.push(\n `${file.name}: ${Math.round(file.size / 1024 / 1024)} MB (${file.size} bytes)`,\n );\n }\n\n if (totalMegaBytes > 60) {\n throw new Error(messageBits.join('\\n'));\n }\n\n console.warn(messageBits.join('\\n'));\n}\n", "import { styleText } from 'node:util';\n\ntype PrintFunction = (str: string) => void;\n\nconst red = (str: string) => styleText('red', str);\nconst green = (str: string) => styleText('green', str);\nconst dim = (str: string) => styleText('dim', str);\nconst underline = (str: string) => styleText('underline', str);\n\nexport function logTag(project?: string): string {\n return project ? `[${project}] ` : '';\n}\n\nfunction printDuration(print: PrintFunction, startTime?: number): void {\n if (startTime) {\n print(dim(` (${Date.now() - startTime}ms)`));\n }\n}\n\ninterface LoggerOptions {\n stderrPrint?: PrintFunction;\n print?: PrintFunction;\n}\n\ninterface StartOptions {\n startTime?: number;\n}\n\nexport default class Logger {\n private print: PrintFunction;\n private stderrPrint: PrintFunction;\n private startTime?: number | undefined;\n private startMsg?: string | undefined;\n\n constructor({\n stderrPrint = (str: string) => process.stderr.write(str),\n print = (str: string) => process.stdout.write(str),\n }: LoggerOptions = {}) {\n this.print = print;\n this.stderrPrint = stderrPrint;\n this.startTime = undefined;\n this.startMsg = undefined;\n }\n\n mute(): void {\n this.print = () => null;\n this.stderrPrint = () => null;\n }\n\n divider(): void {\n this.info('-----------------------------------------');\n }\n\n info(msg: string): void {\n this.print(`${msg}`.replaceAll(/https?:\\/\\/[^ ]+/g, underline));\n this.print('\\n');\n }\n\n start(msg?: string, { startTime }: StartOptions = {}): void {\n this.startTime = startTime || Date.now();\n this.startMsg = msg;\n if (msg) {\n this.print(`Starting: ${msg} `);\n this.print('\\n');\n }\n }\n\n success(msg?: string): void {\n this.print(green('\u2713'));\n\n if (this.startMsg) {\n this.print(green(` ${this.startMsg}:`));\n }\n\n if (msg) {\n this.print(green(` ${msg}`));\n }\n printDuration(this.print, this.startTime);\n this.print('\\n');\n\n this.startMsg = undefined;\n }\n\n fail(msg?: string): void {\n this.print(red('\u2717'));\n\n if (this.startMsg) {\n this.print(red(` ${this.startMsg}:`));\n }\n\n if (msg) {\n this.print(red(` ${msg}`));\n }\n printDuration(this.print, this.startTime);\n this.print('\\n');\n\n this.startMsg = undefined;\n }\n\n error(e: Error | string): void {\n let stack: string | undefined;\n if (typeof e === 'object' && e.stack) {\n stack = e.stack;\n if (stack) {\n stack = stack.split(`file://${process.cwd()}/`).join('');\n }\n }\n this.stderrPrint(\n red(stack || (typeof e === 'object' ? e.message : e) || String(e)),\n );\n this.stderrPrint('\\n');\n }\n\n warn(message: string): void {\n this.stderrPrint(red(message));\n this.stderrPrint('\\n');\n }\n}\n", "import retry from 'async-retry';\n\nimport type { ConfigWithDefaults } from '../config/index.ts';\nimport { logTag } from '../utils/Logger.ts';\nimport makeHappoAPIRequest from './makeHappoAPIRequest.ts';\n\n// Type definitions\ninterface Logger {\n info: (message: string) => void;\n warn: (message: string) => void;\n}\n\ninterface UploadAssetsOptions {\n hash: string;\n logger: Logger;\n}\n\nexport default async function uploadAssets(\n buffer: Buffer<ArrayBuffer>,\n options: UploadAssetsOptions,\n config: ConfigWithDefaults,\n): Promise<string> {\n const { project } = config;\n const { hash, logger } = options;\n\n // First we need to get the signed URL from Happo.\n const signedUrlRes = await makeHappoAPIRequest(\n {\n path: `/api/snap-requests/assets/${hash}/signed-url`,\n method: 'GET',\n json: true,\n },\n config,\n { retryCount: 3 },\n );\n\n if (!signedUrlRes) {\n throw new Error('Failed to get signed URL');\n }\n\n if ('path' in signedUrlRes) {\n // If the asset has already been uploaded the response will have a path and\n // we can return it now.\n const { path: signedUrlPath } = signedUrlRes;\n\n logger.info(`${logTag(project)}Reusing existing assets at ${signedUrlPath}`);\n return typeof signedUrlPath === 'string' ? signedUrlPath : String(signedUrlPath);\n }\n\n if (!('signedUrl' in signedUrlRes)) {\n throw new Error(\n `Signed URL response does not have path or signedUrl. Response: ${JSON.stringify(signedUrlRes, null, 2)}`,\n );\n }\n\n const { signedUrl } = signedUrlRes;\n\n // Upload the assets to the signed URL using node's built-in fetch with\n // retries\n await retry(\n async (bail: (error: Error) => void) => {\n const res = await fetch(String(signedUrl), {\n method: 'PUT',\n body: buffer,\n headers: {\n 'Content-Type': 'application/zip',\n },\n });\n\n if (!res.ok) {\n const error = new Error(\n `Failed to upload assets to S3 signed URL: ${res.status} ${res.statusText}`,\n );\n\n if (res.status < 500 || res.status >= 600) {\n // If it's not a 5xx error, bail immediately instead of retrying\n bail(error);\n return;\n }\n\n throw error;\n }\n\n return res;\n },\n {\n retries: 3,\n onRetry: (error: Error, attempt: number) => {\n logger.warn(\n `${logTag(project)}PUT request attempt ${attempt} failed: ${error.message}. Retrying...`,\n );\n },\n },\n );\n\n // Finally, we need to tell Happo that we've uploaded the assets.\n const finalizeRes = await makeHappoAPIRequest(\n {\n path: `/api/snap-requests/assets/${hash}/signed-url/finalize`,\n method: 'POST',\n json: true,\n },\n config,\n { retryCount: 3 },\n );\n\n if (!finalizeRes) {\n throw new Error('Failed to finalize assets');\n }\n\n if (!('path' in finalizeRes)) {\n throw new Error('Finalize response is missing path');\n }\n\n const { path: finalizedPath } = finalizeRes;\n\n return typeof finalizedPath === 'string' ? finalizedPath : String(finalizedPath);\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["fs", "path", "fs", "path", "fs", "path", "fs", "path", "HAPPO_DEBUG", "fs", "path", "fs", "path", "path", "fs", "path", "fs"]
7
+ }
@@ -0,0 +1,10 @@
1
+ import {
2
+ startJob
3
+ } from "./chunk-JQ5JKJGY.js";
4
+ import "./chunk-XM2DXDSO.js";
5
+ import "./chunk-JAUTKTZY.js";
6
+ import "./chunk-FZHTC4L5.js";
7
+ export {
8
+ startJob as default
9
+ };
10
+ //# sourceMappingURL=startJob-KT7MPC4H.js.map
@@ -3,21 +3,21 @@ import {
3
3
  } from "./chunk-JTRP4JVC.js";
4
4
  import {
5
5
  startJob
6
- } from "./chunk-QIVIGY3K.js";
6
+ } from "./chunk-JQ5JKJGY.js";
7
7
  import {
8
8
  createAsyncComparison
9
- } from "./chunk-GBORF5SP.js";
9
+ } from "./chunk-NAK4M3PS.js";
10
10
  import {
11
11
  postGitHubComment
12
12
  } from "./chunk-X4TE2VNY.js";
13
13
  import {
14
14
  cancelJob
15
- } from "./chunk-2F4ONKOX.js";
15
+ } from "./chunk-F4CUEMIS.js";
16
16
  import {
17
17
  makeHappoAPIRequest
18
- } from "./chunk-B4NWDBAN.js";
19
- import "./chunk-4FHG27V2.js";
20
- import "./chunk-VOPCZYUD.js";
18
+ } from "./chunk-XM2DXDSO.js";
19
+ import "./chunk-JAUTKTZY.js";
20
+ import "./chunk-FZHTC4L5.js";
21
21
 
22
22
  // src/e2e/wrapper.ts
23
23
  import { spawn } from "node:child_process";
@@ -219,4 +219,4 @@ export {
219
219
  runWithWrapper as default,
220
220
  finalizeAll
221
221
  };
222
- //# sourceMappingURL=wrapper-UNP6YKH6.js.map
222
+ //# sourceMappingURL=wrapper-KRUJ2F4T.js.map
@@ -13,14 +13,20 @@ export interface ExecuteParams {
13
13
  snapPayloads?: Array<unknown>;
14
14
  pages?: Array<Page>;
15
15
  targetName?: string;
16
+ /**
17
+ * Total number of snapshots in the package. When provided for staticPackage
18
+ * requests without explicit chunks, used to automatically determine the
19
+ * optimal number of parallel chunks.
20
+ */
21
+ estimatedSnapsCount?: number;
16
22
  }
17
23
  export default class RemoteBrowserTarget {
18
- readonly chunks: number;
24
+ readonly chunks: number | undefined;
19
25
  readonly browserName: BrowserType;
20
26
  readonly viewport: string;
21
27
  readonly maxHeight: number | undefined;
22
28
  readonly otherOptions: Record<string, unknown>;
23
29
  constructor(browserName: BrowserType, { viewport, chunks, maxHeight, ...otherOptions }: TargetWithDefaults);
24
- execute({ globalCSS, assetsPackage, staticPackage, snapPayloads, pages, targetName, }: ExecuteParams, config: ConfigWithDefaults): Promise<Array<number>>;
30
+ execute({ globalCSS, assetsPackage, staticPackage, snapPayloads, pages, targetName, estimatedSnapsCount, }: ExecuteParams, config: ConfigWithDefaults): Promise<Array<number>>;
25
31
  }
26
32
  //# sourceMappingURL=RemoteBrowserTarget.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"RemoteBrowserTarget.d.ts","sourceRoot":"","sources":["../../src/config/RemoteBrowserTarget.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,IAAI,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAsB5F,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,OAAO,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;IAErC,iCAAiC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,iCAAiC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,YAAY,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAC9B,KAAK,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAoBD,MAAM,CAAC,OAAO,OAAO,mBAAmB;IACtC,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,SAAgB,WAAW,EAAE,WAAW,CAAC;IACzC,SAAgB,QAAQ,EAAE,MAAM,CAAC;IACjC,SAAgB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9C,SAAgB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAGpD,WAAW,EAAE,WAAW,EACxB,EACE,QAAqB,EACrB,MAAU,EACV,SAAS,EACT,GAAG,YAAY,EAChB,EAAE,kBAAkB;IAsBjB,OAAO,CACX,EACE,SAAS,EACT,aAAa,EACb,aAAa,EACb,YAAY,EACZ,KAAK,EACL,UAAU,GACX,EAAE,aAAa,EAChB,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;CAwG1B"}
1
+ {"version":3,"file":"RemoteBrowserTarget.d.ts","sourceRoot":"","sources":["../../src/config/RemoteBrowserTarget.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,WAAW,EACX,kBAAkB,EAClB,IAAI,EACJ,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAoCpB,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,OAAO,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;IAErC,iCAAiC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,iCAAiC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,YAAY,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAC9B,KAAK,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAoBD,MAAM,CAAC,OAAO,OAAO,mBAAmB;IACtC,SAAgB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,SAAgB,WAAW,EAAE,WAAW,CAAC;IACzC,SAAgB,QAAQ,EAAE,MAAM,CAAC;IACjC,SAAgB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9C,SAAgB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAGpD,WAAW,EAAE,WAAW,EACxB,EACE,QAAqB,EACrB,MAAM,EACN,SAAS,EACT,GAAG,YAAY,EAChB,EAAE,kBAAkB;IAsBjB,OAAO,CACX,EACE,SAAS,EACT,aAAa,EACb,aAAa,EACb,YAAY,EACZ,KAAK,EACL,UAAU,EACV,mBAAmB,GACpB,EAAE,aAAa,EAChB,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;CA4G1B"}
@@ -52,12 +52,16 @@ interface CustomIntegration {
52
52
  * the path to the folder containing the custom files and the path to the
53
53
  * entry point file relative to the root directory.
54
54
  *
55
+ * Optionally return `estimatedSnapsCount` to enable server-side auto-chunking,
56
+ * which parallelizes rendering across multiple workers.
57
+ *
55
58
  * @example
56
- * { rootDir: 'dist/custom', entryPoint: 'index.js' }
59
+ * { rootDir: 'dist/custom', entryPoint: 'index.js', estimatedSnapsCount: 42 }
57
60
  */
58
61
  build: () => Promise<{
59
62
  rootDir: string;
60
63
  entryPoint: string;
64
+ estimatedSnapsCount?: number;
61
65
  }>;
62
66
  }
63
67
  export interface Page {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"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"}