UNPKG

@dephub/package-install

Version:

Install packages with flexible scope support using your preferred package manager

143 lines (142 loc) 3.99 kB
import { confirm as r } from "@dephub/ask"; import { logger as t } from "@dephub/logger"; import { packageManager as s } from "@dephub/package-manager"; import { spawnStream as n } from "@dephub/spawn"; class i { #a; #e = ""; #t = "production"; /** * Creates a new InstallBuilder instance. * @param options - Optional initial configuration for the builder. */ constructor(a) { a?.packageManager && (this.#a = a.packageManager), a?.name && (this.#e = a.name), a?.scope && (this.#t = a.scope); } /** * Sets the package manager to use for installation. * @param packageManager - The package manager to use (npm, yarn, pnpm, bun) * @returns The InstallBuilder instance for method chaining. */ setPackageManager(a) { return this.#a = a, this; } /** * Sets the name of the package to install. * @param name - The name of the package to install. * @returns The InstallBuilder instance for method chaining. */ setName(a) { return this.#e = a, this; } /** * Sets the installation scope. * @param scope - The installation scope (e.g., 'global', 'workspace', 'dev', 'production'). * @returns The InstallBuilder instance for method chaining. */ setScope(a) { return this.#t = a, this; } /** * Automatically detects and sets the package manager from the environment. * @returns A promise that resolves when detection is complete. * @throws {Error} When no package manager is detected in the current environment */ async detectPackageManager() { const a = await s.detectFirst(); if (a) this.#a = a; else throw new Error("No package manager detected in the current environment"); } /** * Installs the package using the configured settings. * @returns A promise resolving to installation result. * @throws {Error} If package name is not set * @throws {Error} If no package manager is set and automatic detection fails */ async install() { if (!this.#e) throw new Error("Package name must be set"); this.#a || await this.detectPackageManager(); try { const a = this.#s(); return t.log(this.#a, ...a), await n(this.#a, a), this.#r(!0); } catch (a) { const e = a instanceof Error ? a.message : String(a); return t.error(`Failed to install ${this.#e}: ${e}`), this.#r(!1, e); } } /** * Prompts the user for confirmation before installing the package. * @returns A promise resolving to installation result, including user cancellation. * @example * const result = await builder.askInstall(); * if (result.skipped) { * warn('User cancelled installation'); * } */ async askInstall() { return await this.#n() ? await this.install() : (t.warn("Skipped installation."), { ...this.#r(!1), skipped: !0 }); } #s() { const a = { bun: ["add"], npm: ["install"], pnpm: ["add"], yarn: ["add"] }, e = { dev: { bun: ["--dev"], npm: ["--save-dev"], pnpm: ["--save-dev"], yarn: ["--dev"] }, global: { bun: ["global", "add"], npm: ["install", "--global"], pnpm: ["add", "--global"], yarn: ["global", "add"] }, production: { bun: [], npm: ["--save"], pnpm: ["--save-prod"], yarn: [] }, workspace: { bun: ["workspace"], npm: ["install", "--workspace"], pnpm: ["add", "--workspace"], yarn: ["workspace"] } }; return [ ...a[this.#a], ...e[this.#t][this.#a], this.#e ]; } #r(a, e) { return { error: e, name: this.#e, packageManager: this.#a, scope: this.#t, success: a }; } async #n() { return this.#a || await this.detectPackageManager(), await r( `? Install ${this.#e} with ${this.#a}? [y/N]: ` ); } } const g = new i(); export { i as InstallBuilder, g as installer };