diff options
| author | Dax <[email protected]> | 2026-04-26 23:54:59 -0400 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-04-27 03:54:59 +0000 |
| commit | a9b62d67df08e6b984c51ead12339c845db49e93 (patch) | |
| tree | 30890d600d6cc10369e1d57f1e8972c16cfb7d90 /packages/core/test | |
| parent | 3525e619069069db10f13cc31959de879d7830eb (diff) | |
| download | opencode-a9b62d67df08e6b984c51ead12339c845db49e93.tar.gz opencode-a9b62d67df08e6b984c51ead12339c845db49e93.zip | |
Refactor npm config handling (#24565)
Diffstat (limited to 'packages/core/test')
| -rw-r--r-- | packages/core/test/fixture/tmpdir.ts | 13 | ||||
| -rw-r--r-- | packages/core/test/npm-config.test.ts | 51 | ||||
| -rw-r--r-- | packages/core/test/npm.test.ts | 56 |
3 files changed, 120 insertions, 0 deletions
diff --git a/packages/core/test/fixture/tmpdir.ts b/packages/core/test/fixture/tmpdir.ts new file mode 100644 index 000000000..950b1401b --- /dev/null +++ b/packages/core/test/fixture/tmpdir.ts @@ -0,0 +1,13 @@ +import fs from "fs/promises" +import { tmpdir as osTmpdir } from "os" +import path from "path" + +export const tmpdir = async () => { + const dir = await fs.mkdtemp(path.join(osTmpdir(), "opencode-core-test-")) + return { + path: dir, + async [Symbol.asyncDispose]() { + await fs.rm(dir, { recursive: true, force: true }) + }, + } +} diff --git a/packages/core/test/npm-config.test.ts b/packages/core/test/npm-config.test.ts new file mode 100644 index 000000000..895b35db5 --- /dev/null +++ b/packages/core/test/npm-config.test.ts @@ -0,0 +1,51 @@ +import path from "path" +import { describe, expect, test } from "bun:test" +import { Effect } from "effect" +import { NpmConfig } from "@opencode-ai/core/npm-config" +import { tmpdir } from "./fixture/tmpdir" + +describe("NpmConfig.load", () => { + test("reads registry from project .npmrc", async () => { + await using tmp = await tmpdir() + await Bun.write(path.join(tmp.path, ".npmrc"), "registry=https://registry.example.test/\n") + + const config = await Effect.runPromise(NpmConfig.load(tmp.path)) + + expect(config.registry).toBe("https://registry.example.test/") + }) + + test("reads scoped registries from project .npmrc", async () => { + await using tmp = await tmpdir() + await Bun.write(path.join(tmp.path, ".npmrc"), "@acme:registry=https://npm.acme.test/\n") + + const config = await Effect.runPromise(NpmConfig.load(tmp.path)) + + expect(config["@acme:registry"]).toBe("https://npm.acme.test/") + }) + + test("flattens boolean and list options", async () => { + await using tmp = await tmpdir() + await Bun.write(path.join(tmp.path, ".npmrc"), "ignore-scripts=true\nomit[]=dev\nomit[]=optional\n") + + const config = await Effect.runPromise(NpmConfig.load(tmp.path)) + + expect(config.ignoreScripts).toBe(true) + expect(config.omit).toEqual(["dev", "optional"]) + }) +}) + +describe("NpmConfig.registry", () => { + test("normalizes configured registry without trailing slash", async () => { + await using tmp = await tmpdir() + await Bun.write(path.join(tmp.path, ".npmrc"), "registry=https://registry.example.test/\n") + + await expect(Effect.runPromise(NpmConfig.registry(tmp.path))).resolves.toBe("https://registry.example.test") + }) + + test("leaves configured registry without trailing slash unchanged", async () => { + await using tmp = await tmpdir() + await Bun.write(path.join(tmp.path, ".npmrc"), "registry=https://registry.example.test\n") + + await expect(Effect.runPromise(NpmConfig.registry(tmp.path))).resolves.toBe("https://registry.example.test") + }) +}) diff --git a/packages/core/test/npm.test.ts b/packages/core/test/npm.test.ts new file mode 100644 index 000000000..3e94a0869 --- /dev/null +++ b/packages/core/test/npm.test.ts @@ -0,0 +1,56 @@ +import fs from "fs/promises" +import path from "path" +import { describe, expect, test } from "bun:test" +import { Npm } from "@opencode-ai/core/npm" +import { tmpdir } from "./fixture/tmpdir" + +const win = process.platform === "win32" + +const writePackage = (dir: string, pkg: Record<string, unknown>) => + Bun.write( + path.join(dir, "package.json"), + JSON.stringify({ + version: "1.0.0", + ...pkg, + }), + ) + +describe("Npm.sanitize", () => { + test("keeps normal scoped package specs unchanged", () => { + expect(Npm.sanitize("@opencode/acme")).toBe("@opencode/acme") + expect(Npm.sanitize("@opencode/[email protected]")).toBe("@opencode/[email protected]") + expect(Npm.sanitize("prettier")).toBe("prettier") + }) + + test("handles git https specs", () => { + const spec = "acme@git+https://github.com/opencode/acme.git" + const expected = win ? "acme@git+https_//github.com/opencode/acme.git" : spec + expect(Npm.sanitize(spec)).toBe(expected) + }) +}) + +describe("Npm.install", () => { + test("respects omit from project .npmrc", async () => { + await using tmp = await tmpdir() + + await writePackage(tmp.path, { + name: "fixture", + dependencies: { + "prod-pkg": "file:./prod-pkg", + }, + devDependencies: { + "dev-pkg": "file:./dev-pkg", + }, + }) + await Bun.write(path.join(tmp.path, ".npmrc"), "omit=dev\n") + await fs.mkdir(path.join(tmp.path, "prod-pkg")) + await fs.mkdir(path.join(tmp.path, "dev-pkg")) + await writePackage(path.join(tmp.path, "prod-pkg"), { name: "prod-pkg" }) + await writePackage(path.join(tmp.path, "dev-pkg"), { name: "dev-pkg" }) + + await Npm.install(tmp.path) + + await expect(fs.stat(path.join(tmp.path, "node_modules", "prod-pkg"))).resolves.toBeDefined() + await expect(fs.stat(path.join(tmp.path, "node_modules", "dev-pkg"))).rejects.toThrow() + }) +}) |
