@juangadm/pre-post 1.0.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 (103) hide show
  1. package/README.md +99 -20
  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 +80 -41
  7. package/dist/bin/cli.js.map +1 -1
  8. package/dist/browser.d.ts +31 -3
  9. package/dist/browser.d.ts.map +1 -1
  10. package/dist/browser.js +239 -97
  11. package/dist/browser.js.map +1 -1
  12. package/dist/commands/compare.d.ts.map +1 -1
  13. package/dist/commands/compare.js +21 -3
  14. package/dist/commands/compare.js.map +1 -1
  15. package/dist/commands/detect.d.ts +5 -0
  16. package/dist/commands/detect.d.ts.map +1 -1
  17. package/dist/commands/detect.js +4 -1
  18. package/dist/commands/detect.js.map +1 -1
  19. package/dist/commands/doctor.d.ts +32 -0
  20. package/dist/commands/doctor.d.ts.map +1 -1
  21. package/dist/commands/doctor.js +90 -9
  22. package/dist/commands/doctor.js.map +1 -1
  23. package/dist/commands/login.js +1 -1
  24. package/dist/commands/pr.d.ts +4 -0
  25. package/dist/commands/pr.d.ts.map +1 -1
  26. package/dist/commands/pr.js +150 -50
  27. package/dist/commands/pr.js.map +1 -1
  28. package/dist/commands/prune.js +1 -1
  29. package/dist/commands/prune.js.map +1 -1
  30. package/dist/comparison.d.ts +104 -0
  31. package/dist/comparison.d.ts.map +1 -0
  32. package/dist/comparison.js +236 -0
  33. package/dist/comparison.js.map +1 -0
  34. package/dist/config.d.ts +12 -2
  35. package/dist/config.d.ts.map +1 -1
  36. package/dist/config.js +25 -3
  37. package/dist/config.js.map +1 -1
  38. package/dist/deployments.d.ts +71 -0
  39. package/dist/deployments.d.ts.map +1 -0
  40. package/dist/deployments.js +204 -0
  41. package/dist/deployments.js.map +1 -0
  42. package/dist/diff-pool.d.ts.map +1 -1
  43. package/dist/diff-pool.js +5 -2
  44. package/dist/diff-pool.js.map +1 -1
  45. package/dist/diff-worker.d.ts +3 -0
  46. package/dist/diff-worker.d.ts.map +1 -1
  47. package/dist/diff-worker.js +1 -0
  48. package/dist/diff-worker.js.map +1 -1
  49. package/dist/diff.d.ts +10 -0
  50. package/dist/diff.d.ts.map +1 -1
  51. package/dist/diff.js +117 -7
  52. package/dist/diff.js.map +1 -1
  53. package/dist/doctor.d.ts +42 -1
  54. package/dist/doctor.d.ts.map +1 -1
  55. package/dist/doctor.js +73 -7
  56. package/dist/doctor.js.map +1 -1
  57. package/dist/git.d.ts +41 -3
  58. package/dist/git.d.ts.map +1 -1
  59. package/dist/git.js +103 -7
  60. package/dist/git.js.map +1 -1
  61. package/dist/github.d.ts +92 -2
  62. package/dist/github.d.ts.map +1 -1
  63. package/dist/github.js +191 -20
  64. package/dist/github.js.map +1 -1
  65. package/dist/landing.d.ts +48 -0
  66. package/dist/landing.d.ts.map +1 -0
  67. package/dist/landing.js +93 -0
  68. package/dist/landing.js.map +1 -0
  69. package/dist/pkg.d.ts +9 -0
  70. package/dist/pkg.d.ts.map +1 -1
  71. package/dist/pkg.js +14 -0
  72. package/dist/pkg.js.map +1 -1
  73. package/dist/report.d.ts.map +1 -1
  74. package/dist/report.js +49 -26
  75. package/dist/report.js.map +1 -1
  76. package/dist/routes.d.ts +27 -0
  77. package/dist/routes.d.ts.map +1 -1
  78. package/dist/routes.js +98 -23
  79. package/dist/routes.js.map +1 -1
  80. package/dist/run.d.ts +88 -8
  81. package/dist/run.d.ts.map +1 -1
  82. package/dist/run.js +214 -26
  83. package/dist/run.js.map +1 -1
  84. package/dist/sameness.d.ts +91 -0
  85. package/dist/sameness.d.ts.map +1 -0
  86. package/dist/sameness.js +157 -0
  87. package/dist/sameness.js.map +1 -0
  88. package/dist/sessions.d.ts.map +1 -1
  89. package/dist/sessions.js +7 -1
  90. package/dist/sessions.js.map +1 -1
  91. package/dist/shift.d.ts +67 -0
  92. package/dist/shift.d.ts.map +1 -0
  93. package/dist/shift.js +184 -0
  94. package/dist/shift.js.map +1 -0
  95. package/dist/types.d.ts +67 -5
  96. package/dist/types.d.ts.map +1 -1
  97. package/dist/types.js.map +1 -1
  98. package/dist/url.d.ts +12 -0
  99. package/dist/url.d.ts.map +1 -0
  100. package/dist/url.js +30 -0
  101. package/dist/url.js.map +1 -0
  102. package/package.json +1 -1
  103. package/skill/SKILL.md +40 -7
@@ -0,0 +1,204 @@
1
+ /**
2
+ * Deployment URLs from the GitHub Deployments API.
3
+ *
4
+ * Vercel, Cloudflare Pages, Netlify and Render all report their deploys to
5
+ * GitHub against a commit, so one lookup covers every provider: no per-host
6
+ * API tokens, and nothing to configure per repo.
7
+ */
8
+ import { normalizeUrl } from './url.js';
9
+ /**
10
+ * Bots whose PR comments may be read for a preview URL. A comment is only
11
+ * trusted when GitHub reports its author as one of these apps: anyone can post
12
+ * a comment that looks like Vercel's, and following it would point a capture at
13
+ * a URL a stranger chose.
14
+ */
15
+ const TRUSTED_BOTS = new Set(['vercel[bot]', 'netlify[bot]']);
16
+ /** Commit-status contexts these same providers post under. */
17
+ const PROVIDER_STATUS = /vercel|netlify|cloudflare|render/i;
18
+ const PRODUCTION = /^prod/i;
19
+ /** How many deployments to inspect per page; each costs one status request. */
20
+ const MAX_DEPLOYMENTS = 5;
21
+ /** Deployments per page when scanning for production. */
22
+ const SCAN_PAGE_SIZE = 100;
23
+ /** How far back to scan. A repo can bury production under a wall of previews. */
24
+ const SCAN_PAGES = 3;
25
+ /**
26
+ * The newest successful deployment URL matching a query.
27
+ *
28
+ * Shared by the two questions callers ask — "what was deployed for this
29
+ * commit?" and "what is deployed to production right now?" — so both apply the
30
+ * same production/preview split and the same "success with a URL" rule.
31
+ */
32
+ async function listDeployments(gh, ownerRepo, query) {
33
+ try {
34
+ const deployments = await gh.request('GET', `/repos/${ownerRepo}/deployments?${query}`);
35
+ return Array.isArray(deployments) ? deployments : null;
36
+ }
37
+ catch {
38
+ return null;
39
+ }
40
+ }
41
+ /** The first of these deployments that reported success with a live URL. */
42
+ async function firstReady(gh, ownerRepo, candidates) {
43
+ const ready = await Promise.all(candidates.map(async (deployment) => {
44
+ try {
45
+ const statuses = await gh.request('GET', `/repos/${ownerRepo}/deployments/${deployment.id}/statuses?per_page=20`);
46
+ if (!Array.isArray(statuses))
47
+ return null;
48
+ const ok = statuses.find((s) => s.state === 'success' && !!s.environment_url);
49
+ return ok ? { url: ok.environment_url, environment: deployment.environment, sha: deployment.sha } : null;
50
+ }
51
+ catch {
52
+ return null;
53
+ }
54
+ }));
55
+ // Candidates stay in newest-first order, so the first hit is the newest.
56
+ return ready.find(Boolean) ?? null;
57
+ }
58
+ /** One page of deployments, narrowed to production or preview. */
59
+ async function newestSuccessful(gh, ownerRepo, query, production) {
60
+ const deployments = await listDeployments(gh, ownerRepo, query);
61
+ if (!deployments)
62
+ return null;
63
+ return firstReady(gh, ownerRepo, matching(deployments, production));
64
+ }
65
+ /** Production or preview, newest first, capped at what is worth a status call. */
66
+ function matching(deployments, production) {
67
+ return deployments.filter(d => PRODUCTION.test(d.environment || '') === production).slice(0, MAX_DEPLOYMENTS);
68
+ }
69
+ /**
70
+ * The newest successful deployment URL for a commit.
71
+ *
72
+ * `production: true` accepts only production environments (the baseline for
73
+ * "Pre"); `false` accepts only the others, which is where every provider puts
74
+ * per-PR previews. Neither falls back to the other kind — a preview standing in
75
+ * for production would silently compare against the wrong thing.
76
+ *
77
+ * Returns null whenever the answer is not unambiguous, so callers fall through
78
+ * to their next option. Never throws: a repo with no deployments, or a token
79
+ * without `deployments: read`, is a normal outcome, not a failure.
80
+ */
81
+ export async function deploymentUrlForSha(gh, ownerRepo, sha, opts) {
82
+ return newestSuccessful(gh, ownerRepo, `sha=${encodeURIComponent(sha)}&per_page=20`, opts.production);
83
+ }
84
+ /**
85
+ * What is deployed to production right now, whatever commit it was built from.
86
+ *
87
+ * `deploymentUrlForSha` pins Pre to the commit the branch forked from, which is
88
+ * the most honest baseline there is — but it only exists if production happened
89
+ * to be deployed at exactly that commit. Production is a moving branch, so on
90
+ * most repositories it was not, and pinning alone leaves the deployed
91
+ * comparison with no Pre at all.
92
+ *
93
+ * This asks the same question without the pin. It reports the commit it found,
94
+ * so the caller can name what Pre actually is rather than implying the base.
95
+ */
96
+ export async function latestProductionDeployment(gh, ownerRepo) {
97
+ // Deployments come back newest first, previews and production interleaved.
98
+ // A busy repository can push its live production deployment well past the
99
+ // first page, so scan a few pages rather than reading one and giving up —
100
+ // but stop the moment a page comes back short, which is the end of the list.
101
+ for (let page = 1; page <= SCAN_PAGES; page++) {
102
+ const deployments = await listDeployments(gh, ownerRepo, `per_page=${SCAN_PAGE_SIZE}&page=${page}`);
103
+ if (!deployments)
104
+ return null;
105
+ const found = await firstReady(gh, ownerRepo, matching(deployments, true));
106
+ if (found)
107
+ return { ...found, url: normalizeUrl(found.url) };
108
+ if (deployments.length < SCAN_PAGE_SIZE)
109
+ return null;
110
+ }
111
+ return null;
112
+ }
113
+ /** Has a deployment provider reported success against this exact commit? */
114
+ async function providerSucceededFor(gh, ownerRepo, sha) {
115
+ try {
116
+ const combined = await gh.request('GET', `/repos/${ownerRepo}/commits/${sha}/status`);
117
+ return (combined.statuses ?? []).some(s => s.state === 'success' && PROVIDER_STATUS.test(s.context));
118
+ }
119
+ catch {
120
+ return false;
121
+ }
122
+ }
123
+ /**
124
+ * The preview for a commit, from whichever mechanism the provider uses.
125
+ *
126
+ * The freshness rule lives here rather than in the caller: a bot comment is
127
+ * edited in place and carries no SHA, so mid-deploy it still advertises the
128
+ * previous commit's preview. Screenshotting that and labelling it as this
129
+ * branch is the worst failure this tool has, because it looks exactly like a
130
+ * correct result. Every caller gets that guarantee by construction.
131
+ */
132
+ export async function findPreviewForCommit(gh, ownerRepo, opts) {
133
+ const recorded = await deploymentUrlForSha(gh, ownerRepo, opts.sha, { production: false });
134
+ if (recorded)
135
+ return { ...recorded, url: normalizeUrl(recorded.url) };
136
+ if (opts.prNumber === undefined)
137
+ return null;
138
+ const [fresh, commented] = await Promise.all([
139
+ providerSucceededFor(gh, ownerRepo, opts.sha),
140
+ previewUrlFromComments(gh, ownerRepo, opts.prNumber, { appPrefix: opts.appPrefix }),
141
+ ]);
142
+ return fresh && commented ? { ...commented, url: normalizeUrl(commented.url) } : null;
143
+ }
144
+ function decodeVercelPayload(body) {
145
+ const marker = /^\[vc\]: #[^:\n]+:(\S+)/m.exec(body);
146
+ if (!marker)
147
+ return null;
148
+ try {
149
+ const json = JSON.parse(Buffer.from(marker[1], 'base64').toString('utf8'));
150
+ return json && typeof json === 'object' ? json : null;
151
+ }
152
+ catch {
153
+ return null;
154
+ }
155
+ }
156
+ /**
157
+ * The preview URL a deployment bot posted on the PR.
158
+ *
159
+ * Not every provider records a GitHub Deployment — Vercel's GitHub app reports
160
+ * a commit status and a comment, and the commit status only links to its own
161
+ * dashboard. The comment is where the deployed URL actually appears, so this is
162
+ * the fallback when `deploymentUrlForSha` finds nothing.
163
+ *
164
+ * `appPrefix` disambiguates a monorepo comment listing several projects, by
165
+ * matching the project whose root directory is the app being captured.
166
+ */
167
+ export async function previewUrlFromComments(gh, ownerRepo, prNumber, opts = {}) {
168
+ let comments;
169
+ try {
170
+ comments = await gh.request('GET', `/repos/${ownerRepo}/issues/${prNumber}/comments?per_page=100`);
171
+ }
172
+ catch {
173
+ return null;
174
+ }
175
+ if (!Array.isArray(comments))
176
+ return null;
177
+ // Newest first: a re-run posts an updated URL.
178
+ for (const comment of [...comments].reverse()) {
179
+ const body = comment.body ?? '';
180
+ if (!comment.user || !TRUSTED_BOTS.has(comment.user.login))
181
+ continue;
182
+ const payload = decodeVercelPayload(body);
183
+ const projects = (payload?.projects ?? []).filter(p => p.previewUrl);
184
+ if (projects.length) {
185
+ // Only projects that could be the app being captured. A project that
186
+ // declares a different root directory is a different app, so falling back
187
+ // to it would screenshot the wrong site.
188
+ const norm = (dir) => (dir ?? '').replace(/^\.?\//, '').replace(/\/$/, '');
189
+ const candidates = projects.filter(p => !opts.appPrefix || !p.rootDirectory || norm(p.rootDirectory) === opts.appPrefix);
190
+ const chosen = candidates.length === 1 ? candidates[0] : undefined;
191
+ // A build still running has a URL that does not serve the branch yet.
192
+ if (chosen && (chosen.nextCommitStatus ?? 'DEPLOYED') === 'DEPLOYED') {
193
+ return { url: normalizeUrl(chosen.previewUrl), environment: chosen.name ? `Preview (${chosen.name})` : 'Preview' };
194
+ }
195
+ continue;
196
+ }
197
+ // Providers without a structured payload still link the preview by name.
198
+ const link = /\[(?:Preview|Deploy Preview)\]\((https?:\/\/[^\s)]+)\)/i.exec(body);
199
+ if (link)
200
+ return { url: link[1], environment: 'Preview' };
201
+ }
202
+ return null;
203
+ }
204
+ //# sourceMappingURL=deployments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deployments.js","sourceRoot":"","sources":["../src/deployments.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"diff-pool.d.ts","sourceRoot":"","sources":["../src/diff-pool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,OAAO,EAAE,aAAa,EAAkB,MAAM,kBAAkB,CAAC;AAa1E,qBAAa,QAAQ;IAKP,OAAO,CAAC,QAAQ,CAAC,IAAI;IAJjC,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,KAAK,CAAiB;IAC9B,OAAO,CAAC,MAAM,CAAS;gBAEM,IAAI,SAAiD;IAElF,GAAG,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC;IAOzC,OAAO,CAAC,KAAK;IA8Bb,OAAO,CAAC,IAAI;IAmBN,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAI7B"}
1
+ {"version":3,"file":"diff-pool.d.ts","sourceRoot":"","sources":["../src/diff-pool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,OAAO,EAAE,aAAa,EAAkB,MAAM,kBAAkB,CAAC;AAa1E,qBAAa,QAAQ;IAKP,OAAO,CAAC,QAAQ,CAAC,IAAI;IAJjC,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,KAAK,CAAiB;IAC9B,OAAO,CAAC,MAAM,CAAS;gBAEM,IAAI,SAAiD;IAElF,GAAG,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC;IAOzC,OAAO,CAAC,KAAK;IA8Bb,OAAO,CAAC,IAAI;IAsBN,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAI7B"}
package/dist/diff-pool.js CHANGED
@@ -77,8 +77,11 @@ export class DiffPool {
77
77
  }
78
78
  const pending = this.queue.shift();
79
79
  slot.busy = pending;
80
- const { before, after } = pending.job;
81
- slot.worker.postMessage(pending.job, [before.buffer, after.buffer]);
80
+ // Copied, not transferred. Transferring detaches the buffers here, which
81
+ // leaves the `error` handler above holding a job it cannot run inline —
82
+ // so the fallback it exists to provide could never work. A structured
83
+ // clone of two PNGs costs far less than the diff that follows it.
84
+ slot.worker.postMessage(pending.job);
82
85
  }
83
86
  }
84
87
  async close() {
@@ -1 +1 @@
1
- {"version":3,"file":"diff-pool.js","sourceRoot":"","sources":["../src/diff-pool.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"diff-pool.js","sourceRoot":"","sources":["../src/diff-pool.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,7 @@
3
3
  * Keeps pixel work and file I/O off the main thread so captures keep flowing.
4
4
  */
5
5
  import { DiffOptions } from './diff.js';
6
+ import { ShiftSummary } from './types.js';
6
7
  export interface DiffJob {
7
8
  /** PNG bytes; transferred to the worker, so the caller must not reuse them. */
8
9
  before: Uint8Array;
@@ -23,6 +24,8 @@ export interface DiffJobResult {
23
24
  sizeChanged: boolean;
24
25
  hasCrop: boolean;
25
26
  hasHighlight: boolean;
27
+ /** Plain numbers, so the summary survives the structured clone back to the pool. */
28
+ shift?: ShiftSummary;
26
29
  error?: string;
27
30
  }
28
31
  export declare function executeDiffJob(job: DiffJob): DiffJobResult;
@@ -1 +1 @@
1
- {"version":3,"file":"diff-worker.d.ts","sourceRoot":"","sources":["../src/diff-worker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAc,WAAW,EAAE,MAAM,WAAW,CAAC;AAEpD,MAAM,WAAW,OAAO;IACtB,+EAA+E;IAC/E,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,UAAU,CAAC;IAClB,iEAAiE;IACjE,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAChG,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,aAAa,CAkB1D"}
1
+ {"version":3,"file":"diff-worker.d.ts","sourceRoot":"","sources":["../src/diff-worker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAc,WAAW,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,OAAO;IACtB,+EAA+E;IAC/E,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,UAAU,CAAC;IAClB,iEAAiE;IACjE,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAChG,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;IACtB,oFAAoF;IACpF,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,aAAa,CAmB1D"}
@@ -23,6 +23,7 @@ export function executeDiffJob(job) {
23
23
  sizeChanged: result.sizeChanged,
24
24
  hasCrop: Boolean(result.crop),
25
25
  hasHighlight: Boolean(result.highlight),
26
+ shift: result.shift,
26
27
  };
27
28
  }
28
29
  if (parentPort) {
@@ -1 +1 @@
1
- {"version":3,"file":"diff-worker.js","sourceRoot":"","sources":["../src/diff-worker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAe,MAAM,WAAW,CAAC;AAoBpD,MAAM,UAAU,cAAc,CAAC,GAAY;IACzC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC5F,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACxF,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACtD,IAAI,MAAM,CAAC,SAAS;QAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;IAC3E,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAChB,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7D,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7D,CAAC;IACD,OAAO;QACL,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC;QAC7B,YAAY,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC;KACxC,CAAC;AACJ,CAAC;AAED,IAAI,UAAU,EAAE,CAAC;IACf,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,GAAY,EAAE,EAAE;QACxC,IAAI,CAAC;YACH,UAAW,CAAC,WAAW,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,UAAW,CAAC,WAAW,CAAC,EAAE,KAAK,EAAG,GAAa,CAAC,OAAO,EAAmB,CAAC,CAAC;QAC9E,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"diff-worker.js","sourceRoot":"","sources":["../src/diff-worker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAe,MAAM,WAAW,CAAC;AAuBpD,MAAM,UAAU,cAAc,CAAC,GAAY;IACzC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC5F,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACxF,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACtD,IAAI,MAAM,CAAC,SAAS;QAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;IAC3E,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAChB,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7D,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7D,CAAC;IACD,OAAO;QACL,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC;QAC7B,YAAY,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC;QACvC,KAAK,EAAE,MAAM,CAAC,KAAK;KACpB,CAAC;AACJ,CAAC;AAED,IAAI,UAAU,EAAE,CAAC;IACf,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,GAAY,EAAE,EAAE;QACxC,IAAI,CAAC;YACH,UAAW,CAAC,WAAW,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,UAAW,CAAC,WAAW,CAAC,EAAE,KAAK,EAAG,GAAa,CAAC,OAAO,EAAmB,CAAC,CAAC;QAC9E,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
package/dist/diff.d.ts CHANGED
@@ -17,6 +17,16 @@ export interface DiffOptions {
17
17
  };
18
18
  /** Integer factor to shrink the highlight image by (e.g. 2 for 2x captures). Default 1 */
19
19
  highlightDownscale?: number;
20
+ /**
21
+ * Produce the red-highlight overlay. Default true.
22
+ *
23
+ * The pr pipeline uses the bounding box to crop Pre and Post, and ships that
24
+ * pair; it never publishes the overlay, and a wall of red pixels is not
25
+ * something a reviewer reads anyway. Encoding one per capture is a downscale
26
+ * and a deflate of a full-page image for nothing, so that path turns it off.
27
+ * Image mode still writes diff.png.
28
+ */
29
+ highlight?: boolean;
20
30
  }
21
31
  /** Box-filter downscale by an integer factor. */
22
32
  export declare function downscale(src: PNG, factor: number): PNG;
@@ -1 +1 @@
1
- {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../src/diff.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEpD,MAAM,WAAW,WAAW;IAC1B,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0DAA0D;IAC1D,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,0FAA0F;IAC1F,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AA+BD,iDAAiD;AACjD,wBAAgB,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAG,GAAG,CAoBvD;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,CAE7C;AAsBD,+EAA+E;AAC/E,wBAAgB,YAAY,CAC1B,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EACzC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACrC,UAAU,CAqBZ;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,UAAU,CAsDrG"}
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../src/diff.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,UAAU,EAAgB,MAAM,YAAY,CAAC;AAGlE,MAAM,WAAW,WAAW;IAC1B,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0DAA0D;IAC1D,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,0FAA0F;IAC1F,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AA8ED,iDAAiD;AACjD,wBAAgB,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAG,GAAG,CAoBvD;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,CAE7C;AAoCD,+EAA+E;AAC/E,wBAAgB,YAAY,CAC1B,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EACzC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACrC,UAAU,CAqBZ;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,UAAU,CAuGrG"}
package/dist/diff.js CHANGED
@@ -7,14 +7,62 @@
7
7
  */
8
8
  import pixelmatch from 'pixelmatch';
9
9
  import { PNG } from 'pngjs';
10
+ import { alignBefore, detectShift, insertedBand } from './shift.js';
10
11
  const DIFF_COLOR = [255, 0, 0];
11
12
  const AA_COLOR = [255, 200, 0];
12
13
  /** Background used to pad images of different sizes. */
13
14
  const PAD_COLOR = [255, 255, 255];
14
- /** pixelmatch per-pixel color distance (0..1). */
15
- const PIXEL_THRESHOLD = 0.1;
15
+ /**
16
+ * pixelmatch per-pixel colour distance (0..1).
17
+ *
18
+ * Calibrated, not chosen. At the old 0.1 a 600x320 card recoloured from #ffffff
19
+ * to #e6e6e6 — plainly visible, a sixth of the viewport — reported *zero*
20
+ * changed pixels, and `rung-6-section` measured 1649 CSS px² instead of 67539.
21
+ * The ladder never caught it because every rung varies painted *area* while the
22
+ * threshold governs *contrast*, so nothing in the suite moved along that axis.
23
+ * `contrast-*` is that missing axis.
24
+ *
25
+ * Measured across the fixtures, changed CSS px² by threshold:
26
+ *
27
+ * 0.1 0.05 0.03 0.02 0.01
28
+ * contrast-25 0 191754 191754 191754 191754
29
+ * contrast-15 0 191758 191758 191758 191758
30
+ * contrast-10 0 0 191758 191758 191758
31
+ * contrast-05 0 0 0 0 191762
32
+ * rung-6 1649 1649 67539 67539 67539
33
+ * noise-* 0 0 0 0 0
34
+ *
35
+ * Every no-op stays at zero the whole way down, and so does the strongest
36
+ * real-world check available: the same page captured from two different
37
+ * deployments, which reports 0 at every value above, desktop and mobile.
38
+ *
39
+ * 0.02 catches every delta a reader would call visible and keeps a margin above
40
+ * the floor for sites noisier than the ones measured. 0.01 was also clean here;
41
+ * the margin is deliberate, since the alternative to a marginal false positive
42
+ * is silently publishing "No visual changes" about a page that changed.
43
+ */
44
+ const PIXEL_THRESHOLD = 0.02;
16
45
  /** No crop when the change covers more than this fraction of the canvas. */
17
46
  const CROP_MAX_RATIO = 0.5;
47
+ /**
48
+ * A shift is only worth reporting when putting the two sides back in register
49
+ * accounts for most of the difference. This is the whole test: an offset that
50
+ * does not remove the pixels it claims to explain is not the story.
51
+ *
52
+ * Judged over the rows Pre and Post share. Content Post gained is excluded
53
+ * from both sides of the comparison, because an insertion is the reason for
54
+ * the move rather than evidence against it: a page pushed down by a banner
55
+ * would otherwise be refused for the size of the banner.
56
+ *
57
+ * Measured on the shift ladder, as a share of the changed pixels over those
58
+ * shared rows: every true shift leaves 0.23 or less, and the horizontal
59
+ * reflow — the one case no vertical offset explains — leaves 0.45. This sits
60
+ * in the empty band between, nearer the real changes so a genuine shift
61
+ * carrying a larger change still reads as one. Erring low is deliberate:
62
+ * rejecting a shift falls back to the old behaviour, while claiming one that
63
+ * isn't there tells a reviewer something untrue.
64
+ */
65
+ const MAX_ALIGNED_SHARE = 0.3;
18
66
  function padTo(src, width, height, bg) {
19
67
  if (src.width === width && src.height === height)
20
68
  return src;
@@ -68,6 +116,20 @@ export function downscale(src, factor) {
68
116
  export function decodePng(buffer) {
69
117
  return PNG.sync.read(buffer);
70
118
  }
119
+ /** Diff-coloured pixels within a row range, for weighing one band against another. */
120
+ function countChangedRows(diff, y0, y1) {
121
+ const { width, data } = diff;
122
+ let count = 0;
123
+ for (let y = Math.max(0, y0); y < Math.min(diff.height, y1); y++) {
124
+ const row = y * width * 4;
125
+ for (let x = 0; x < width; x++) {
126
+ const i = row + x * 4;
127
+ if (data[i] === DIFF_COLOR[0] && data[i + 1] === DIFF_COLOR[1] && data[i + 2] === DIFF_COLOR[2])
128
+ count++;
129
+ }
130
+ }
131
+ return count;
132
+ }
71
133
  /** Bounding box of pixels painted with the diff color. */
72
134
  function boundingBox(diff) {
73
135
  const { width, height, data } = diff;
@@ -141,6 +203,46 @@ export function diffImages(beforePng, afterPng, options = {}) {
141
203
  aaColor: AA_COLOR,
142
204
  diffMask: false,
143
205
  });
206
+ // A vertical shift repaints everything below where it starts, so the raw
207
+ // bounding box covers most of the page and the crop guards below refuse to
208
+ // zoom in. Comparing Post put back in register with Pre isolates the change
209
+ // the branch actually made, which is small enough to crop and to describe.
210
+ let shift;
211
+ let alignedBefore;
212
+ let alignedDiff;
213
+ if (changedPixels > 0) {
214
+ const candidate = detectShift(before, after);
215
+ if (candidate) {
216
+ const aligned = alignBefore(before, candidate, bg);
217
+ const diffOfAligned = new PNG({ width, height });
218
+ const alignedChangedPixels = pixelmatch(aligned.data, after.data, diffOfAligned.data, width, height, {
219
+ threshold: PIXEL_THRESHOLD,
220
+ includeAA: false,
221
+ alpha: 0.5,
222
+ diffColor: DIFF_COLOR,
223
+ aaColor: AA_COLOR,
224
+ diffMask: false,
225
+ });
226
+ // Weigh the offset only on rows both sides have. Whatever Post put in
227
+ // the gap is new content, and it still counts as a change -- it just
228
+ // does not get a vote on whether the move happened.
229
+ const gap = insertedBand(candidate);
230
+ const insertedChanged = gap ? countChangedRows(diffOfAligned, gap.y, gap.y + gap.height) : 0;
231
+ const rawInGap = gap ? countChangedRows(diff, gap.y, gap.y + gap.height) : 0;
232
+ const mappedChanged = alignedChangedPixels - insertedChanged;
233
+ const rawMapped = changedPixels - rawInGap;
234
+ if (mappedChanged <= rawMapped * MAX_ALIGNED_SHARE) {
235
+ shift = {
236
+ dy: candidate.dy,
237
+ from: candidate.from,
238
+ alignedChangedPixels,
239
+ alignedChangedRatio: alignedChangedPixels / (width * height),
240
+ };
241
+ alignedBefore = aligned;
242
+ alignedDiff = diffOfAligned;
243
+ }
244
+ }
245
+ }
144
246
  const region = changedPixels > 0 ? boundingBox(diff) : null;
145
247
  const result = {
146
248
  changedRatio: changedPixels / (width * height),
@@ -150,16 +252,24 @@ export function diffImages(beforePng, afterPng, options = {}) {
150
252
  region,
151
253
  sizeChanged,
152
254
  // Identical pages need no highlight; skip the downscale + deflate.
153
- highlight: region ? encode(downscale(diff, options.highlightDownscale ?? 1)) : undefined,
255
+ highlight: region && options.highlight !== false
256
+ ? encode(downscale(diff, options.highlightDownscale ?? 1))
257
+ : undefined,
258
+ shift,
154
259
  };
155
- if (region) {
156
- const area = region.width * region.height;
260
+ // With a shift, crop what is left once the move is undone; without one, crop
261
+ // the change itself. A pure shift leaves nothing over and gets no crop: the
262
+ // sentence is the report, and the full pages are already published.
263
+ const cropFrom = alignedBefore ?? before;
264
+ const cropRegion = alignedDiff ? boundingBox(alignedDiff) : region;
265
+ if (cropRegion) {
266
+ const area = cropRegion.width * cropRegion.height;
157
267
  if (area / (width * height) <= CROP_MAX_RATIO) {
158
- const expanded = expandRegion(region, { width, height }, options.padding ?? 80, options.minCrop ?? { width: 800, height: 400 });
268
+ const expanded = expandRegion(cropRegion, { width, height }, options.padding ?? 80, options.minCrop ?? { width: 800, height: 400 });
159
269
  // Only crop when it meaningfully zooms in.
160
270
  if (expanded.width * expanded.height < width * height * 0.8) {
161
271
  result.crop = {
162
- before: crop(before, expanded),
272
+ before: crop(cropFrom, expanded),
163
273
  after: crop(after, expanded),
164
274
  region: expanded,
165
275
  };
package/dist/diff.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"diff.js","sourceRoot":"","sources":["../src/diff.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../src/diff.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,UAAU,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAE5B,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAqBpE,MAAM,UAAU,GAA6B,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACzD,MAAM,QAAQ,GAA6B,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;AACzD,wDAAwD;AACxD,MAAM,SAAS,GAA6B,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAC5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,eAAe,GAAG,IAAI,CAAC;AAC7B,4EAA4E;AAC5E,MAAM,cAAc,GAAG,GAAG,CAAC;AAC3B;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAE9B,SAAS,KAAK,CAAC,GAAQ,EAAE,KAAa,EAAE,MAAc,EAAE,EAA4B;IAClF,IAAI,GAAG,CAAC,KAAK,KAAK,KAAK,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM;QAAE,OAAO,GAAG,CAAC;IAC7D,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IACvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5C,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;IAC/F,CAAC;IACD,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACxD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,IAAI,CAAC,GAAQ,EAAE,MAAkB;IACxC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IACpE,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5E,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;AACrB,CAAC;AAED,SAAS,MAAM,CAAC,GAAQ;IACtB,OAAO,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,YAAY,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;AACjE,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,SAAS,CAAC,GAAQ,EAAE,MAAc;IAChD,IAAI,MAAM,IAAI,CAAC;QAAE,OAAO,GAAG,CAAC;IAC5B,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC;IACtD,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC;IACvD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;IAC7C,MAAM,CAAC,GAAG,MAAM,GAAG,MAAM,CAAC;IAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;YAC/B,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC;gBACnC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,EAAE,CAAC,GAAG,GAAG,CAAC,KAAK,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;gBACzD,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC3C,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;oBAAC,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;oBAAC,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;oBAAC,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBACrF,CAAC;YACH,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;YAC1B,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjG,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,MAAc;IACtC,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC;AAED,sFAAsF;AACtF,SAAS,gBAAgB,CAAC,IAAS,EAAE,EAAU,EAAE,EAAU;IACzD,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;IAC7B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACjE,MAAM,GAAG,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;QAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/B,MAAM,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;YACtB,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC;gBAAE,KAAK,EAAE,CAAC;QAC3G,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,0DAA0D;AAC1D,SAAS,WAAW,CAAC,IAAS;IAC5B,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;IACrC,IAAI,IAAI,GAAG,KAAK,EAAE,IAAI,GAAG,MAAM,EAAE,IAAI,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC;IACtD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAChC,MAAM,GAAG,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;QAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/B,MAAM,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;YACtB,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;gBAChG,IAAI,CAAC,GAAG,IAAI;oBAAE,IAAI,GAAG,CAAC,CAAC;gBACvB,IAAI,CAAC,GAAG,IAAI;oBAAE,IAAI,GAAG,CAAC,CAAC;gBACvB,IAAI,CAAC,GAAG,IAAI;oBAAE,IAAI,GAAG,CAAC,CAAC;gBACvB,IAAI,CAAC,GAAG,IAAI;oBAAE,IAAI,GAAG,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,IAAI,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1B,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,GAAG,IAAI,GAAG,CAAC,EAAE,MAAM,EAAE,IAAI,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC;AAC/E,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,YAAY,CAC1B,MAAkB,EAClB,MAAyC,EACzC,OAAe,EACf,GAAsC;IAEtC,IAAI,EAAE,GAAG,MAAM,CAAC,CAAC,GAAG,OAAO,CAAC;IAC5B,IAAI,EAAE,GAAG,MAAM,CAAC,CAAC,GAAG,OAAO,CAAC;IAC5B,IAAI,EAAE,GAAG,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,GAAG,OAAO,CAAC;IAC3C,IAAI,EAAE,GAAG,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,OAAO,CAAC;IAE5C,MAAM,IAAI,GAAG,CAAC,EAAU,EAAE,EAAU,EAAE,MAAc,EAAE,KAAa,EAAoB,EAAE;QACvF,MAAM,IAAI,GAAG,EAAE,GAAG,EAAE,CAAC;QACrB,IAAI,IAAI,GAAG,MAAM,EAAE,CAAC;YAClB,MAAM,KAAK,GAAG,MAAM,GAAG,IAAI,CAAC;YAC5B,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;YAC5B,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QAC7B,CAAC;QACD,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;YAAC,EAAE,IAAI,EAAE,CAAC;YAAC,EAAE,GAAG,CAAC,CAAC;QAAC,CAAC;QACjC,IAAI,EAAE,GAAG,KAAK,EAAE,CAAC;YAAC,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;YAAC,EAAE,GAAG,KAAK,CAAC;QAAC,CAAC;QACjD,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;IAChD,CAAC,CAAC;IAEF,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IACzE,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5E,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC;AAC3D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,SAAiB,EAAE,QAAgB,EAAE,UAAuB,EAAE;IACvF,MAAM,EAAE,GAAG,SAAS,CAAC;IACrB,MAAM,CAAC,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;IAC/B,MAAM,CAAC,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,CAAC;IAEjE,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IAExC,MAAM,aAAa,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE;QAClF,SAAS,EAAE,eAAe;QAC1B,SAAS,EAAE,KAAK;QAChB,KAAK,EAAE,GAAG;QACV,SAAS,EAAE,UAAU;QACrB,OAAO,EAAE,QAAQ;QACjB,QAAQ,EAAE,KAAK;KAChB,CAAC,CAAC;IAEH,yEAAyE;IACzE,2EAA2E;IAC3E,4EAA4E;IAC5E,2EAA2E;IAC3E,IAAI,KAA+B,CAAC;IACpC,IAAI,aAA8B,CAAC;IACnC,IAAI,WAA4B,CAAC;IACjC,IAAI,aAAa,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC7C,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;YACnD,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;YACjD,MAAM,oBAAoB,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,aAAa,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE;gBACnG,SAAS,EAAE,eAAe;gBAC1B,SAAS,EAAE,KAAK;gBAChB,KAAK,EAAE,GAAG;gBACV,SAAS,EAAE,UAAU;gBACrB,OAAO,EAAE,QAAQ;gBACjB,QAAQ,EAAE,KAAK;aAChB,CAAC,CAAC;YACH,sEAAsE;YACtE,qEAAqE;YACrE,oDAAoD;YACpD,MAAM,GAAG,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;YACpC,MAAM,eAAe,GAAG,GAAG,CAAC,CAAC,CAAC,gBAAgB,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC7F,MAAM,QAAQ,GAAG,GAAG,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC7E,MAAM,aAAa,GAAG,oBAAoB,GAAG,eAAe,CAAC;YAC7D,MAAM,SAAS,GAAG,aAAa,GAAG,QAAQ,CAAC;YAC3C,IAAI,aAAa,IAAI,SAAS,GAAG,iBAAiB,EAAE,CAAC;gBACnD,KAAK,GAAG;oBACN,EAAE,EAAE,SAAS,CAAC,EAAE;oBAChB,IAAI,EAAE,SAAS,CAAC,IAAI;oBACpB,oBAAoB;oBACpB,mBAAmB,EAAE,oBAAoB,GAAG,CAAC,KAAK,GAAG,MAAM,CAAC;iBAC7D,CAAC;gBACF,aAAa,GAAG,OAAO,CAAC;gBACxB,WAAW,GAAG,aAAa,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5D,MAAM,MAAM,GAAe;QACzB,YAAY,EAAE,aAAa,GAAG,CAAC,KAAK,GAAG,MAAM,CAAC;QAC9C,aAAa;QACb,KAAK;QACL,MAAM;QACN,MAAM;QACN,WAAW;QACX,mEAAmE;QACnE,SAAS,EAAE,MAAM,IAAI,OAAO,CAAC,SAAS,KAAK,KAAK;YAC9C,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,kBAAkB,IAAI,CAAC,CAAC,CAAC;YAC1D,CAAC,CAAC,SAAS;QACb,KAAK;KACN,CAAC;IAEF,6EAA6E;IAC7E,4EAA4E;IAC5E,oEAAoE;IACpE,MAAM,QAAQ,GAAG,aAAa,IAAI,MAAM,CAAC;IACzC,MAAM,UAAU,GAAG,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IACnE,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC;QAClD,IAAI,IAAI,GAAG,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,cAAc,EAAE,CAAC;YAC9C,MAAM,QAAQ,GAAG,YAAY,CAC3B,UAAU,EACV,EAAE,KAAK,EAAE,MAAM,EAAE,EACjB,OAAO,CAAC,OAAO,IAAI,EAAE,EACrB,OAAO,CAAC,OAAO,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAC/C,CAAC;YACF,2CAA2C;YAC3C,IAAI,QAAQ,CAAC,KAAK,GAAG,QAAQ,CAAC,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,GAAG,EAAE,CAAC;gBAC5D,MAAM,CAAC,IAAI,GAAG;oBACZ,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC;oBAChC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC;oBAC5B,MAAM,EAAE,QAAQ;iBACjB,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
package/dist/doctor.d.ts CHANGED
@@ -13,13 +13,54 @@ export declare function ensureBrowser(): Promise<void>;
13
13
  /** Headed browser for `pre-post login`; caller owns and closes it. */
14
14
  export declare function launchHeadedBrowser(): Promise<import("playwright-core").Browser>;
15
15
  /**
16
- * Find a running local dev server. Returns its base URL or null.
16
+ * Is this a dev server, or just something listening?
17
+ *
18
+ * A reachable socket used to be enough, and it is not: on macOS, AirPlay
19
+ * Receiver holds port 5000 and answers every request 403 with no body. The
20
+ * probe adopted it, the 403 was read as access control, and the run advised
21
+ * signing in to a system service — in place of "no dev server is running",
22
+ * which is the one thing that was true. It bit precisely when nothing else was
23
+ * listening, the case the message exists to describe.
24
+ *
25
+ * So the bar is a plausible *app* response, not a reachable port:
26
+ *
27
+ * - 401/403 never qualifies. That is a wall or a stranger; either way there is
28
+ * no site behind it to capture, and inferring a dev server from one is how
29
+ * the above happened.
30
+ * - A redirect does. Locale prefixes and trailing slashes make it ordinary, and
31
+ * there is no body to inspect, so the status is all there is to go on. If it
32
+ * leads somewhere sign-in shaped, `landing.ts` catches that at capture time
33
+ * with a message about the wall rather than about ports.
34
+ * - Anything else has to have served an HTML document. This deliberately keeps
35
+ * a 404 or a 500 that renders a page: a dev server with no `/` route, or one
36
+ * with a compile error, is still the dev server, and refusing it would send
37
+ * someone hunting for a server they are already running.
17
38
  */
39
+ export declare function looksLikeDevServer(result: ProbeResult): boolean;
40
+ export interface DevServerScan {
41
+ /** Base URL of the dev server, or null when none of the ports had one. */
42
+ url: string | null;
43
+ /** Ports that answered but are not serving a site — worth naming, not using. */
44
+ ignored: Array<{
45
+ port: number;
46
+ status: number;
47
+ }>;
48
+ }
49
+ /**
50
+ * Probe the usual ports and say what was found *and* what was passed over.
51
+ *
52
+ * `doctor` reports the ignored ports because "nothing on the usual ports" is
53
+ * confusing when something is plainly listening on one of them.
54
+ */
55
+ export declare function scanDevServers(ports?: number[]): Promise<DevServerScan>;
56
+ /** Find a running local dev server. Returns its base URL or null. */
18
57
  export declare function detectDevServer(ports?: number[]): Promise<string | null>;
19
58
  export interface ProbeResult {
20
59
  /** HTTP status, or null when the host could not be reached at all */
21
60
  status: number | null;
22
61
  vercel: boolean;
62
+ /** Response Content-Type, lowercased and without parameters. */
63
+ contentType?: string;
23
64
  }
24
65
  /**
25
66
  * Probe a base URL with the headers we will use for capture.
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAwB,eAAe,EAAqC,MAAM,aAAa,CAAC;AACvG,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAe9C;;;GAGG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAMnD;AAED,sEAAsE;AACtE,wBAAsB,mBAAmB,+CAMxC;AAID;;GAEG;AACH,wBAAsB,eAAe,CAAC,KAAK,GAAE,MAAM,EAAc,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAIzF;AAED,MAAM,WAAW,WAAW;IAC1B,qEAAqE;IACrE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAC5B,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EACpC,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,eAAe,CAAA;CAAO,GAC/D,OAAO,CAAC,WAAW,CAAC,CAOtB;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,eAAe,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAO3F"}
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAwB,eAAe,EAAqC,MAAM,aAAa,CAAC;AACvG,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAe9C;;;GAGG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAMnD;AAED,sEAAsE;AACtE,wBAAsB,mBAAmB,+CAMxC;AAoBD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAM/D;AAED,MAAM,WAAW,aAAa;IAC5B,0EAA0E;IAC1E,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,gFAAgF;IAChF,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClD;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,KAAK,GAAE,MAAM,EAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAWxF;AAED,qEAAqE;AACrE,wBAAsB,eAAe,CAAC,KAAK,GAAE,MAAM,EAAc,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAEzF;AAED,MAAM,WAAW,WAAW;IAC1B,qEAAqE;IACrE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAChB,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAC5B,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EACpC,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,eAAe,CAAA;CAAO,GAC/D,OAAO,CAAC,WAAW,CAAC,CAQtB;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,eAAe,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAO3F"}