From 5f6198059fa72359a8b1f9895952f04c7616ff76 Mon Sep 17 00:00:00 2001 From: Conner Bachmann Date: Fri, 24 Feb 2023 11:08:06 +0100 Subject: [PATCH 1/3] feat!: add yarn berry support --- src/api.ts | 10 +++++----- src/detect.ts | 34 ++++++++++++++++++---------------- src/types.ts | 9 ++++++++- test/index.test.ts | 2 +- 4 files changed, 32 insertions(+), 23 deletions(-) diff --git a/src/api.ts b/src/api.ts index df6622c..62a47d8 100644 --- a/src/api.ts +++ b/src/api.ts @@ -1,19 +1,19 @@ import { detectPackageManager } from "./detect"; import { runCorepack } from "./spawn"; -import { PackageManagerName } from "./types"; +import { PackageManager } from "./types"; export interface APICallOptions { cwd: string; - packageManager: PackageManagerName; + packageManager: PackageManager; silent: boolean; } export interface AddDependencyOptions extends Partial { dev?: boolean; } export async function addDependency (name: string, _options: AddDependencyOptions = {}) { const options = await _resolveOptions(_options); - const command = options.packageManager === "npm" ? "install" : "add"; + const command = options.packageManager.name === "npm" ? "install" : "add"; const argv = [options.dev ? "-D" : ""].filter(Boolean); - await runCorepack(options.packageManager, [command, ...argv, name], { cwd: options.cwd, silent: options.silent }); + await runCorepack(options.packageManager.command, [command, ...argv, name], { cwd: options.cwd, silent: options.silent }); return {}; } @@ -22,7 +22,7 @@ async function _resolveOptions (options: Partial = options.silent = options.silent ?? (process.env.NODE_ENV === "test"); if (!options.packageManager) { const detected = await detectPackageManager(options.cwd); - options.packageManager = detected?.name || "npm"; + options.packageManager = detected; } return options as T; } diff --git a/src/detect.ts b/src/detect.ts index e18a80b..7e04bbc 100644 --- a/src/detect.ts +++ b/src/detect.ts @@ -1,20 +1,21 @@ import { existsSync } from "node:fs"; import { readFile } from "node:fs/promises"; import { join, normalize } from "pathe"; -import type { PackageManagerName } from "./types"; +import type { PackageManager } from "./types"; -const packageManagerLocks: Record = { - "yarn.lock": "yarn", - "package-lock.json": "npm", - "pnpm-lock.yaml": "pnpm" -}; +const packageManagers: PackageManager[] = [ + { name: "npm", command: "npm", lockFile: "package-lock.json" }, + { name: "yarn", command: "yarn", lockFile: "yarn.lock" }, + { name: "pnpm", command: "pnpm", lockFile: "pnpm-lock.yaml" }, + { name: "yarn@berry", command: "yarn" }, +] export interface DetectPackageManagerOptions { ignoreLockFile?: boolean; ignorePackageJSON?: boolean; } -export async function detectPackageManager (cwd: string, options: DetectPackageManagerOptions = {}): Promise<{ name: PackageManagerName, version?: string }> { +export async function detectPackageManager (cwd: string, options: DetectPackageManagerOptions = {}): Promise { const detected = await findup(cwd, async (path) => { if (!options.ignorePackageJSON) { const packageJSONPath = join(path, "package.json"); @@ -22,23 +23,24 @@ export async function detectPackageManager (cwd: string, options: DetectPackageM const packageJSON = JSON.parse(await readFile(packageJSONPath, "utf8")); if (packageJSON?.packageManager) { const [name, version] = packageJSON.packageManager.split("@"); - return { name, version }; + const packageManager = packageManagers.find((pm) => pm.name === name); + + if (name.startsWith("yarn") && Number.parseInt(version) > 1) { + return packageManagers.find((pm) => pm.name === "yarn@berry"); + } + return packageManager; } } } if (!options.ignoreLockFile) { - for (const lockFile in packageManagerLocks) { - if (existsSync(join(path, lockFile))) { - return { name: packageManagerLocks[lockFile] }; + for (const packageManager of packageManagers) { + if (packageManager.lockFile && existsSync(join(path, packageManager.lockFile))) { + return { name: packageManager.name }; } } } }); - return { - name: "npm", - version: "latest", // TODO - ...detected - }; + return { ...packageManagers.find((pm) => pm.name === detected?.name) || packageManagers[0], version: "latest" }; // TODO: better version detection } async function findup (cwd: string, match: (path: string) => T | Promise): Promise { diff --git a/src/types.ts b/src/types.ts index 479ba7c..836731e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1 +1,8 @@ -export type PackageManagerName = "npm" | "yarn" | "pnpm" +export type PackageManagerName = "npm" | "yarn" | "pnpm" | "yarn@berry"; + +export interface PackageManager { + name: PackageManagerName; + command: string; + lockFile?: string; + version?: string; +} diff --git a/test/index.test.ts b/test/index.test.ts index f097e7a..8024b80 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -21,7 +21,7 @@ describe("detectPackageManager", () => { it("should return default", async () => { const fixtureDirectory = resolveFixtureDirectory("default"); const detected = await detectPackageManager(fixtureDirectory, { ignoreLockFile: true, ignorePackageJSON: true }); - expect(detected).toMatchObject({ name: "npm", version: expect.any(String) }); + expect(detected).toMatchObject({ name: 'npm', command: 'npm', lockFile: 'package-lock.json', version: expect.any(String) }); }); }); From 6120ab62ad20228fbe2d61df0f232bcd3450ae25 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 29 Mar 2023 13:13:43 +0200 Subject: [PATCH 2/3] improve multi version handling and extend fixture --- src/detect.ts | 70 ++++++++++++++----- src/types.ts | 12 ++-- test/fixtures/npm/package-lock.json | 28 ++++---- test/fixtures/npm/package.json | 4 +- test/fixtures/pnpm/package.json | 2 +- test/fixtures/pnpm/pnpm-lock.yaml | 18 ++--- .../{yarn => yarn-berry}/package.json | 4 +- test/fixtures/yarn-berry/yarn.lock | 13 ++++ test/fixtures/yarn-classic/package.json | 12 ++++ test/fixtures/yarn-classic/yarn.lock | 13 ++++ test/fixtures/yarn/yarn.lock | 13 ---- test/index.test.ts | 62 +++++++++++----- 12 files changed, 171 insertions(+), 80 deletions(-) rename test/fixtures/{yarn => yarn-berry}/package.json (79%) create mode 100644 test/fixtures/yarn-berry/yarn.lock create mode 100644 test/fixtures/yarn-classic/package.json create mode 100644 test/fixtures/yarn-classic/yarn.lock delete mode 100644 test/fixtures/yarn/yarn.lock diff --git a/src/detect.ts b/src/detect.ts index 7e04bbc..a9f04a9 100644 --- a/src/detect.ts +++ b/src/detect.ts @@ -1,49 +1,87 @@ import { existsSync } from "node:fs"; import { readFile } from "node:fs/promises"; +import { resolve } from "node:path"; import { join, normalize } from "pathe"; import type { PackageManager } from "./types"; const packageManagers: PackageManager[] = [ { name: "npm", command: "npm", lockFile: "package-lock.json" }, - { name: "yarn", command: "yarn", lockFile: "yarn.lock" }, - { name: "pnpm", command: "pnpm", lockFile: "pnpm-lock.yaml" }, - { name: "yarn@berry", command: "yarn" }, -] + { + name: "pnpm", + command: "pnpm", + lockFile: "pnpm-lock.yaml", + files: ["pnpm-workspace.yaml"], + }, + { + name: "yarn", + command: "yarn", + majorVersion: "1.0.0", + lockFile: "yarn.lock", + }, + { + name: "yarn", + command: "yarn", + majorVersion: "2.0.0", + lockFile: "yarn.lock", + files: [".yarnrc.yml"], + }, +]; export interface DetectPackageManagerOptions { ignoreLockFile?: boolean; ignorePackageJSON?: boolean; } -export async function detectPackageManager (cwd: string, options: DetectPackageManagerOptions = {}): Promise { +export async function detectPackageManager( + cwd: string, + options: DetectPackageManagerOptions = {} +): Promise { const detected = await findup(cwd, async (path) => { + // 1. Use `packageManager` field from package.json if (!options.ignorePackageJSON) { const packageJSONPath = join(path, "package.json"); if (existsSync(packageJSONPath)) { const packageJSON = JSON.parse(await readFile(packageJSONPath, "utf8")); if (packageJSON?.packageManager) { - const [name, version] = packageJSON.packageManager.split("@"); - const packageManager = packageManagers.find((pm) => pm.name === name); - - if (name.startsWith("yarn") && Number.parseInt(version) > 1) { - return packageManagers.find((pm) => pm.name === "yarn@berry"); - } - return packageManager; + const [name, version = "0.0.0"] = + packageJSON.packageManager.split("@"); + const majorVersion = version.split(".")[0]; + const packageManager = + packageManagers.find( + (pm) => pm.name === name && pm.majorVersion === majorVersion + ) || packageManagers.find((pm) => pm.name === name); + return { + ...packageManager, + name, + command: name, + version, + majorVersion, + }; } } } + // 2. Use implicit file detection if (!options.ignoreLockFile) { for (const packageManager of packageManagers) { - if (packageManager.lockFile && existsSync(join(path, packageManager.lockFile))) { - return { name: packageManager.name }; + const detectionsFiles = [ + packageManager.lockFile, + ...(packageManager.files || []), + ].filter(Boolean) as string[]; + if (detectionsFiles.some((file) => existsSync(resolve(path, file)))) { + return { + ...packageManager, + }; } } } }); - return { ...packageManagers.find((pm) => pm.name === detected?.name) || packageManagers[0], version: "latest" }; // TODO: better version detection + return detected; } -async function findup (cwd: string, match: (path: string) => T | Promise): Promise { +async function findup( + cwd: string, + match: (path: string) => T | Promise +): Promise { const segments = normalize(cwd).split("/"); while (segments.length > 0) { const path = segments.join("/"); diff --git a/src/types.ts b/src/types.ts index 836731e..0981f92 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,8 +1,10 @@ -export type PackageManagerName = "npm" | "yarn" | "pnpm" | "yarn@berry"; +export type PackageManagerName = "npm" | "yarn" | "pnpm"; export interface PackageManager { - name: PackageManagerName; - command: string; - lockFile?: string; - version?: string; + name: PackageManagerName; + command: string; + version?: string; + majorVersion?: string; + lockFile?: string; + files?: string[]; } diff --git a/test/fixtures/npm/package-lock.json b/test/fixtures/npm/package-lock.json index 6a6b64c..8146f95 100644 --- a/test/fixtures/npm/package-lock.json +++ b/test/fixtures/npm/package-lock.json @@ -8,34 +8,34 @@ "name": "fixture-npm", "version": "0.0.0", "dependencies": { - "pathe": "^1.0.0" + "pathe": "^1.1.0" }, "devDependencies": { - "ufo": "^1.0.1" + "ufo": "^1.1.1" } }, "node_modules/pathe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.0.0.tgz", - "integrity": "sha512-nPdMG0Pd09HuSsr7QOKUXO2Jr9eqaDiZvDwdyIhNG5SHYujkQHYKDfGQkulBxvbDHz8oHLsTgKN86LSwYzSHAg==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.0.tgz", + "integrity": "sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==" }, "node_modules/ufo": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.0.1.tgz", - "integrity": "sha512-boAm74ubXHY7KJQZLlXrtMz52qFvpsbOxDcZOnw/Wf+LS4Mmyu7JxmzD4tDLtUQtmZECypJ0FrCz4QIe6dvKRA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.1.1.tgz", + "integrity": "sha512-MvlCc4GHrmZdAllBc0iUDowff36Q9Ndw/UzqmEKyrfSzokTd9ZCy1i+IIk5hrYKkjoYVQyNbrw7/F8XJ2rEwTg==", "dev": true } }, "dependencies": { "pathe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.0.0.tgz", - "integrity": "sha512-nPdMG0Pd09HuSsr7QOKUXO2Jr9eqaDiZvDwdyIhNG5SHYujkQHYKDfGQkulBxvbDHz8oHLsTgKN86LSwYzSHAg==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.0.tgz", + "integrity": "sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==" }, "ufo": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.0.1.tgz", - "integrity": "sha512-boAm74ubXHY7KJQZLlXrtMz52qFvpsbOxDcZOnw/Wf+LS4Mmyu7JxmzD4tDLtUQtmZECypJ0FrCz4QIe6dvKRA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.1.1.tgz", + "integrity": "sha512-MvlCc4GHrmZdAllBc0iUDowff36Q9Ndw/UzqmEKyrfSzokTd9ZCy1i+IIk5hrYKkjoYVQyNbrw7/F8XJ2rEwTg==", "dev": true } } diff --git a/test/fixtures/npm/package.json b/test/fixtures/npm/package.json index e651887..406b673 100644 --- a/test/fixtures/npm/package.json +++ b/test/fixtures/npm/package.json @@ -3,10 +3,10 @@ "private": true, "version": "0.0.0", "dependencies": { - "pathe": "^1.0.0" + "pathe": "^1.1.0" }, "packageManager": "npm@9.1.3", "devDependencies": { - "ufo": "^1.0.1" + "ufo": "^1.1.1" } } diff --git a/test/fixtures/pnpm/package.json b/test/fixtures/pnpm/package.json index d195ea8..4ae80e2 100644 --- a/test/fixtures/pnpm/package.json +++ b/test/fixtures/pnpm/package.json @@ -5,7 +5,7 @@ "dependencies": { "pathe": "^1.0.0" }, - "packageManager": "pnpm@7.18.0", + "packageManager": "pnpm@8.0.0", "devDependencies": { "ufo": "^1.0.1" } diff --git a/test/fixtures/pnpm/pnpm-lock.yaml b/test/fixtures/pnpm/pnpm-lock.yaml index 8613d3e..6413254 100644 --- a/test/fixtures/pnpm/pnpm-lock.yaml +++ b/test/fixtures/pnpm/pnpm-lock.yaml @@ -1,21 +1,21 @@ -lockfileVersion: 5.4 - -specifiers: - pathe: ^1.0.0 - ufo: ^1.0.1 +lockfileVersion: '6.0' dependencies: - pathe: 1.0.0 + pathe: + specifier: ^1.0.0 + version: 1.0.0 devDependencies: - ufo: 1.0.1 + ufo: + specifier: ^1.0.1 + version: 1.0.1 packages: - /pathe/1.0.0: + /pathe@1.0.0: resolution: {integrity: sha512-nPdMG0Pd09HuSsr7QOKUXO2Jr9eqaDiZvDwdyIhNG5SHYujkQHYKDfGQkulBxvbDHz8oHLsTgKN86LSwYzSHAg==} dev: false - /ufo/1.0.1: + /ufo@1.0.1: resolution: {integrity: sha512-boAm74ubXHY7KJQZLlXrtMz52qFvpsbOxDcZOnw/Wf+LS4Mmyu7JxmzD4tDLtUQtmZECypJ0FrCz4QIe6dvKRA==} dev: true diff --git a/test/fixtures/yarn/package.json b/test/fixtures/yarn-berry/package.json similarity index 79% rename from test/fixtures/yarn/package.json rename to test/fixtures/yarn-berry/package.json index 8aa44cb..9f76e66 100644 --- a/test/fixtures/yarn/package.json +++ b/test/fixtures/yarn-berry/package.json @@ -3,10 +3,10 @@ "private": true, "version": "0.0.0", "dependencies": { - "pathe": "^1.0.0" + "pathe": "^1.1.0" }, "packageManager": "yarn@1.22.19", "devDependencies": { - "ufo": "^1.0.1" + "ufo": "^1.1.1" } } diff --git a/test/fixtures/yarn-berry/yarn.lock b/test/fixtures/yarn-berry/yarn.lock new file mode 100644 index 0000000..df88cee --- /dev/null +++ b/test/fixtures/yarn-berry/yarn.lock @@ -0,0 +1,13 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +pathe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.0.tgz#e2e13f6c62b31a3289af4ba19886c230f295ec03" + integrity sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w== + +ufo@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.1.1.tgz#e70265e7152f3aba425bd013d150b2cdf4056d7c" + integrity sha512-MvlCc4GHrmZdAllBc0iUDowff36Q9Ndw/UzqmEKyrfSzokTd9ZCy1i+IIk5hrYKkjoYVQyNbrw7/F8XJ2rEwTg== diff --git a/test/fixtures/yarn-classic/package.json b/test/fixtures/yarn-classic/package.json new file mode 100644 index 0000000..9f76e66 --- /dev/null +++ b/test/fixtures/yarn-classic/package.json @@ -0,0 +1,12 @@ +{ + "name": "fixture-yarn", + "private": true, + "version": "0.0.0", + "dependencies": { + "pathe": "^1.1.0" + }, + "packageManager": "yarn@1.22.19", + "devDependencies": { + "ufo": "^1.1.1" + } +} diff --git a/test/fixtures/yarn-classic/yarn.lock b/test/fixtures/yarn-classic/yarn.lock new file mode 100644 index 0000000..df88cee --- /dev/null +++ b/test/fixtures/yarn-classic/yarn.lock @@ -0,0 +1,13 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +pathe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.0.tgz#e2e13f6c62b31a3289af4ba19886c230f295ec03" + integrity sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w== + +ufo@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.1.1.tgz#e70265e7152f3aba425bd013d150b2cdf4056d7c" + integrity sha512-MvlCc4GHrmZdAllBc0iUDowff36Q9Ndw/UzqmEKyrfSzokTd9ZCy1i+IIk5hrYKkjoYVQyNbrw7/F8XJ2rEwTg== diff --git a/test/fixtures/yarn/yarn.lock b/test/fixtures/yarn/yarn.lock deleted file mode 100644 index 7c2a8dc..0000000 --- a/test/fixtures/yarn/yarn.lock +++ /dev/null @@ -1,13 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -pathe@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.0.0.tgz#135fc11464fc57c84ef93d5c5ed21247e24571df" - integrity sha512-nPdMG0Pd09HuSsr7QOKUXO2Jr9eqaDiZvDwdyIhNG5SHYujkQHYKDfGQkulBxvbDHz8oHLsTgKN86LSwYzSHAg== - -ufo@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.0.1.tgz#64ed43b530706bda2e4892f911f568cf4cf67d29" - integrity sha512-boAm74ubXHY7KJQZLlXrtMz52qFvpsbOxDcZOnw/Wf+LS4Mmyu7JxmzD4tDLtUQtmZECypJ0FrCz4QIe6dvKRA== diff --git a/test/index.test.ts b/test/index.test.ts index 8024b80..bbe1d58 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -2,36 +2,62 @@ import { fileURLToPath } from "node:url"; import { expect, it, describe } from "vitest"; import { detectPackageManager, addDependency } from "../src"; -const resolveFixtureDirectory = (name: string) => fileURLToPath(new URL(`fixtures/${name}`, import.meta.url)); +const resolveFixtureDirectory = (name: string) => + fileURLToPath(new URL(`fixtures/${name}`, import.meta.url)); + +const fixtures = [ + { + name: "npm", + pm: "npm", + }, + { + name: "pnpm", + pm: "pnpm", + }, + { + name: "yarn-classic", + pm: "yarn", + }, + { + name: "yarn-berry", + pm: "yarn", + }, +]; describe("detectPackageManager", () => { - for (const pm of ["npm", "yarn", "pnpm"]) { - describe(pm, () => { - const fixtureDirectory = resolveFixtureDirectory(pm); + for (const fixture of fixtures) { + describe(fixture.name, () => { + const fixtureDirectory = resolveFixtureDirectory(fixture.name); it("should detect with lock file", async () => { - const detected = await detectPackageManager(fixtureDirectory, { ignorePackageJSON: true }); - expect(detected).toMatchObject({ name: pm }); + const detected = await detectPackageManager(fixtureDirectory, { + ignorePackageJSON: true, + }); + expect(detected).toMatchObject({ name: fixture.pm }); }); it("should detect with package.json", async () => { - const detected = await detectPackageManager(fixtureDirectory, { ignoreLockFile: true }); - expect(detected).toMatchObject({ name: pm, version: expect.any(String) }); + const detected = await detectPackageManager(fixtureDirectory, { + ignoreLockFile: true, + }); + expect(detected).toMatchObject({ + name: fixture.pm, + version: expect.any(String), + }); }); }); } - it("should return default", async () => { - const fixtureDirectory = resolveFixtureDirectory("default"); - const detected = await detectPackageManager(fixtureDirectory, { ignoreLockFile: true, ignorePackageJSON: true }); - expect(detected).toMatchObject({ name: 'npm', command: 'npm', lockFile: 'package-lock.json', version: expect.any(String) }); - }); }); describe("api", () => { - for (const pm of ["npm", "yarn", "pnpm"]) { - describe(pm, () => { - const fixtureDirectory = resolveFixtureDirectory(pm); + for (const fixture of fixtures) { + describe(fixture.name, () => { + const fixtureDirectory = resolveFixtureDirectory(fixture.name); it("addDependency", async () => { - expect(await addDependency("pathe", { cwd: fixtureDirectory })).toBeTruthy(); - expect(await addDependency("ufo", { cwd: fixtureDirectory, dev: true })).toBeTruthy(); + expect( + await addDependency("pathe", { cwd: fixtureDirectory }) + ).toBeTruthy(); + expect( + await addDependency("ufo", { cwd: fixtureDirectory, dev: true }) + ).toBeTruthy(); }); }); } From 3f0887be59a49e33c6667af6fe84d9fd2be0c05e Mon Sep 17 00:00:00 2001 From: Conner Bachmann Date: Sun, 2 Apr 2023 21:59:02 +0200 Subject: [PATCH 3/3] feat: add getPackageInfo utility function --- package.json | 3 +++ pnpm-lock.yaml | 9 +++++---- src/api.ts | 13 ++++++++++++- src/types.ts | 20 ++++++++++++++++++++ test/index.test.ts | 9 ++++++++- 5 files changed, 48 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 5a9bba6..15d489c 100644 --- a/package.json +++ b/package.json @@ -43,5 +43,8 @@ "packageManager": "pnpm@8.0.0", "engines": { "node": "^14.16.0 || ^16.10.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "dependencies": { + "ofetch": "^1.0.1" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1bef472..5967605 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,5 +1,10 @@ lockfileVersion: '6.0' +dependencies: + ofetch: + specifier: ^1.0.1 + version: 1.0.1 + devDependencies: '@types/node': specifier: ^18.15.11 @@ -1367,7 +1372,6 @@ packages: /destr@1.2.2: resolution: {integrity: sha512-lrbCJwD9saUQrqUfXvl6qoM+QN3W7tLV5pAOs+OqOmopCCz/JkE05MHedJR1xfk4IAnZuJXPVuN5+7jNA2ZCiA==} - dev: true /diff@5.1.0: resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==} @@ -2840,7 +2844,6 @@ packages: /node-fetch-native@1.0.2: resolution: {integrity: sha512-KIkvH1jl6b3O7es/0ShyCgWLcfXxlBrLBbP3rOr23WArC66IMcU4DeZEeYEOwnopYhawLTn7/y+YtmASe8DFVQ==} - dev: true /node-releases@2.0.10: resolution: {integrity: sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==} @@ -2903,7 +2906,6 @@ packages: destr: 1.2.2 node-fetch-native: 1.0.2 ufo: 1.1.1 - dev: true /once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -3608,7 +3610,6 @@ packages: /ufo@1.1.1: resolution: {integrity: sha512-MvlCc4GHrmZdAllBc0iUDowff36Q9Ndw/UzqmEKyrfSzokTd9ZCy1i+IIk5hrYKkjoYVQyNbrw7/F8XJ2rEwTg==} - dev: true /unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} diff --git a/src/api.ts b/src/api.ts index 62a47d8..a770780 100644 --- a/src/api.ts +++ b/src/api.ts @@ -1,6 +1,7 @@ +import { ofetch } from 'ofetch' import { detectPackageManager } from "./detect"; import { runCorepack } from "./spawn"; -import { PackageManager } from "./types"; +import { Package, PackageManager } from "./types"; export interface APICallOptions { cwd: string; @@ -17,6 +18,16 @@ export async function addDependency (name: string, _options: AddDependencyOption return {}; } +export async function getPackageInfo (name: string): Promise { + const pkg = await ofetch(`https://registry.npmjs.org/${name}`, { + onResponseError({ request, response }) { + console.error('Could not fetch package: ' + name + "\n", request, response.status) + } + }); + + return pkg; +} + async function _resolveOptions (options: Partial = {}): Promise { options.cwd = options.cwd || process.cwd(); options.silent = options.silent ?? (process.env.NODE_ENV === "test"); diff --git a/src/types.ts b/src/types.ts index 0981f92..fc4153f 100644 --- a/src/types.ts +++ b/src/types.ts @@ -8,3 +8,23 @@ export interface PackageManager { lockFile?: string; files?: string[]; } + +export interface PackageMaintainer { + name: string; + email: string; +} + +export interface Package { + _id: string; + _rev: string; + time: Record; + name: string; + versions: Record>; + maintainers: PackageMaintainer[] + readme: string; + readmeFilename: string; + description: string; + homepage: string; + repository: string; + license: string; +} diff --git a/test/index.test.ts b/test/index.test.ts index bbe1d58..bd6799e 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -1,6 +1,6 @@ import { fileURLToPath } from "node:url"; import { expect, it, describe } from "vitest"; -import { detectPackageManager, addDependency } from "../src"; +import { detectPackageManager, addDependency, getPackageInfo } from "../src"; const resolveFixtureDirectory = (name: string) => fileURLToPath(new URL(`fixtures/${name}`, import.meta.url)); @@ -24,6 +24,13 @@ const fixtures = [ }, ]; +describe("getPackageInfo", () => { + it("should get package info", async () => { + const pkg = await getPackageInfo("pathe"); + expect(pkg._id).toBe("pathe"); + }); +}) + describe("detectPackageManager", () => { for (const fixture of fixtures) { describe(fixture.name, () => {