@juangadm/pre-post 0.3.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.
Files changed (125) hide show
  1. package/README.md +102 -240
  2. package/dist/bin/cli.js +200 -454
  3. package/dist/bin/cli.js.map +1 -1
  4. package/dist/browser.d.ts +42 -27
  5. package/dist/browser.d.ts.map +1 -1
  6. package/dist/browser.js +358 -105
  7. package/dist/browser.js.map +1 -1
  8. package/dist/capture.d.ts +1 -6
  9. package/dist/capture.d.ts.map +1 -1
  10. package/dist/capture.js +12 -36
  11. package/dist/capture.js.map +1 -1
  12. package/dist/commands/compare.d.ts +18 -0
  13. package/dist/commands/compare.d.ts.map +1 -0
  14. package/dist/commands/compare.js +64 -0
  15. package/dist/commands/compare.js.map +1 -0
  16. package/dist/commands/detect.d.ts +20 -0
  17. package/dist/commands/detect.d.ts.map +1 -0
  18. package/dist/commands/detect.js +19 -0
  19. package/dist/commands/detect.js.map +1 -0
  20. package/dist/commands/doctor.d.ts +10 -0
  21. package/dist/commands/doctor.d.ts.map +1 -0
  22. package/dist/commands/doctor.js +38 -0
  23. package/dist/commands/doctor.js.map +1 -0
  24. package/dist/commands/login.d.ts +6 -0
  25. package/dist/commands/login.d.ts.map +1 -0
  26. package/dist/commands/login.js +34 -0
  27. package/dist/commands/login.js.map +1 -0
  28. package/dist/commands/pr.d.ts +28 -0
  29. package/dist/commands/pr.d.ts.map +1 -0
  30. package/dist/commands/pr.js +159 -0
  31. package/dist/commands/pr.js.map +1 -0
  32. package/dist/commands/prune.d.ts +10 -0
  33. package/dist/commands/prune.d.ts.map +1 -0
  34. package/dist/commands/prune.js +13 -0
  35. package/dist/commands/prune.js.map +1 -0
  36. package/dist/config.d.ts +36 -0
  37. package/dist/config.d.ts.map +1 -0
  38. package/dist/config.js +60 -0
  39. package/dist/config.js.map +1 -0
  40. package/dist/diff-pool.d.ts +17 -0
  41. package/dist/diff-pool.d.ts.map +1 -0
  42. package/dist/diff-pool.js +89 -0
  43. package/dist/diff-pool.js.map +1 -0
  44. package/dist/diff-worker.d.ts +29 -0
  45. package/dist/diff-worker.d.ts.map +1 -0
  46. package/dist/diff-worker.js +38 -0
  47. package/dist/diff-worker.js.map +1 -0
  48. package/dist/diff.d.ts +37 -0
  49. package/dist/diff.d.ts.map +1 -0
  50. package/dist/diff.js +171 -0
  51. package/dist/diff.js.map +1 -0
  52. package/dist/doctor.d.ts +38 -0
  53. package/dist/doctor.d.ts.map +1 -0
  54. package/dist/doctor.js +72 -0
  55. package/dist/doctor.js.map +1 -0
  56. package/dist/errors.d.ts +38 -0
  57. package/dist/errors.d.ts.map +1 -0
  58. package/dist/errors.js +59 -0
  59. package/dist/errors.js.map +1 -0
  60. package/dist/git.d.ts +23 -0
  61. package/dist/git.d.ts.map +1 -0
  62. package/dist/git.js +86 -0
  63. package/dist/git.js.map +1 -0
  64. package/dist/github.d.ts +73 -0
  65. package/dist/github.d.ts.map +1 -0
  66. package/dist/github.js +240 -0
  67. package/dist/github.js.map +1 -0
  68. package/dist/index.d.ts +22 -23
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/index.js +17 -67
  71. package/dist/index.js.map +1 -1
  72. package/dist/pkg.d.ts +8 -0
  73. package/dist/pkg.d.ts.map +1 -0
  74. package/dist/pkg.js +35 -0
  75. package/dist/pkg.js.map +1 -0
  76. package/dist/report.d.ts +20 -0
  77. package/dist/report.d.ts.map +1 -0
  78. package/dist/report.js +107 -0
  79. package/dist/report.js.map +1 -0
  80. package/dist/routes/imports.d.ts +46 -0
  81. package/dist/routes/imports.d.ts.map +1 -0
  82. package/dist/routes/imports.js +208 -0
  83. package/dist/routes/imports.js.map +1 -0
  84. package/dist/routes/vite.d.ts +15 -0
  85. package/dist/routes/vite.d.ts.map +1 -0
  86. package/dist/routes/vite.js +130 -0
  87. package/dist/routes/vite.js.map +1 -0
  88. package/dist/routes.d.ts +41 -14
  89. package/dist/routes.d.ts.map +1 -1
  90. package/dist/routes.js +271 -141
  91. package/dist/routes.js.map +1 -1
  92. package/dist/run.d.ts +36 -0
  93. package/dist/run.d.ts.map +1 -0
  94. package/dist/run.js +128 -0
  95. package/dist/run.js.map +1 -0
  96. package/dist/sessions.d.ts +50 -0
  97. package/dist/sessions.d.ts.map +1 -0
  98. package/dist/sessions.js +74 -0
  99. package/dist/sessions.js.map +1 -0
  100. package/dist/types.d.ts +118 -69
  101. package/dist/types.d.ts.map +1 -1
  102. package/dist/types.js +1 -0
  103. package/dist/types.js.map +1 -1
  104. package/dist/viewport.d.ts +6 -1
  105. package/dist/viewport.d.ts.map +1 -1
  106. package/dist/viewport.js +13 -7
  107. package/dist/viewport.js.map +1 -1
  108. package/package.json +21 -14
  109. package/skill/SKILL.md +31 -229
  110. package/dist/clipboard.d.ts +0 -9
  111. package/dist/clipboard.d.ts.map +0 -1
  112. package/dist/clipboard.js +0 -26
  113. package/dist/clipboard.js.map +0 -1
  114. package/dist/upload.d.ts +0 -39
  115. package/dist/upload.d.ts.map +0 -1
  116. package/dist/upload.js +0 -159
  117. package/dist/upload.js.map +0 -1
  118. package/dist/video.d.ts +0 -19
  119. package/dist/video.d.ts.map +0 -1
  120. package/dist/video.js +0 -263
  121. package/dist/video.js.map +0 -1
  122. package/skill/scripts/adapters/0x0st.sh +0 -36
  123. package/skill/scripts/adapters/blob.sh +0 -55
  124. package/skill/scripts/adapters/git-native.sh +0 -51
  125. package/skill/scripts/upload-and-copy.sh +0 -230
package/dist/capture.js CHANGED
@@ -1,53 +1,29 @@
1
1
  import { resolveViewport } from './viewport.js';
2
2
  import { captureScreenshot as browserCapture } from './browser.js';
3
3
  function normalizeOptions(input) {
4
- if (typeof input === 'string') {
5
- return { url: input };
6
- }
7
- return input;
4
+ return typeof input === 'string' ? { url: input } : input;
8
5
  }
9
6
  export async function captureScreenshot(options) {
10
7
  const viewport = resolveViewport(options.viewport);
11
- const image = await browserCapture(options.url, {
8
+ return browserCapture(options.url, {
12
9
  viewport,
13
10
  fullPage: options.fullPage ?? false,
11
+ maxHeight: options.maxHeight,
12
+ scale: options.scale,
14
13
  selector: options.selector,
14
+ settleTimeout: options.settleTimeout,
15
+ wait: options.wait,
16
+ auth: options.auth,
15
17
  });
16
- return {
17
- image,
18
- viewport,
19
- url: options.url,
20
- selector: options.selector,
21
- };
22
18
  }
23
19
  export async function captureBeforeAfter(options) {
24
- const sharedViewport = options.viewport;
25
20
  const beforeOpts = normalizeOptions(options.before);
26
21
  const afterOpts = normalizeOptions(options.after);
27
- // Apply shared options if not overridden individually
28
- if (sharedViewport && !beforeOpts.viewport) {
29
- beforeOpts.viewport = sharedViewport;
30
- }
31
- if (sharedViewport && !afterOpts.viewport) {
32
- afterOpts.viewport = sharedViewport;
33
- }
34
- // Capture in parallel — each gets its own page from the pool
35
- const [before, after] = await Promise.all([
36
- captureScreenshot(beforeOpts),
37
- captureScreenshot(afterOpts),
38
- ]);
22
+ if (options.viewport && !beforeOpts.viewport)
23
+ beforeOpts.viewport = options.viewport;
24
+ if (options.viewport && !afterOpts.viewport)
25
+ afterOpts.viewport = options.viewport;
26
+ const [before, after] = await Promise.all([captureScreenshot(beforeOpts), captureScreenshot(afterOpts)]);
39
27
  return { before, after };
40
28
  }
41
- /**
42
- * Capture a URL at multiple viewports (desktop + mobile by default).
43
- * Returns a map of viewport label → CaptureResult.
44
- */
45
- export async function captureResponsive(url, viewports = ['desktop', 'mobile']) {
46
- const entries = await Promise.all(viewports.map(async (vp) => {
47
- const label = typeof vp === 'string' ? vp : `${vp.width}x${vp.height}`;
48
- const result = await captureScreenshot({ url, viewport: vp });
49
- return [label, result];
50
- }));
51
- return new Map(entries);
52
- }
53
29
  //# sourceMappingURL=capture.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"capture.js","sourceRoot":"","sources":["../src/capture.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,iBAAiB,IAAI,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnE,SAAS,gBAAgB,CAAC,KAA8B;IACtD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;IACxB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAAuB;IAC7D,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAEnD,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE;QAC9C,QAAQ;QACR,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,KAAK;QACnC,QAAQ,EAAE,OAAO,CAAC,QAAQ;KAC3B,CAAC,CAAC;IAEH,OAAO;QACL,KAAK;QACL,QAAQ;QACR,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,QAAQ,EAAE,OAAO,CAAC,QAAQ;KAC3B,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,OAAkC;IAElC,MAAM,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC;IAExC,MAAM,UAAU,GAAG,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD,MAAM,SAAS,GAAG,gBAAgB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAElD,sDAAsD;IACtD,IAAI,cAAc,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC;QAC3C,UAAU,CAAC,QAAQ,GAAG,cAAc,CAAC;IACvC,CAAC;IACD,IAAI,cAAc,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC;QAC1C,SAAS,CAAC,QAAQ,GAAG,cAAc,CAAC;IACtC,CAAC;IAED,6DAA6D;IAC7D,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACxC,iBAAiB,CAAC,UAAU,CAAC;QAC7B,iBAAiB,CAAC,SAAS,CAAC;KAC7B,CAAC,CAAC;IAEH,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,GAAW,EACX,YAA8B,CAAC,SAAS,EAAE,QAAQ,CAAC;IAEnD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;QACzB,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC;QACvE,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;QAC9D,OAAO,CAAC,KAAK,EAAE,MAAM,CAAU,CAAC;IAClC,CAAC,CAAC,CACH,CAAC;IACF,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;AAC1B,CAAC"}
1
+ {"version":3,"file":"capture.js","sourceRoot":"","sources":["../src/capture.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,iBAAiB,IAAI,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnE,SAAS,gBAAgB,CAAC,KAA8B;IACtD,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;AAC5D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAAuB;IAC7D,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnD,OAAO,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE;QACjC,QAAQ;QACR,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,KAAK;QACnC,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,IAAI,EAAE,OAAO,CAAC,IAAI;KACnB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,OAAkC;IACzE,MAAM,UAAU,GAAG,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD,MAAM,SAAS,GAAG,gBAAgB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAClD,IAAI,OAAO,CAAC,QAAQ,IAAI,CAAC,UAAU,CAAC,QAAQ;QAAE,UAAU,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IACrF,IAAI,OAAO,CAAC,QAAQ,IAAI,CAAC,SAAS,CAAC,QAAQ;QAAE,SAAS,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IACnF,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,iBAAiB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IACzG,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * `pre-post <before> <after>` — compare two URLs (or two PNG files) without
3
+ * any GitHub involvement. Writes pre/post/diff images and prints a summary.
4
+ */
5
+ import { PrRunResult } from '../types.js';
6
+ import { Settings } from '../config.js';
7
+ export interface CompareOptions extends Partial<Settings> {
8
+ before: string;
9
+ after: string;
10
+ routes?: string[];
11
+ wait?: number;
12
+ headers?: Record<string, string>;
13
+ output?: string;
14
+ log?: (msg: string) => void;
15
+ }
16
+ export declare function isImageFile(p: string): boolean;
17
+ export declare function runCompare(opts: CompareOptions): Promise<PrRunResult>;
18
+ //# sourceMappingURL=compare.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compare.d.ts","sourceRoot":"","sources":["../../src/commands/compare.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,WAAW,EAAuB,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAmB,QAAQ,EAAE,MAAM,cAAc,CAAC;AAQzD,MAAM,WAAW,cAAe,SAAQ,OAAO,CAAC,QAAQ,CAAC;IACvD,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAE9C;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,CA6C3E"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * `pre-post <before> <after>` — compare two URLs (or two PNG files) without
3
+ * any GitHub involvement. Writes pre/post/diff images and prints a summary.
4
+ */
5
+ import fs from 'fs';
6
+ import os from 'os';
7
+ import path from 'path';
8
+ import { resolveSettings } from '../config.js';
9
+ import { closeBrowser } from '../browser.js';
10
+ import { ensureBrowser } from '../doctor.js';
11
+ import { diffImages } from '../diff.js';
12
+ import { parseViewport } from '../viewport.js';
13
+ import { resolveAuth } from '../sessions.js';
14
+ import { isChanged, joinUrl, normalizeUrl, runTasks } from '../run.js';
15
+ export function isImageFile(p) {
16
+ return /\.png$/i.test(p) && fs.existsSync(p);
17
+ }
18
+ export async function runCompare(opts) {
19
+ const started = Date.now();
20
+ const outputDir = opts.output || path.join(os.tmpdir(), 'pre-post', 'compare', String(Date.now()));
21
+ fs.mkdirSync(outputDir, { recursive: true });
22
+ // Ad-hoc comparisons default to the first screen and one viewport; `pr` is the full-page path.
23
+ const settings = resolveSettings({}, { fullPage: false, viewports: ['desktop'], ...opts });
24
+ let outcomes;
25
+ let before = opts.before;
26
+ let after = opts.after;
27
+ if (isImageFile(before) && isImageFile(after)) {
28
+ const diff = diffImages(fs.readFileSync(before), fs.readFileSync(after));
29
+ const diffPath = path.join(outputDir, 'diff.png');
30
+ if (diff.highlight)
31
+ fs.writeFileSync(diffPath, diff.highlight);
32
+ outcomes = [{
33
+ route: path.basename(before),
34
+ resolvedRoute: before,
35
+ viewport: 'image',
36
+ status: isChanged(diff, settings.threshold, settings.minChangedPixels) ? 'changed' : 'unchanged',
37
+ changedRatio: diff.changedRatio,
38
+ sizeChanged: diff.sizeChanged,
39
+ files: { before, after, diff: diff.highlight ? diffPath : undefined },
40
+ }];
41
+ }
42
+ else {
43
+ before = normalizeUrl(before);
44
+ after = normalizeUrl(after);
45
+ const routes = opts.routes?.length ? opts.routes : ['/'];
46
+ const viewports = settings.viewports.map(parseViewport);
47
+ const tasks = [];
48
+ for (const route of routes) {
49
+ for (const vp of viewports) {
50
+ tasks.push({ route, resolvedRoute: route, viewport: vp.label, size: vp.size, beforeUrl: joinUrl(before, route), afterUrl: joinUrl(after, route) });
51
+ }
52
+ }
53
+ const auth = resolveAuth({ headers: opts.headers, urls: [before, after] });
54
+ await ensureBrowser();
55
+ try {
56
+ outcomes = await runTasks(tasks, { outputDir, ...settings, wait: opts.wait, auth, log: opts.log });
57
+ }
58
+ finally {
59
+ await closeBrowser();
60
+ }
61
+ }
62
+ return { repo: '', beforeBase: before, afterBase: after, outcomes, skippedDynamic: [], durationMs: Date.now() - started, markdown: '', outputDir };
63
+ }
64
+ //# sourceMappingURL=compare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compare.js","sourceRoot":"","sources":["../../src/commands/compare.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * `pre-post detect` — which routes does this branch touch? Compact JSON for agents.
3
+ */
4
+ import { Framework } from '../types.js';
5
+ export declare function runDetect(opts?: {
6
+ cwd?: string;
7
+ maxRoutes?: number;
8
+ framework?: Framework;
9
+ }): {
10
+ framework: Framework;
11
+ appRoot: string;
12
+ changedFiles: number;
13
+ routes: {
14
+ path: string;
15
+ confidence: "high" | "medium" | "low";
16
+ reason: string;
17
+ }[];
18
+ skippedDynamic: string[];
19
+ };
20
+ //# sourceMappingURL=detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../src/commands/detect.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAKxC,wBAAgB,SAAS,CAAC,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,SAAS,CAAA;CAAO;;;;;;;;;;EAU/F"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * `pre-post detect` — which routes does this branch touch? Compact JSON for agents.
3
+ */
4
+ import path from 'path';
5
+ import { loadConfig } from '../config.js';
6
+ import { repoRoot } from '../git.js';
7
+ import { detectRoutesForRepo } from '../routes.js';
8
+ export function runDetect(opts = {}) {
9
+ const root = repoRoot(opts.cwd);
10
+ const detection = detectRoutesForRepo({ cwd: root, config: loadConfig(root), maxRoutes: opts.maxRoutes, framework: opts.framework });
11
+ return {
12
+ framework: detection.framework,
13
+ appRoot: path.relative(root, detection.appRoot) || '.',
14
+ changedFiles: detection.changedFiles.length,
15
+ routes: detection.routes.map(r => ({ path: r.path, confidence: r.confidence, reason: r.reason })),
16
+ skippedDynamic: detection.skippedDynamic,
17
+ };
18
+ }
19
+ //# sourceMappingURL=detect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/commands/detect.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,MAAM,UAAU,SAAS,CAAC,OAAoE,EAAE;IAC9F,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,SAAS,GAAG,mBAAmB,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;IACrI,OAAO;QACL,SAAS,EAAE,SAAS,CAAC,SAAS;QAC9B,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,OAAO,CAAC,IAAI,GAAG;QACtD,YAAY,EAAE,SAAS,CAAC,YAAY,CAAC,MAAM;QAC3C,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QACjG,cAAc,EAAE,SAAS,CAAC,cAAc;KACzC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * `pre-post doctor` — the same checks `pr` performs, reported instead of enforced.
3
+ */
4
+ export interface DoctorCheck {
5
+ name: string;
6
+ ok: boolean;
7
+ detail: string;
8
+ }
9
+ export declare function runDoctor(cwd?: string): Promise<DoctorCheck[]>;
10
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAWH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,SAAS,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAsBpE"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * `pre-post doctor` — the same checks `pr` performs, reported instead of enforced.
3
+ */
4
+ import fs from 'fs';
5
+ import { browserDescription } from '../browser.js';
6
+ import { configPath, CONFIG_FILENAME, loadConfig } from '../config.js';
7
+ import { detectDevServer, ensureBrowser } from '../doctor.js';
8
+ import { GH_LOGIN_HINT } from '../errors.js';
9
+ import { repoRoot } from '../git.js';
10
+ import { getToken } from '../github.js';
11
+ import { closeBrowser } from '../browser.js';
12
+ export async function runDoctor(cwd) {
13
+ const checks = [];
14
+ try {
15
+ await ensureBrowser();
16
+ checks.push({ name: 'browser', ok: true, detail: browserDescription() });
17
+ }
18
+ catch (err) {
19
+ checks.push({ name: 'browser', ok: false, detail: err.message });
20
+ }
21
+ finally {
22
+ await closeBrowser();
23
+ }
24
+ checks.push(getToken() ? { name: 'github', ok: true, detail: 'token found' } : { name: 'github', ok: false, detail: GH_LOGIN_HINT });
25
+ const dev = await detectDevServer();
26
+ checks.push(dev ? { name: 'devserver', ok: true, detail: dev } : { name: 'devserver', ok: false, detail: 'none found on the usual ports' });
27
+ try {
28
+ const root = repoRoot(cwd);
29
+ const cfg = loadConfig(root);
30
+ checks.push(cfg.before ? { name: 'before', ok: true, detail: cfg.before } : { name: 'before', ok: false, detail: 'not set — pass --before once and it is saved' });
31
+ checks.push({ name: 'config', ok: true, detail: fs.existsSync(configPath(root)) ? CONFIG_FILENAME : 'none (defaults)' });
32
+ }
33
+ catch {
34
+ checks.push({ name: 'git', ok: false, detail: 'not a repository' });
35
+ }
36
+ return checks;
37
+ }
38
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAQ7C,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAY;IAC1C,MAAM,MAAM,GAAkB,EAAE,CAAC;IACjC,IAAI,CAAC;QACH,MAAM,aAAa,EAAE,CAAC;QACtB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,kBAAkB,EAAE,EAAE,CAAC,CAAC;IAC3E,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAG,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IAC9E,CAAC;YAAS,CAAC;QACT,MAAM,YAAY,EAAE,CAAC;IACvB,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC,CAAC;IACrI,MAAM,GAAG,GAAG,MAAM,eAAe,EAAE,CAAC;IACpC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,+BAA+B,EAAE,CAAC,CAAC;IAC5I,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC3B,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC7B,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,8CAA8C,EAAE,CAAC,CAAC;QACnK,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAC3H,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * `pre-post login <url>` — open a real browser once, let the human sign in,
3
+ * and keep the session for future captures of that host.
4
+ */
5
+ export declare function runLogin(url: string, log?: (msg: string) => void): Promise<string>;
6
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAcH,wBAAsB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBvG"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * `pre-post login <url>` — open a real browser once, let the human sign in,
3
+ * and keep the session for future captures of that host.
4
+ */
5
+ import readline from 'readline';
6
+ import { launchHeadedBrowser } from '../doctor.js';
7
+ import { saveSession } from '../sessions.js';
8
+ import { normalizeUrl } from '../run.js';
9
+ function waitForEnter(prompt) {
10
+ return new Promise(resolve => {
11
+ const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
12
+ rl.question(prompt, () => { rl.close(); resolve(); });
13
+ });
14
+ }
15
+ export async function runLogin(url, log = console.error) {
16
+ const target = normalizeUrl(url);
17
+ const host = new URL(target).hostname;
18
+ const browser = await launchHeadedBrowser();
19
+ try {
20
+ const ctx = await browser.newContext({ viewport: { width: 1280, height: 800 } });
21
+ const page = await ctx.newPage();
22
+ await page.goto(target, { waitUntil: 'domcontentloaded' }).catch(() => undefined);
23
+ log(`A browser window is open at ${target}.`);
24
+ await waitForEnter('Log in there, then press Enter here to save the session... ');
25
+ const state = await ctx.storageState();
26
+ const file = saveSession(host, state);
27
+ log(`Saved session for ${host} (${state.cookies.length} cookie(s)) to ${file}`);
28
+ return file;
29
+ }
30
+ finally {
31
+ await browser.close().catch(() => undefined);
32
+ }
33
+ }
34
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,SAAS,YAAY,CAAC,MAAc;IAClC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;QAC3B,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QACtF,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,GAAW,EAAE,MAA6B,OAAO,CAAC,KAAK;IACpF,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IACjC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC;IACtC,MAAM,OAAO,GAAG,MAAM,mBAAmB,EAAE,CAAC;IAC5C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QACjF,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC;QACjC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAClF,GAAG,CAAC,+BAA+B,MAAM,GAAG,CAAC,CAAC;QAC9C,MAAM,YAAY,CAAC,6DAA6D,CAAC,CAAC;QAClF,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,YAAY,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,EAAE,KAAY,CAAC,CAAC;QAC7C,GAAG,CAAC,qBAAqB,IAAI,KAAK,KAAK,CAAC,OAAO,CAAC,MAAM,kBAAkB,IAAI,EAAE,CAAC,CAAC;QAChF,OAAO,IAAI,CAAC;IACd,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * `pre-post pr` — the one-shot path: detect → capture → diff → publish → comment.
3
+ */
4
+ import { Framework, PrRunResult } from '../types.js';
5
+ import { Settings } from '../config.js';
6
+ export interface PrCommandOptions extends Partial<Settings> {
7
+ cwd?: string;
8
+ before?: string;
9
+ after?: string;
10
+ routes?: string[];
11
+ framework?: Framework;
12
+ headers?: Record<string, string>;
13
+ cookies?: Array<{
14
+ name: string;
15
+ value: string;
16
+ }>;
17
+ wait?: number;
18
+ output?: string;
19
+ /** Capture and diff only; do not publish or comment */
20
+ dryRun?: boolean;
21
+ /** Publish assets but do not touch the PR */
22
+ comment?: boolean;
23
+ pr?: number;
24
+ version?: string;
25
+ log?: (msg: string) => void;
26
+ }
27
+ export declare function runPr(opts?: PrCommandOptions): Promise<PrRunResult>;
28
+ //# sourceMappingURL=pr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pr.d.ts","sourceRoot":"","sources":["../../src/commands/pr.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,EAA+B,SAAS,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAClF,OAAO,EAA+B,QAAQ,EAAgB,MAAM,cAAc,CAAC;AAYnF,MAAM,WAAW,gBAAiB,SAAQ,OAAO,CAAC,QAAQ,CAAC;IACzD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B;AAWD,wBAAsB,KAAK,CAAC,IAAI,GAAE,gBAAqB,GAAG,OAAO,CAAC,WAAW,CAAC,CA0I7E"}
@@ -0,0 +1,159 @@
1
+ /**
2
+ * `pre-post pr` — the one-shot path: detect → capture → diff → publish → comment.
3
+ */
4
+ import fs from 'fs';
5
+ import os from 'os';
6
+ import path from 'path';
7
+ import { ARTIFACT_KINDS } from '../types.js';
8
+ import { loadConfig, resolveSettings, updateConfig } from '../config.js';
9
+ import { currentBranch, headSha, repoRoot, resolveOwnerRepo } from '../git.js';
10
+ import { detectRoutesForRepo, resolveSample } from '../routes.js';
11
+ import { closeBrowser } from '../browser.js';
12
+ import { parseViewport } from '../viewport.js';
13
+ import { authHint, detectDevServer, ensureBrowser, NeedsHumanError, probeUrl } from '../doctor.js';
14
+ import { findOpenPr, getPr, GitHub, publishAssets, requireToken, upsertStickyComment } from '../github.js';
15
+ import { buildComment, STICKY_MARKER } from '../report.js';
16
+ import { resolveAuth } from '../sessions.js';
17
+ import { readPackage } from '../pkg.js';
18
+ import { joinUrl, normalizeUrl, routeSlug, runTasks } from '../run.js';
19
+ function packageHomepage(root) {
20
+ const hp = readPackage(root)?.homepage;
21
+ return typeof hp === 'string' && /^https?:\/\//.test(hp) && !/github\.com/.test(hp) ? hp : undefined;
22
+ }
23
+ function runId(now) {
24
+ return now.toISOString().replace(/[-:]/g, '').replace('T', '-').slice(0, 15);
25
+ }
26
+ export async function runPr(opts = {}) {
27
+ const started = Date.now();
28
+ const log = opts.log ?? (() => undefined);
29
+ const root = repoRoot(opts.cwd);
30
+ const config = loadConfig(root);
31
+ const settings = resolveSettings(config, opts);
32
+ const ownerRepo = resolveOwnerRepo(root);
33
+ const branch = currentBranch(root);
34
+ // --- Production URL --------------------------------------------------------
35
+ const beforeRaw = opts.before || config.before || packageHomepage(root);
36
+ if (!beforeRaw) {
37
+ throw new NeedsHumanError('No production URL known for the "before" state. Re-run with --before https://your-production-url (it is saved to .pre-post.json for next time).');
38
+ }
39
+ const before = normalizeUrl(beforeRaw);
40
+ if (opts.before && config.before !== before) {
41
+ updateConfig(root, { before });
42
+ log('Saved production URL to .pre-post.json');
43
+ }
44
+ // --- GitHub access (checked before any time is spent) -----------------------
45
+ const gh = opts.dryRun ? null : new GitHub(requireToken());
46
+ // --- Start the slow, independent things now; they overlap route detection ----
47
+ const browserReady = ensureBrowser();
48
+ const prLookup = gh
49
+ ? opts.pr ? getPr(gh, ownerRepo, opts.pr) : branch ? findOpenPr(gh, ownerRepo, branch) : Promise.resolve(null)
50
+ : Promise.resolve(null);
51
+ const devServer = opts.after || config.after ? Promise.resolve(opts.after || config.after) : detectDevServer();
52
+ // Headers alone are enough to probe production; cookies need the final URL list.
53
+ const headers = resolveAuth({ configHeaders: config.headers, headers: opts.headers, urls: [before] })?.headers ?? {};
54
+ const beforeProbe = probeUrl(before, headers);
55
+ // --- Routes (sync: git + import graph) ----------------------------------------
56
+ const samples = config.samples || {};
57
+ let routes;
58
+ let skippedDynamic = [];
59
+ if (opts.routes?.length) {
60
+ routes = opts.routes;
61
+ }
62
+ else {
63
+ const detection = detectRoutesForRepo({ cwd: root, config, maxRoutes: settings.maxRoutes, framework: opts.framework });
64
+ routes = detection.routes.map(r => r.path);
65
+ skippedDynamic = detection.skippedDynamic;
66
+ log(`Routes (${detection.framework}, ${detection.durationMs}ms): ${routes.length ? routes.join(', ') : 'none detected'}`);
67
+ for (const r of detection.routes)
68
+ log(` ${r.path.padEnd(28)} ${r.confidence.padEnd(6)} ${r.reason}`);
69
+ if (routes.length === 0) {
70
+ routes = ['/'];
71
+ log('No routes detected from the diff; capturing / only.');
72
+ }
73
+ }
74
+ // --- Dev server and reachability --------------------------------------------
75
+ const afterRaw = await devServer;
76
+ if (!afterRaw) {
77
+ throw new NeedsHumanError('No dev server found on the usual ports (3000, 5173, ...). Start it (e.g. npm run dev), then re-run — or pass --after http://localhost:PORT.');
78
+ }
79
+ const after = normalizeUrl(afterRaw);
80
+ if (!opts.after && !config.after)
81
+ log(`Dev server: ${after}`);
82
+ const [probe, afterProbe] = await Promise.all([beforeProbe, probeUrl(after, headers)]);
83
+ if (probe.status === null)
84
+ throw new NeedsHumanError(`Cannot reach ${before}. Check the URL (or your VPN) and re-run.`);
85
+ if (probe.status === 401 || probe.status === 403)
86
+ throw new NeedsHumanError(authHint({ url: before, vercel: probe.vercel }));
87
+ if (afterProbe.status === null)
88
+ throw new NeedsHumanError(`Cannot reach ${after}. Is the dev server running?`);
89
+ const auth = resolveAuth({ configHeaders: config.headers, headers: opts.headers, cookies: opts.cookies, cookieUrl: before, urls: [before, after] });
90
+ // --- Capture -------------------------------------------------------------------
91
+ const now = new Date();
92
+ const id = runId(now);
93
+ const outputDir = opts.output || path.join(os.tmpdir(), 'pre-post', ownerRepo.replace('/', '__'), id);
94
+ const viewports = settings.viewports.map(parseViewport);
95
+ const tasks = [];
96
+ for (const route of routes) {
97
+ const resolved = resolveSample(route, samples);
98
+ for (const vp of viewports) {
99
+ tasks.push({ route, resolvedRoute: resolved, viewport: vp.label, size: vp.size, beforeUrl: joinUrl(before, resolved), afterUrl: joinUrl(after, resolved) });
100
+ }
101
+ }
102
+ log(`Capturing ${tasks.length * 2} screenshots (${routes.length} route(s) × ${viewports.length} viewport(s)) ...`);
103
+ await browserReady;
104
+ let outcomes;
105
+ try {
106
+ outcomes = await runTasks(tasks, { outputDir, ...settings, wait: opts.wait, auth, log });
107
+ }
108
+ finally {
109
+ await closeBrowser();
110
+ }
111
+ // --- Publish -------------------------------------------------------------------
112
+ const pr = await prLookup;
113
+ const changed = outcomes.filter(o => o.status === 'changed' && o.files);
114
+ if (gh && changed.length) {
115
+ const folder = pr ? `pr-${pr.number}/${id}` : `branch/${routeSlug(branch || 'detached')}/${id}`;
116
+ const keyFor = (o, kind) => `${folder}/${routeSlug(o.route)}-${o.viewport}-${kind}.png`;
117
+ const files = [];
118
+ for (const o of changed) {
119
+ for (const kind of ARTIFACT_KINDS) {
120
+ const local = o.files[kind];
121
+ if (local)
122
+ files.push({ path: keyFor(o, kind), content: fs.readFileSync(local) });
123
+ }
124
+ }
125
+ log(`Publishing ${files.length} image(s) to ${ownerRepo}@${settings.assetsBranch} ...`);
126
+ const published = await publishAssets(gh, ownerRepo, settings.assetsBranch, files, pr ? `Screenshots for #${pr.number} (${id})` : `Screenshots for ${branch || 'detached'} (${id})`);
127
+ for (const o of changed) {
128
+ const urls = {};
129
+ for (const kind of ARTIFACT_KINDS)
130
+ if (o.files[kind])
131
+ urls[kind] = published.urls.get(keyFor(o, kind));
132
+ o.urls = urls;
133
+ }
134
+ }
135
+ const result = {
136
+ repo: ownerRepo,
137
+ prNumber: pr?.number,
138
+ beforeBase: before,
139
+ afterBase: after,
140
+ outcomes,
141
+ skippedDynamic,
142
+ durationMs: Date.now() - started,
143
+ markdown: '',
144
+ outputDir,
145
+ };
146
+ result.markdown = buildComment(result, { version: opts.version, headSha: headSha(root), now });
147
+ if (gh && (opts.comment ?? true)) {
148
+ if (pr) {
149
+ const comment = await upsertStickyComment(gh, ownerRepo, pr.number, result.markdown, STICKY_MARKER);
150
+ result.commentUrl = comment.html_url;
151
+ log(`${comment.created ? 'Posted' : 'Updated'} PR comment: ${comment.html_url}`);
152
+ }
153
+ else {
154
+ log(`No open PR for branch "${branch}". Open one and re-run, or paste the markdown below.`);
155
+ }
156
+ }
157
+ return result;
158
+ }
159
+ //# sourceMappingURL=pr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pr.js","sourceRoot":"","sources":["../../src/commands/pr.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * `pre-post prune` — delete screenshots for PRs closed more than N days ago.
3
+ */
4
+ import { PruneResult } from '../github.js';
5
+ export declare function runPrune(opts?: {
6
+ cwd?: string;
7
+ days?: number;
8
+ dryRun?: boolean;
9
+ }): Promise<PruneResult>;
10
+ //# sourceMappingURL=prune.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prune.d.ts","sourceRoot":"","sources":["../../src/commands/prune.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAuB,WAAW,EAAgB,MAAM,cAAc,CAAC;AAE9E,wBAAsB,QAAQ,CAAC,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAKjH"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * `pre-post prune` — delete screenshots for PRs closed more than N days ago.
3
+ */
4
+ import { loadConfig, resolveSettings } from '../config.js';
5
+ import { repoRoot, resolveOwnerRepo } from '../git.js';
6
+ import { GitHub, pruneAssets, requireToken } from '../github.js';
7
+ export async function runPrune(opts = {}) {
8
+ const root = repoRoot(opts.cwd);
9
+ const settings = resolveSettings(loadConfig(root), { pruneDays: opts.days });
10
+ const gh = new GitHub(requireToken('prune screenshots'));
11
+ return pruneAssets(gh, resolveOwnerRepo(root), settings.assetsBranch, settings.pruneDays, opts.dryRun);
12
+ }
13
+ //# sourceMappingURL=prune.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prune.js","sourceRoot":"","sources":["../../src/commands/prune.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAe,YAAY,EAAE,MAAM,cAAc,CAAC;AAE9E,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAA0D,EAAE;IACzF,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,QAAQ,GAAG,eAAe,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7E,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,YAAY,CAAC,mBAAmB,CAAC,CAAC,CAAC;IACzD,OAAO,WAAW,CAAC,EAAE,EAAE,gBAAgB,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;AACzG,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * .pre-post.json — per-repo configuration. Optional; every field has a default.
3
+ * `resolveSettings` is the one place defaults, config, and CLI overrides meet.
4
+ */
5
+ import { PrePostConfig } from './types.js';
6
+ export declare const CONFIG_FILENAME = ".pre-post.json";
7
+ export declare const CONFIG_DEFAULTS: {
8
+ viewports: string[];
9
+ threshold: number;
10
+ minChangedPixels: number;
11
+ maxRoutes: number;
12
+ fullPage: boolean;
13
+ maxHeight: number;
14
+ scale: number;
15
+ assetsBranch: string;
16
+ pruneDays: number;
17
+ };
18
+ export interface Settings {
19
+ viewports: string[];
20
+ threshold: number;
21
+ minChangedPixels: number;
22
+ maxRoutes: number;
23
+ fullPage: boolean;
24
+ maxHeight: number;
25
+ scale: number;
26
+ assetsBranch: string;
27
+ pruneDays: number;
28
+ }
29
+ /** Defaults < .pre-post.json < explicit overrides (undefined overrides are ignored). */
30
+ export declare function resolveSettings(config?: PrePostConfig, overrides?: Partial<Settings>): Settings;
31
+ export declare function configPath(repoRoot: string): string;
32
+ export declare function loadConfig(repoRoot: string): PrePostConfig;
33
+ export declare function saveConfig(repoRoot: string, config: PrePostConfig): void;
34
+ /** Merge a partial update into the on-disk config (creating it if needed). */
35
+ export declare function updateConfig(repoRoot: string, patch: Partial<PrePostConfig>): PrePostConfig;
36
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,eAAO,MAAM,eAAe,mBAAmB,CAAC;AAEhD,eAAO,MAAM,eAAe;eACU,MAAM,EAAE;;;;;;;;;CAS7C,CAAC;AAEF,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wFAAwF;AACxF,wBAAgB,eAAe,CAAC,MAAM,GAAE,aAAkB,EAAE,SAAS,GAAE,OAAO,CAAC,QAAQ,CAAM,GAAG,QAAQ,CAcvG;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CAU1D;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CAExE;AAED,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,aAAa,CAI3F"}