refactor(util): load npm package parser lazily (#42467)

This commit is contained in:
Kit Langton 2026-08-13 21:48:48 -04:00 committed by GitHub
parent 9d9e57941c
commit de28ca9f0e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 45 additions and 3 deletions

View file

@ -1,7 +1,7 @@
import fs from "fs/promises"
import path from "path"
import { describe, expect, test } from "bun:test"
import { Effect, Option } from "effect"
import { Effect } from "effect"
import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
import { Global } from "@opencode-ai/util/global"
import { Npm } from "@opencode-ai/util/npm"
@ -36,6 +36,48 @@ describe("Npm.sanitize", () => {
})
describe("Npm.add", () => {
test("resolves cached scoped package specs without reifying", async () => {
await using tmp = await tmpdir()
const spec = "@fixture/provider@1.0.0"
const directory = path.join(
tmp.path,
"cache",
"packages",
Npm.sanitize(spec),
"node_modules",
"@fixture",
"provider",
)
await fs.mkdir(directory, { recursive: true })
await writePackage(directory, { name: "@fixture/provider", exports: "./index.js" })
await Bun.write(path.join(directory, "index.js"), "export const fixture = true\n")
const entry = await Effect.gen(function* () {
const npm = yield* Npm.Service
return yield* npm.add(spec)
}).pipe(Effect.scoped, Effect.provide(npmLayer(path.join(tmp.path, "cache"))), Effect.runPromise)
expect(entry.directory).toBe(directory)
expect(entry.entrypoint).toEndWith("/index.js")
})
test("falls back to the original spec when parsing fails", async () => {
await using tmp = await tmpdir()
const spec = "fixture provider"
const directory = path.join(tmp.path, "cache", "packages", Npm.sanitize(spec), "node_modules", spec)
await fs.mkdir(directory, { recursive: true })
await writePackage(directory, { name: spec, exports: "./index.js" })
await Bun.write(path.join(directory, "index.js"), "export const fixture = true\n")
const entry = await Effect.gen(function* () {
const npm = yield* Npm.Service
return yield* npm.add(spec)
}).pipe(Effect.scoped, Effect.provide(npmLayer(path.join(tmp.path, "cache"))), Effect.runPromise)
expect(entry.directory).toBe(directory)
expect(entry.entrypoint).toEndWith("/index.js")
})
test("reifies when package cache directory exists without the package installed", async () => {
await using tmp = await tmpdir()
await fs.mkdir(path.join(tmp.path, "fixture-provider"))

View file

@ -1,7 +1,6 @@
export * as Npm from "./npm.js"
import path from "path"
import npa from "npm-package-arg"
import { Effect, Schema, Context, Layer, Option, FileSystem } from "effect"
import * as NodeFileSystem from "@effect/platform-node/NodeFileSystem"
import { FSUtil } from "./fs-util.js"
@ -111,6 +110,7 @@ const layer = Layer.effect(
)
const add = Effect.fn("Npm.add")(function* (pkg: string, options?: { readonly subpaths?: readonly string[] }) {
const { default: npa } = yield* Effect.promise(() => import("npm-package-arg"))
const dir = directory(pkg)
const name = (() => {
try {

View file

@ -52,7 +52,7 @@ export default defineWorkersConfig({
// lookup surface but back it with a static shim.
{ find: /^mime-types$/, replacement: new URL("./test/shims/mime-types.mjs", import.meta.url).pathname },
// Plugin installs never happen in the workerd profile (plugin discovery
// is precompiled-only), so mock the package installation toolchain.
// is precompiled-only), so mock package installation when it is loaded.
{ find: /^@npmcli\/arborist(\/.*)?$/, replacement: mockProxy },
{ find: /^pacote(\/.*)?$/, replacement: mockProxy },
],