Skip to content

Commit

Permalink
feat: add remove provider command and enhance add provider functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
rsaz committed Nov 19, 2024
1 parent 8f2ab90 commit 9a29024
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 70 deletions.
3 changes: 2 additions & 1 deletion src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { generateProject } from "./generate";
import { helpCommand } from "./help/cli";
import { infoProject } from "./info";
import { createProject } from "./new";
import { addProviderCMD } from "./providers";
import { addProviderCMD, removeProviderCMD } from "./providers";
import { createExternalProviderCMD } from "./providers/create/cli";
import { printError } from "./utils/cli-ui";
import { scriptsCommand } from "./scripts";
Expand All @@ -34,6 +34,7 @@ yargs(hideBin(process.argv))
.command(prodCommand)
.command(createExternalProviderCMD())
.command(addProviderCMD())
.command(removeProviderCMD())
.command(generateProject())
.command(scriptsCommand())
.command(infoProject())
Expand Down
7 changes: 6 additions & 1 deletion src/help/form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@ const helpForm = async (): Promise<void> => {
["dto", "g d", "Generate a dto"],
["entity", "g e", "Generate an entity"],
["provider", "g p", "Generate internal provider"],
["provider", "add", "Add external provider to the project"],
[
"provider",
"add",
"Add provider to the project. Use -d to add as dev dependency",
],
["provider", "remove", "Remove provider from the project"],
["provider", "create", "Create external provider"],
["module", "g mo", "Generate a module"],
["middleware", "g mi", "Generate a middleware"],
Expand Down
31 changes: 27 additions & 4 deletions src/providers/add/cli.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Argv, CommandModule } from "yargs";
import { addExternalProvider } from "./form";
import { addProvider, removeProvider } from "./form";

// eslint-disable-next-line @typescript-eslint/ban-types
type CommandModuleArgs = {};
Expand All @@ -17,13 +17,36 @@ export const addProviderCMD = (): CommandModule<CommandModuleArgs, any> => {
.option("version", {
describe: "The provider version to be installed",
type: "string",
default: "latest",
default: false,
alias: "v",
})
.option("dev", {
describe: "Add provider as a dev dependency",
type: "boolean",
default: false,
alias: "d",
});
return yargs;
},
handler: async ({ provider, version }) => {
await addExternalProvider(provider, version);
handler: async ({ provider, version, dev }) => {
await addProvider(provider, version, dev);
},
};
};

export const removeProviderCMD = (): CommandModule<CommandModuleArgs, any> => {
return {
command: "remove <provider>",
describe: "Remove provider from the project.",
builder: (yargs: Argv): Argv => {
yargs.positional("provider", {
describe: "The provider to be removed from the project",
type: "string",
});
return yargs;
},
handler: async ({ provider: packageName }) => {
await removeProvider(packageName);
},
};
};
166 changes: 102 additions & 64 deletions src/providers/add/form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,103 +4,141 @@ import fs from "node:fs";
import { exit } from "node:process";
import { printError } from "../../utils/cli-ui";

export const addExternalProvider = async (
provider: string,
version: string,
): Promise<void> => {
await installProvider(provider, version);
type PackageManagerConfig = {
install: string;
addDev: string;
remove: string;
};

async function installProvider(provider: string, version: string) {
const packageManager = fs.existsSync(
"package-lock.json" || "yarn.lock" || "pnpm-lock.yaml",
)
? "npm"
: fs.existsSync("yarn.lock")
? "yarn"
: fs.existsSync("pnpm-lock.yaml")
? "pnpm"
: null;

if (packageManager) {
console.log(`Installing ${provider} provider ...`);
const currentVersion = version === "latest" ? "" : `@${version}`;
await execProcess({
commandArg: packageManager,
args: ["add", `${provider}${currentVersion}`, "--prefer-offline"],
directory: process.cwd(),
});
} else {
printError(
"No package manager found in the project",
"install-provider",
);
return;
type PackageManager = {
npm: PackageManagerConfig;
yarn: PackageManagerConfig;
pnpm: PackageManagerConfig;
};

const PACKAGE_MANAGERS: PackageManager = {
npm: {
install: "install",
addDev: "install --save-dev",
remove: "uninstall",
},
yarn: {
install: "add",
addDev: "add --dev",
remove: "remove",
},
pnpm: {
install: "add",
addDev: "add --save-dev",
remove: "remove",
},
};

function detectPackageManager(): string | null {
const lockFiles = ["package-lock.json", "yarn.lock", "pnpm-lock.yaml"];
const managers = Object.keys(PACKAGE_MANAGERS);

for (let i = 0; i < lockFiles.length; i++) {
if (fs.existsSync(lockFiles[i])) {
return managers[i];
}
}
return null;
}

async function execProcess({
commandArg,
command,
args,
directory,
}: {
commandArg: string;
command: string;
args: string[];
directory: string;
}) {
}): Promise<void> {
return new Promise((resolve, reject) => {
const isWindows: boolean = process.platform === "win32";
const command: string = isWindows ? `${commandArg}.cmd` : commandArg;
const isWindows = process.platform === "win32";
const execCommand = isWindows ? `${command}.cmd` : command;

const installProcess = spawn(command, args, {
const processRunner = spawn(execCommand, args, {
cwd: directory,
shell: true,
});

console.log(
chalk.bold.blue(`Executing: ${commandArg} ${args.join(" ")}`),
);
console.log(chalk.bold.blue(`Executing: ${command} ${args.join(" ")}`));
console.log(
chalk.yellow("-------------------------------------------------"),
);

installProcess.stdout.on("data", (data) => {
console.log(chalk.green(data.toString().trim())); // Display regular messages in green
processRunner.stdout.on("data", (data) => {
console.log(chalk.green(data.toString().trim()));
});

installProcess.stderr.on("data", (data) => {
console.error(chalk.red(data.toString().trim())); // Display error messages in red
processRunner.stderr.on("data", (data) => {
console.error(chalk.red(data.toString().trim()));
});

installProcess.on("close", (code) => {
processRunner.on("close", (code) => {
if (code === 0) {
console.log(
chalk.bold.green(
"-------------------------------------------------",
),
chalk.bold.green("Operation completed successfully!\n"),
);
console.log(chalk.bold.green("Installation Done!\n"));
resolve("Installation Done!");
resolve();
} else {
console.error(
chalk.bold.red("---------------------------------------"),
);
console.error(
chalk.bold.red(
`Command ${command} ${args.join(
" ",
)} exited with code ${code}`,
),
);
reject(
new Error(
`Command ${command} ${args.join(
" ",
)} exited with code ${code}`,
),
chalk.bold.red(`Command failed with exit code ${code}`),
);
reject(new Error(`Command failed with exit code ${code}`));
exit(1);
}
});
});
}

export async function addProvider(
packageName: string,
version?: string,
isDevDependency = false,
): Promise<void> {
const packageManager = detectPackageManager();

if (!packageManager) {
printError("No package manager found in the project", "add-package");
return;
}

const pkgManagerConfig: PackageManagerConfig =
PACKAGE_MANAGERS[packageManager as keyof PackageManager];

const command = isDevDependency
? pkgManagerConfig.addDev
: pkgManagerConfig.install;
const versionSuffix = version && version !== "latest" ? `@${version}` : "";

console.log(
`${isDevDependency ? "Adding devDependency" : "Installing"} ${packageName}...`,
);
await execProcess({
command: packageManager,
args: [...command.split(" "), `${packageName}${versionSuffix}`],
directory: process.cwd(),
});
}

export async function removeProvider(packageName: string): Promise<void> {
const packageManager = detectPackageManager();

if (!packageManager) {
printError("No package manager found in the project", "remove-package");
return;
}

const command =
PACKAGE_MANAGERS[packageManager as keyof PackageManager].remove;

console.log(`Removing ${packageName}...`);
await execProcess({
command: packageManager,
args: [...command.split(" "), packageName],
directory: process.cwd(),
});
}

0 comments on commit 9a29024

Please sign in to comment.