happo 6.0.3 → 6.0.5

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 (37) hide show
  1. package/dist/cli/{cancelJob-6IYR4YZT.js → cancelJob-FZN3FED2.js} +4 -3
  2. package/dist/cli/{cancelJob-6IYR4YZT.js.map → cancelJob-FZN3FED2.js.map} +1 -1
  3. package/dist/cli/{chunk-G63DXNAV.js → chunk-GS5VDGV6.js} +3 -48
  4. package/dist/cli/chunk-GS5VDGV6.js.map +7 -0
  5. package/dist/cli/chunk-L2YFFA77.js +51 -0
  6. package/dist/cli/chunk-L2YFFA77.js.map +7 -0
  7. package/dist/cli/{chunk-TXOXC6WO.js → chunk-O5GJGAW5.js} +2 -2
  8. package/dist/cli/{chunk-TXOXC6WO.js.map → chunk-O5GJGAW5.js.map} +1 -1
  9. package/dist/cli/{chunk-VB6YWDBQ.js → chunk-UVYFRXQW.js} +2 -2
  10. package/dist/cli/createAsyncComparison-5AUI4A72.js +10 -0
  11. package/dist/cli/{createAsyncReport-WFZS224O.js → createAsyncReport-ZJG3YRUK.js} +4 -3
  12. package/dist/cli/{createAsyncReport-WFZS224O.js.map → createAsyncReport-ZJG3YRUK.js.map} +1 -1
  13. package/dist/cli/index.d.ts.map +1 -1
  14. package/dist/cli/index.js +74 -28
  15. package/dist/cli/index.js.map +2 -2
  16. package/dist/cli/package-X4FVUDQZ.js +7 -0
  17. package/dist/cli/{prepareSnapRequests-APQNWGR6.js → prepareSnapRequests-7DDDCYNL.js} +4 -3
  18. package/dist/cli/{prepareSnapRequests-APQNWGR6.js.map → prepareSnapRequests-7DDDCYNL.js.map} +1 -1
  19. package/dist/cli/{startJob-ELIGC4S6.js → startJob-JUDYTDEM.js} +4 -3
  20. package/dist/cli/{startJob-ELIGC4S6.js.map → startJob-JUDYTDEM.js.map} +1 -1
  21. package/dist/cli/{wrapper-SK4CQB2Y.js → wrapper-ZMK7MDL2.js} +8 -5
  22. package/dist/cli/wrapper-ZMK7MDL2.js.map +7 -0
  23. package/dist/config/loadConfig.d.ts +3 -1
  24. package/dist/config/loadConfig.d.ts.map +1 -1
  25. package/dist/cypress/task.js +120 -77
  26. package/dist/cypress/task.js.map +3 -3
  27. package/dist/e2e/wrapper.d.ts.map +1 -1
  28. package/dist/playwright/index.js +120 -77
  29. package/dist/playwright/index.js.map +3 -3
  30. package/package.json +1 -1
  31. package/dist/cli/chunk-G63DXNAV.js.map +0 -7
  32. package/dist/cli/createAsyncComparison-37UCMTAK.js +0 -9
  33. package/dist/cli/package-LV7GRXKC.js +0 -7
  34. package/dist/cli/wrapper-SK4CQB2Y.js.map +0 -7
  35. /package/dist/cli/{chunk-VB6YWDBQ.js.map → chunk-UVYFRXQW.js.map} +0 -0
  36. /package/dist/cli/{createAsyncComparison-37UCMTAK.js.map → createAsyncComparison-5AUI4A72.js.map} +0 -0
  37. /package/dist/cli/{package-LV7GRXKC.js.map → package-X4FVUDQZ.js.map} +0 -0
@@ -1,7 +1,8 @@
1
1
  import {
2
2
  makeHappoAPIRequest
3
- } from "./chunk-G63DXNAV.js";
4
- import "./chunk-TXOXC6WO.js";
3
+ } from "./chunk-L2YFFA77.js";
4
+ import "./chunk-GS5VDGV6.js";
5
+ import "./chunk-O5GJGAW5.js";
5
6
 
6
7
  // src/network/cancelJob.ts
7
8
  async function cancelJob(status, config, { beforeSha, afterSha, link, message }, logger) {
@@ -24,4 +25,4 @@ async function cancelJob(status, config, { beforeSha, afterSha, link, message },
24
25
  export {
25
26
  cancelJob as default
26
27
  };
27
- //# sourceMappingURL=cancelJob-6IYR4YZT.js.map
28
+ //# sourceMappingURL=cancelJob-FZN3FED2.js.map
@@ -2,6 +2,6 @@
2
2
  "version": 3,
3
3
  "sources": ["../../src/network/cancelJob.ts"],
4
4
  "sourcesContent": ["import type { ConfigWithDefaults } from '../config/index.ts';\nimport type { EnvironmentResult } from '../environment/index.ts';\nimport type { Logger } from '../isomorphic/types.ts';\nimport makeHappoAPIRequest from './makeHappoAPIRequest.ts';\n\ntype Status = 'failure' | 'success';\n\n/**\n * Tell Happo that a job comparing two SHAs had to be cancelled for some reason.\n *\n * @see https://happo.io/docs/api#cancelJob\n */\nexport default async function cancelJob(\n status: Status,\n config: ConfigWithDefaults,\n { beforeSha, afterSha, link, message }: EnvironmentResult,\n logger: Logger,\n): Promise<void> {\n await makeHappoAPIRequest(\n {\n path: `/api/jobs/${beforeSha}/${afterSha}/cancel`,\n method: 'POST',\n body: {\n link,\n message,\n project: config.project,\n status,\n },\n },\n config,\n { retryCount: 5 },\n logger,\n );\n}\n"],
5
- "mappings": ";;;;;;AAYA,eAAO,UACL,QACA,QACA,EAAE,WAAW,UAAU,MAAM,QAAQ,GACrC,QACe;AACf,QAAM;AAAA,IACJ;AAAA,MACE,MAAM,aAAa,SAAS,IAAI,QAAQ;AAAA,MACxC,QAAQ;AAAA,MACR,MAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA,SAAS,OAAO;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,IACA,EAAE,YAAY,EAAE;AAAA,IAChB;AAAA,EACF;AACF;",
5
+ "mappings": ";;;;;;;AAYA,eAAO,UACL,QACA,QACA,EAAE,WAAW,UAAU,MAAM,QAAQ,GACrC,QACe;AACf,QAAM;AAAA,IACJ;AAAA,MACE,MAAM,aAAa,SAAS,IAAI,QAAQ;AAAA,MACxC,QAAQ;AAAA,MACR,MAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA,SAAS,OAAO;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,IACA,EAAE,YAAY,EAAE;AAAA,IAChB;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -1,9 +1,6 @@
1
1
  import {
2
2
  package_default
3
- } from "./chunk-TXOXC6WO.js";
4
-
5
- // src/network/makeHappoAPIRequest.ts
6
- import { SignJWT } from "jose";
3
+ } from "./chunk-O5GJGAW5.js";
7
4
 
8
5
  // src/network/fetchWithRetry.ts
9
6
  import asyncRetry from "async-retry";
@@ -93,49 +90,7 @@ async function fetchWithRetry(url, {
93
90
  );
94
91
  }
95
92
 
96
- // src/network/makeHappoAPIRequest.ts
97
- async function signRequest(apiKey, apiSecret) {
98
- const encodedSecret = new TextEncoder().encode(apiSecret);
99
- return await new SignJWT({ key: apiKey }).setProtectedHeader({ alg: "HS256", kid: apiKey }).sign(encodedSecret);
100
- }
101
- async function makeHappoAPIRequest({ url, path, method = "GET", formData, body }, { apiKey, apiSecret, endpoint }, {
102
- retryCount = 0,
103
- timeout = 6e4,
104
- retryMinTimeout = 1e3,
105
- retryMaxTimeout = Infinity
106
- }, logger = console) {
107
- const fetchURL = path ? new URL(path, endpoint) : url;
108
- if (!fetchURL) {
109
- throw new Error(
110
- "No fetch URL provided. Either `path` (preferred) or `url` must be provided."
111
- );
112
- }
113
- const signed = await signRequest(apiKey, apiSecret);
114
- const headers = {
115
- Authorization: `Bearer ${signed}`
116
- };
117
- const response = await fetchWithRetry(
118
- fetchURL,
119
- {
120
- method,
121
- headers,
122
- formData,
123
- body,
124
- timeout,
125
- retryCount,
126
- retryMinTimeout,
127
- retryMaxTimeout
128
- },
129
- logger
130
- );
131
- const result = await response.json();
132
- if (typeof result !== "object") {
133
- throw new TypeError(`Response is not an object: ${JSON.stringify(result)}`);
134
- }
135
- return result;
136
- }
137
-
138
93
  export {
139
- makeHappoAPIRequest
94
+ fetchWithRetry
140
95
  };
141
- //# sourceMappingURL=chunk-G63DXNAV.js.map
96
+ //# sourceMappingURL=chunk-GS5VDGV6.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/network/fetchWithRetry.ts"],
4
+ "sourcesContent": ["import asyncRetry from 'async-retry';\n\nimport packageJson from '../../package.json' with { type: 'json' };\nimport type { Logger } from '../isomorphic/types.ts';\n\nconst { version } = packageJson;\n\nexport class ErrorWithStatusCode extends Error {\n statusCode: number;\n\n constructor(message: string, statusCode: number) {\n super(message);\n this.statusCode = statusCode;\n }\n}\n\ntype FormDataValue = string | File | undefined;\n\nfunction prepareFormData(data: Record<string, FormDataValue>): FormData | null {\n if (!data) {\n return null;\n }\n\n const form = new FormData();\n\n for (const [key, value] of Object.entries(data)) {\n if (value) {\n form.append(key, value);\n }\n }\n\n return form;\n}\n\ninterface FetchParams {\n method?: string;\n headers?: Record<string, string>;\n formData?: Record<string, FormDataValue> | undefined;\n body?: unknown;\n\n /**\n * The timeout in milliseconds\n * @default 60_000\n */\n timeout?: number;\n\n /**\n * The number of times to retry the request\n * @default 0\n */\n retryCount?: number;\n\n /**\n * The minimum timeout in milliseconds\n * @default 1000\n */\n retryMinTimeout?: number;\n\n /**\n * The maximum timeout in milliseconds\n * @default Infinity\n */\n retryMaxTimeout?: number;\n}\n\nconst defaultHeaders = {\n 'User-Agent': `happo@${version}`,\n};\n\nexport default async function fetchWithRetry(\n url: string | URL,\n {\n method = 'GET',\n headers = {},\n formData,\n body: jsonBody,\n timeout = 60_000,\n retryCount = 0,\n retryMinTimeout = 1000,\n retryMaxTimeout = Infinity,\n }: FetchParams,\n logger: Logger = console,\n): Promise<Response> {\n return asyncRetry(\n async (bail: (error: Error) => void) => {\n const start = Date.now();\n\n // We must avoid reusing FormData instances when retrying requests\n // because they are consumed and cannot be reused.\n // More info: https://github.com/node-fetch/node-fetch/issues/1743\n const body = formData\n ? prepareFormData(formData)\n : jsonBody\n ? JSON.stringify(jsonBody)\n : null;\n\n if (jsonBody) {\n headers['Content-Type'] = 'application/json';\n }\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers: { ...defaultHeaders, ...headers },\n signal: AbortSignal.timeout(timeout),\n body,\n });\n } catch (maybeError) {\n const originalError =\n maybeError instanceof Error ? maybeError : new Error(String(maybeError));\n\n const message =\n originalError.name === 'TimeoutError'\n ? `Timeout when fetching ${url} using method ${method}`\n : originalError.message;\n\n // This WILL be retried\n throw new Error(`${message} (took ${Date.now() - start} ms)`, {\n cause: originalError,\n });\n }\n\n if (response.status >= 400 && response.status < 500) {\n // This WILL NOT be retried\n bail(\n new ErrorWithStatusCode(\n `[HAPPO] Request to ${url} failed: ${response.status} - ${await response.text()}`,\n response.status,\n ),\n );\n\n return response;\n }\n\n if (!response.ok) {\n // This WILL be retried\n throw new ErrorWithStatusCode(\n `[HAPPO] Request to ${url} failed: ${response.status} - ${await response.text()}`,\n response.status,\n );\n }\n\n return response;\n },\n\n {\n retries: retryCount,\n minTimeout: retryMinTimeout,\n maxTimeout: retryMaxTimeout,\n onRetry: (error: Error) => {\n logger.error(\n `[HAPPO] Failed fetching ${url} using method ${method}. Retrying (at ${new Date().toISOString()}) ...`,\n );\n logger.error(error);\n },\n },\n );\n}\n"],
5
+ "mappings": ";;;;;AAAA,OAAO,gBAAgB;AAKvB,IAAM,EAAE,QAAQ,IAAI;AAEb,IAAM,sBAAN,cAAkC,MAAM;AAAA,EAC7C;AAAA,EAEA,YAAY,SAAiB,YAAoB;AAC/C,UAAM,OAAO;AACb,SAAK,aAAa;AAAA,EACpB;AACF;AAIA,SAAS,gBAAgB,MAAsD;AAC7E,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,IAAI,SAAS;AAE1B,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC/C,QAAI,OAAO;AACT,WAAK,OAAO,KAAK,KAAK;AAAA,IACxB;AAAA,EACF;AAEA,SAAO;AACT;AAiCA,IAAM,iBAAiB;AAAA,EACrB,cAAc,SAAS,OAAO;AAChC;AAEA,eAAO,eACL,KACA;AAAA,EACE,SAAS;AAAA,EACT,UAAU,CAAC;AAAA,EACX;AAAA,EACA,MAAM;AAAA,EACN,UAAU;AAAA,EACV,aAAa;AAAA,EACb,kBAAkB;AAAA,EAClB,kBAAkB;AACpB,GACA,SAAiB,SACE;AACnB,SAAO;AAAA,IACL,OAAO,SAAiC;AACtC,YAAM,QAAQ,KAAK,IAAI;AAKvB,YAAM,OAAO,WACT,gBAAgB,QAAQ,IACxB,WACE,KAAK,UAAU,QAAQ,IACvB;AAEN,UAAI,UAAU;AACZ,gBAAQ,cAAc,IAAI;AAAA,MAC5B;AAEA,UAAI;AACJ,UAAI;AACF,mBAAW,MAAM,MAAM,KAAK;AAAA,UAC1B;AAAA,UACA,SAAS,EAAE,GAAG,gBAAgB,GAAG,QAAQ;AAAA,UACzC,QAAQ,YAAY,QAAQ,OAAO;AAAA,UACnC;AAAA,QACF,CAAC;AAAA,MACH,SAAS,YAAY;AACnB,cAAM,gBACJ,sBAAsB,QAAQ,aAAa,IAAI,MAAM,OAAO,UAAU,CAAC;AAEzE,cAAM,UACJ,cAAc,SAAS,iBACnB,yBAAyB,GAAG,iBAAiB,MAAM,KACnD,cAAc;AAGpB,cAAM,IAAI,MAAM,GAAG,OAAO,UAAU,KAAK,IAAI,IAAI,KAAK,QAAQ;AAAA,UAC5D,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAEA,UAAI,SAAS,UAAU,OAAO,SAAS,SAAS,KAAK;AAEnD;AAAA,UACE,IAAI;AAAA,YACF,sBAAsB,GAAG,YAAY,SAAS,MAAM,MAAM,MAAM,SAAS,KAAK,CAAC;AAAA,YAC/E,SAAS;AAAA,UACX;AAAA,QACF;AAEA,eAAO;AAAA,MACT;AAEA,UAAI,CAAC,SAAS,IAAI;AAEhB,cAAM,IAAI;AAAA,UACR,sBAAsB,GAAG,YAAY,SAAS,MAAM,MAAM,MAAM,SAAS,KAAK,CAAC;AAAA,UAC/E,SAAS;AAAA,QACX;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAAA,IAEA;AAAA,MACE,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,SAAS,CAAC,UAAiB;AACzB,eAAO;AAAA,UACL,2BAA2B,GAAG,iBAAiB,MAAM,mBAAkB,oBAAI,KAAK,GAAE,YAAY,CAAC;AAAA,QACjG;AACA,eAAO,MAAM,KAAK;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,51 @@
1
+ import {
2
+ fetchWithRetry
3
+ } from "./chunk-GS5VDGV6.js";
4
+
5
+ // src/network/makeHappoAPIRequest.ts
6
+ import { SignJWT } from "jose";
7
+ async function signRequest(apiKey, apiSecret) {
8
+ const encodedSecret = new TextEncoder().encode(apiSecret);
9
+ return await new SignJWT({ key: apiKey }).setProtectedHeader({ alg: "HS256", kid: apiKey }).sign(encodedSecret);
10
+ }
11
+ async function makeHappoAPIRequest({ url, path, method = "GET", formData, body }, { apiKey, apiSecret, endpoint }, {
12
+ retryCount = 0,
13
+ timeout = 6e4,
14
+ retryMinTimeout = 1e3,
15
+ retryMaxTimeout = Infinity
16
+ }, logger = console) {
17
+ const fetchURL = path ? new URL(path, endpoint) : url;
18
+ if (!fetchURL) {
19
+ throw new Error(
20
+ "No fetch URL provided. Either `path` (preferred) or `url` must be provided."
21
+ );
22
+ }
23
+ const signed = await signRequest(apiKey, apiSecret);
24
+ const headers = {
25
+ Authorization: `Bearer ${signed}`
26
+ };
27
+ const response = await fetchWithRetry(
28
+ fetchURL,
29
+ {
30
+ method,
31
+ headers,
32
+ formData,
33
+ body,
34
+ timeout,
35
+ retryCount,
36
+ retryMinTimeout,
37
+ retryMaxTimeout
38
+ },
39
+ logger
40
+ );
41
+ const result = await response.json();
42
+ if (typeof result !== "object") {
43
+ throw new TypeError(`Response is not an object: ${JSON.stringify(result)}`);
44
+ }
45
+ return result;
46
+ }
47
+
48
+ export {
49
+ makeHappoAPIRequest
50
+ };
51
+ //# sourceMappingURL=chunk-L2YFFA77.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/network/makeHappoAPIRequest.ts"],
4
+ "sourcesContent": ["import { SignJWT } from 'jose';\n\nimport type { ConfigWithDefaults } from '../config/index.ts';\nimport type { Logger } from '../isomorphic/types.ts';\nimport fetchWithRetry from './fetchWithRetry.ts';\n\nexport { ErrorWithStatusCode } from './fetchWithRetry.ts';\n\ntype FormDataValue = string | File | undefined;\n\nexport interface RequestAttributes {\n /**\n * The path to the API endpoint\n *\n * @example\n * '/api/snap-requests/with-results'\n */\n path?: `/api/${string}`;\n\n /**\n * The URL to fetch\n *\n * Prefer using the `path` property instead. If both are provided, the `path`\n * property will be used.\n */\n url?: string;\n\n method?: 'GET' | 'POST' | 'PUT' | 'DELETE';\n formData?: Record<string, FormDataValue>;\n body?: unknown;\n json?: boolean;\n}\n\nexport interface MakeHappoAPIRequestOptions {\n /**\n * The timeout in milliseconds\n * @default 60_000\n */\n timeout?: number;\n\n /**\n * The number of times to retry the request\n * @default 0\n */\n retryCount?: number;\n\n /**\n * The minimum timeout in milliseconds\n * @default 1000\n */\n retryMinTimeout?: number;\n\n /**\n * The maximum timeout in milliseconds\n * @default Infinity\n */\n retryMaxTimeout?: number;\n}\n\nasync function signRequest(apiKey: string, apiSecret: string): Promise<string> {\n const encodedSecret = new TextEncoder().encode(apiSecret);\n return await new SignJWT({ key: apiKey })\n .setProtectedHeader({ alg: 'HS256', kid: apiKey })\n .sign(encodedSecret);\n}\n\nexport default async function makeHappoAPIRequest(\n { url, path, method = 'GET', formData, body }: RequestAttributes,\n { apiKey, apiSecret, endpoint }: ConfigWithDefaults,\n {\n retryCount = 0,\n timeout = 60_000,\n retryMinTimeout = 1000,\n retryMaxTimeout = Infinity,\n }: MakeHappoAPIRequestOptions,\n logger: Logger = console,\n): Promise<object | null> {\n const fetchURL = path ? new URL(path, endpoint) : url;\n\n if (!fetchURL) {\n throw new Error(\n 'No fetch URL provided. Either `path` (preferred) or `url` must be provided.',\n );\n }\n\n const signed = await signRequest(apiKey, apiSecret);\n\n const headers = {\n Authorization: `Bearer ${signed}`,\n };\n\n const response = await fetchWithRetry(\n fetchURL,\n {\n method,\n headers,\n formData,\n body,\n timeout,\n retryCount,\n retryMinTimeout,\n retryMaxTimeout,\n },\n logger,\n );\n\n // We expect API responses to be JSON, so let's parse it as JSON here for\n // convenience.\n const result = await response.json();\n\n if (typeof result !== 'object') {\n throw new TypeError(`Response is not an object: ${JSON.stringify(result)}`);\n }\n\n return result;\n}\n"],
5
+ "mappings": ";;;;;AAAA,SAAS,eAAe;AA2DxB,eAAe,YAAY,QAAgB,WAAoC;AAC7E,QAAM,gBAAgB,IAAI,YAAY,EAAE,OAAO,SAAS;AACxD,SAAO,MAAM,IAAI,QAAQ,EAAE,KAAK,OAAO,CAAC,EACrC,mBAAmB,EAAE,KAAK,SAAS,KAAK,OAAO,CAAC,EAChD,KAAK,aAAa;AACvB;AAEA,eAAO,oBACL,EAAE,KAAK,MAAM,SAAS,OAAO,UAAU,KAAK,GAC5C,EAAE,QAAQ,WAAW,SAAS,GAC9B;AAAA,EACE,aAAa;AAAA,EACb,UAAU;AAAA,EACV,kBAAkB;AAAA,EAClB,kBAAkB;AACpB,GACA,SAAiB,SACO;AACxB,QAAM,WAAW,OAAO,IAAI,IAAI,MAAM,QAAQ,IAAI;AAElD,MAAI,CAAC,UAAU;AACb,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,YAAY,QAAQ,SAAS;AAElD,QAAM,UAAU;AAAA,IACd,eAAe,UAAU,MAAM;AAAA,EACjC;AAEA,QAAM,WAAW,MAAM;AAAA,IACrB;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,EACF;AAIA,QAAM,SAAS,MAAM,SAAS,KAAK;AAEnC,MAAI,OAAO,WAAW,UAAU;AAC9B,UAAM,IAAI,UAAU,8BAA8B,KAAK,UAAU,MAAM,CAAC,EAAE;AAAA,EAC5E;AAEA,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -1,7 +1,7 @@
1
1
  // package.json
2
2
  var package_default = {
3
3
  name: "happo",
4
- version: "6.0.3",
4
+ version: "6.0.5",
5
5
  description: "Catch unexpected visual and accessibility changes and UI bugs",
6
6
  license: "MIT",
7
7
  repository: {
@@ -184,4 +184,4 @@ var package_default = {
184
184
  export {
185
185
  package_default
186
186
  };
187
- //# sourceMappingURL=chunk-TXOXC6WO.js.map
187
+ //# sourceMappingURL=chunk-O5GJGAW5.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../package.json"],
4
- "sourcesContent": ["{\n \"name\": \"happo\",\n \"version\": \"6.0.3\",\n \"description\": \"Catch unexpected visual and accessibility changes and UI bugs\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/happo/happo.git\"\n },\n \"bugs\": \"https://github.com/happo/happo/issues\",\n \"homepage\": \"https://happo.io\",\n \"bin\": {\n \"happo\": \"dist/cli/index.js\"\n },\n \"type\": \"module\",\n \"main\": \"./dist/config/index.js\",\n \"types\": \"./dist/config/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/config/index.d.ts\",\n \"default\": \"./dist/config/index.js\"\n },\n \"./cypress\": {\n \"types\": \"./dist/cypress/index.d.ts\",\n \"default\": \"./dist/cypress/index.js\"\n },\n \"./cypress/task\": {\n \"types\": \"./dist/cypress/task.d.ts\",\n \"default\": \"./dist/cypress/task.js\"\n },\n \"./playwright\": {\n \"types\": \"./dist/playwright/index.d.ts\",\n \"default\": \"./dist/playwright/index.js\"\n },\n \"./custom\": {\n \"types\": \"./dist/custom/index.d.ts\",\n \"default\": \"./dist/custom/index.js\"\n },\n \"./storybook/addon\": {\n \"types\": \"./dist/storybook/browser/addon.d.ts\",\n \"default\": \"./dist/storybook/browser/addon.js\"\n },\n \"./storybook/decorator\": {\n \"types\": \"./dist/storybook/browser/decorator.d.ts\",\n \"default\": \"./dist/storybook/browser/decorator.js\"\n },\n \"./storybook/preset\": {\n \"types\": \"./dist/storybook/preset.d.ts\",\n \"default\": \"./dist/storybook/preset.js\"\n },\n \"./storybook/register\": {\n \"types\": \"./dist/storybook/browser/register.d.ts\",\n \"default\": \"./dist/storybook/browser/register.js\"\n }\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"all\": \"node ./scripts/allchecks.ts\",\n \"build\": \"pnpm build:types && pnpm build:dist\",\n \"build:custom\": \"esbuild src/custom/__happo__/index.ts --bundle --format=iife --global-name=happoCustom --outfile=tmp/happo-custom/bundle.js --platform=browser --target=esnext\",\n \"build:dist\": \"./scripts/build.ts\",\n \"build:types\": \"pnpm tsc --pretty\",\n \"build:watch\": \"tsc --build --watch\",\n \"clean\": \"rm -rf dist tmp/tsc tmp/happo-custom\",\n \"lint\": \"eslint .\",\n \"prepublishOnly\": \"pnpm clean && pnpm build\",\n \"storybook:dev\": \"storybook dev --config-dir src/storybook/__tests__/storybook-app -p ${PORT:-6007}\",\n \"test\": \"node --env-file-if-exists=.env.local ./scripts/test.ts\",\n \"test:custom\": \"pnpm build:dist && pnpm build:custom && node --env-file-if-exists=.env.local dist/cli/index.js -c ./happoconfigs/happo.custom.config.ts\",\n \"test:cypress\": \"pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/index.js -c ./happoconfigs/happo.cypress.config.ts e2e -- cypress run -C src/cypress/__cypress__/cypress.config.ts\",\n \"test:cypress:open\": \"cypress open -C src/cypress/__cypress__/cypress.config.ts\",\n \"test:playwright\": \"pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/index.js -c ./happoconfigs/happo.playwright.config.ts e2e -- playwright test\",\n \"test:storybook\": \"pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/index.js -c ./happoconfigs/happo.storybook.config.ts\",\n \"test:pages\": \"pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/index.js -c ./happoconfigs/happo.pages.config.ts\",\n \"tsc\": \"tsc --build tsconfig.json\"\n },\n \"browserslist\": {\n \"node\": [\n \"node 22\"\n ],\n \"browser\": [\n \"last 2 Chrome major versions\",\n \"last 2 Firefox major versions\",\n \"last 2 Safari major versions\",\n \"last 2 Edge major versions\"\n ],\n \"isomorphic\": [\n \"node 22\",\n \"last 2 Chrome major versions\",\n \"last 2 Firefox major versions\",\n \"last 2 Safari major versions\",\n \"last 2 Edge major versions\"\n ]\n },\n \"prettier\": {\n \"printWidth\": 85,\n \"singleQuote\": true,\n \"trailingComma\": \"all\",\n \"arrowParens\": \"always\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.36.0\",\n \"@playwright/test\": \"^1.55.1\",\n \"@reporters/github\": \"^1.11.0\",\n \"@storybook/builder-vite\": \"^10.0.1\",\n \"@storybook/react-vite\": \"^10.0.1\",\n \"@types/async-retry\": \"^1.4.9\",\n \"@types/base64-stream\": \"^1.0.5\",\n \"@types/jsdom\": \"^27.0.0\",\n \"@types/mime-types\": \"^3.0.1\",\n \"@types/multiparty\": \"^4.2.1\",\n \"@types/node\": \"^24.9.1\",\n \"@types/react\": \"^19.2.0\",\n \"@types/react-dom\": \"^19.2.0\",\n \"@types/serve-handler\": \"^6.1.4\",\n \"cypress\": \"^15.5.0\",\n \"esbuild\": \"^0.27.0\",\n \"eslint\": \"^9.36.0\",\n \"eslint-config-prettier\": \"^10.1.8\",\n \"eslint-plugin-compat\": \"^6.0.2\",\n \"eslint-plugin-depend\": \"^1.3.1\",\n \"eslint-plugin-simple-import-sort\": \"^12.1.1\",\n \"eslint-plugin-unicorn\": \"^62.0.0\",\n \"jiti\": \"^2.6.0\",\n \"jsdom\": \"^27.0.0\",\n \"multiparty\": \"^4.2.3\",\n \"prettier\": \"^3.6.2\",\n \"react\": \"^19.2.0\",\n \"react-dom\": \"^19.2.0\",\n \"react-error-boundary\": \"^6.0.0\",\n \"serve-handler\": \"^6.1.6\",\n \"storybook\": \"^10.0.1\",\n \"typescript\": \"^5.9.2\",\n \"typescript-eslint\": \"^8.44.1\"\n },\n \"dependencies\": {\n \"async-retry\": \"^1.3.3\",\n \"base64-stream\": \"^1.0.0\",\n \"empathic\": \"^2.0.0\",\n \"fflate\": \"^0.8.2\",\n \"jose\": \"^6.1.0\",\n \"limit-concur\": \"^4.0.0\",\n \"mime-types\": \"^3.0.1\",\n \"srcset\": \"^5.0.2\"\n },\n \"storybook\": {\n \"displayName\": \"Happo\",\n \"icon\": \"https://happo.io/static/happo-hippo.png\",\n \"supportedFrameworks\": [\n \"angular\",\n \"ember\",\n \"html\",\n \"preact\",\n \"react\",\n \"react-native\",\n \"svelte\",\n \"vue\",\n \"web-components\"\n ],\n \"unsupportedFrameworks\": []\n },\n \"keywords\": [\n \"storybook-addon\",\n \"accessibility\",\n \"cypress\",\n \"playwright\",\n \"regression\",\n \"storybook\",\n \"test\",\n \"testing\",\n \"ui\",\n \"visual-regression\",\n \"visual\",\n \"vrt\"\n ],\n \"engines\": {\n \"node\": \">=22\"\n }\n}\n"],
4
+ "sourcesContent": ["{\n \"name\": \"happo\",\n \"version\": \"6.0.5\",\n \"description\": \"Catch unexpected visual and accessibility changes and UI bugs\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/happo/happo.git\"\n },\n \"bugs\": \"https://github.com/happo/happo/issues\",\n \"homepage\": \"https://happo.io\",\n \"bin\": {\n \"happo\": \"dist/cli/index.js\"\n },\n \"type\": \"module\",\n \"main\": \"./dist/config/index.js\",\n \"types\": \"./dist/config/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/config/index.d.ts\",\n \"default\": \"./dist/config/index.js\"\n },\n \"./cypress\": {\n \"types\": \"./dist/cypress/index.d.ts\",\n \"default\": \"./dist/cypress/index.js\"\n },\n \"./cypress/task\": {\n \"types\": \"./dist/cypress/task.d.ts\",\n \"default\": \"./dist/cypress/task.js\"\n },\n \"./playwright\": {\n \"types\": \"./dist/playwright/index.d.ts\",\n \"default\": \"./dist/playwright/index.js\"\n },\n \"./custom\": {\n \"types\": \"./dist/custom/index.d.ts\",\n \"default\": \"./dist/custom/index.js\"\n },\n \"./storybook/addon\": {\n \"types\": \"./dist/storybook/browser/addon.d.ts\",\n \"default\": \"./dist/storybook/browser/addon.js\"\n },\n \"./storybook/decorator\": {\n \"types\": \"./dist/storybook/browser/decorator.d.ts\",\n \"default\": \"./dist/storybook/browser/decorator.js\"\n },\n \"./storybook/preset\": {\n \"types\": \"./dist/storybook/preset.d.ts\",\n \"default\": \"./dist/storybook/preset.js\"\n },\n \"./storybook/register\": {\n \"types\": \"./dist/storybook/browser/register.d.ts\",\n \"default\": \"./dist/storybook/browser/register.js\"\n }\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"all\": \"node ./scripts/allchecks.ts\",\n \"build\": \"pnpm build:types && pnpm build:dist\",\n \"build:custom\": \"esbuild src/custom/__happo__/index.ts --bundle --format=iife --global-name=happoCustom --outfile=tmp/happo-custom/bundle.js --platform=browser --target=esnext\",\n \"build:dist\": \"./scripts/build.ts\",\n \"build:types\": \"pnpm tsc --pretty\",\n \"build:watch\": \"tsc --build --watch\",\n \"clean\": \"rm -rf dist tmp/tsc tmp/happo-custom\",\n \"lint\": \"eslint .\",\n \"prepublishOnly\": \"pnpm clean && pnpm build\",\n \"storybook:dev\": \"storybook dev --config-dir src/storybook/__tests__/storybook-app -p ${PORT:-6007}\",\n \"test\": \"node --env-file-if-exists=.env.local ./scripts/test.ts\",\n \"test:custom\": \"pnpm build:dist && pnpm build:custom && node --env-file-if-exists=.env.local dist/cli/index.js -c ./happoconfigs/happo.custom.config.ts\",\n \"test:cypress\": \"pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/index.js -c ./happoconfigs/happo.cypress.config.ts e2e -- cypress run -C src/cypress/__cypress__/cypress.config.ts\",\n \"test:cypress:open\": \"cypress open -C src/cypress/__cypress__/cypress.config.ts\",\n \"test:playwright\": \"pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/index.js -c ./happoconfigs/happo.playwright.config.ts e2e -- playwright test\",\n \"test:storybook\": \"pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/index.js -c ./happoconfigs/happo.storybook.config.ts\",\n \"test:pages\": \"pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/index.js -c ./happoconfigs/happo.pages.config.ts\",\n \"tsc\": \"tsc --build tsconfig.json\"\n },\n \"browserslist\": {\n \"node\": [\n \"node 22\"\n ],\n \"browser\": [\n \"last 2 Chrome major versions\",\n \"last 2 Firefox major versions\",\n \"last 2 Safari major versions\",\n \"last 2 Edge major versions\"\n ],\n \"isomorphic\": [\n \"node 22\",\n \"last 2 Chrome major versions\",\n \"last 2 Firefox major versions\",\n \"last 2 Safari major versions\",\n \"last 2 Edge major versions\"\n ]\n },\n \"prettier\": {\n \"printWidth\": 85,\n \"singleQuote\": true,\n \"trailingComma\": \"all\",\n \"arrowParens\": \"always\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.36.0\",\n \"@playwright/test\": \"^1.55.1\",\n \"@reporters/github\": \"^1.11.0\",\n \"@storybook/builder-vite\": \"^10.0.1\",\n \"@storybook/react-vite\": \"^10.0.1\",\n \"@types/async-retry\": \"^1.4.9\",\n \"@types/base64-stream\": \"^1.0.5\",\n \"@types/jsdom\": \"^27.0.0\",\n \"@types/mime-types\": \"^3.0.1\",\n \"@types/multiparty\": \"^4.2.1\",\n \"@types/node\": \"^24.9.1\",\n \"@types/react\": \"^19.2.0\",\n \"@types/react-dom\": \"^19.2.0\",\n \"@types/serve-handler\": \"^6.1.4\",\n \"cypress\": \"^15.5.0\",\n \"esbuild\": \"^0.27.0\",\n \"eslint\": \"^9.36.0\",\n \"eslint-config-prettier\": \"^10.1.8\",\n \"eslint-plugin-compat\": \"^6.0.2\",\n \"eslint-plugin-depend\": \"^1.3.1\",\n \"eslint-plugin-simple-import-sort\": \"^12.1.1\",\n \"eslint-plugin-unicorn\": \"^62.0.0\",\n \"jiti\": \"^2.6.0\",\n \"jsdom\": \"^27.0.0\",\n \"multiparty\": \"^4.2.3\",\n \"prettier\": \"^3.6.2\",\n \"react\": \"^19.2.0\",\n \"react-dom\": \"^19.2.0\",\n \"react-error-boundary\": \"^6.0.0\",\n \"serve-handler\": \"^6.1.6\",\n \"storybook\": \"^10.0.1\",\n \"typescript\": \"^5.9.2\",\n \"typescript-eslint\": \"^8.44.1\"\n },\n \"dependencies\": {\n \"async-retry\": \"^1.3.3\",\n \"base64-stream\": \"^1.0.0\",\n \"empathic\": \"^2.0.0\",\n \"fflate\": \"^0.8.2\",\n \"jose\": \"^6.1.0\",\n \"limit-concur\": \"^4.0.0\",\n \"mime-types\": \"^3.0.1\",\n \"srcset\": \"^5.0.2\"\n },\n \"storybook\": {\n \"displayName\": \"Happo\",\n \"icon\": \"https://happo.io/static/happo-hippo.png\",\n \"supportedFrameworks\": [\n \"angular\",\n \"ember\",\n \"html\",\n \"preact\",\n \"react\",\n \"react-native\",\n \"svelte\",\n \"vue\",\n \"web-components\"\n ],\n \"unsupportedFrameworks\": []\n },\n \"keywords\": [\n \"storybook-addon\",\n \"accessibility\",\n \"cypress\",\n \"playwright\",\n \"regression\",\n \"storybook\",\n \"test\",\n \"testing\",\n \"ui\",\n \"visual-regression\",\n \"visual\",\n \"vrt\"\n ],\n \"engines\": {\n \"node\": \">=22\"\n }\n}\n"],
5
5
  "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  makeHappoAPIRequest
3
- } from "./chunk-G63DXNAV.js";
3
+ } from "./chunk-L2YFFA77.js";
4
4
 
5
5
  // src/network/createAsyncComparison.ts
6
6
  function assertResultIsCreateAsyncComparisonResult(result) {
@@ -56,4 +56,4 @@ async function createAsyncComparison(config, {
56
56
  export {
57
57
  createAsyncComparison
58
58
  };
59
- //# sourceMappingURL=chunk-VB6YWDBQ.js.map
59
+ //# sourceMappingURL=chunk-UVYFRXQW.js.map
@@ -0,0 +1,10 @@
1
+ import {
2
+ createAsyncComparison
3
+ } from "./chunk-UVYFRXQW.js";
4
+ import "./chunk-L2YFFA77.js";
5
+ import "./chunk-GS5VDGV6.js";
6
+ import "./chunk-O5GJGAW5.js";
7
+ export {
8
+ createAsyncComparison as default
9
+ };
10
+ //# sourceMappingURL=createAsyncComparison-5AUI4A72.js.map
@@ -1,7 +1,8 @@
1
1
  import {
2
2
  makeHappoAPIRequest
3
- } from "./chunk-G63DXNAV.js";
4
- import "./chunk-TXOXC6WO.js";
3
+ } from "./chunk-L2YFFA77.js";
4
+ import "./chunk-GS5VDGV6.js";
5
+ import "./chunk-O5GJGAW5.js";
5
6
 
6
7
  // src/network/createAsyncReport.ts
7
8
  function assertResultIsCreateAsyncReportResult(result) {
@@ -37,4 +38,4 @@ async function createAsyncReport(snapRequestIds, config, { afterSha, link, messa
37
38
  export {
38
39
  createAsyncReport as default
39
40
  };
40
- //# sourceMappingURL=createAsyncReport-WFZS224O.js.map
41
+ //# sourceMappingURL=createAsyncReport-ZJG3YRUK.js.map
@@ -2,6 +2,6 @@
2
2
  "version": 3,
3
3
  "sources": ["../../src/network/createAsyncReport.ts"],
4
4
  "sourcesContent": ["import type { ConfigWithDefaults } from '../config/index.ts';\nimport type { EnvironmentResult } from '../environment/index.ts';\nimport type { Logger } from '../isomorphic/types.ts';\nimport makeHappoAPIRequest from './makeHappoAPIRequest.ts';\n\ninterface CreateAsyncReportResult {\n id: number;\n url: string;\n}\n\nfunction assertResultIsCreateAsyncReportResult(\n result: unknown,\n): asserts result is CreateAsyncReportResult {\n if (typeof result !== 'object' || result === null) {\n throw new TypeError('Result is not an object');\n }\n\n if (!('id' in result) || typeof result.id !== 'number') {\n throw new TypeError('Result is missing id');\n }\n\n if (!('url' in result) || typeof result.url !== 'string') {\n throw new TypeError('Result is missing url');\n }\n}\n\nexport default async function createAsyncReport(\n snapRequestIds: Array<number>,\n config: ConfigWithDefaults,\n { afterSha, link, message }: EnvironmentResult,\n logger: Logger,\n): Promise<CreateAsyncReportResult> {\n const result = await makeHappoAPIRequest(\n {\n path: `/api/async-reports/${afterSha}`,\n method: 'POST',\n body: {\n requestIds: snapRequestIds,\n link,\n message,\n project: config.project,\n },\n },\n config,\n { retryCount: 3 },\n logger,\n );\n\n assertResultIsCreateAsyncReportResult(result);\n\n return result;\n}\n"],
5
- "mappings": ";;;;;;AAUA,SAAS,sCACP,QAC2C;AAC3C,MAAI,OAAO,WAAW,YAAY,WAAW,MAAM;AACjD,UAAM,IAAI,UAAU,yBAAyB;AAAA,EAC/C;AAEA,MAAI,EAAE,QAAQ,WAAW,OAAO,OAAO,OAAO,UAAU;AACtD,UAAM,IAAI,UAAU,sBAAsB;AAAA,EAC5C;AAEA,MAAI,EAAE,SAAS,WAAW,OAAO,OAAO,QAAQ,UAAU;AACxD,UAAM,IAAI,UAAU,uBAAuB;AAAA,EAC7C;AACF;AAEA,eAAO,kBACL,gBACA,QACA,EAAE,UAAU,MAAM,QAAQ,GAC1B,QACkC;AAClC,QAAM,SAAS,MAAM;AAAA,IACnB;AAAA,MACE,MAAM,sBAAsB,QAAQ;AAAA,MACpC,QAAQ;AAAA,MACR,MAAM;AAAA,QACJ,YAAY;AAAA,QACZ;AAAA,QACA;AAAA,QACA,SAAS,OAAO;AAAA,MAClB;AAAA,IACF;AAAA,IACA;AAAA,IACA,EAAE,YAAY,EAAE;AAAA,IAChB;AAAA,EACF;AAEA,wCAAsC,MAAM;AAE5C,SAAO;AACT;",
5
+ "mappings": ";;;;;;;AAUA,SAAS,sCACP,QAC2C;AAC3C,MAAI,OAAO,WAAW,YAAY,WAAW,MAAM;AACjD,UAAM,IAAI,UAAU,yBAAyB;AAAA,EAC/C;AAEA,MAAI,EAAE,QAAQ,WAAW,OAAO,OAAO,OAAO,UAAU;AACtD,UAAM,IAAI,UAAU,sBAAsB;AAAA,EAC5C;AAEA,MAAI,EAAE,SAAS,WAAW,OAAO,OAAO,QAAQ,UAAU;AACxD,UAAM,IAAI,UAAU,uBAAuB;AAAA,EAC7C;AACF;AAEA,eAAO,kBACL,gBACA,QACA,EAAE,UAAU,MAAM,QAAQ,GAC1B,QACkC;AAClC,QAAM,SAAS,MAAM;AAAA,IACnB;AAAA,MACE,MAAM,sBAAsB,QAAQ;AAAA,MACpC,QAAQ;AAAA,MACR,MAAM;AAAA,QACJ,YAAY;AAAA,QACZ;AAAA,QACA;AAAA,QACA,SAAS,OAAO;AAAA,MAClB;AAAA,IACF;AAAA,IACA;AAAA,IACA,EAAE,YAAY,EAAE;AAAA,IAChB;AAAA,EACF;AAEA,wCAAsC,MAAM;AAE5C,SAAO;AACT;",
6
6
  "names": []
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AASA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AA+KrD,wBAAsB,IAAI,CACxB,OAAO,GAAE,KAAK,CAAC,MAAM,CAAgB,EACrC,MAAM,GAAE,MAAgB,GACvB,OAAO,CAAC,IAAI,CAAC,CA0Df"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AASA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AA+KrD,wBAAsB,IAAI,CACxB,OAAO,GAAE,KAAK,CAAC,MAAM,CAAgB,EACrC,MAAM,GAAE,MAAgB,GACvB,OAAO,CAAC,IAAI,CAAC,CA2Df"}
package/dist/cli/index.js CHANGED
@@ -1,7 +1,10 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ fetchWithRetry
4
+ } from "./chunk-GS5VDGV6.js";
2
5
  import {
3
6
  package_default
4
- } from "./chunk-TXOXC6WO.js";
7
+ } from "./chunk-O5GJGAW5.js";
5
8
 
6
9
  // src/cli/index.ts
7
10
  import path2 from "node:path";
@@ -18,6 +21,7 @@ var CONFIG_FILENAMES = [
18
21
  "happo.config.mts",
19
22
  "happo.config.cts"
20
23
  ];
24
+ var DEFAULT_ENDPOINT = "https://happo.io";
21
25
  function findConfigFile() {
22
26
  if (process.env.HAPPO_CONFIG_FILE) {
23
27
  return process.env.HAPPO_CONFIG_FILE;
@@ -30,19 +34,32 @@ function findConfigFile() {
30
34
  }
31
35
  return configFilePath;
32
36
  }
33
- function validateConfig(config) {
34
- if (!config.apiKey) {
35
- throw new Error(
36
- "Missing `apiKey` in your Happo config. Reference yours at https://happo.io/settings"
37
- );
37
+ function assertIsPullRequestTokenResponse(response) {
38
+ if (typeof response !== "object" || response === null || !("secret" in response)) {
39
+ throw new TypeError("Unexpected pull request token response");
38
40
  }
39
- if (!config.apiSecret) {
41
+ }
42
+ async function getPullRequestSecret(endpoint, prUrl, logger) {
43
+ const url = new URL("/api/pull-request-token", endpoint);
44
+ const res = await fetchWithRetry(
45
+ url,
46
+ {
47
+ method: "POST",
48
+ body: { prUrl },
49
+ retryCount: 3
50
+ },
51
+ logger
52
+ );
53
+ if (!res || !res.ok) {
40
54
  throw new Error(
41
- "Missing `apiSecret` in your Happo config. Reference yours at https://happo.io/settings"
55
+ `Failed to get pull request secret: ${res.status} - ${await res.text()}`
42
56
  );
43
57
  }
58
+ const json = await res.json();
59
+ assertIsPullRequestTokenResponse(json);
60
+ return json.secret;
44
61
  }
45
- async function loadConfigFile(configFilePath) {
62
+ async function loadConfigFile(configFilePath, environment, logger = console) {
46
63
  try {
47
64
  const stats = await fs.promises.stat(configFilePath);
48
65
  if (!stats.isFile()) {
@@ -54,33 +71,62 @@ async function loadConfigFile(configFilePath) {
54
71
  }
55
72
  throw error;
56
73
  }
57
- const config = await import(configFilePath);
58
- if (!config.default.targets) {
59
- config.default.targets = {
74
+ const config = (await import(configFilePath)).default;
75
+ if (!config.apiKey && process.env.HAPPO_API_KEY) {
76
+ config.apiKey = process.env.HAPPO_API_KEY;
77
+ }
78
+ if (!config.apiSecret && process.env.HAPPO_API_SECRET) {
79
+ config.apiSecret = process.env.HAPPO_API_SECRET;
80
+ }
81
+ if (!config.apiKey || !config.apiSecret) {
82
+ const missing = [
83
+ config.apiKey ? null : "apiKey",
84
+ config.apiSecret ? null : "apiSecret"
85
+ ].filter(Boolean).map((key) => `\`${key}\``).join(" and ");
86
+ if (!environment?.link) {
87
+ throw new Error(
88
+ `Missing ${missing} in your Happo config. Reference yours at https://happo.io/settings`
89
+ );
90
+ }
91
+ try {
92
+ logger.log(
93
+ `Missing ${missing} in Happo config. Falling back to pull-request authentication.`
94
+ );
95
+ config.apiKey = environment.link;
96
+ config.apiSecret = await getPullRequestSecret(
97
+ config.endpoint || DEFAULT_ENDPOINT,
98
+ environment.link,
99
+ logger
100
+ );
101
+ } catch (e) {
102
+ throw new Error("Failed to obtain temporary pull-request token", { cause: e });
103
+ }
104
+ }
105
+ if (!config.targets) {
106
+ config.targets = {
60
107
  chrome: {
61
108
  type: "chrome",
62
109
  viewport: "1024x768"
63
110
  }
64
111
  };
65
112
  }
66
- if (!config.default.integration) {
67
- config.default.integration = {
113
+ if (!config.integration) {
114
+ config.integration = {
68
115
  type: "storybook"
69
116
  };
70
117
  }
71
- const allTargets = Object.values(config.default.targets);
118
+ const allTargets = Object.values(config.targets);
72
119
  for (const target of allTargets) {
73
120
  target.viewport = target.viewport || "1024x768";
74
121
  target.freezeAnimations = target.freezeAnimations || "last-frame";
75
122
  target.prefersReducedMotion = target.prefersReducedMotion ?? true;
76
123
  }
77
124
  const configWithDefaults = {
78
- endpoint: "https://happo.io",
125
+ endpoint: DEFAULT_ENDPOINT,
79
126
  githubApiUrl: "https://api.github.com",
80
127
  targets: allTargets,
81
- ...config.default
128
+ ...config
82
129
  };
83
- validateConfig(configWithDefaults);
84
130
  return configWithDefaults;
85
131
  }
86
132
 
@@ -762,7 +808,7 @@ function createReporter(opts = {}) {
762
808
 
763
809
  // src/cli/index.ts
764
810
  async function getVersion() {
765
- const packageJson = await import("./package-LV7GRXKC.js");
811
+ const packageJson = await import("./package-X4FVUDQZ.js");
766
812
  return packageJson.default.version;
767
813
  }
768
814
  function parseDashdashCommandParts(rawArgs) {
@@ -915,9 +961,9 @@ async function main(rawArgs = process.argv, logger = console) {
915
961
  logger.log(helpText);
916
962
  return;
917
963
  }
918
- const configFilePath = makeAbsolute(args.values.config || findConfigFile());
919
- const config = await loadConfigFile(configFilePath);
920
964
  const environment = await resolveEnvironment(args.values);
965
+ const configFilePath = makeAbsolute(args.values.config || findConfigFile());
966
+ const config = await loadConfigFile(configFilePath, environment, logger);
921
967
  const command = args.positionals[0];
922
968
  if (args.dashdashCommandParts) {
923
969
  await handleE2ECommand(
@@ -952,10 +998,10 @@ async function main(rawArgs = process.argv, logger = console) {
952
998
  async function handleDefaultCommand(config, environment, logger) {
953
999
  logger.log("Running happo tests...");
954
1000
  const [startJob, createAsyncComparison, createAsyncReport, prepareSnapRequests] = await Promise.all([
955
- (await import("./startJob-ELIGC4S6.js")).default,
956
- (await import("./createAsyncComparison-37UCMTAK.js")).default,
957
- (await import("./createAsyncReport-WFZS224O.js")).default,
958
- (await import("./prepareSnapRequests-APQNWGR6.js")).default
1001
+ (await import("./startJob-JUDYTDEM.js")).default,
1002
+ (await import("./createAsyncComparison-5AUI4A72.js")).default,
1003
+ (await import("./createAsyncReport-ZJG3YRUK.js")).default,
1004
+ (await import("./prepareSnapRequests-7DDDCYNL.js")).default
959
1005
  ]);
960
1006
  await startJob(config, environment, logger);
961
1007
  try {
@@ -977,7 +1023,7 @@ async function handleDefaultCommand(config, environment, logger) {
977
1023
  }
978
1024
  } catch (e) {
979
1025
  logger.error(e instanceof Error ? e.message : String(e), e);
980
- const cancelJob = (await import("./cancelJob-6IYR4YZT.js")).default;
1026
+ const cancelJob = (await import("./cancelJob-FZN3FED2.js")).default;
981
1027
  await cancelJob("failure", config, environment, logger);
982
1028
  process.exitCode = 1;
983
1029
  return;
@@ -988,7 +1034,7 @@ async function handleFinalizeCommand(config, environment, logger) {
988
1034
  logger.log("Config:", config);
989
1035
  logger.log("Environment:", environment);
990
1036
  try {
991
- const finalizeAll = (await import("./wrapper-SK4CQB2Y.js")).finalizeAll;
1037
+ const finalizeAll = (await import("./wrapper-ZMK7MDL2.js")).finalizeAll;
992
1038
  await finalizeAll({ happoConfig: config, environment, logger });
993
1039
  } catch (e) {
994
1040
  logger.error(e instanceof Error ? e.message : String(e), e);
@@ -1017,7 +1063,7 @@ async function handleE2ECommand(config, environment, dashdashCommandParts, confi
1017
1063
  logger.log("Config:", config);
1018
1064
  logger.log("Environment:", environment);
1019
1065
  logger.log("Dashdash command parts:", dashdashCommandParts);
1020
- const runWithWrapper = (await import("./wrapper-SK4CQB2Y.js")).default;
1066
+ const runWithWrapper = (await import("./wrapper-ZMK7MDL2.js")).default;
1021
1067
  const exitCode = await runWithWrapper(
1022
1068
  dashdashCommandParts,
1023
1069
  config,