@grove-dev/core 0.16.0 → 0.18.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 (62) hide show
  1. package/dist/build-data.d.ts.map +1 -1
  2. package/dist/build-data.js +2 -0
  3. package/dist/build-data.js.map +1 -1
  4. package/dist/candidate-collector.d.ts +61 -0
  5. package/dist/candidate-collector.d.ts.map +1 -0
  6. package/dist/candidate-collector.js +545 -0
  7. package/dist/candidate-collector.js.map +1 -0
  8. package/dist/candidate-discovery.d.ts +92 -0
  9. package/dist/candidate-discovery.d.ts.map +1 -0
  10. package/dist/candidate-discovery.js +488 -0
  11. package/dist/candidate-discovery.js.map +1 -0
  12. package/dist/candidate-schema.d.ts +209 -0
  13. package/dist/candidate-schema.d.ts.map +1 -0
  14. package/dist/candidate-schema.js +84 -0
  15. package/dist/candidate-schema.js.map +1 -0
  16. package/dist/github-cache.d.ts +87 -1
  17. package/dist/github-cache.d.ts.map +1 -1
  18. package/dist/github-cache.js +19 -1
  19. package/dist/github-cache.js.map +1 -1
  20. package/dist/image-probe.d.ts +27 -0
  21. package/dist/image-probe.d.ts.map +1 -0
  22. package/dist/image-probe.js +124 -0
  23. package/dist/image-probe.js.map +1 -0
  24. package/dist/index-policy.d.ts +48 -0
  25. package/dist/index-policy.d.ts.map +1 -0
  26. package/dist/index-policy.js +58 -0
  27. package/dist/index-policy.js.map +1 -0
  28. package/dist/index.d.ts +18 -4
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +12 -2
  31. package/dist/index.js.map +1 -1
  32. package/dist/normalize-records.d.ts +4 -3
  33. package/dist/normalize-records.d.ts.map +1 -1
  34. package/dist/normalize-records.js +10 -3
  35. package/dist/normalize-records.js.map +1 -1
  36. package/dist/page-document.d.ts +48 -0
  37. package/dist/page-document.d.ts.map +1 -1
  38. package/dist/page-document.js +93 -8
  39. package/dist/page-document.js.map +1 -1
  40. package/dist/prepare.d.ts.map +1 -1
  41. package/dist/prepare.js +31 -10
  42. package/dist/prepare.js.map +1 -1
  43. package/dist/record-candidates.d.ts +61 -0
  44. package/dist/record-candidates.d.ts.map +1 -0
  45. package/dist/record-candidates.js +261 -0
  46. package/dist/record-candidates.js.map +1 -0
  47. package/dist/record-markdown.d.ts +67 -0
  48. package/dist/record-markdown.d.ts.map +1 -0
  49. package/dist/record-markdown.js +244 -0
  50. package/dist/record-markdown.js.map +1 -0
  51. package/dist/schema.d.ts +78 -18
  52. package/dist/schema.d.ts.map +1 -1
  53. package/dist/schema.js +55 -2
  54. package/dist/schema.js.map +1 -1
  55. package/dist/sitemap.d.ts +3 -0
  56. package/dist/sitemap.d.ts.map +1 -1
  57. package/dist/sitemap.js +2 -0
  58. package/dist/sitemap.js.map +1 -1
  59. package/dist/validate.d.ts.map +1 -1
  60. package/dist/validate.js +14 -2
  61. package/dist/validate.js.map +1 -1
  62. package/package.json +1 -1
@@ -0,0 +1,545 @@
1
+ import { findAssetLogos, findFastlane, findGradleAppFiles, findMetainfoFiles, findWebManifests, installableAssets, parseAppstream, parseGradleApplicationIds, pickManifestIcon, repologyChannels, sameVersion, } from './candidate-discovery.js';
2
+ import { resolveGithubToken } from './github.js';
3
+ import { IMAGE_PROBE_BYTES, imageFormatFromPath, probeImageBytes } from './image-probe.js';
4
+ import { mergeRecordCandidates } from './record-candidates.js';
5
+ /**
6
+ * Network side of `integrations.github.candidates`: for one record,
7
+ * read the repository's file tree and latest release from GitHub, a
8
+ * few small files from it, and ask F-Droid, Flathub and Repology
9
+ * whether they carry the app. The result is review material for the
10
+ * sync cache — never written into the record.
11
+ *
12
+ * Every request counts against a per-record budget. A host that keeps
13
+ * failing, or answers 429, is skipped for the rest of the run.
14
+ * Repology is asked at most once a second with an identifying
15
+ * User-Agent, as its API rules require. Nothing here throws: failures
16
+ * come back as strings for `partialFailures`.
17
+ */
18
+ export const GITHUB_API = 'https://api.github.com';
19
+ export const RAW_GITHUB = 'https://raw.githubusercontent.com';
20
+ /** Serves Git LFS objects; a probe follows an LFS pointer here. */
21
+ export const MEDIA_GITHUB = 'https://media.githubusercontent.com/media';
22
+ export const FDROID_API = 'https://f-droid.org/api/v1/packages';
23
+ export const FLATHUB_API = 'https://flathub.org/api/v2';
24
+ export const REPOLOGY_API = 'https://repology.org/api/v1/project';
25
+ /** Requests one record may make while collecting candidates. */
26
+ export const CANDIDATE_REQUESTS_PER_RECORD = 24;
27
+ /** Repology asks API clients for no more than one request per second. */
28
+ export const REPOLOGY_MIN_INTERVAL_MS = 1_000;
29
+ /** Consecutive network errors or 5xx after which a host is skipped for the run. */
30
+ const HOST_ERROR_LIMIT = 2;
31
+ const MAX_LOGOS = 6;
32
+ const MAX_SCREENSHOTS = 8;
33
+ /** Screenshots whose size is probed; the rest carry type and bytes only. */
34
+ const PROBED_SCREENSHOTS = 3;
35
+ /** Raster logos smaller than this on both sides are toolbar icons, not logos. */
36
+ const MIN_RASTER_LOGO = 128;
37
+ const LFS_POINTER = /^version https:\/\/git-lfs\.github\.com\/spec\/v1\b[\s\S]*?\bsize (\d+)/;
38
+ class SkipError extends Error {
39
+ }
40
+ const DEFAULT_USER_AGENT = 'grove (+https://github.com/tortuvshin/grove)';
41
+ function encodePath(path) {
42
+ return path.split('/').map(encodeURIComponent).join('/');
43
+ }
44
+ function reasonOf(error) {
45
+ // undici reports "fetch failed" and keeps the useful part in `cause`.
46
+ const cause = error instanceof Error ? error.cause : undefined;
47
+ const base = error instanceof Error ? error.message : String(error);
48
+ const text = cause?.code ? `${base} (${cause.code})` : base;
49
+ return text.replace(/\s+/g, ' ').trim().slice(0, 120);
50
+ }
51
+ /**
52
+ * Create a collector for one sync run. Host health and the Repology
53
+ * clock are shared by every record in the run; the request budget is
54
+ * per record.
55
+ */
56
+ export function createCandidateCollector(options = {}) {
57
+ const fetchImpl = options.fetch ?? fetch;
58
+ const sleep = options.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
59
+ const clock = options.clock ?? Date.now;
60
+ const now = options.now ?? (() => new Date());
61
+ const userAgent = options.userAgent ?? DEFAULT_USER_AGENT;
62
+ const timeoutMs = options.timeoutMs ?? 15_000;
63
+ const perRecord = options.requestsPerRecord ?? CANDIDATE_REQUESTS_PER_RECORD;
64
+ const token = options.token ?? resolveGithubToken();
65
+ const hostErrors = new Map();
66
+ const disabledHosts = new Map();
67
+ let lastRepologyAt = Number.NEGATIVE_INFINITY;
68
+ async function collect(input) {
69
+ const { owner, repo } = input;
70
+ const fetchedAt = now().toISOString();
71
+ let requests = 0;
72
+ const failures = [];
73
+ const failedSources = new Set();
74
+ const fail = (step, sources, error) => {
75
+ failures.push(`${step}: ${reasonOf(error)}`);
76
+ for (const source of sources)
77
+ failedSources.add(source);
78
+ };
79
+ async function request(url, init = {}) {
80
+ const host = new URL(url).host;
81
+ const disabled = disabledHosts.get(host);
82
+ if (disabled)
83
+ throw new SkipError(`${host} skipped for this run (${disabled})`);
84
+ if (requests >= perRecord)
85
+ throw new SkipError(`request budget of ${perRecord} used up`);
86
+ requests += 1;
87
+ if (url.startsWith(REPOLOGY_API)) {
88
+ const wait = lastRepologyAt + REPOLOGY_MIN_INTERVAL_MS - clock();
89
+ if (wait > 0)
90
+ await sleep(wait);
91
+ lastRepologyAt = clock();
92
+ }
93
+ const headers = { 'User-Agent': userAgent, ...init.headers };
94
+ if (url.startsWith(GITHUB_API)) {
95
+ headers['X-GitHub-Api-Version'] = '2022-11-28';
96
+ if (token)
97
+ headers.Authorization = `Bearer ${token}`;
98
+ }
99
+ let response;
100
+ try {
101
+ response = await fetchImpl(url, {
102
+ method: init.method ?? 'GET',
103
+ headers,
104
+ ...(init.body ? { body: init.body } : {}),
105
+ signal: AbortSignal.timeout(timeoutMs),
106
+ });
107
+ }
108
+ catch (error) {
109
+ const count = (hostErrors.get(host) ?? 0) + 1;
110
+ hostErrors.set(host, count);
111
+ if (count >= HOST_ERROR_LIMIT) {
112
+ disabledHosts.set(host, `${count} network errors, last: ${reasonOf(error)}`);
113
+ }
114
+ throw error;
115
+ }
116
+ const rateLimited = response.status === 429 ||
117
+ (response.status === 403 && response.headers.get('x-ratelimit-remaining') === '0');
118
+ if (rateLimited) {
119
+ disabledHosts.set(host, 'rate limited');
120
+ throw new Error(`${host} rate limited (HTTP ${response.status})`);
121
+ }
122
+ if (response.status >= 500) {
123
+ const count = (hostErrors.get(host) ?? 0) + 1;
124
+ hostErrors.set(host, count);
125
+ if (count >= HOST_ERROR_LIMIT)
126
+ disabledHosts.set(host, `${count} server errors`);
127
+ throw new Error(`${host} HTTP ${response.status}`);
128
+ }
129
+ hostErrors.set(host, 0);
130
+ return response;
131
+ }
132
+ async function json(url, init) {
133
+ const response = await request(url, init);
134
+ if (response.status === 404)
135
+ return undefined;
136
+ if (!response.ok)
137
+ throw new Error(`HTTP ${response.status} for ${new URL(url).host}`);
138
+ return response.json();
139
+ }
140
+ const apiBase = `${GITHUB_API}/repos/${owner}/${repo}`;
141
+ const permalink = (commit, path) => `https://github.com/${owner}/${repo}/blob/${commit}/${encodePath(path)}`;
142
+ const rawUrl = (commit, path) => `${RAW_GITHUB}/${owner}/${repo}/${commit}/${encodePath(path)}`;
143
+ async function rawText(commit, path) {
144
+ const response = await request(rawUrl(commit, path));
145
+ if (!response.ok)
146
+ throw new Error(`HTTP ${response.status} for ${path}`);
147
+ return response.text();
148
+ }
149
+ const channels = [];
150
+ const logos = [];
151
+ const screenshots = [];
152
+ // ── Repository tree ───────────────────────────────────────────
153
+ const treeSources = [
154
+ 'fastlane',
155
+ 'appstream',
156
+ 'web-manifest',
157
+ 'repo-asset',
158
+ 'fdroid',
159
+ ];
160
+ let commit;
161
+ let files = [];
162
+ try {
163
+ const response = await request(`${apiBase}/commits/HEAD`, {
164
+ headers: { Accept: 'application/vnd.github.sha' },
165
+ });
166
+ if (!response.ok)
167
+ throw new Error(`HTTP ${response.status} resolving HEAD`);
168
+ commit = (await response.text()).trim();
169
+ if (!/^[0-9a-f]{40}$/.test(commit))
170
+ throw new Error('HEAD did not resolve to a commit');
171
+ const tree = (await json(`${apiBase}/git/trees/${commit}?recursive=1`, {
172
+ headers: { Accept: 'application/vnd.github+json' },
173
+ }));
174
+ files = (tree?.tree ?? [])
175
+ .filter((node) => node.type === 'blob' && typeof node.path === 'string')
176
+ .map((node) => ({
177
+ path: node.path,
178
+ sha: String(node.sha ?? ''),
179
+ ...(typeof node.size === 'number' ? { size: node.size } : {}),
180
+ }));
181
+ if (tree?.truncated)
182
+ fail('tree', treeSources, 'GitHub truncated the file tree');
183
+ }
184
+ catch (error) {
185
+ commit = undefined;
186
+ fail('tree', treeSources, error);
187
+ }
188
+ const byPath = new Map(files.map((file) => [file.path, file]));
189
+ const repoMedia = (file, source, evidenceUrl, extra = {}) => {
190
+ const format = imageFormatFromPath(file.path);
191
+ const url = permalink(commit, file.path);
192
+ return {
193
+ url,
194
+ path: file.path,
195
+ blobSha: file.sha,
196
+ ...extra,
197
+ ...(format ? { format } : {}),
198
+ ...(file.size !== undefined ? { bytes: file.size } : {}),
199
+ provenance: { source, url: evidenceUrl ?? url, fetchedAt },
200
+ };
201
+ };
202
+ // ── Latest release ────────────────────────────────────────────
203
+ let releaseTag;
204
+ try {
205
+ const release = (await json(`${apiBase}/releases/latest`, {
206
+ headers: { Accept: 'application/vnd.github+json' },
207
+ }));
208
+ if (release) {
209
+ releaseTag = release.tag_name;
210
+ const names = (release.assets ?? []).map((a) => a.name).filter((n) => !!n);
211
+ for (const [platform, assets] of installableAssets(names)) {
212
+ channels.push({
213
+ type: 'github-releases',
214
+ platform,
215
+ label: 'GitHub Releases',
216
+ url: `https://github.com/${owner}/${repo}/releases/latest`,
217
+ facts: { ...(releaseTag ? { tag: releaseTag } : {}), assets: assets.slice(0, 6) },
218
+ provenance: {
219
+ source: 'github-releases',
220
+ url: release.html_url ?? `https://github.com/${owner}/${repo}/releases/latest`,
221
+ fetchedAt,
222
+ },
223
+ });
224
+ }
225
+ }
226
+ }
227
+ catch (error) {
228
+ fail('releases', ['github-releases'], error);
229
+ }
230
+ // ── fastlane: icon, screenshots, and the Android app id ────────
231
+ const fastlane = commit ? findFastlane(files, MAX_SCREENSHOTS) : undefined;
232
+ if (fastlane?.icon)
233
+ logos.push(repoMedia(fastlane.icon, 'fastlane', undefined, { locale: fastlane.locale }));
234
+ for (const shot of fastlane?.screenshots ?? []) {
235
+ screenshots.push(repoMedia(shot, 'fastlane', undefined, { locale: fastlane?.locale ?? '' }));
236
+ }
237
+ if (commit) {
238
+ const appIds = [];
239
+ try {
240
+ for (const file of findGradleAppFiles(files, fastlane?.root)) {
241
+ for (const id of parseGradleApplicationIds(await rawText(commit, file.path))) {
242
+ if (!appIds.some((a) => a.id === id))
243
+ appIds.push({ id, evidence: permalink(commit, file.path) });
244
+ }
245
+ }
246
+ }
247
+ catch (error) {
248
+ fail('gradle', ['fdroid'], error);
249
+ }
250
+ for (const { id, evidence } of appIds.slice(0, 3)) {
251
+ try {
252
+ const api = `${FDROID_API}/${encodeURIComponent(id)}`;
253
+ const pkg = (await json(api));
254
+ if (!pkg?.packageName)
255
+ continue;
256
+ channels.push({
257
+ type: 'fdroid',
258
+ platform: 'android',
259
+ label: 'F-Droid',
260
+ url: `https://f-droid.org/packages/${pkg.packageName}/`,
261
+ facts: {
262
+ appId: pkg.packageName,
263
+ ...(pkg.suggestedVersionCode
264
+ ? { suggestedVersionCode: pkg.suggestedVersionCode }
265
+ : {}),
266
+ evidence,
267
+ ...(fastlane
268
+ ? {
269
+ fastlane: `${fastlane.root ? `${fastlane.root}/` : ''}fastlane/metadata/android`,
270
+ }
271
+ : {}),
272
+ },
273
+ provenance: { source: 'fdroid', url: api, fetchedAt },
274
+ });
275
+ }
276
+ catch (error) {
277
+ fail('fdroid', ['fdroid'], error);
278
+ break;
279
+ }
280
+ }
281
+ }
282
+ // ── AppStream: Flathub id, icon, screenshots ──────────────────
283
+ const flathubIds = new Map();
284
+ if (commit) {
285
+ for (const file of findMetainfoFiles(files)) {
286
+ try {
287
+ const facts = parseAppstream(await rawText(commit, file.path), file.path);
288
+ const evidence = permalink(commit, file.path);
289
+ if (facts.id && !flathubIds.has(facts.id))
290
+ flathubIds.set(facts.id, evidence);
291
+ for (const url of facts.icons.slice(0, 2)) {
292
+ logos.push(appstreamMedia(url, evidence));
293
+ }
294
+ for (const url of facts.screenshots.slice(0, MAX_SCREENSHOTS)) {
295
+ screenshots.push(appstreamMedia(url, evidence));
296
+ }
297
+ }
298
+ catch (error) {
299
+ fail('appstream', ['appstream', 'flathub'], error);
300
+ }
301
+ }
302
+ }
303
+ function ownRepoPath(url) {
304
+ const prefixes = [
305
+ `${RAW_GITHUB}/${owner}/${repo}/`,
306
+ `https://github.com/${owner}/${repo}/raw/`,
307
+ `https://github.com/${owner}/${repo}/blob/`,
308
+ ].map((p) => p.toLowerCase());
309
+ const prefix = prefixes.find((p) => url.toLowerCase().startsWith(p));
310
+ if (!prefix)
311
+ return undefined;
312
+ const rest = url.slice(prefix.length).split(/[?#]/)[0] ?? '';
313
+ const afterRef = rest
314
+ .replace(/^refs\/(?:heads|tags)\//, '')
315
+ .split('/')
316
+ .slice(1)
317
+ .join('/');
318
+ try {
319
+ return byPath.get(decodeURIComponent(afterRef));
320
+ }
321
+ catch {
322
+ return undefined;
323
+ }
324
+ }
325
+ function appstreamMedia(url, evidence) {
326
+ // A raw URL into this repository is the same file as a tree
327
+ // entry: pin it to the commit like one.
328
+ const file = ownRepoPath(url);
329
+ if (file && commit)
330
+ return repoMedia(file, 'appstream', evidence);
331
+ const format = imageFormatFromPath(url);
332
+ return {
333
+ url,
334
+ ...(format ? { format } : {}),
335
+ provenance: { source: 'appstream', url: evidence, fetchedAt },
336
+ };
337
+ }
338
+ const repoUrl = `https://github.com/${owner}/${repo}`.toLowerCase();
339
+ const pointsAtRepo = (urls) => Object.values(urls ?? {}).some((u) => typeof u === 'string' && u.toLowerCase().replace(/(\.git)?\/*$/, '') === repoUrl);
340
+ async function flathubApp(id) {
341
+ const api = `${FLATHUB_API}/appstream/${encodeURIComponent(id)}`;
342
+ const app = (await json(api));
343
+ return app ? { api, app } : undefined;
344
+ }
345
+ try {
346
+ for (const [id, evidence] of [...flathubIds].slice(0, 2)) {
347
+ const found = await flathubApp(id);
348
+ if (!found)
349
+ continue;
350
+ channels.push({
351
+ type: 'flathub',
352
+ platform: 'linux',
353
+ label: 'Flathub',
354
+ url: `https://flathub.org/apps/${id}`,
355
+ facts: { appId: id, match: 'metainfo', evidence },
356
+ provenance: { source: 'flathub', url: found.api, fetchedAt },
357
+ });
358
+ }
359
+ if (!channels.some((c) => c.type === 'flathub')) {
360
+ // No metainfo in the repository: most Flathub manifests live in
361
+ // flathub/<app-id>. Search by name and keep only an app whose
362
+ // AppStream URLs point back at this repository.
363
+ const search = (await json(`${FLATHUB_API}/search`, {
364
+ method: 'POST',
365
+ headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
366
+ body: JSON.stringify({ query: repo }),
367
+ }));
368
+ const wanted = repo.toLowerCase().replace(/[^a-z0-9]/g, '');
369
+ const hits = (search?.hits ?? [])
370
+ .filter((hit) => {
371
+ const last = (hit.app_id ?? '')
372
+ .split('.')
373
+ .pop()
374
+ ?.toLowerCase()
375
+ .replace(/[^a-z0-9]/g, '');
376
+ const name = (hit.name ?? '').toLowerCase().replace(/[^a-z0-9]/g, '');
377
+ return hit.app_id && (last === wanted || name === wanted);
378
+ })
379
+ .slice(0, 2);
380
+ for (const hit of hits) {
381
+ const found = await flathubApp(hit.app_id);
382
+ if (!found || !pointsAtRepo(found.app.urls))
383
+ continue;
384
+ channels.push({
385
+ type: 'flathub',
386
+ platform: 'linux',
387
+ label: 'Flathub',
388
+ url: `https://flathub.org/apps/${hit.app_id}`,
389
+ facts: { appId: hit.app_id, match: 'appstream-urls' },
390
+ provenance: { source: 'flathub', url: found.api, fetchedAt },
391
+ });
392
+ break;
393
+ }
394
+ }
395
+ }
396
+ catch (error) {
397
+ fail('flathub', ['flathub'], error);
398
+ }
399
+ // ── Repology ──────────────────────────────────────────────────
400
+ try {
401
+ const project = repo.toLowerCase();
402
+ const api = `${REPOLOGY_API}/${encodeURIComponent(project)}`;
403
+ const packages = ((await json(api, { headers: { Accept: 'application/json' } })) ??
404
+ []);
405
+ const known = new Set(channels.map((c) => `${c.type}\u0000${c.url}`));
406
+ for (const channel of repologyChannels(Array.isArray(packages) ? packages : [])) {
407
+ if (known.has(`${channel.type}\u0000${channel.url}`))
408
+ continue;
409
+ channels.push({
410
+ type: channel.type,
411
+ platform: channel.platform,
412
+ label: channel.label,
413
+ url: channel.url,
414
+ facts: {
415
+ repository: channel.repository,
416
+ package: channel.packageName,
417
+ ...(channel.version ? { version: channel.version } : {}),
418
+ project,
419
+ // Repology projects are matched by name only; a version
420
+ // equal to the latest release tag makes a mix-up unlikely.
421
+ match: 'project-name',
422
+ versionMatchesRelease: sameVersion(releaseTag, channel.version),
423
+ },
424
+ provenance: {
425
+ source: 'repology',
426
+ url: `https://repology.org/project/${project}/versions`,
427
+ fetchedAt,
428
+ },
429
+ });
430
+ }
431
+ }
432
+ catch (error) {
433
+ fail('repology', ['repology'], error);
434
+ }
435
+ // ── Web manifest and asset logos ──────────────────────────────
436
+ if (commit) {
437
+ for (const manifest of findWebManifests(files)) {
438
+ try {
439
+ const iconPath = pickManifestIcon(await rawText(commit, manifest.path), manifest.path);
440
+ const icon = iconPath ? byPath.get(iconPath) : undefined;
441
+ if (icon)
442
+ logos.push(repoMedia(icon, 'web-manifest', permalink(commit, manifest.path)));
443
+ }
444
+ catch (error) {
445
+ fail('web-manifest', ['web-manifest'], error);
446
+ }
447
+ }
448
+ for (const file of findAssetLogos(files, repo))
449
+ logos.push(repoMedia(file, 'repo-asset'));
450
+ }
451
+ // One candidate per file: the most trustworthy source wins.
452
+ const uniqueLogos = mergeRecordCandidates(undefined, {
453
+ channels: [],
454
+ logos: dedupeByUrl(logos),
455
+ screenshots: [],
456
+ }).logos.slice(0, MAX_LOGOS);
457
+ const uniqueShots = dedupeByUrl(screenshots).slice(0, MAX_SCREENSHOTS);
458
+ // ── Dimensions: a small range read per image in the repository ─
459
+ const previousMedia = new Map();
460
+ for (const media of [
461
+ ...(input.previous?.logos ?? []),
462
+ ...(input.previous?.screenshots ?? []),
463
+ ]) {
464
+ if (media.path && media.blobSha)
465
+ previousMedia.set(`${media.path}\u0000${media.blobSha}`, media);
466
+ }
467
+ const probe = async (media) => {
468
+ if (!media.path || !commit)
469
+ return media;
470
+ const known = previousMedia.get(`${media.path}\u0000${media.blobSha}`);
471
+ if (known?.width && known.height) {
472
+ return {
473
+ ...media,
474
+ ...(known.format ? { format: known.format } : {}),
475
+ ...(known.bytes !== undefined ? { bytes: known.bytes } : {}),
476
+ width: known.width,
477
+ height: known.height,
478
+ };
479
+ }
480
+ try {
481
+ const range = { headers: { Range: `bytes=0-${IMAGE_PROBE_BYTES - 1}` } };
482
+ let response = await request(rawUrl(commit, media.path), range);
483
+ if (!response.ok)
484
+ return media;
485
+ let bytes = new Uint8Array(await response.arrayBuffer());
486
+ let size = media.bytes;
487
+ // Git LFS: the tree holds a pointer; the image is on the media host.
488
+ const lfs = LFS_POINTER.exec(new TextDecoder().decode(bytes.subarray(0, 200)));
489
+ if (lfs) {
490
+ size = Number(lfs[1]);
491
+ response = await request(`${MEDIA_GITHUB}/${owner}/${repo}/${commit}/${encodePath(media.path)}`, range);
492
+ if (!response.ok)
493
+ return { ...media, bytes: size };
494
+ bytes = new Uint8Array(await response.arrayBuffer());
495
+ }
496
+ const facts = probeImageBytes(bytes);
497
+ return {
498
+ ...media,
499
+ ...(facts.format ? { format: facts.format } : {}),
500
+ ...(size !== undefined ? { bytes: size } : {}),
501
+ ...(facts.width ? { width: facts.width } : {}),
502
+ ...(facts.height ? { height: facts.height } : {}),
503
+ };
504
+ }
505
+ catch (error) {
506
+ if (!(error instanceof SkipError))
507
+ failures.push(`probe: ${reasonOf(error)}`);
508
+ return media;
509
+ }
510
+ };
511
+ const probedLogos = [];
512
+ for (const logo of uniqueLogos) {
513
+ const probed = await probe(logo);
514
+ const tiny = probed.provenance.source === 'repo-asset' &&
515
+ probed.format !== 'svg' &&
516
+ probed.width !== undefined &&
517
+ probed.height !== undefined &&
518
+ Math.max(probed.width, probed.height) < MIN_RASTER_LOGO;
519
+ if (!tiny)
520
+ probedLogos.push(probed);
521
+ }
522
+ const probedShots = [];
523
+ for (const [i, shot] of uniqueShots.entries()) {
524
+ probedShots.push(i < PROBED_SCREENSHOTS ? await probe(shot) : shot);
525
+ }
526
+ const candidates = mergeRecordCandidates(input.previous, { channels, logos: probedLogos, screenshots: probedShots }, failedSources);
527
+ return { candidates, failures: [...new Set(failures)], requests };
528
+ }
529
+ return { collect };
530
+ }
531
+ /** One candidate per file: same path, same URL or same blob (a copy of the file elsewhere). */
532
+ function dedupeByUrl(list) {
533
+ const seen = new Set();
534
+ const out = [];
535
+ for (const media of list) {
536
+ const keys = [media.path ?? media.url, ...(media.blobSha ? [`blob:${media.blobSha}`] : [])];
537
+ if (keys.some((key) => seen.has(key)))
538
+ continue;
539
+ for (const key of keys)
540
+ seen.add(key);
541
+ out.push(media);
542
+ }
543
+ return out;
544
+ }
545
+ //# sourceMappingURL=candidate-collector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"candidate-collector.js","sourceRoot":"","sources":["../src/candidate-collector.ts"],"names":[],"mappings":"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"}