@dephub/package-install
Version:
Install packages with flexible scope support using your preferred package manager
143 lines (142 loc) • 3.99 kB
JavaScript
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
};