@juangadm/pre-post 0.2.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +102 -222
- package/dist/bin/cli.js +199 -347
- package/dist/bin/cli.js.map +1 -1
- package/dist/browser.d.ts +42 -11
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +371 -94
- package/dist/browser.js.map +1 -1
- package/dist/capture.d.ts +1 -6
- package/dist/capture.d.ts.map +1 -1
- package/dist/capture.js +12 -35
- package/dist/capture.js.map +1 -1
- package/dist/commands/compare.d.ts +18 -0
- package/dist/commands/compare.d.ts.map +1 -0
- package/dist/commands/compare.js +64 -0
- package/dist/commands/compare.js.map +1 -0
- package/dist/commands/detect.d.ts +20 -0
- package/dist/commands/detect.d.ts.map +1 -0
- package/dist/commands/detect.js +19 -0
- package/dist/commands/detect.js.map +1 -0
- package/dist/commands/doctor.d.ts +10 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +38 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/login.d.ts +6 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +34 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/pr.d.ts +28 -0
- package/dist/commands/pr.d.ts.map +1 -0
- package/dist/commands/pr.js +159 -0
- package/dist/commands/pr.js.map +1 -0
- package/dist/commands/prune.d.ts +10 -0
- package/dist/commands/prune.d.ts.map +1 -0
- package/dist/commands/prune.js +13 -0
- package/dist/commands/prune.js.map +1 -0
- package/dist/config.d.ts +36 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +60 -0
- package/dist/config.js.map +1 -0
- package/dist/diff-pool.d.ts +17 -0
- package/dist/diff-pool.d.ts.map +1 -0
- package/dist/diff-pool.js +89 -0
- package/dist/diff-pool.js.map +1 -0
- package/dist/diff-worker.d.ts +29 -0
- package/dist/diff-worker.d.ts.map +1 -0
- package/dist/diff-worker.js +38 -0
- package/dist/diff-worker.js.map +1 -0
- package/dist/diff.d.ts +37 -0
- package/dist/diff.d.ts.map +1 -0
- package/dist/diff.js +171 -0
- package/dist/diff.js.map +1 -0
- package/dist/doctor.d.ts +38 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +72 -0
- package/dist/doctor.js.map +1 -0
- package/dist/errors.d.ts +38 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +59 -0
- package/dist/errors.js.map +1 -0
- package/dist/filename.d.ts +2 -0
- package/dist/filename.d.ts.map +1 -1
- package/dist/filename.js +2 -1
- package/dist/filename.js.map +1 -1
- package/dist/git.d.ts +23 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +86 -0
- package/dist/git.js.map +1 -0
- package/dist/github.d.ts +73 -0
- package/dist/github.d.ts.map +1 -0
- package/dist/github.js +240 -0
- package/dist/github.js.map +1 -0
- package/dist/index.d.ts +22 -22
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -66
- package/dist/index.js.map +1 -1
- package/dist/pkg.d.ts +8 -0
- package/dist/pkg.d.ts.map +1 -0
- package/dist/pkg.js +35 -0
- package/dist/pkg.js.map +1 -0
- package/dist/report.d.ts +20 -0
- package/dist/report.d.ts.map +1 -0
- package/dist/report.js +107 -0
- package/dist/report.js.map +1 -0
- package/dist/routes/imports.d.ts +46 -0
- package/dist/routes/imports.d.ts.map +1 -0
- package/dist/routes/imports.js +208 -0
- package/dist/routes/imports.js.map +1 -0
- package/dist/routes/vite.d.ts +15 -0
- package/dist/routes/vite.d.ts.map +1 -0
- package/dist/routes/vite.js +130 -0
- package/dist/routes/vite.js.map +1 -0
- package/dist/routes.d.ts +41 -14
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +271 -141
- package/dist/routes.js.map +1 -1
- package/dist/run.d.ts +36 -0
- package/dist/run.d.ts.map +1 -0
- package/dist/run.js +128 -0
- package/dist/run.js.map +1 -0
- package/dist/sessions.d.ts +50 -0
- package/dist/sessions.d.ts.map +1 -0
- package/dist/sessions.js +74 -0
- package/dist/sessions.js.map +1 -0
- package/dist/types.d.ts +118 -41
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -1
- package/dist/viewport.d.ts +6 -1
- package/dist/viewport.d.ts.map +1 -1
- package/dist/viewport.js +13 -7
- package/dist/viewport.js.map +1 -1
- package/package.json +21 -13
- package/skill/SKILL.md +31 -229
- package/dist/clipboard.d.ts +0 -9
- package/dist/clipboard.d.ts.map +0 -1
- package/dist/clipboard.js +0 -26
- package/dist/clipboard.js.map +0 -1
- package/dist/upload.d.ts +0 -39
- package/dist/upload.d.ts.map +0 -1
- package/dist/upload.js +0 -149
- package/dist/upload.js.map +0 -1
- package/skill/scripts/adapters/0x0st.sh +0 -36
- package/skill/scripts/adapters/blob.sh +0 -55
- package/skill/scripts/adapters/git-native.sh +0 -51
- package/skill/scripts/upload-and-copy.sh +0 -230
package/dist/run.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The capture → diff pipeline shared by `pr` and the two-URL mode.
|
|
3
|
+
* Every route/viewport pair runs concurrently; the browser's page pool bounds it.
|
|
4
|
+
*/
|
|
5
|
+
import fs from 'fs';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import { captureScreenshot } from './browser.js';
|
|
8
|
+
import { HttpStatusError, NavigationError } from './errors.js';
|
|
9
|
+
import { DiffPool } from './diff-pool.js';
|
|
10
|
+
import { authHint } from './doctor.js';
|
|
11
|
+
export function routeSlug(route) {
|
|
12
|
+
const slug = route.replace(/^\/+|\/+$/g, '').replace(/[^\w.-]+/g, '-').replace(/^-+|-+$/g, '');
|
|
13
|
+
return slug || 'home';
|
|
14
|
+
}
|
|
15
|
+
export function joinUrl(base, route) {
|
|
16
|
+
return base.replace(/\/+$/, '') + (route.startsWith('/') ? route : `/${route}`);
|
|
17
|
+
}
|
|
18
|
+
/** Add a scheme to a bare URL (http for loopback hosts, https otherwise) and drop trailing slashes. */
|
|
19
|
+
export function normalizeUrl(url) {
|
|
20
|
+
const withScheme = /^(https?|file):\/\//i.test(url)
|
|
21
|
+
? url
|
|
22
|
+
: /^(localhost|127\.0\.0\.1|0\.0\.0\.0|\[::1\])(:|\/|$)/i.test(url) ? `http://${url}` : `https://${url}`;
|
|
23
|
+
return withScheme.replace(/\/+$/, '');
|
|
24
|
+
}
|
|
25
|
+
export function hostOf(url) {
|
|
26
|
+
try {
|
|
27
|
+
return new URL(url).host;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return url;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** The one rule for "did this capture change": a ratio for big pages, an absolute floor for small edits. */
|
|
34
|
+
export function isChanged(diff, threshold, minChangedPixels) {
|
|
35
|
+
return diff.changedPixels > 0 && (diff.changedRatio >= threshold || diff.changedPixels >= minChangedPixels);
|
|
36
|
+
}
|
|
37
|
+
function describeError(err, side, url) {
|
|
38
|
+
if (err instanceof HttpStatusError)
|
|
39
|
+
return authHint(err);
|
|
40
|
+
if (err instanceof NavigationError) {
|
|
41
|
+
switch (err.kind) {
|
|
42
|
+
case 'refused': return `connection refused at ${url} (is the ${side === 'after' ? 'dev server' : 'site'} running?)`;
|
|
43
|
+
case 'timeout': return `timed out loading ${url}`;
|
|
44
|
+
case 'dns': return `cannot resolve ${hostOf(url)}`;
|
|
45
|
+
default: return `${side}: ${err.message.slice(0, 160)}`;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const msg = err?.message || String(err);
|
|
49
|
+
return `${side}: ${msg.split('\n')[0].slice(0, 160)}`;
|
|
50
|
+
}
|
|
51
|
+
async function runTask(task, opts, pool) {
|
|
52
|
+
const started = Date.now();
|
|
53
|
+
const base = { route: task.route, resolvedRoute: task.resolvedRoute, viewport: task.viewport, status: 'error' };
|
|
54
|
+
const captureOpts = {
|
|
55
|
+
viewport: task.size,
|
|
56
|
+
fullPage: opts.fullPage,
|
|
57
|
+
maxHeight: opts.maxHeight,
|
|
58
|
+
scale: opts.scale,
|
|
59
|
+
wait: opts.wait,
|
|
60
|
+
auth: opts.auth,
|
|
61
|
+
};
|
|
62
|
+
const [beforeRes, afterRes] = await Promise.allSettled([
|
|
63
|
+
captureScreenshot(task.beforeUrl, captureOpts),
|
|
64
|
+
captureScreenshot(task.afterUrl, captureOpts),
|
|
65
|
+
]);
|
|
66
|
+
if (beforeRes.status === 'rejected' || afterRes.status === 'rejected') {
|
|
67
|
+
const errors = [];
|
|
68
|
+
if (beforeRes.status === 'rejected')
|
|
69
|
+
errors.push(describeError(beforeRes.reason, 'before', task.beforeUrl));
|
|
70
|
+
if (afterRes.status === 'rejected')
|
|
71
|
+
errors.push(describeError(afterRes.reason, 'after', task.afterUrl));
|
|
72
|
+
return { ...base, error: errors.join('; '), durationMs: Date.now() - started };
|
|
73
|
+
}
|
|
74
|
+
const before = beforeRes.value;
|
|
75
|
+
const after = afterRes.value;
|
|
76
|
+
if (before.status === 404 && after.status === 404) {
|
|
77
|
+
return { ...base, error: `404 on both ${task.beforeUrl} and ${task.afterUrl} (wrong route or missing sample?)`, durationMs: Date.now() - started };
|
|
78
|
+
}
|
|
79
|
+
const prefix = `${routeSlug(task.route)}-${task.viewport}`;
|
|
80
|
+
const file = (kind) => path.join(opts.outputDir, `${prefix}-${kind}.png`);
|
|
81
|
+
const outputs = { before: file('pre'), after: file('post'), diff: file('diff'), cropBefore: file('pre-crop'), cropAfter: file('post-crop') };
|
|
82
|
+
// Copy into standalone buffers so they can be transferred to the worker.
|
|
83
|
+
const diff = await pool.run({
|
|
84
|
+
before: new Uint8Array(before.image),
|
|
85
|
+
after: new Uint8Array(after.image),
|
|
86
|
+
outputs,
|
|
87
|
+
options: {
|
|
88
|
+
padding: 40 * opts.scale,
|
|
89
|
+
minCrop: { width: 400 * opts.scale, height: 200 * opts.scale },
|
|
90
|
+
highlightDownscale: opts.scale >= 2 ? 2 : 1,
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
const notes = [];
|
|
94
|
+
if (before.status === 404 && after.status && after.status < 400)
|
|
95
|
+
notes.push('new page (404 on production)');
|
|
96
|
+
else if (before.status && before.status >= 400)
|
|
97
|
+
notes.push(`production returned ${before.status}`);
|
|
98
|
+
if (after.status && after.status >= 400)
|
|
99
|
+
notes.push(`local returned ${after.status}`);
|
|
100
|
+
const changed = isChanged(diff, opts.threshold, opts.minChangedPixels);
|
|
101
|
+
opts.log?.(` ${changed ? 'changed ' : 'same '} ${task.route} @ ${task.viewport} (${(diff.changedRatio * 100).toFixed(2)}%, ${Date.now() - started}ms)`);
|
|
102
|
+
return {
|
|
103
|
+
...base,
|
|
104
|
+
status: changed ? 'changed' : 'unchanged',
|
|
105
|
+
changedRatio: diff.changedRatio,
|
|
106
|
+
sizeChanged: diff.sizeChanged,
|
|
107
|
+
files: {
|
|
108
|
+
before: outputs.before,
|
|
109
|
+
after: outputs.after,
|
|
110
|
+
diff: diff.hasHighlight ? outputs.diff : undefined,
|
|
111
|
+
cropBefore: diff.hasCrop ? outputs.cropBefore : undefined,
|
|
112
|
+
cropAfter: diff.hasCrop ? outputs.cropAfter : undefined,
|
|
113
|
+
},
|
|
114
|
+
note: notes.join('; ') || undefined,
|
|
115
|
+
durationMs: Date.now() - started,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
export async function runTasks(tasks, opts) {
|
|
119
|
+
fs.mkdirSync(opts.outputDir, { recursive: true });
|
|
120
|
+
const pool = new DiffPool();
|
|
121
|
+
try {
|
|
122
|
+
return await Promise.all(tasks.map(t => runTask(t, opts, pool)));
|
|
123
|
+
}
|
|
124
|
+
finally {
|
|
125
|
+
await pool.close();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=run.js.map
|
package/dist/run.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Saved browser sessions from `pre-post login <url>`.
|
|
3
|
+
* Stored per host under the user's config dir, never inside the repo.
|
|
4
|
+
*/
|
|
5
|
+
import { AuthOptions } from './types.js';
|
|
6
|
+
export interface StorageState {
|
|
7
|
+
cookies: Array<{
|
|
8
|
+
name: string;
|
|
9
|
+
value: string;
|
|
10
|
+
domain: string;
|
|
11
|
+
path: string;
|
|
12
|
+
expires: number;
|
|
13
|
+
httpOnly: boolean;
|
|
14
|
+
secure: boolean;
|
|
15
|
+
sameSite: 'Strict' | 'Lax' | 'None';
|
|
16
|
+
}>;
|
|
17
|
+
origins: Array<{
|
|
18
|
+
origin: string;
|
|
19
|
+
localStorage: Array<{
|
|
20
|
+
name: string;
|
|
21
|
+
value: string;
|
|
22
|
+
}>;
|
|
23
|
+
}>;
|
|
24
|
+
}
|
|
25
|
+
export declare function sessionsDir(): string;
|
|
26
|
+
export declare function sessionPath(host: string): string;
|
|
27
|
+
export declare function saveSession(host: string, state: StorageState): string;
|
|
28
|
+
export declare function loadSession(host: string): StorageState | null;
|
|
29
|
+
/** Cookies from every saved session whose host matches one of the URLs. */
|
|
30
|
+
export declare function cookiesForUrls(urls: string[]): StorageState['cookies'];
|
|
31
|
+
export interface ResolveAuthInput {
|
|
32
|
+
/** Headers from .pre-post.json */
|
|
33
|
+
configHeaders?: Record<string, string>;
|
|
34
|
+
/** Headers from the command line */
|
|
35
|
+
headers?: Record<string, string>;
|
|
36
|
+
/** Cookies from the command line, applied to `cookieUrl` */
|
|
37
|
+
cookies?: Array<{
|
|
38
|
+
name: string;
|
|
39
|
+
value: string;
|
|
40
|
+
}>;
|
|
41
|
+
cookieUrl?: string;
|
|
42
|
+
/** URLs whose saved login sessions should be reused */
|
|
43
|
+
urls: string[];
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Everything that authenticates a capture, from every source: config headers,
|
|
47
|
+
* CLI headers, the Vercel bypass secret, CLI cookies, and saved login sessions.
|
|
48
|
+
*/
|
|
49
|
+
export declare function resolveAuth(input: ResolveAuthInput): AuthOptions | undefined;
|
|
50
|
+
//# sourceMappingURL=sessions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../src/sessions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAC1D,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;KAC1F,CAAC,CAAC;IACH,OAAO,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC,CAAC;CAC1F;AAED,wBAAgB,WAAW,IAAI,MAAM,CAKpC;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,MAAM,CAKrE;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAQ7D;AAED,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,YAAY,CAAC,SAAS,CAAC,CAkBtE;AAED,MAAM,WAAW,gBAAgB;IAC/B,kCAAkC;IAClC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,oCAAoC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,4DAA4D;IAC5D,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,WAAW,GAAG,SAAS,CAY5E"}
|
package/dist/sessions.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Saved browser sessions from `pre-post login <url>`.
|
|
3
|
+
* Stored per host under the user's config dir, never inside the repo.
|
|
4
|
+
*/
|
|
5
|
+
import fs from 'fs';
|
|
6
|
+
import os from 'os';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
export function sessionsDir() {
|
|
9
|
+
const base = process.env.XDG_CONFIG_HOME
|
|
10
|
+
|| (process.platform === 'win32' ? process.env.APPDATA : undefined)
|
|
11
|
+
|| path.join(os.homedir(), '.config');
|
|
12
|
+
return path.join(base, 'pre-post', 'sessions');
|
|
13
|
+
}
|
|
14
|
+
export function sessionPath(host) {
|
|
15
|
+
return path.join(sessionsDir(), `${host.replace(/[^\w.-]/g, '_')}.json`);
|
|
16
|
+
}
|
|
17
|
+
export function saveSession(host, state) {
|
|
18
|
+
fs.mkdirSync(sessionsDir(), { recursive: true, mode: 0o700 });
|
|
19
|
+
const file = sessionPath(host);
|
|
20
|
+
fs.writeFileSync(file, JSON.stringify(state), { mode: 0o600 });
|
|
21
|
+
return file;
|
|
22
|
+
}
|
|
23
|
+
export function loadSession(host) {
|
|
24
|
+
const file = sessionPath(host);
|
|
25
|
+
if (!fs.existsSync(file))
|
|
26
|
+
return null;
|
|
27
|
+
try {
|
|
28
|
+
return JSON.parse(fs.readFileSync(file, 'utf-8'));
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** Cookies from every saved session whose host matches one of the URLs. */
|
|
35
|
+
export function cookiesForUrls(urls) {
|
|
36
|
+
const out = [];
|
|
37
|
+
const hosts = new Set();
|
|
38
|
+
for (const u of urls) {
|
|
39
|
+
try {
|
|
40
|
+
hosts.add(new URL(u).hostname);
|
|
41
|
+
}
|
|
42
|
+
catch { /* ignore */ }
|
|
43
|
+
}
|
|
44
|
+
for (const host of hosts) {
|
|
45
|
+
const state = loadSession(host);
|
|
46
|
+
if (!state)
|
|
47
|
+
continue;
|
|
48
|
+
const now = Date.now() / 1000;
|
|
49
|
+
for (const c of state.cookies) {
|
|
50
|
+
if (c.expires && c.expires > 0 && c.expires < now)
|
|
51
|
+
continue;
|
|
52
|
+
out.push(c);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Everything that authenticates a capture, from every source: config headers,
|
|
59
|
+
* CLI headers, the Vercel bypass secret, CLI cookies, and saved login sessions.
|
|
60
|
+
*/
|
|
61
|
+
export function resolveAuth(input) {
|
|
62
|
+
const headers = { ...(input.configHeaders || {}), ...(input.headers || {}) };
|
|
63
|
+
const bypass = process.env.VERCEL_AUTOMATION_BYPASS_SECRET;
|
|
64
|
+
if (bypass && !headers['x-vercel-protection-bypass']) {
|
|
65
|
+
headers['x-vercel-protection-bypass'] = bypass;
|
|
66
|
+
headers['x-vercel-set-bypass-cookie'] = 'true';
|
|
67
|
+
}
|
|
68
|
+
const cookies = [
|
|
69
|
+
...cookiesForUrls(input.urls),
|
|
70
|
+
...(input.cookies || []).map(c => ({ ...c, url: input.cookieUrl ?? input.urls[0] })),
|
|
71
|
+
];
|
|
72
|
+
return Object.keys(headers).length || cookies.length ? { headers, cookies } : undefined;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=sessions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../src/sessions.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -5,6 +5,18 @@ export interface ViewportSize {
|
|
|
5
5
|
export type ViewportPreset = 'desktop' | 'tablet' | 'mobile';
|
|
6
6
|
export type ViewportConfig = ViewportPreset | ViewportSize;
|
|
7
7
|
export declare const VIEWPORT_PRESETS: Record<ViewportPreset, ViewportSize>;
|
|
8
|
+
export interface AuthOptions {
|
|
9
|
+
/** Extra request headers sent with every request (e.g. Vercel bypass). */
|
|
10
|
+
headers?: Record<string, string>;
|
|
11
|
+
/** Cookies to set before navigation. */
|
|
12
|
+
cookies?: Array<{
|
|
13
|
+
name: string;
|
|
14
|
+
value: string;
|
|
15
|
+
domain?: string;
|
|
16
|
+
path?: string;
|
|
17
|
+
url?: string;
|
|
18
|
+
}>;
|
|
19
|
+
}
|
|
8
20
|
export interface CaptureOptions {
|
|
9
21
|
/** URL to capture (file://, http://, https://) */
|
|
10
22
|
url: string;
|
|
@@ -14,6 +26,16 @@ export interface CaptureOptions {
|
|
|
14
26
|
viewport?: ViewportConfig;
|
|
15
27
|
/** Capture full scrollable page instead of viewport. Default: false */
|
|
16
28
|
fullPage?: boolean;
|
|
29
|
+
/** Maximum page height (CSS px) for full-page captures. Default: 3× viewport height */
|
|
30
|
+
maxHeight?: number;
|
|
31
|
+
/** Device scale factor. Default: 2 */
|
|
32
|
+
scale?: number;
|
|
33
|
+
/** Hard cap on settle wait (ms). Default: 8000 */
|
|
34
|
+
settleTimeout?: number;
|
|
35
|
+
/** Extra fixed wait after settle (ms). Default: 0 */
|
|
36
|
+
wait?: number;
|
|
37
|
+
/** Auth headers / cookies */
|
|
38
|
+
auth?: AuthOptions;
|
|
17
39
|
}
|
|
18
40
|
export interface CaptureResult {
|
|
19
41
|
/** Raw PNG image data */
|
|
@@ -24,6 +46,10 @@ export interface CaptureResult {
|
|
|
24
46
|
url: string;
|
|
25
47
|
/** CSS selector used, if any */
|
|
26
48
|
selector?: string;
|
|
49
|
+
/** HTTP status of the main document */
|
|
50
|
+
status?: number;
|
|
51
|
+
/** Wall-clock milliseconds for navigation + settle + screenshot */
|
|
52
|
+
durationMs: number;
|
|
27
53
|
}
|
|
28
54
|
export interface BeforeAfterCaptureOptions {
|
|
29
55
|
before: CaptureOptions | string;
|
|
@@ -35,32 +61,34 @@ export interface BeforeAfterCaptureResult {
|
|
|
35
61
|
before: CaptureResult;
|
|
36
62
|
after: CaptureResult;
|
|
37
63
|
}
|
|
38
|
-
export
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
after: ImageInput;
|
|
44
|
-
/** Labels for markdown output */
|
|
45
|
-
labels?: {
|
|
46
|
-
before?: string;
|
|
47
|
-
after?: string;
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
export interface FromImagesResult {
|
|
51
|
-
/** Markdown table for PR comments */
|
|
52
|
-
markdown: string;
|
|
53
|
-
/** Before image buffer */
|
|
54
|
-
beforeImage: Buffer;
|
|
55
|
-
/** After image buffer */
|
|
56
|
-
afterImage: Buffer;
|
|
64
|
+
export interface DiffRegion {
|
|
65
|
+
x: number;
|
|
66
|
+
y: number;
|
|
67
|
+
width: number;
|
|
68
|
+
height: number;
|
|
57
69
|
}
|
|
58
|
-
export interface
|
|
59
|
-
/**
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
|
|
70
|
+
export interface DiffResult {
|
|
71
|
+
/** Fraction of pixels that differ, 0..1 (over the union canvas) */
|
|
72
|
+
changedRatio: number;
|
|
73
|
+
/** Number of differing pixels */
|
|
74
|
+
changedPixels: number;
|
|
75
|
+
/** Canvas size used for comparison (device pixels) */
|
|
76
|
+
width: number;
|
|
77
|
+
height: number;
|
|
78
|
+
/** Bounding box of all changes in device pixels, or null when identical */
|
|
79
|
+
region: DiffRegion | null;
|
|
80
|
+
/** Whether the two images had different dimensions */
|
|
81
|
+
sizeChanged: boolean;
|
|
82
|
+
/** Highlight image: grayscale page with changed pixels in red (PNG). Absent when identical. */
|
|
83
|
+
highlight?: Buffer;
|
|
84
|
+
/** Crops of before/after around the changed region, when the change is localized */
|
|
85
|
+
crop?: {
|
|
86
|
+
before: Buffer;
|
|
87
|
+
after: Buffer;
|
|
88
|
+
region: DiffRegion;
|
|
89
|
+
};
|
|
63
90
|
}
|
|
91
|
+
export type Framework = 'nextjs-app' | 'nextjs-pages' | 'vite' | 'generic';
|
|
64
92
|
export interface DetectedRoute {
|
|
65
93
|
/** Route path, e.g., "/dashboard" */
|
|
66
94
|
path: string;
|
|
@@ -73,26 +101,75 @@ export interface DetectedRoute {
|
|
|
73
101
|
}
|
|
74
102
|
export interface RouteDetectionOptions {
|
|
75
103
|
/** Force a specific framework instead of auto-detecting */
|
|
76
|
-
framework?:
|
|
77
|
-
/** Maximum number of routes to return (default:
|
|
104
|
+
framework?: Framework;
|
|
105
|
+
/** Maximum number of routes to return (default: 6) */
|
|
106
|
+
maxRoutes?: number;
|
|
107
|
+
}
|
|
108
|
+
export interface PrePostConfig {
|
|
109
|
+
/** Production base URL — the "before" state */
|
|
110
|
+
before?: string;
|
|
111
|
+
/** Local base URL — the "after" state (auto-detected when omitted) */
|
|
112
|
+
after?: string;
|
|
113
|
+
/** Routes to always include */
|
|
114
|
+
routes?: string[];
|
|
115
|
+
/** Sample URLs for dynamic routes, e.g. { "/blog/[slug]": "/blog/hello" } */
|
|
116
|
+
samples?: Record<string, string>;
|
|
117
|
+
/** Viewports to capture. Default: ["desktop", "mobile"] */
|
|
118
|
+
viewports?: Array<ViewportPreset | string>;
|
|
119
|
+
/** Extra headers for every request */
|
|
120
|
+
headers?: Record<string, string>;
|
|
121
|
+
/** Change ratio (fraction 0..1) at or above which a route counts as changed. Default 0.001 */
|
|
122
|
+
threshold?: number;
|
|
123
|
+
/** Absolute changed-pixel floor at or above which a route counts as changed, so small edits on tall pages register. Default 40 */
|
|
124
|
+
minChangedPixels?: number;
|
|
125
|
+
/** Max detected routes. Default 6 */
|
|
78
126
|
maxRoutes?: number;
|
|
79
|
-
/**
|
|
80
|
-
|
|
127
|
+
/** Capture full page. Default true */
|
|
128
|
+
fullPage?: boolean;
|
|
129
|
+
/** Max full-page height in CSS px. Default 2400 */
|
|
130
|
+
maxHeight?: number;
|
|
131
|
+
/** Device scale factor. Default 2 */
|
|
132
|
+
scale?: number;
|
|
133
|
+
/** Assets branch name. Default "pre-post-assets" */
|
|
134
|
+
assetsBranch?: string;
|
|
135
|
+
/** Skip paths (glob-ish prefixes) from route detection */
|
|
136
|
+
ignore?: string[];
|
|
81
137
|
}
|
|
82
|
-
|
|
83
|
-
|
|
138
|
+
/** Pre, post, and (when there was a change) diff and crop images, as local paths or URLs. */
|
|
139
|
+
export interface ArtifactSet {
|
|
140
|
+
before: string;
|
|
141
|
+
after: string;
|
|
142
|
+
diff?: string;
|
|
143
|
+
cropBefore?: string;
|
|
144
|
+
cropAfter?: string;
|
|
145
|
+
}
|
|
146
|
+
export declare const ARTIFACT_KINDS: readonly ["before", "after", "diff", "cropBefore", "cropAfter"];
|
|
147
|
+
export interface RouteCaptureOutcome {
|
|
148
|
+
route: string;
|
|
149
|
+
/** Route actually requested (after sample substitution) */
|
|
150
|
+
resolvedRoute: string;
|
|
151
|
+
viewport: string;
|
|
152
|
+
status: 'changed' | 'unchanged' | 'error';
|
|
153
|
+
changedRatio?: number;
|
|
154
|
+
sizeChanged?: boolean;
|
|
155
|
+
error?: string;
|
|
156
|
+
files?: ArtifactSet;
|
|
157
|
+
urls?: ArtifactSet;
|
|
158
|
+
durationMs?: number;
|
|
159
|
+
/** Extra context, e.g. "new page (404 on production)" */
|
|
160
|
+
note?: string;
|
|
161
|
+
}
|
|
162
|
+
export interface PrRunResult {
|
|
163
|
+
repo: string;
|
|
164
|
+
prNumber?: number;
|
|
165
|
+
commentUrl?: string;
|
|
84
166
|
beforeBase: string;
|
|
85
|
-
/** Base URL for "after" state (e.g., localhost) */
|
|
86
167
|
afterBase: string;
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
|
|
93
|
-
/** Output directory for screenshots */
|
|
94
|
-
output?: string;
|
|
95
|
-
/** Generate markdown output */
|
|
96
|
-
markdown?: boolean;
|
|
168
|
+
outcomes: RouteCaptureOutcome[];
|
|
169
|
+
skippedDynamic: string[];
|
|
170
|
+
durationMs: number;
|
|
171
|
+
markdown: string;
|
|
172
|
+
/** Local directory holding every captured file */
|
|
173
|
+
outputDir: string;
|
|
97
174
|
}
|
|
98
175
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE7D,MAAM,MAAM,cAAc,GAAG,cAAc,GAAG,YAAY,CAAC;AAE3D,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,cAAc,EAAE,YAAY,CAIjE,CAAC;AAMF,MAAM,WAAW,cAAc;IAC7B,kDAAkD;IAClD,GAAG,EAAE,MAAM,CAAC;IACZ,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,uEAAuE;IACvE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,QAAQ,EAAE,YAAY,CAAC;IACvB,4BAA4B;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,gCAAgC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
CHANGED
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,WAAW;AACX,+DAA+D;AAW/D,MAAM,CAAC,MAAM,gBAAgB,GAAyC;IACpE,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE;IACrC,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;IACpC,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;CACpC,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,WAAW;AACX,+DAA+D;AAW/D,MAAM,CAAC,MAAM,gBAAgB,GAAyC;IACpE,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE;IACrC,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;IACpC,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;CACpC,CAAC;AAkKF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,CAAU,CAAC"}
|
package/dist/viewport.d.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
import { ViewportConfig, ViewportSize } from './types.js';
|
|
2
|
-
|
|
2
|
+
/** Accepts a preset name, a "WxH" string, or a size object. */
|
|
3
|
+
export declare function parseViewport(spec: ViewportConfig | string): {
|
|
4
|
+
label: string;
|
|
5
|
+
size: ViewportSize;
|
|
6
|
+
};
|
|
7
|
+
export declare function resolveViewport(config?: ViewportConfig | string): ViewportSize;
|
|
3
8
|
//# sourceMappingURL=viewport.d.ts.map
|
package/dist/viewport.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"viewport.d.ts","sourceRoot":"","sources":["../src/viewport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAoC,MAAM,YAAY,CAAC;AAE5F,wBAAgB,eAAe,CAAC,MAAM,CAAC,EAAE,cAAc,GAAG,YAAY,
|
|
1
|
+
{"version":3,"file":"viewport.d.ts","sourceRoot":"","sources":["../src/viewport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAoC,MAAM,YAAY,CAAC;AAE5F,+DAA+D;AAC/D,wBAAgB,aAAa,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,YAAY,CAAA;CAAE,CAOlG;AAED,wBAAgB,eAAe,CAAC,MAAM,CAAC,EAAE,cAAc,GAAG,MAAM,GAAG,YAAY,CAE9E"}
|
package/dist/viewport.js
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { VIEWPORT_PRESETS } from './types.js';
|
|
2
|
+
/** Accepts a preset name, a "WxH" string, or a size object. */
|
|
3
|
+
export function parseViewport(spec) {
|
|
4
|
+
if (typeof spec !== 'string')
|
|
5
|
+
return { label: `${spec.width}x${spec.height}`, size: spec };
|
|
6
|
+
const preset = VIEWPORT_PRESETS[spec];
|
|
7
|
+
if (preset)
|
|
8
|
+
return { label: spec, size: preset };
|
|
9
|
+
const m = spec.match(/^(\d+)x(\d+)$/);
|
|
10
|
+
if (!m)
|
|
11
|
+
throw new Error(`Invalid viewport "${spec}". Use desktop, tablet, mobile, or WxH (e.g. 1440x900).`);
|
|
12
|
+
return { label: spec, size: { width: Number(m[1]), height: Number(m[2]) } };
|
|
13
|
+
}
|
|
2
14
|
export function resolveViewport(config) {
|
|
3
|
-
|
|
4
|
-
return VIEWPORT_PRESETS.desktop;
|
|
5
|
-
}
|
|
6
|
-
if (typeof config === 'string') {
|
|
7
|
-
return VIEWPORT_PRESETS[config];
|
|
8
|
-
}
|
|
9
|
-
return config;
|
|
15
|
+
return config ? parseViewport(config).size : VIEWPORT_PRESETS.desktop;
|
|
10
16
|
}
|
|
11
17
|
//# sourceMappingURL=viewport.js.map
|
package/dist/viewport.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"viewport.js","sourceRoot":"","sources":["../src/viewport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgD,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE5F,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"viewport.js","sourceRoot":"","sources":["../src/viewport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgD,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE5F,+DAA+D;AAC/D,MAAM,UAAU,aAAa,CAAC,IAA6B;IACzD,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC3F,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAsB,CAAC,CAAC;IACxD,IAAI,MAAM;QAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IACjD,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IACtC,IAAI,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,yDAAyD,CAAC,CAAC;IAC5G,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAgC;IAC9D,OAAO,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,OAAO,CAAC;AACxE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juangadm/pre-post",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Before/after screenshots for pull requests: detect changed routes, capture, pixel-diff, and post a sticky PR comment",
|
|
5
5
|
"author": "Juan Gabriel Delgado (forked from James Clements)",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -16,13 +16,12 @@
|
|
|
16
16
|
"screenshot",
|
|
17
17
|
"before-after",
|
|
18
18
|
"visual-diff",
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"web",
|
|
22
|
-
"testing",
|
|
23
|
-
"cli",
|
|
19
|
+
"visual-regression",
|
|
20
|
+
"pull-request",
|
|
24
21
|
"playwright",
|
|
25
|
-
"
|
|
22
|
+
"pixelmatch",
|
|
23
|
+
"cli",
|
|
24
|
+
"claude-code-skill"
|
|
26
25
|
],
|
|
27
26
|
"type": "module",
|
|
28
27
|
"main": "dist/index.js",
|
|
@@ -38,22 +37,23 @@
|
|
|
38
37
|
},
|
|
39
38
|
"files": [
|
|
40
39
|
"dist",
|
|
41
|
-
"skill"
|
|
40
|
+
"skill",
|
|
41
|
+
"README.md",
|
|
42
|
+
"LICENSE"
|
|
42
43
|
],
|
|
43
44
|
"scripts": {
|
|
44
45
|
"build": "tsc -p tsconfig.pkg.json",
|
|
46
|
+
"prepare": "npm run build",
|
|
45
47
|
"prepublishOnly": "rm -rf dist && npm run build && npm run test:unit",
|
|
46
48
|
"test": "vitest run",
|
|
47
49
|
"test:watch": "vitest",
|
|
48
50
|
"test:unit": "vitest run tests/unit",
|
|
49
|
-
"test:browser": "vitest run tests/browser",
|
|
51
|
+
"test:browser": "TEST_BROWSER=true vitest run tests/browser tests/integration",
|
|
50
52
|
"test:integration": "vitest run tests/integration"
|
|
51
53
|
},
|
|
52
|
-
"dependencies": {
|
|
53
|
-
"playwright": "^1.50.0"
|
|
54
|
-
},
|
|
55
54
|
"devDependencies": {
|
|
56
55
|
"@types/node": "^22",
|
|
56
|
+
"@types/pngjs": "^6.0.5",
|
|
57
57
|
"typescript": "5.7.3",
|
|
58
58
|
"vitest": "^3.2.1"
|
|
59
59
|
},
|
|
@@ -62,5 +62,13 @@
|
|
|
62
62
|
"@types/react": "19.2.7",
|
|
63
63
|
"@types/react-dom": "19.2.3"
|
|
64
64
|
}
|
|
65
|
+
},
|
|
66
|
+
"dependencies": {
|
|
67
|
+
"pixelmatch": "^7.2.0",
|
|
68
|
+
"playwright-core": "1.58.0",
|
|
69
|
+
"pngjs": "^7.0.0"
|
|
70
|
+
},
|
|
71
|
+
"engines": {
|
|
72
|
+
"node": ">=20"
|
|
65
73
|
}
|
|
66
74
|
}
|