@juangadm/pre-post 0.3.0 → 1.1.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 (153) hide show
  1. package/README.md +174 -233
  2. package/dist/baseline.d.ts +119 -0
  3. package/dist/baseline.d.ts.map +1 -0
  4. package/dist/baseline.js +316 -0
  5. package/dist/baseline.js.map +1 -0
  6. package/dist/bin/cli.js +243 -458
  7. package/dist/bin/cli.js.map +1 -1
  8. package/dist/browser.d.ts +68 -25
  9. package/dist/browser.d.ts.map +1 -1
  10. package/dist/browser.js +500 -105
  11. package/dist/browser.js.map +1 -1
  12. package/dist/capture.d.ts +1 -6
  13. package/dist/capture.d.ts.map +1 -1
  14. package/dist/capture.js +12 -36
  15. package/dist/capture.js.map +1 -1
  16. package/dist/commands/compare.d.ts +18 -0
  17. package/dist/commands/compare.d.ts.map +1 -0
  18. package/dist/commands/compare.js +82 -0
  19. package/dist/commands/compare.js.map +1 -0
  20. package/dist/commands/detect.d.ts +25 -0
  21. package/dist/commands/detect.d.ts.map +1 -0
  22. package/dist/commands/detect.js +22 -0
  23. package/dist/commands/detect.js.map +1 -0
  24. package/dist/commands/doctor.d.ts +42 -0
  25. package/dist/commands/doctor.d.ts.map +1 -0
  26. package/dist/commands/doctor.js +119 -0
  27. package/dist/commands/doctor.js.map +1 -0
  28. package/dist/commands/login.d.ts +6 -0
  29. package/dist/commands/login.d.ts.map +1 -0
  30. package/dist/commands/login.js +34 -0
  31. package/dist/commands/login.js.map +1 -0
  32. package/dist/commands/pr.d.ts +32 -0
  33. package/dist/commands/pr.d.ts.map +1 -0
  34. package/dist/commands/pr.js +259 -0
  35. package/dist/commands/pr.js.map +1 -0
  36. package/dist/commands/prune.d.ts +10 -0
  37. package/dist/commands/prune.d.ts.map +1 -0
  38. package/dist/commands/prune.js +13 -0
  39. package/dist/commands/prune.js.map +1 -0
  40. package/dist/comparison.d.ts +104 -0
  41. package/dist/comparison.d.ts.map +1 -0
  42. package/dist/comparison.js +236 -0
  43. package/dist/comparison.js.map +1 -0
  44. package/dist/config.d.ts +46 -0
  45. package/dist/config.d.ts.map +1 -0
  46. package/dist/config.js +82 -0
  47. package/dist/config.js.map +1 -0
  48. package/dist/deployments.d.ts +71 -0
  49. package/dist/deployments.d.ts.map +1 -0
  50. package/dist/deployments.js +204 -0
  51. package/dist/deployments.js.map +1 -0
  52. package/dist/diff-pool.d.ts +17 -0
  53. package/dist/diff-pool.d.ts.map +1 -0
  54. package/dist/diff-pool.js +92 -0
  55. package/dist/diff-pool.js.map +1 -0
  56. package/dist/diff-worker.d.ts +32 -0
  57. package/dist/diff-worker.d.ts.map +1 -0
  58. package/dist/diff-worker.js +39 -0
  59. package/dist/diff-worker.js.map +1 -0
  60. package/dist/diff.d.ts +47 -0
  61. package/dist/diff.d.ts.map +1 -0
  62. package/dist/diff.js +281 -0
  63. package/dist/diff.js.map +1 -0
  64. package/dist/doctor.d.ts +79 -0
  65. package/dist/doctor.d.ts.map +1 -0
  66. package/dist/doctor.js +138 -0
  67. package/dist/doctor.js.map +1 -0
  68. package/dist/errors.d.ts +38 -0
  69. package/dist/errors.d.ts.map +1 -0
  70. package/dist/errors.js +59 -0
  71. package/dist/errors.js.map +1 -0
  72. package/dist/git.d.ts +61 -0
  73. package/dist/git.d.ts.map +1 -0
  74. package/dist/git.js +182 -0
  75. package/dist/git.js.map +1 -0
  76. package/dist/github.d.ts +163 -0
  77. package/dist/github.d.ts.map +1 -0
  78. package/dist/github.js +411 -0
  79. package/dist/github.js.map +1 -0
  80. package/dist/index.d.ts +22 -23
  81. package/dist/index.d.ts.map +1 -1
  82. package/dist/index.js +17 -67
  83. package/dist/index.js.map +1 -1
  84. package/dist/landing.d.ts +48 -0
  85. package/dist/landing.d.ts.map +1 -0
  86. package/dist/landing.js +93 -0
  87. package/dist/landing.js.map +1 -0
  88. package/dist/pkg.d.ts +17 -0
  89. package/dist/pkg.d.ts.map +1 -0
  90. package/dist/pkg.js +49 -0
  91. package/dist/pkg.js.map +1 -0
  92. package/dist/report.d.ts +20 -0
  93. package/dist/report.d.ts.map +1 -0
  94. package/dist/report.js +130 -0
  95. package/dist/report.js.map +1 -0
  96. package/dist/routes/imports.d.ts +46 -0
  97. package/dist/routes/imports.d.ts.map +1 -0
  98. package/dist/routes/imports.js +208 -0
  99. package/dist/routes/imports.js.map +1 -0
  100. package/dist/routes/vite.d.ts +15 -0
  101. package/dist/routes/vite.d.ts.map +1 -0
  102. package/dist/routes/vite.js +130 -0
  103. package/dist/routes/vite.js.map +1 -0
  104. package/dist/routes.d.ts +65 -11
  105. package/dist/routes.d.ts.map +1 -1
  106. package/dist/routes.js +346 -141
  107. package/dist/routes.js.map +1 -1
  108. package/dist/run.d.ts +116 -0
  109. package/dist/run.d.ts.map +1 -0
  110. package/dist/run.js +316 -0
  111. package/dist/run.js.map +1 -0
  112. package/dist/sameness.d.ts +91 -0
  113. package/dist/sameness.d.ts.map +1 -0
  114. package/dist/sameness.js +157 -0
  115. package/dist/sameness.js.map +1 -0
  116. package/dist/sessions.d.ts +50 -0
  117. package/dist/sessions.d.ts.map +1 -0
  118. package/dist/sessions.js +80 -0
  119. package/dist/sessions.js.map +1 -0
  120. package/dist/shift.d.ts +67 -0
  121. package/dist/shift.d.ts.map +1 -0
  122. package/dist/shift.js +184 -0
  123. package/dist/shift.js.map +1 -0
  124. package/dist/types.d.ts +179 -68
  125. package/dist/types.d.ts.map +1 -1
  126. package/dist/types.js +1 -0
  127. package/dist/types.js.map +1 -1
  128. package/dist/url.d.ts +12 -0
  129. package/dist/url.d.ts.map +1 -0
  130. package/dist/url.js +30 -0
  131. package/dist/url.js.map +1 -0
  132. package/dist/viewport.d.ts +6 -1
  133. package/dist/viewport.d.ts.map +1 -1
  134. package/dist/viewport.js +13 -7
  135. package/dist/viewport.js.map +1 -1
  136. package/package.json +21 -14
  137. package/skill/SKILL.md +56 -221
  138. package/dist/clipboard.d.ts +0 -9
  139. package/dist/clipboard.d.ts.map +0 -1
  140. package/dist/clipboard.js +0 -26
  141. package/dist/clipboard.js.map +0 -1
  142. package/dist/upload.d.ts +0 -39
  143. package/dist/upload.d.ts.map +0 -1
  144. package/dist/upload.js +0 -159
  145. package/dist/upload.js.map +0 -1
  146. package/dist/video.d.ts +0 -19
  147. package/dist/video.d.ts.map +0 -1
  148. package/dist/video.js +0 -263
  149. package/dist/video.js.map +0 -1
  150. package/skill/scripts/adapters/0x0st.sh +0 -36
  151. package/skill/scripts/adapters/blob.sh +0 -55
  152. package/skill/scripts/adapters/git-native.sh +0 -51
  153. package/skill/scripts/upload-and-copy.sh +0 -230
package/dist/github.js ADDED
@@ -0,0 +1,411 @@
1
+ /**
2
+ * GitHub REST client used for:
3
+ * - finding the open PR for a branch
4
+ * - publishing screenshots to an orphan assets branch (Git Data API, one commit per run)
5
+ * - upserting a sticky PR comment
6
+ * - pruning old assets
7
+ *
8
+ * Authentication: GH_TOKEN / GITHUB_TOKEN, else the gh CLI's stored token.
9
+ */
10
+ import { execFileSync } from 'child_process';
11
+ import { GitHubError, NeedsHumanError, GH_LOGIN_HINT } from './errors.js';
12
+ export { GitHubError } from './errors.js';
13
+ export const API_BASE = process.env.GITHUB_API_URL || 'https://api.github.com';
14
+ /**
15
+ * The token this run will use, and where it came from.
16
+ *
17
+ * The source is not bookkeeping: the env vars take precedence over the `gh`
18
+ * CLI, so advice aimed at the wrong one is advice that cannot work. Someone
19
+ * whose `GH_TOKEN` is refused gains nothing from `gh auth login`, because the
20
+ * variable still wins on the next run.
21
+ */
22
+ export function findToken() {
23
+ if (process.env.GH_TOKEN)
24
+ return { token: process.env.GH_TOKEN, source: 'GH_TOKEN' };
25
+ if (process.env.GITHUB_TOKEN)
26
+ return { token: process.env.GITHUB_TOKEN, source: 'GITHUB_TOKEN' };
27
+ try {
28
+ const out = execFileSync('gh', ['auth', 'token'], { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
29
+ return out ? { token: out, source: 'gh' } : null;
30
+ }
31
+ catch {
32
+ return null;
33
+ }
34
+ }
35
+ export function getToken() {
36
+ return findToken()?.token ?? null;
37
+ }
38
+ /** A token and its source, or the one sentence telling the human how to get one. */
39
+ export function requireToken(purpose = 'publish screenshots') {
40
+ const found = findToken();
41
+ if (!found)
42
+ throw new NeedsHumanError(`GitHub access is needed to ${purpose}. ${GH_LOGIN_HINT}`);
43
+ return found;
44
+ }
45
+ export class GitHub {
46
+ token;
47
+ base;
48
+ constructor(token, base = API_BASE) {
49
+ this.token = token;
50
+ this.base = base;
51
+ }
52
+ async request(method, path, body) {
53
+ const res = await fetch(`${this.base}${path}`, {
54
+ method,
55
+ headers: {
56
+ Authorization: `Bearer ${this.token}`,
57
+ Accept: 'application/vnd.github+json',
58
+ 'X-GitHub-Api-Version': '2022-11-28',
59
+ 'User-Agent': 'pre-post',
60
+ ...(body ? { 'Content-Type': 'application/json' } : {}),
61
+ },
62
+ body: body ? JSON.stringify(body) : undefined,
63
+ });
64
+ if (res.status === 204)
65
+ return undefined;
66
+ const text = await res.text();
67
+ let json = null;
68
+ try {
69
+ json = text ? JSON.parse(text) : null;
70
+ }
71
+ catch { /* non-JSON */ }
72
+ if (res.status === 401 || (res.status === 403 && !/rate limit/i.test(json?.message || ''))) {
73
+ throw new NeedsHumanError(`GitHub rejected the token (${res.status}). ${GH_LOGIN_HINT}`);
74
+ }
75
+ if (!res.ok) {
76
+ const msg = json?.message || text || res.statusText;
77
+ throw new GitHubError(res.status, `GitHub ${method} ${path} → ${res.status}: ${msg}`);
78
+ }
79
+ return json;
80
+ }
81
+ }
82
+ /**
83
+ * Can this token write to `ownerRepo`?
84
+ *
85
+ * `getToken()` checks that a token exists, which is a different question. A
86
+ * GitHub Actions job that maps `secrets.GITHUB_TOKEN` gets one that reads
87
+ * everything this tool reads and writes nothing: measured on this repository,
88
+ * `GET /repos/juangadm/pre-post` answers 200 with `permissions.push: false`
89
+ * and `POST .../git/blobs` answers 403. Those reads are the ones `pr` makes
90
+ * before it captures, so without this the run spends its screenshots first and
91
+ * discovers the refusal after.
92
+ *
93
+ * The probe is the first write `publishAssets` makes, on the one piece of
94
+ * content that cannot add anything: the empty blob already exists in every
95
+ * repository, so a successful call stores nothing new. A read cannot stand in
96
+ * for it — `permissions.push` describes the account's access to the repository,
97
+ * not the scopes the token carries, so it can report `true` for a credential
98
+ * the write still refuses. That is the confident all-clear this check exists to
99
+ * avoid, which is why it writes.
100
+ *
101
+ * What it proves is bounded: the token may write objects. Creating the assets
102
+ * *ref* is a separate permission a ruleset can refuse, so `writable: true` is
103
+ * "not this failure", never "the publish will work".
104
+ */
105
+ export async function checkWriteAccess(gh, ownerRepo) {
106
+ try {
107
+ await gh.request('POST', `/repos/${ownerRepo}/git/blobs`, { content: '', encoding: 'utf-8' });
108
+ return { writable: true };
109
+ }
110
+ catch (err) {
111
+ // 401/403 arrive as NeedsHumanError from `request`; a repository an
112
+ // installation cannot write is often hidden as 404 rather than refused.
113
+ if (err instanceof NeedsHumanError)
114
+ return { writable: false, reason: 'rejected' };
115
+ if (err instanceof GitHubError) {
116
+ if (err.status === 404)
117
+ return { writable: false, reason: 'rejected' };
118
+ return { writable: false, reason: 'unknown', detail: `GitHub answered ${err.status}` };
119
+ }
120
+ return { writable: false, reason: 'unknown', detail: err instanceof Error ? err.message : String(err) };
121
+ }
122
+ }
123
+ /**
124
+ * The one thing to do about a token that cannot publish.
125
+ *
126
+ * It follows the credential that was actually chosen, not just the
127
+ * environment. Being inside a runner does not make `permissions:` the fix: a
128
+ * workflow that sets `GH_TOKEN` to a PAT is refused by that PAT, and rewriting
129
+ * the job's permissions changes only the `GITHUB_TOKEN` the run never reaches.
130
+ * The same holds the other way round on a laptop, where `gh auth login` cannot
131
+ * help while an env var is shadowing it.
132
+ *
133
+ * The runner sentence names both permissions, though only `contents` is what
134
+ * this check tested. Naming `contents` alone would be advice that fails on its
135
+ * own terms: a `permissions:` block sets every scope it omits to none, so
136
+ * following it leaves a token that uploads the screenshots and is then refused
137
+ * the PR description — measured on this repository, `PATCH /pulls/23` answers
138
+ * 403 with only `contents: write` and 200 with `pull-requests: write` beside it.
139
+ * A second trip through a full capture is not worth the tighter sentence.
140
+ */
141
+ export function cannotPublishHint(ownerRepo, source) {
142
+ const inActions = process.env.GITHUB_ACTIONS === 'true';
143
+ const perms = '"permissions: { contents: write, pull-requests: write }"';
144
+ const nowhere = `cannot write to ${ownerRepo}, so the screenshots would have nowhere to go`;
145
+ if (source === 'gh') {
146
+ return `The gh CLI login ${nowhere}: run gh auth login as someone with write access, or set GH_TOKEN to a token carrying repo scope.`;
147
+ }
148
+ if (inActions && source === 'GITHUB_TOKEN') {
149
+ return `This workflow's GITHUB_TOKEN ${nowhere}: give the job ${perms} and re-run.`;
150
+ }
151
+ if (inActions) {
152
+ return `The GH_TOKEN this workflow sets ${nowhere}: give that credential write access, or unset it so the job's own GITHUB_TOKEN is used with ${perms}.`;
153
+ }
154
+ return `The ${source} set in this environment ${nowhere}: set it to a token carrying repo scope, or unset it to fall back on your gh CLI login.`;
155
+ }
156
+ export async function findOpenPr(gh, ownerRepo, branch) {
157
+ const owner = ownerRepo.split('/')[0];
158
+ const prs = await gh.request('GET', `/repos/${ownerRepo}/pulls?state=open&head=${encodeURIComponent(`${owner}:${branch}`)}&per_page=1`);
159
+ return prs[0] ?? null;
160
+ }
161
+ export async function getPr(gh, ownerRepo, number) {
162
+ return gh.request('GET', `/repos/${ownerRepo}/pulls/${number}`);
163
+ }
164
+ export function blobUrl(ownerRepo, sha, filePath) {
165
+ const encoded = filePath.split('/').map(encodeURIComponent).join('/');
166
+ return `https://github.com/${ownerRepo}/blob/${sha}/${encoded}?raw=true`;
167
+ }
168
+ async function mapLimit(items, limit, fn) {
169
+ const results = new Array(items.length);
170
+ let next = 0;
171
+ const workers = Array.from({ length: Math.min(limit, items.length) }, async () => {
172
+ while (next < items.length) {
173
+ const i = next++;
174
+ results[i] = await fn(items[i]);
175
+ }
176
+ });
177
+ await Promise.all(workers);
178
+ return results;
179
+ }
180
+ /**
181
+ * Publish files to `branch` as a single commit. Creates the branch as an
182
+ * orphan (no parents) when it does not exist. Retries once on a ref race.
183
+ */
184
+ export async function publishAssets(gh, ownerRepo, branch, files, message) {
185
+ if (files.length === 0)
186
+ throw new Error('publishAssets: no files');
187
+ // 1. Blobs in parallel (content is base64; 6 at a time keeps well under abuse limits).
188
+ const blobs = await mapLimit(files, 6, async (f) => {
189
+ const res = await gh.request('POST', `/repos/${ownerRepo}/git/blobs`, {
190
+ content: f.content.toString('base64'),
191
+ encoding: 'base64',
192
+ });
193
+ return { path: f.path, sha: res.sha };
194
+ });
195
+ for (let attempt = 0; attempt < 3; attempt++) {
196
+ // 2. Current head of the assets branch (if any).
197
+ let parentSha = null;
198
+ let baseTree;
199
+ try {
200
+ const ref = await gh.request('GET', `/repos/${ownerRepo}/git/ref/${encodeURIComponent(`heads/${branch}`)}`);
201
+ parentSha = ref.object.sha;
202
+ const commit = await gh.request('GET', `/repos/${ownerRepo}/git/commits/${parentSha}`);
203
+ baseTree = commit.tree.sha;
204
+ }
205
+ catch (err) {
206
+ if (!(err instanceof GitHubError) || err.status !== 404)
207
+ throw err;
208
+ }
209
+ // 3. One tree, one commit.
210
+ const tree = await gh.request('POST', `/repos/${ownerRepo}/git/trees`, {
211
+ ...(baseTree ? { base_tree: baseTree } : {}),
212
+ tree: blobs.map(b => ({ path: b.path, mode: '100644', type: 'blob', sha: b.sha })),
213
+ });
214
+ const commit = await gh.request('POST', `/repos/${ownerRepo}/git/commits`, {
215
+ message,
216
+ tree: tree.sha,
217
+ parents: parentSha ? [parentSha] : [],
218
+ });
219
+ // 4. Move the ref (create when missing). A 422 here means another run raced us; retry.
220
+ try {
221
+ if (parentSha) {
222
+ await gh.request('PATCH', `/repos/${ownerRepo}/git/refs/${encodeURIComponent(`heads/${branch}`)}`, { sha: commit.sha, force: false });
223
+ }
224
+ else {
225
+ await gh.request('POST', `/repos/${ownerRepo}/git/refs`, { ref: `refs/heads/${branch}`, sha: commit.sha });
226
+ }
227
+ }
228
+ catch (err) {
229
+ if (err instanceof GitHubError && (err.status === 422 || err.status === 409) && attempt < 2)
230
+ continue;
231
+ throw err;
232
+ }
233
+ const urls = new Map();
234
+ for (const f of files)
235
+ urls.set(f.path, blobUrl(ownerRepo, commit.sha, f.path));
236
+ return { sha: commit.sha, urls };
237
+ }
238
+ throw new Error(`Could not update ${branch} after 3 attempts (concurrent runs?)`);
239
+ }
240
+ /**
241
+ * Create or update the single pre-post comment on a PR, identified by `marker`.
242
+ */
243
+ export async function upsertStickyComment(gh, ownerRepo, prNumber, body, marker) {
244
+ for (let page = 1; page <= 5; page++) {
245
+ const comments = await gh.request('GET', `/repos/${ownerRepo}/issues/${prNumber}/comments?per_page=100&page=${page}`);
246
+ const existing = comments.find(c => c.body?.includes(marker));
247
+ if (existing) {
248
+ const updated = await gh.request('PATCH', `/repos/${ownerRepo}/issues/comments/${existing.id}`, { body });
249
+ return { html_url: updated.html_url, created: false };
250
+ }
251
+ if (comments.length < 100)
252
+ break;
253
+ }
254
+ const created = await gh.request('POST', `/repos/${ownerRepo}/issues/${prNumber}/comments`, { body });
255
+ return { html_url: created.html_url, created: true };
256
+ }
257
+ /**
258
+ * Write `body` into a marked block in the PR description, replacing the block
259
+ * from a previous run. The description is where reviewers look first, so this
260
+ * is preferred over a comment.
261
+ *
262
+ * Returns updated: false when the token cannot edit the PR (a fork, or no write
263
+ * access), so the caller can fall back to a comment instead of failing.
264
+ */
265
+ export async function upsertPrDescription(gh, ownerRepo, prNumber, body, marker) {
266
+ const open = `<!-- ${marker}:start -->`;
267
+ const close = `<!-- ${marker}:end -->`;
268
+ const pr = await gh.request('GET', `/repos/${ownerRepo}/pulls/${prNumber}`);
269
+ const section = `${open}\n${body}\n${close}`;
270
+ const existing = pr.body ?? '';
271
+ const start = existing.indexOf(open);
272
+ const end = existing.indexOf(close);
273
+ // Prepend: the screenshots are the first thing a reviewer should see.
274
+ const next = start !== -1 && end > start
275
+ ? existing.slice(0, start) + section + existing.slice(end + close.length)
276
+ : section + (existing.trim() ? '\n\n' + existing.trimStart() : '');
277
+ if (next === existing)
278
+ return { html_url: pr.html_url, updated: true };
279
+ try {
280
+ await gh.request('PATCH', `/repos/${ownerRepo}/pulls/${prNumber}`, { body: next });
281
+ }
282
+ catch {
283
+ return { html_url: pr.html_url, updated: false };
284
+ }
285
+ return { html_url: pr.html_url, updated: true };
286
+ }
287
+ const ASSETS_README_PATH = 'README.md';
288
+ /** Kept so pruning the last folder does not ask the API for an empty tree. */
289
+ const ASSETS_README = `# pre-post assets
290
+
291
+ Screenshots published by [pre-post](https://github.com/juangadm/pre-post), one folder per
292
+ pull request (\`pr-<number>/\`). Nothing here is edited by hand.
293
+
294
+ \`pre-post prune\` removes folders for pull requests closed more than \`pruneDays\` ago. This
295
+ file is what keeps the branch from becoming an empty tree, which the GitHub tree API
296
+ refuses to create.
297
+ `;
298
+ /**
299
+ * Remove `pr-<n>/` folders on the assets branch whose PR closed more than
300
+ * `olderThanDays` ago. One commit; no history rewrite.
301
+ */
302
+ export async function pruneAssets(gh, ownerRepo, branch, olderThanDays, dryRun = false) {
303
+ let headSha;
304
+ try {
305
+ const ref = await gh.request('GET', `/repos/${ownerRepo}/git/ref/${encodeURIComponent(`heads/${branch}`)}`);
306
+ headSha = ref.object.sha;
307
+ }
308
+ catch (err) {
309
+ if (err instanceof GitHubError && err.status === 404)
310
+ return { removed: [], kept: [] };
311
+ throw err;
312
+ }
313
+ const commit = await gh.request('GET', `/repos/${ownerRepo}/git/commits/${headSha}`);
314
+ const tree = await gh.request('GET', `/repos/${ownerRepo}/git/trees/${commit.tree.sha}?recursive=1`);
315
+ const folders = new Map();
316
+ for (const entry of tree.tree) {
317
+ const m = entry.path.match(/^pr-(\d+)\//);
318
+ if (m && entry.type === 'blob') {
319
+ const n = Number(m[1]);
320
+ const list = folders.get(n);
321
+ if (list)
322
+ list.push(entry.path);
323
+ else
324
+ folders.set(n, [entry.path]);
325
+ }
326
+ }
327
+ const cutoff = Date.now() - olderThanDays * 86_400_000;
328
+ const removed = [];
329
+ const kept = [];
330
+ const deletions = [];
331
+ const entries = Array.from(folders.entries()).sort((a, b) => a[0] - b[0]);
332
+ const staleFlags = await mapLimit(entries, 6, async ([n]) => {
333
+ try {
334
+ const pr = await getPr(gh, ownerRepo, n);
335
+ const closedAt = pr.merged_at || pr.closed_at;
336
+ return pr.state === 'closed' && Boolean(closedAt) && new Date(closedAt).getTime() < cutoff;
337
+ }
338
+ catch (err) {
339
+ if (err instanceof GitHubError && err.status === 404)
340
+ return true;
341
+ throw err;
342
+ }
343
+ });
344
+ entries.forEach(([n, paths], i) => {
345
+ if (staleFlags[i]) {
346
+ removed.push(`pr-${n}`);
347
+ deletions.push(...paths);
348
+ }
349
+ else {
350
+ kept.push(`pr-${n}`);
351
+ }
352
+ });
353
+ if (dryRun || deletions.length === 0)
354
+ return { removed, kept };
355
+ // Deleting every blob would leave an empty tree, and git's empty tree is not
356
+ // something the API will build: `tree: []` is refused as "Invalid tree info"
357
+ // (422), and the canonical empty-tree SHA is not resolvable through the REST
358
+ // API either (404) even though every repository contains that object. So the
359
+ // last folder could never be removed -- prune worked in every case except the
360
+ // one that finishes the job.
361
+ //
362
+ // The branch therefore keeps one file. `README.md` is chosen over an empty
363
+ // marker because the branch is otherwise undocumented, and it is inert on
364
+ // both sides: prune only ever counts `pr-<n>/` paths, and publish adds to
365
+ // whatever tree it finds.
366
+ const doomed = new Set(deletions);
367
+ const survivors = tree.tree.filter(e => e.type === 'blob' && !doomed.has(e.path));
368
+ // Rebuilding from scratch is only safe on a complete listing. A truncated one
369
+ // does not show every entry, so "nothing survives" would be a statement about
370
+ // the page that came back rather than about the branch, and the rebuild would
371
+ // silently drop whatever GitHub left out. Subtracting from `base_tree` is the
372
+ // safe answer there, and it cannot empty the tree either: truncation means
373
+ // there are more entries than the ones being removed.
374
+ const rebuild = survivors.length === 0 && !tree.truncated;
375
+ try {
376
+ const newTree = await gh.request('POST', `/repos/${ownerRepo}/git/trees`, rebuild
377
+ // No base_tree: the surviving tree is this file and nothing else.
378
+ ? { tree: [{ path: ASSETS_README_PATH, mode: '100644', type: 'blob', content: ASSETS_README }] }
379
+ : {
380
+ base_tree: commit.tree.sha,
381
+ tree: deletions.map(p => ({ path: p, mode: '100644', type: 'blob', sha: null })),
382
+ });
383
+ const newCommit = await gh.request('POST', `/repos/${ownerRepo}/git/commits`, {
384
+ message: `Prune screenshots for ${removed.length} closed PR(s)`,
385
+ tree: newTree.sha,
386
+ parents: [headSha],
387
+ });
388
+ await gh.request('PATCH', `/repos/${ownerRepo}/git/refs/${encodeURIComponent(`heads/${branch}`)}`, { sha: newCommit.sha });
389
+ return { removed, kept, sha: newCommit.sha };
390
+ }
391
+ catch (err) {
392
+ // Everything above this point was a read, so a write that fails here has
393
+ // left the branch untouched and the run is always safe to repeat. What
394
+ // changes is what the human should do about it, and naming the wrong cause
395
+ // is worse than naming none: `request` has already turned 401 and 403 into
396
+ // NeedsHumanError, so what reaches here is a refusal disguised as a 404, a
397
+ // race, or GitHub being unwell -- and only the first is about permissions.
398
+ if (err instanceof GitHubError) {
399
+ if (err.status === 409 || err.status === 422) {
400
+ throw new NeedsHumanError(`Another run moved ${branch} while prune was working on it; nothing was changed, so run pre-post prune again.`);
401
+ }
402
+ if (err.status === 429 || err.status >= 500) {
403
+ throw new NeedsHumanError(`GitHub could not finish pruning ${branch} (it answered ${err.status}); nothing was changed, so run pre-post prune again in a few minutes.`);
404
+ }
405
+ throw new NeedsHumanError(`Could not update the ${branch} branch to prune ${removed.length} folder(s) (GitHub answered ${err.status}); ` +
406
+ `check that your token still has contents: write on ${ownerRepo}, then run pre-post prune again.`);
407
+ }
408
+ throw err;
409
+ }
410
+ }
411
+ //# sourceMappingURL=github.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.js","sourceRoot":"","sources":["../src/github.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,26 +1,25 @@
1
+ /**
2
+ * Public API. Everything else under src/ is internal and may change.
3
+ */
1
4
  export * from './types.js';
2
- export { resolveViewport } from './viewport.js';
3
- export { captureScreenshot, captureBeforeAfter, captureResponsive } from './capture.js';
4
- export { captureVideo, captureGif } from './video.js';
5
+ export type { Settings } from './config.js';
6
+ export { loadConfig, resolveSettings, CONFIG_DEFAULTS } from './config.js';
7
+ export { NeedsHumanError, HttpStatusError, NavigationError, BrowserNotFoundError, GitHubError } from './errors.js';
8
+ export { captureScreenshot, captureBeforeAfter } from './capture.js';
9
+ export { closeBrowser } from './browser.js';
10
+ export { diffImages } from './diff.js';
11
+ export type { DiffOptions } from './diff.js';
12
+ export { parseViewport, resolveViewport } from './viewport.js';
5
13
  export { generateFilename } from './filename.js';
6
- export { closeBrowser, readScreenshot } from './browser.js';
7
- export { detectRoutes, detectFramework, getChangedFiles } from './routes.js';
8
- import { BeforeAndAfterOptions, CaptureOptions, CaptureResult, BeforeAfterCaptureOptions, BeforeAfterCaptureResult, ViewportSize, FromImagesOptions, FromImagesResult, ImageInput } from './types.js';
9
- export declare class BeforeAndAfter {
10
- private options;
11
- constructor(options?: BeforeAndAfterOptions);
12
- get viewport(): ViewportSize;
13
- capture(options: CaptureOptions): Promise<CaptureResult>;
14
- captureBeforeAfter(options: BeforeAfterCaptureOptions): Promise<BeforeAfterCaptureResult>;
15
- /**
16
- * Create output from existing images (no browser capture needed).
17
- * Outputs GitHub-flavored markdown table.
18
- */
19
- fromImages(options: FromImagesOptions): Promise<FromImagesResult>;
20
- /**
21
- * Generate GitHub-flavored markdown table for before/after images.
22
- */
23
- generateMarkdown(beforeLabel: string, afterLabel: string, beforePath: ImageInput, afterPath: ImageInput): string;
24
- private resolveImageInput;
25
- }
14
+ export { detectRoutes, detectRoutesForRepo, detectFramework, getChangedFiles } from './routes.js';
15
+ export type { RepoRouteDetection, RepoDetectionOptions } from './routes.js';
16
+ export { buildComment, buildSummary, STICKY_MARKER } from './report.js';
17
+ export { runPr } from './commands/pr.js';
18
+ export type { PrCommandOptions } from './commands/pr.js';
19
+ export { runCompare } from './commands/compare.js';
20
+ export type { CompareOptions } from './commands/compare.js';
21
+ export { runLogin } from './commands/login.js';
22
+ export { runPrune } from './commands/prune.js';
23
+ export { runDoctor } from './commands/doctor.js';
24
+ export { runDetect } from './commands/detect.js';
26
25
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACxF,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAI7E,OAAO,EACL,qBAAqB,EACrB,cAAc,EACd,aAAa,EACb,yBAAyB,EACzB,wBAAwB,EACxB,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACX,MAAM,YAAY,CAAC;AAKpB,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAwB;gBAE3B,OAAO,GAAE,qBAA0B;IAI/C,IAAI,QAAQ,IAAI,YAAY,CAE3B;IAEK,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAOxD,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAO/F;;;OAGG;IACG,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAevE;;OAEG;IACH,gBAAgB,CACd,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,UAAU,GACpB,MAAM;IAYT,OAAO,CAAC,iBAAiB;CAQ1B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAc,YAAY,CAAC;AAC3B,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACnH,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAClG,YAAY,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC"}
package/dist/index.js CHANGED
@@ -1,70 +1,20 @@
1
+ /**
2
+ * Public API. Everything else under src/ is internal and may change.
3
+ */
1
4
  export * from './types.js';
2
- export { resolveViewport } from './viewport.js';
3
- export { captureScreenshot, captureBeforeAfter, captureResponsive } from './capture.js';
4
- export { captureVideo, captureGif } from './video.js';
5
+ export { loadConfig, resolveSettings, CONFIG_DEFAULTS } from './config.js';
6
+ export { NeedsHumanError, HttpStatusError, NavigationError, BrowserNotFoundError, GitHubError } from './errors.js';
7
+ export { captureScreenshot, captureBeforeAfter } from './capture.js';
8
+ export { closeBrowser } from './browser.js';
9
+ export { diffImages } from './diff.js';
10
+ export { parseViewport, resolveViewport } from './viewport.js';
5
11
  export { generateFilename } from './filename.js';
6
- export { closeBrowser, readScreenshot } from './browser.js';
7
- export { detectRoutes, detectFramework, getChangedFiles } from './routes.js';
8
- import fs from 'fs';
9
- import path from 'path';
10
- import { resolveViewport } from './viewport.js';
11
- import { captureScreenshot, captureBeforeAfter } from './capture.js';
12
- export class BeforeAndAfter {
13
- options;
14
- constructor(options = {}) {
15
- this.options = options;
16
- }
17
- get viewport() {
18
- return resolveViewport(this.options.viewport);
19
- }
20
- async capture(options) {
21
- return captureScreenshot({
22
- viewport: this.options.viewport,
23
- ...options,
24
- });
25
- }
26
- async captureBeforeAfter(options) {
27
- return captureBeforeAfter({
28
- viewport: this.options.viewport,
29
- ...options,
30
- });
31
- }
32
- /**
33
- * Create output from existing images (no browser capture needed).
34
- * Outputs GitHub-flavored markdown table.
35
- */
36
- async fromImages(options) {
37
- const beforeImage = this.resolveImageInput(options.before);
38
- const afterImage = this.resolveImageInput(options.after);
39
- const beforeLabel = options.labels?.before || 'Before';
40
- const afterLabel = options.labels?.after || 'After';
41
- const markdown = this.generateMarkdown(beforeLabel, afterLabel, options.before, options.after);
42
- return {
43
- markdown,
44
- beforeImage,
45
- afterImage,
46
- };
47
- }
48
- /**
49
- * Generate GitHub-flavored markdown table for before/after images.
50
- */
51
- generateMarkdown(beforeLabel, afterLabel, beforePath, afterPath) {
52
- // For markdown, we use the path if it's a string, otherwise a placeholder
53
- const beforeSrc = typeof beforePath === 'string' ? beforePath : 'before.png';
54
- const afterSrc = typeof afterPath === 'string' ? afterPath : 'after.png';
55
- return [
56
- `| ${beforeLabel} | ${afterLabel} |`,
57
- `|:------:|:-----:|`,
58
- `| ![${beforeLabel}](${beforeSrc}) | ![${afterLabel}](${afterSrc}) |`,
59
- ].join('\n');
60
- }
61
- resolveImageInput(input) {
62
- if (Buffer.isBuffer(input)) {
63
- return input;
64
- }
65
- // It's a file path
66
- const resolvedPath = path.isAbsolute(input) ? input : path.resolve(process.cwd(), input);
67
- return fs.readFileSync(resolvedPath);
68
- }
69
- }
12
+ export { detectRoutes, detectRoutesForRepo, detectFramework, getChangedFiles } from './routes.js';
13
+ export { buildComment, buildSummary, STICKY_MARKER } from './report.js';
14
+ export { runPr } from './commands/pr.js';
15
+ export { runCompare } from './commands/compare.js';
16
+ export { runLogin } from './commands/login.js';
17
+ export { runPrune } from './commands/prune.js';
18
+ export { runDoctor } from './commands/doctor.js';
19
+ export { runDetect } from './commands/detect.js';
70
20
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAc,YAAY,CAAC;AAE3B,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACnH,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAElG,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC"}