pm-auto 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,7 +5,7 @@ import * as fsd from "fs";
5
5
  import * as path from "path";
6
6
  import type { CommandResult, ConfigType } from "./types/index.js";
7
7
  import { display } from "./display.js";
8
- import { confirm } from "@inquirer/prompts";
8
+ import { confirm, isCancel, cancel } from "@clack/prompts";
9
9
 
10
10
  type PackageManager = "npm" | "yarn" | "pnpm";
11
11
 
@@ -49,7 +49,10 @@ export const getConfigObject = async (
49
49
  try {
50
50
  configContent = await fs.readFile(configPath as string, "utf8");
51
51
  } catch (error) {
52
- display(`File not found ${error}`, "error");
52
+ display(
53
+ `File not found ${error} Try updating the config file path`,
54
+ "error",
55
+ );
53
56
  }
54
57
  const configObject = JSON.parse(configContent);
55
58
  let result: ConfigType[] = Object.values(configObject);
@@ -91,9 +94,14 @@ export const getConfigObject = async (
91
94
  });
92
95
  const continueWithInstall = await confirm({
93
96
  message: "Continue with installation?",
94
- default: true,
97
+ initialValue: true,
95
98
  });
96
99
 
100
+ if (isCancel(continueWithInstall)) {
101
+ cancel("Operation cancelled.");
102
+ process.exit(0);
103
+ }
104
+
97
105
  if (!continueWithInstall) {
98
106
  display("Installation cancelled ", "success");
99
107
  }
package/src/display.ts CHANGED
@@ -1,33 +1,37 @@
1
- /**
2
- * Display a message with a specified type.
3
- *
4
- * @param text - The message to display.
5
- * @param type - The type of message to display to determine the color.
6
- */
7
-
1
+ import { log, spinner } from "@clack/prompts";
8
2
  import chalk from "chalk";
9
3
 
10
- export const display = (
11
- text: string,
12
- type: "error" | "success" | "warning" | "info" | "loading" | "",
13
- ) => {
4
+ type DisplayType = "error" | "success" | "warning" | "info" | "loading" | "";
5
+
6
+ export const stopSpinner = (s: any, text: string, code: number = 0) => {
7
+ if (!s || typeof s.stop !== "function") return;
8
+ s.stop(code === 0 ? chalk.green(text) : chalk.red(text));
9
+ };
10
+
11
+ export const display = (text: string, type: DisplayType) => {
14
12
  switch (type) {
15
13
  case "error":
16
- console.error(chalk.red(text));
14
+ log.error(chalk.red(text));
17
15
  process.exit(1);
16
+
18
17
  case "success":
19
- console.log(chalk.green(text));
20
- process.exit(0);
18
+ log.success(chalk.green(text)); // Use log.success instead
19
+ break;
20
+
21
21
  case "warning":
22
- console.warn(chalk.yellow(text));
22
+ log.warn(chalk.yellow(text));
23
23
  break;
24
+
24
25
  case "info":
25
- console.info(chalk.blue(text));
26
+ log.info(chalk.blue(text));
26
27
  break;
28
+
27
29
  case "loading":
28
- console.log(`Loading... ${text}`);
29
- break;
30
+ const s = spinner();
31
+ s.start(text);
32
+ return s; // Return spinner so it can be stopped later
33
+
30
34
  default:
31
- console.log(text);
35
+ log.message(text);
32
36
  }
33
37
  };
package/src/index.ts CHANGED
@@ -2,25 +2,35 @@
2
2
 
3
3
  import { Command } from "commander";
4
4
  import { saveConfigPath } from "./config_path.js";
5
+ import { intro } from "@clack/prompts";
5
6
  import { orchestrator } from "./orchestrator.js";
7
+ import chalk from "chalk";
8
+
9
+ intro(chalk.inverse(" pm-auto "));
6
10
 
7
11
  const program = new Command();
8
12
 
9
13
  program
10
14
  .name("pm-auto")
11
- .version("1.0.0")
12
- .description("CLI for automated npm,yarn,pnpm package installation");
15
+ .version("1.0.1")
16
+ .description(
17
+ "A CLI tool to define and install your tech stack presets with one command.",
18
+ );
13
19
 
14
20
  program
15
21
  .command("config <path>")
16
- .description("Set the config file path")
22
+ .description("Set the path to the configuration file")
17
23
  .action((path) => {
18
24
  saveConfigPath(path);
19
25
  });
20
26
 
21
27
  program
22
28
  .command("install [packages...]")
23
- .description("Install packages")
29
+ .alias("add")
30
+ .alias("i")
31
+ .description(
32
+ "Install packages using the detected package manager (Aliases: add, i)",
33
+ )
24
34
  .option("-p, --pkg-json", "Install packages from package.json")
25
35
  .option(
26
36
  "-A, --add-command <command>",
@@ -33,7 +43,12 @@ program
33
43
 
34
44
  program
35
45
  .command("uninstall <packages...>")
36
- .description("Uninstall packages")
46
+ .alias("remove")
47
+ .alias("u")
48
+ .alias("un")
49
+ .description(
50
+ "Remove packages using the detected package manager (Aliases: remove, u, un)",
51
+ )
37
52
  .option(
38
53
  "-A, --add-command <command>",
39
54
  "Add a custom command to all installation commands from config file",
package/src/install.ts CHANGED
@@ -1,15 +1,26 @@
1
1
  import { execa } from "execa";
2
2
  import type { CommandResult } from "./types/index.js";
3
- import { display } from "./display.js";
3
+ import { display, stopSpinner } from "./display.js";
4
4
 
5
- async function runCommand(command: string) {
5
+ async function runCommand(command: string, interactive: boolean = false) {
6
6
  try {
7
7
  const [commandName, ...args] = command.split(" ");
8
8
 
9
- await execa(commandName as string, args, {
10
- stdio: "inherit",
11
- });
9
+ if (interactive) {
10
+ // Stop spinner before interactive command
11
+ stopSpinner("Starting interactive command...", 0);
12
+ await execa(commandName as string, args, {
13
+ stdio: "inherit",
14
+ });
15
+ } else {
16
+ await execa(commandName as string, args, {
17
+ stdio: "inherit",
18
+ });
19
+ }
12
20
  } catch (error: any) {
21
+ // If pipe failed, we should show the output
22
+ if (error.stdout) display(error.stdout, "");
23
+ if (error.stderr) display(error.stderr, "error");
13
24
  display(`Error:, ${error.message}`, "error");
14
25
  }
15
26
  }
@@ -23,15 +34,16 @@ export async function install(commands: CommandResult[]) {
23
34
  // Wait for all interactive commands to finish first
24
35
  if (command.interactive) {
25
36
  for (const interactiveCommand of command.interactive) {
26
- display(`Running command: ${interactiveCommand}`, "loading");
27
- await runCommand(interactiveCommand);
37
+ display(`Running interactive command: ${interactiveCommand}`, "info");
38
+ await runCommand(interactiveCommand, true);
28
39
  }
29
40
  }
30
41
 
31
42
  // Then run non-interactive
32
43
  if (command.nonInteractive) {
44
+ // For non-interactive, we show a spinner
33
45
  display(`Running command: ${command.nonInteractive[0]}`, "loading");
34
- await runCommand(command.nonInteractive[0] as string);
46
+ await runCommand(command.nonInteractive[0] as string, false);
35
47
  }
36
48
  }
37
49
  } catch (error: any) {
@@ -1,8 +1,9 @@
1
1
  import { buildCommands, buildUninstallCommands } from "./build_command.js";
2
2
  import { getConfigObject } from "./config_reader.js";
3
- import { display } from "./display.js";
3
+ import { display, stopSpinner } from "./display.js";
4
4
  import { install } from "./install.js";
5
5
  import type { ConfigType } from "./types/index.js";
6
+ import { outro } from "@clack/prompts";
6
7
 
7
8
  //Check if the value is an array of ConfigType objects
8
9
  function isConfigTypeArray(value: unknown): value is ConfigType[] {
@@ -38,15 +39,14 @@ export const orchestrator = (
38
39
  if (isConfigTypeArray(config)) {
39
40
  const commands = buildCommands(config);
40
41
  await install(commands);
41
- display("Packages installed successfully", "success");
42
+ stopSpinner("Packages installed successfully");
42
43
  process.stdout.write("\x07");
44
+ outro("Done!");
43
45
  } else {
44
46
  await install(config);
45
47
 
46
- display(
47
- "✅ Packages from package.json installed successfully",
48
- "success",
49
- );
48
+ stopSpinner("Packages from package.json installed successfully");
49
+ outro("Done!");
50
50
  }
51
51
  });
52
52
  } else {
@@ -64,7 +64,8 @@ export const orchestrator = (
64
64
  if (isConfigTypeArray(config)) {
65
65
  const commands = buildUninstallCommands(config);
66
66
  await install(commands);
67
- display("Packages uninstalled successfully", "success");
67
+ stopSpinner("Packages uninstalled successfully");
68
+ outro("Done!");
68
69
  }
69
70
  });
70
71
  }
@@ -1,16 +1,16 @@
1
- export interface ConfigType {
2
- name: string;
3
- packageManager: string;
4
- packages: { command: string; interactive: boolean }[];
5
- }
6
-
7
- export interface PackageType {
8
- command: string;
9
- interactive: boolean;
10
- }
11
-
12
- export interface CommandResult {
13
- name: string;
14
- interactive: string[];
15
- nonInteractive: string[];
16
- }
1
+ export interface ConfigType {
2
+ name: string;
3
+ packageManager: string;
4
+ packages: { command: string; interactive: boolean }[];
5
+ }
6
+
7
+ export interface PackageType {
8
+ command: string;
9
+ interactive: boolean;
10
+ }
11
+
12
+ export interface CommandResult {
13
+ name: string;
14
+ interactive: string[];
15
+ nonInteractive: string[];
16
+ }
package/test.json CHANGED
@@ -1,83 +1,94 @@
1
- {
2
- "vite": {
3
- "name": "vite",
4
- "packageManager": "npm",
5
- "packages": [
6
- {
7
- "command": "@types/three --save-dev",
8
- "interactive": false
9
- },
10
- {
11
- "command": "@react-three/fiber",
12
- "interactive": false
13
- },
14
- {
15
- "command": "gsap",
16
- "interactive": false
17
- },
18
- {
19
- "command": "create-vite@latest my-app",
20
- "interactive": true
21
- }
22
- ]
23
- },
24
-
25
- "next": {
26
- "name": "next",
27
- "packageManager": "pnpm",
28
- "packages": [
29
- {
30
- "command": "three --save-dev",
31
- "interactive": false
32
- },
33
- {
34
- "command": "@react-three/drei",
35
- "interactive": false
36
- },
37
- {
38
- "command": "framer-motion",
39
- "interactive": false
40
- },
41
- {
42
- "command": "create-next-app@latest my-app",
43
- "interactive": true
44
- }
45
- ]
46
- },
47
- "test": {
48
- "name": "test",
49
- "packageManager": "npm",
50
- "packages": [
51
- {
52
- "command": "three",
53
- "interactive": false
54
- },
55
- {
56
- "command": "gsap",
57
- "interactive": false
58
- },
59
- {
60
- "command": "@react-three/fiber",
61
- "interactive": false
62
- }
63
- ]
64
- },
65
- "test2": {
66
- "name": "test2",
67
- "packageManager": "npm",
68
- "packages": [
69
- {
70
- "command": "@react-three/drei",
71
- "interactive": false
72
- },
73
- {
74
- "command": "framer-motion",
75
- "interactive": false
76
- },
77
- {
78
- "command": "@react-three/postprocessing",
79
- "interactive": false
80
- }
81
- ]
82
- }
83
- }
1
+ {
2
+ "sample": {
3
+ "name": "sample",
4
+ "packageManager": "npm",
5
+ "packages": [
6
+ {
7
+ "command": "gsap",
8
+ "interactive": false
9
+ }
10
+ ]
11
+ },
12
+
13
+ "vite": {
14
+ "name": "vite",
15
+ "packageManager": "npm",
16
+ "packages": [
17
+ {
18
+ "command": "@types/three --save-dev",
19
+ "interactive": false
20
+ },
21
+ {
22
+ "command": "@react-three/fiber",
23
+ "interactive": false
24
+ },
25
+ {
26
+ "command": "gsap",
27
+ "interactive": false
28
+ },
29
+ {
30
+ "command": "create-vite@latest my-app",
31
+ "interactive": true
32
+ }
33
+ ]
34
+ },
35
+
36
+ "next": {
37
+ "name": "next",
38
+ "packageManager": "pnpm",
39
+ "packages": [
40
+ {
41
+ "command": "three --save-dev",
42
+ "interactive": false
43
+ },
44
+ {
45
+ "command": "@react-three/drei",
46
+ "interactive": false
47
+ },
48
+ {
49
+ "command": "framer-motion",
50
+ "interactive": false
51
+ },
52
+ {
53
+ "command": "create-next-app@latest my-app",
54
+ "interactive": true
55
+ }
56
+ ]
57
+ },
58
+ "test": {
59
+ "name": "test",
60
+ "packageManager": "npm",
61
+ "packages": [
62
+ {
63
+ "command": "three",
64
+ "interactive": false
65
+ },
66
+ {
67
+ "command": "gsap",
68
+ "interactive": false
69
+ },
70
+ {
71
+ "command": "@react-three/fiber",
72
+ "interactive": false
73
+ }
74
+ ]
75
+ },
76
+ "test2": {
77
+ "name": "test2",
78
+ "packageManager": "npm",
79
+ "packages": [
80
+ {
81
+ "command": "@react-three/drei",
82
+ "interactive": false
83
+ },
84
+ {
85
+ "command": "framer-motion",
86
+ "interactive": false
87
+ },
88
+ {
89
+ "command": "@react-three/postprocessing",
90
+ "interactive": false
91
+ }
92
+ ]
93
+ }
94
+ }