Skip to content

Commit 3cdf6b6

Browse files
authored
fix npm cache collision (#1176)
1 parent e6e4774 commit 3cdf6b6

File tree

1 file changed

+12
-7
lines changed

1 file changed

+12
-7
lines changed

src/npm.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export async function populateNpmCache(root: string, path: string): Promise<stri
7777
if (!path.startsWith("/_npm/")) throw new Error(`invalid npm path: ${path}`);
7878
const filePath = join(root, ".observablehq", "cache", path);
7979
if (existsSync(filePath)) return filePath;
80-
let promise = npmRequests.get(path);
80+
let promise = npmRequests.get(filePath);
8181
if (promise) return promise; // coalesce concurrent requests
8282
promise = (async function () {
8383
const specifier = extractNpmSpecifier(path);
@@ -96,8 +96,8 @@ export async function populateNpmCache(root: string, path: string): Promise<stri
9696
}
9797
return filePath;
9898
})();
99-
promise.catch(() => {}).then(() => npmRequests.delete(path));
100-
npmRequests.set(path, promise);
99+
promise.catch(() => {}).then(() => npmRequests.delete(filePath));
100+
npmRequests.set(filePath, promise);
101101
return promise;
102102
}
103103

@@ -177,9 +177,7 @@ export async function getDependencyResolver(
177177
};
178178
}
179179

180-
let npmVersionCache: Promise<Map<string, string[]>>;
181-
182-
async function initializeNpmVersionCache(root: string): typeof npmVersionCache {
180+
async function initializeNpmVersionCache(root: string): Promise<Map<string, string[]>> {
183181
const cache = new Map<string, string[]>();
184182
const cacheDir = join(root, ".observablehq", "cache", "_npm");
185183
try {
@@ -207,12 +205,19 @@ async function initializeNpmVersionCache(root: string): typeof npmVersionCache {
207205
return cache;
208206
}
209207

208+
const npmVersionCaches = new Map<string, Promise<Map<string, string[]>>>();
210209
const npmVersionRequests = new Map<string, Promise<string>>();
211210

211+
function getNpmVersionCache(root: string): Promise<Map<string, string[]>> {
212+
let cache = npmVersionCaches.get(root);
213+
if (!cache) npmVersionCaches.set(root, (cache = initializeNpmVersionCache(root)));
214+
return cache;
215+
}
216+
212217
async function resolveNpmVersion(root: string, specifier: NpmSpecifier): Promise<string> {
213218
const {name, range} = specifier;
214219
if (range && /^\d+\.\d+\.\d+([-+].*)?$/.test(range)) return range; // exact version specified
215-
const cache = await (npmVersionCache ??= initializeNpmVersionCache(root));
220+
const cache = await getNpmVersionCache(root);
216221
const versions = cache.get(specifier.name);
217222
if (versions) for (const version of versions) if (!range || satisfies(version, range)) return version;
218223
const href = `https://data.jsdelivr.com/v1/packages/npm/${name}/resolved${range ? `?specifier=${range}` : ""}`;

0 commit comments

Comments
 (0)