diff --git a/src/node.ts b/src/node.ts index 2573f84fd..b155d98c2 100644 --- a/src/node.ts +++ b/src/node.ts @@ -44,7 +44,7 @@ async function resolveNodeImportInternal(cacheRoot: string, packageRoot: string, } })(); bundlePromises.set(outputPath, promise); - promise.catch(() => {}).then(() => bundlePromises.delete(outputPath)); + promise.catch(console.error).then(() => bundlePromises.delete(outputPath)); } await promise; } diff --git a/src/npm.ts b/src/npm.ts index 5bf49881f..ba309411a 100644 --- a/src/npm.ts +++ b/src/npm.ts @@ -237,7 +237,7 @@ async function resolveNpmVersion(root: string, specifier: NpmSpecifier): Promise mkdir(join(root, ".observablehq", "cache", "_npm", spec), {recursive: true}); // disk cache return version; })(); - promise.catch(() => {}).then(() => npmVersionRequests.delete(href)); + promise.catch(console.error).then(() => npmVersionRequests.delete(href)); npmVersionRequests.set(href, promise); return promise; } diff --git a/src/resolvers.ts b/src/resolvers.ts index db4b77340..cab5bef5b 100644 --- a/src/resolvers.ts +++ b/src/resolvers.ts @@ -327,6 +327,8 @@ export function getModuleResolver(root: string, path: string): (specifier: strin ? relativePath(servePath, `/_observablehq/${specifier.slice("observablehq:".length)}${extname(specifier) ? "" : ".js"}`) // prettier-ignore : specifier.startsWith("npm:") ? relativePath(servePath, await resolveNpmImport(root, specifier.slice("npm:".length))) + : !/^\w+:/.test(specifier) + ? relativePath(servePath, await resolveNodeImport(root, specifier)) : specifier; }; } diff --git a/test/javascript/transpile-test.ts b/test/javascript/transpile-test.ts index c898d11c8..70d6118c1 100644 --- a/test/javascript/transpile-test.ts +++ b/test/javascript/transpile-test.ts @@ -6,6 +6,7 @@ import {isEnoent} from "../../src/error.js"; import {parseJavaScript} from "../../src/javascript/parse.js"; import type {TranspileModuleOptions} from "../../src/javascript/transpile.js"; import {transpileJavaScript, transpileModule} from "../../src/javascript/transpile.js"; +import {mockJsDelivr} from "../mocks/jsdelivr.js"; function isJsFile(inputRoot: string, fileName: string) { if (!fileName.endsWith(".js")) return false; @@ -106,6 +107,7 @@ describe("transpileModule(input, root, path, sourcePath)", () => { }); describe("transpileModule(input, root, path)", () => { + mockJsDelivr(); const options: TranspileModuleOptions = {root: "docs", path: "test.js"}; it("rewrites relative files with import.meta.resolve", async () => { assert.strictEqual(await testFile("./test.txt", "test.js"), 'FileAttachment("../test.txt", import.meta.url)'); // prettier-ignore @@ -139,7 +141,7 @@ describe("transpileModule(input, root, path)", () => { assert.strictEqual(output, '(1, FileAttachment)("./test.txt")'); }); it("ignores FileAttachment if not imported from @observablehq/stdlib", async () => { - const input = 'import {FileAttachment} from "@observablehq/not-stdlib";\nFileAttachment("./test.txt")'; + const input = 'import {FileAttachment} from "npm:@observablehq/inputs";\nFileAttachment("./test.txt")'; const output = (await transpileModule(input, options)).split("\n").pop()!; assert.strictEqual(output, 'FileAttachment("./test.txt")'); }); @@ -191,4 +193,14 @@ describe("transpileModule(input, root, path)", () => { await assert.rejects(() => transpileModule(input3, {...options, path: "sub/test.js"}), /non-local file path/); // prettier-ignore await assert.rejects(() => transpileModule(input4, {...options, path: "sub/test.js"}), /non-local file path/); // prettier-ignore }); + it("rewrites npm imports", async () => { + const input = 'import "npm:d3-array";'; + const output = (await transpileModule(input, options)).split("\n").pop()!; + assert.strictEqual(output, 'import "../_npm/d3-array@3.2.4/_esm.js";'); + }); + it("rewrites node imports", async () => { + const input = 'import "d3-array";'; + const output = (await transpileModule(input, options)).split("\n").pop()!; + assert.strictEqual(output, 'import "../_node/d3-array@3.2.4/index.js";'); + }); });