Skip to content

Commit a027bd5

Browse files
committed
refactor: extract createCachedFetch
1 parent 2fc01e1 commit a027bd5

File tree

6 files changed

+77
-76
lines changed

6 files changed

+77
-76
lines changed

src/constants.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,4 @@ export const PNPM_WORKSPACE_PATTERN = `**/${PNPM_WORKSPACE_BASENAME}`
66

77
export const VERSION_TRIGGER_CHARACTERS = ['.', '^', '~', ...Array.from({ length: 10 }).map((_, i) => `${i}`)]
88

9-
export const NPM_REGISTRY = 'https://registry.npmjs.org'
10-
export const NPMX_DEV_API = 'https://npmx.dev/api'
9+
export const CACHE_TTL_ONE_DAY = 1000 * 60 * 60 * 24

src/providers/diagnostics/rules/replacement.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { ModuleReplacement } from 'module-replacements'
22
import type { DiagnosticRule } from '..'
3-
import { getReplacement } from '#utils/replacement'
3+
import { getReplacement } from '#utils/npmx'
44
import { DiagnosticSeverity } from 'vscode'
55

66
// https://github.com/npmx-dev/npmx.dev/blob/main/app/components/PackageReplacement.vue#L8-L30

src/utils/cache.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { CACHE_TTL_ONE_DAY } from '#constants'
2+
import { logger } from '#state'
3+
import { LRUCache } from 'lru-cache'
4+
5+
export function createCachedFetch<T extends object>(
6+
key: string,
7+
fetchMethod: (name: string, staleValue: T | undefined, options: LRUCache.FetcherOptions<string, T, unknown>) => Promise<T | undefined>,
8+
) {
9+
const cache = new LRUCache<string, T>({
10+
max: 500,
11+
ttl: CACHE_TTL_ONE_DAY,
12+
updateAgeOnGet: true,
13+
allowStale: true,
14+
fetchMethod: async (name, staleValue, options) => {
15+
try {
16+
logger.info(`[${name}]: fetching ${key}...`)
17+
const r = await fetchMethod(name, staleValue, options)
18+
logger.info(`[${name}] fetching ${key} done!`)
19+
return r
20+
} catch (err) {
21+
logger.warn(`[${name}] fetching ${key} error: `, err)
22+
}
23+
},
24+
})
25+
26+
return async function getCache(name: string) {
27+
return (await cache.fetch(name))!
28+
}
29+
}

src/utils/npm.ts

Lines changed: 29 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import type { Packument, PackumentVersion } from '@npm/types'
2-
import { NPM_REGISTRY } from '#constants'
3-
import { logger } from '#state'
4-
import { LRUCache } from 'lru-cache'
52
import { ofetch } from 'ofetch'
3+
import { createCachedFetch } from './cache'
4+
5+
const NPM_REGISTRY = 'https://registry.npmjs.org'
66

77
interface ResolvedPackumentVersion extends Pick<PackumentVersion, 'version'> {
88
tag?: string
@@ -25,46 +25,33 @@ export function encodePackageName(name: string): string {
2525
return encodeURIComponent(name)
2626
}
2727

28-
const cache = new LRUCache<string, ResolvedPackument>({
29-
max: 500,
30-
ttl: 5 * 60 * 1000,
31-
updateAgeOnGet: true,
32-
allowStale: true,
33-
fetchMethod: async (name, staleValue, { signal }) => {
28+
export const getPackageInfo = createCachedFetch<ResolvedPackument>(
29+
'package info',
30+
async (name, staleValue, { signal }) => {
3431
const encodedName = encodePackageName(name)
3532

36-
try {
37-
logger.info(`[${name}] fetching package info...`)
38-
const pkg = await ofetch<Packument>(`${NPM_REGISTRY}/${encodedName}`, { signal })
39-
logger.info(`[${name}] fetching package info done!`)
40-
41-
const resolvedVersions = Object.fromEntries(
42-
Object.keys(pkg.versions)
43-
.filter((v) => pkg.time[v])
44-
.map<[string, ResolvedPackumentVersion]>((v) => [
45-
v,
46-
{
47-
version: v,
48-
// @ts-expect-error present if published with provenance
49-
hasProvenance: !!pkg.versions[v].dist.attestations,
50-
deprecated: pkg.versions[v].deprecated,
51-
},
52-
]),
53-
)
54-
55-
Object.entries(pkg['dist-tags']).forEach(([tag, version]) => {
56-
resolvedVersions[version].tag = tag
57-
})
58-
59-
return {
60-
versions: resolvedVersions,
61-
}
62-
} catch (err) {
63-
logger.warn(`[${name}] fetching package info error: `, err)
33+
const pkg = await ofetch<Packument>(`${NPM_REGISTRY}/${encodedName}`, { signal })
34+
35+
const resolvedVersions = Object.fromEntries(
36+
Object.keys(pkg.versions)
37+
.filter((v) => pkg.time[v])
38+
.map<[string, ResolvedPackumentVersion]>((v) => [
39+
v,
40+
{
41+
version: v,
42+
// @ts-expect-error present if published with provenance
43+
hasProvenance: !!pkg.versions[v].dist.attestations,
44+
deprecated: pkg.versions[v].deprecated,
45+
},
46+
]),
47+
)
48+
49+
Object.entries(pkg['dist-tags']).forEach(([tag, version]) => {
50+
resolvedVersions[version].tag = tag
51+
})
52+
53+
return {
54+
versions: resolvedVersions,
6455
}
6556
},
66-
})
67-
68-
export async function getPackageInfo(name: string) {
69-
return (await cache.fetch(name))!
70-
}
57+
)

src/utils/npmx.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import type { ModuleReplacement } from 'module-replacements'
2+
import { ofetch } from 'ofetch'
3+
import { createCachedFetch } from './cache'
4+
import { encodePackageName } from './npm'
5+
6+
export const NPMX_DEV_API = 'https://npmx.dev/api'
7+
8+
export const getReplacement = createCachedFetch<ModuleReplacement>(
9+
'replacement',
10+
(name, staleValue, { signal }) => {
11+
const encodedName = encodePackageName(name)
12+
13+
return ofetch<ModuleReplacement>(`${NPMX_DEV_API}/replacements/${encodedName}`, { signal })
14+
// Fallback for cache compatibility (LRUCache rejects null/undefined)
15+
?? {}
16+
},
17+
)

src/utils/replacement.ts

Lines changed: 0 additions & 31 deletions
This file was deleted.

0 commit comments

Comments
 (0)