[READ-ONLY] a fast, modern browser for the npm registry
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

perf: abort deduped async data handlers (#538)

authored by

Robin and committed by
GitHub
95749a4a 1975cb76

+42 -49
+4 -12
app/composables/useCachedFetch.ts
··· 34 34 if (import.meta.client) { 35 35 return async <T = unknown>( 36 36 url: string, 37 - options: { 38 - method?: string 39 - body?: unknown 40 - headers?: Record<string, string> 41 - } = {}, 37 + options: Parameters<typeof $fetch>[1] = {}, 42 38 _ttl?: number, 43 39 ): Promise<CachedFetchResult<T>> => { 44 - const data = (await $fetch(url, options as Parameters<typeof $fetch>[1])) as T 40 + const data = (await $fetch<T>(url, options)) as T 45 41 return { data, isStale: false, cachedAt: null } 46 42 } 47 43 } ··· 59 55 // (shouldn't happen in normal operation) 60 56 return async <T = unknown>( 61 57 url: string, 62 - options: { 63 - method?: string 64 - body?: unknown 65 - headers?: Record<string, string> 66 - } = {}, 58 + options: Parameters<typeof $fetch>[1] = {}, 67 59 _ttl?: number, 68 60 ): Promise<CachedFetchResult<T>> => { 69 - const data = (await $fetch(url, options as Parameters<typeof $fetch>[1])) as T 61 + const data = (await $fetch<T>(url, options)) as T 70 62 return { data, isStale: false, cachedAt: null } 71 63 } 72 64 }
+11 -6
app/composables/useNpmRegistry.ts
··· 185 185 186 186 const asyncData = useLazyAsyncData( 187 187 () => `package:${toValue(name)}:${toValue(requestedVersion) ?? ''}`, 188 - async () => { 188 + async (_nuxtApp, { signal }) => { 189 189 const encodedName = encodePackageName(toValue(name)) 190 - const { data: r, isStale } = await cachedFetch<Packument>(`${NPM_REGISTRY}/${encodedName}`) 190 + const { data: r, isStale } = await cachedFetch<Packument>(`${NPM_REGISTRY}/${encodedName}`, { 191 + signal, 192 + }) 191 193 const reqVer = toValue(requestedVersion) 192 194 const pkg = transformPackument(r, reqVer) 193 195 const resolvedVersion = getResolvedVersion(pkg, reqVer) ··· 233 235 234 236 const asyncData = useLazyAsyncData( 235 237 () => `downloads:${toValue(name)}:${toValue(period)}`, 236 - async () => { 238 + async (_nuxtApp, { signal }) => { 237 239 const encodedName = encodePackageName(toValue(name)) 238 240 const { data, isStale } = await cachedFetch<NpmDownloadCount>( 239 241 `${NPM_API}/downloads/point/${toValue(period)}/${encodedName}`, 242 + { signal }, 240 243 ) 241 244 return { ...data, isStale } 242 245 }, ··· 306 309 307 310 const asyncData = useLazyAsyncData( 308 311 () => `search:incremental:${toValue(query)}`, 309 - async () => { 312 + async (_nuxtApp, { signal }) => { 310 313 const q = toValue(query) 311 314 if (!q.trim()) { 312 315 return emptySearchResponse ··· 325 328 326 329 const { data: response, isStale } = await cachedFetch<NpmSearchResponse>( 327 330 `${NPM_REGISTRY}/-/v1/search?${params.toString()}`, 328 - {}, 331 + { signal }, 329 332 60, 330 333 ) 331 334 ··· 509 512 510 513 const asyncData = useLazyAsyncData( 511 514 () => `org-packages:${toValue(orgName)}`, 512 - async () => { 515 + async (_nuxtApp, { signal }) => { 513 516 const org = toValue(orgName) 514 517 if (!org) { 515 518 return emptySearchResponse ··· 520 523 try { 521 524 const { data } = await cachedFetch<Record<string, string>>( 522 525 `${NPM_REGISTRY}/-/org/${encodeURIComponent(org)}/package`, 526 + { signal }, 523 527 ) 524 528 packageNames = Object.keys(data) 525 529 } catch (err) { ··· 553 557 const encoded = encodePackageName(name) 554 558 const { data: pkg } = await cachedFetch<MinimalPackument>( 555 559 `${NPM_REGISTRY}/${encoded}`, 560 + { signal }, 556 561 ) 557 562 return pkg 558 563 } catch {
+24 -20
app/composables/useRepoMeta.ts
··· 93 93 cachedFetch: CachedFetchFunction, 94 94 ref: RepoRef, 95 95 links: RepoMetaLinks, 96 + options?: Parameters<typeof $fetch>[1], 96 97 ): Promise<RepoMeta | null> 97 98 } 98 99 ··· 126 127 } 127 128 }, 128 129 129 - async fetchMeta(cachedFetch, ref, links) { 130 + async fetchMeta(cachedFetch, ref, links, options = {}) { 130 131 // Using UNGH to avoid API limitations of the Github API 131 132 let res: UnghRepoResponse | null = null 132 133 try { 133 134 const { data } = await cachedFetch<UnghRepoResponse>( 134 135 `https://ungh.cc/repos/${ref.owner}/${ref.repo}`, 135 - { headers: { 'User-Agent': 'npmx' } }, 136 + { headers: { 'User-Agent': 'npmx', ...options.headers }, ...options }, 136 137 REPO_META_TTL, 137 138 ) 138 139 res = data ··· 191 192 } 192 193 }, 193 194 194 - async fetchMeta(cachedFetch, ref, links) { 195 + async fetchMeta(cachedFetch, ref, links, options = {}) { 195 196 const baseHost = ref.host ?? 'gitlab.com' 196 197 const projectPath = encodeURIComponent(`${ref.owner}/${ref.repo}`) 197 198 let res: GitLabProjectResponse | null = null 198 199 try { 199 200 const { data } = await cachedFetch<GitLabProjectResponse>( 200 201 `https://${baseHost}/api/v4/projects/${projectPath}`, 201 - { headers: { 'User-Agent': 'npmx' } }, 202 + { headers: { 'User-Agent': 'npmx', ...options.headers }, ...options }, 202 203 REPO_META_TTL, 203 204 ) 204 205 res = data ··· 249 250 } 250 251 }, 251 252 252 - async fetchMeta(cachedFetch, ref, links) { 253 + async fetchMeta(cachedFetch, ref, links, options = {}) { 253 254 let res: BitbucketRepoResponse | null = null 254 255 try { 255 256 const { data } = await cachedFetch<BitbucketRepoResponse>( 256 257 `https://api.bitbucket.org/2.0/repositories/${ref.owner}/${ref.repo}`, 257 - { headers: { 'User-Agent': 'npmx' } }, 258 + { headers: { 'User-Agent': 'npmx', ...options.headers }, ...options }, 258 259 REPO_META_TTL, 259 260 ) 260 261 res = data ··· 307 308 } 308 309 }, 309 310 310 - async fetchMeta(cachedFetch, ref, links) { 311 + async fetchMeta(cachedFetch, ref, links, options = {}) { 311 312 let res: GiteaRepoResponse | null = null 312 313 try { 313 314 const { data } = await cachedFetch<GiteaRepoResponse>( 314 315 `https://codeberg.org/api/v1/repos/${ref.owner}/${ref.repo}`, 315 - { headers: { 'User-Agent': 'npmx' } }, 316 + { headers: { 'User-Agent': 'npmx', ...options.headers }, ...options }, 316 317 REPO_META_TTL, 317 318 ) 318 319 res = data ··· 365 366 } 366 367 }, 367 368 368 - async fetchMeta(cachedFetch, ref, links) { 369 + async fetchMeta(cachedFetch, ref, links, options = {}) { 369 370 let res: GiteeRepoResponse | null = null 370 371 try { 371 372 const { data } = await cachedFetch<GiteeRepoResponse>( 372 373 `https://gitee.com/api/v5/repos/${ref.owner}/${ref.repo}`, 373 - { headers: { 'User-Agent': 'npmx' } }, 374 + { headers: { 'User-Agent': 'npmx', ...options.headers }, ...options }, 374 375 REPO_META_TTL, 375 376 ) 376 377 res = data ··· 452 453 } 453 454 }, 454 455 455 - async fetchMeta(cachedFetch, ref, links) { 456 + async fetchMeta(cachedFetch, ref, links, options = {}) { 456 457 if (!ref.host) return null 457 458 458 459 // Note: Generic Gitea instances may not be in the allowlist, ··· 461 462 try { 462 463 const { data } = await cachedFetch<GiteaRepoResponse>( 463 464 `https://${ref.host}/api/v1/repos/${ref.owner}/${ref.repo}`, 464 - { headers: { 'User-Agent': 'npmx' } }, 465 + { headers: { 'User-Agent': 'npmx', ...options.headers }, ...options }, 465 466 REPO_META_TTL, 466 467 ) 467 468 res = data ··· 564 565 } 565 566 }, 566 567 567 - async fetchMeta(cachedFetch, ref, links) { 568 + async fetchMeta(cachedFetch, ref, links, options = {}) { 568 569 // Tangled doesn't have a public JSON API, but we can scrape the star count 569 570 // from the HTML page (it's in the hx-post URL as countHint=N) 570 571 try { 571 572 const { data: html } = await cachedFetch<string>( 572 573 `https://tangled.org/${ref.owner}/${ref.repo}`, 573 - { headers: { 'User-Agent': 'npmx', 'Accept': 'text/html' } }, 574 + { 575 + headers: { 'User-Agent': 'npmx', 'Accept': 'text/html', ...options.headers }, 576 + ...options, 577 + }, 574 578 REPO_META_TTL, 575 579 ) 576 580 // Extracts the at-uri used in atproto ··· 640 644 } 641 645 }, 642 646 643 - async fetchMeta(cachedFetch, ref, links) { 647 + async fetchMeta(cachedFetch, ref, links, options = {}) { 644 648 let res: RadicleProjectResponse | null = null 645 649 try { 646 650 const { data } = await cachedFetch<RadicleProjectResponse>( 647 651 `https://seed.radicle.at/api/v1/projects/${ref.repo}`, 648 - { headers: { 'User-Agent': 'npmx' } }, 652 + { headers: { 'User-Agent': 'npmx', ...options.headers }, ...options }, 649 653 REPO_META_TTL, 650 654 ) 651 655 res = data ··· 704 708 } 705 709 }, 706 710 707 - async fetchMeta(cachedFetch, ref, links) { 711 + async fetchMeta(cachedFetch, ref, links, options = {}) { 708 712 if (!ref.host) return null 709 713 710 714 let res: GiteaRepoResponse | null = null 711 715 try { 712 716 const { data } = await cachedFetch<GiteaRepoResponse>( 713 717 `https://${ref.host}/api/v1/repos/${ref.owner}/${ref.repo}`, 714 - { headers: { 'User-Agent': 'npmx' } }, 718 + { headers: { 'User-Agent': 'npmx', ...options.headers }, ...options }, 715 719 REPO_META_TTL, 716 720 ) 717 721 res = data ··· 766 770 repoRef.value 767 771 ? `repo-meta:${repoRef.value.provider}:${repoRef.value.owner}/${repoRef.value.repo}` 768 772 : 'repo-meta:none', 769 - async () => { 773 + async (_nuxtApp, { signal }) => { 770 774 const ref = repoRef.value 771 775 if (!ref) return null 772 776 ··· 774 778 if (!adapter) return null 775 779 776 780 const links = adapter.links(ref) 777 - return await adapter.fetchMeta(cachedFetch, ref, links) 781 + return await adapter.fetchMeta(cachedFetch, ref, links, { signal }) 778 782 }, 779 783 ) 780 784
+2 -6
server/plugins/fetch-cache.ts
··· 60 60 function createCachedFetch(event: H3Event): CachedFetchFunction { 61 61 return async <T = unknown>( 62 62 url: string, 63 - options: { 64 - method?: string 65 - body?: unknown 66 - headers?: Record<string, string> 67 - } = {}, 63 + options: Parameters<typeof $fetch>[1] = {}, 68 64 ttl: number = FETCH_CACHE_DEFAULT_TTL, 69 65 ): Promise<CachedFetchResult<T>> => { 70 66 // Check if this URL should be cached 71 67 if (!isAllowedDomain(url)) { 72 - const data = (await $fetch(url, options as Parameters<typeof $fetch>[1])) as T 68 + const data = (await $fetch(url, options)) as T 73 69 return { data, isStale: false, cachedAt: null } 74 70 } 75 71
+1 -5
shared/utils/fetch-cache-config.ts
··· 105 105 */ 106 106 export type CachedFetchFunction = <T = unknown>( 107 107 url: string, 108 - options?: { 109 - method?: string 110 - body?: unknown 111 - headers?: Record<string, string> 112 - }, 108 + options?: Parameters<typeof $fetch>[1], 113 109 ttl?: number, 114 110 ) => Promise<CachedFetchResult<T>>