pm-auto 1.0.2 → 1.0.4

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.
@@ -77,7 +77,7 @@ export function buildUninstallCommands(projects) {
77
77
  };
78
78
  // Separate interactive from non-interactive packages
79
79
  const nonInteractive = [];
80
- const interactive = [];
80
+ // const interactive: PackageType[] = [];
81
81
  if (packages) {
82
82
  packages.forEach((pkg) => {
83
83
  if (!pkg.interactive) {
@@ -1 +1 @@
1
- {"version":3,"file":"build_command.js","sourceRoot":"","sources":["../src/build_command.ts"],"names":[],"mappings":"AAEA;;GAEG;AAEH,MAAM,UAAU,aAAa,CAAC,QAAsB;IAClD,6BAA6B;IAE7B,MAAM,YAAY,GAAoB,EAAE,CAAC;IACzC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;QAE7C,MAAM,eAAe,GAAG;YACtB,GAAG,EAAE;gBACH,OAAO,EAAE,aAAa;gBACtB,GAAG,EAAE,KAAK;aACX;YACD,IAAI,EAAE;gBACJ,OAAO,EAAE,UAAU;gBACnB,GAAG,EAAE,UAAU;aAChB;YACD,IAAI,EAAE;gBACJ,OAAO,EAAE,UAAU;gBACnB,GAAG,EAAE,UAAU;aAChB;SACF,CAAC;QAEF,MAAM,OAAO,GACX,eAAe,CAAC,cAA8C,CAAC;YAC/D,eAAe,CAAC,GAAG,CAAC;QAEtB,MAAM,MAAM,GAAkB;YAC5B,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,WAAW,EAAE,EAAE;YACf,cAAc,EAAE,EAAE;SACnB,CAAC;QAEF,qDAAqD;QACrD,MAAM,cAAc,GAAkB,EAAE,CAAC;QACzC,MAAM,WAAW,GAAkB,EAAE,CAAC;QAEtC,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;gBACvB,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;oBACpB,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACxB,CAAC;qBAAM,CAAC;oBACN,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAC3B,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QAED,6DAA6D;QAC7D,WAAW,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YAC1B,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;QAEH,sDAAsD;QACtD,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,MAAM,YAAY,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACxE,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,OAAO,IAAI,YAAY,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,QAAsB;IAC3D,MAAM,YAAY,GAAoB,EAAE,CAAC;IACzC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;QAE7C,MAAM,eAAe,GAAG;YACtB,GAAG,EAAE;gBACH,OAAO,EAAE,eAAe;aACzB;YACD,IAAI,EAAE;gBACJ,OAAO,EAAE,gBAAgB;aAC1B;YACD,IAAI,EAAE;gBACJ,OAAO,EAAE,aAAa;aACvB;SACF,CAAC;QAEF,MAAM,OAAO,GACX,eAAe,CAAC,cAA8C,CAAC;YAC/D,eAAe,CAAC,GAAG,CAAC;QAEtB,MAAM,MAAM,GAAkB;YAC5B,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,WAAW,EAAE,EAAE;YACf,cAAc,EAAE,EAAE;SACnB,CAAC;QAEF,qDAAqD;QACrD,MAAM,cAAc,GAAkB,EAAE,CAAC;QACzC,MAAM,WAAW,GAAkB,EAAE,CAAC;QAEtC,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;gBACvB,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;oBACrB,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAC3B,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QAED,sDAAsD;QACtD,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,MAAM,YAAY,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACxE,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,OAAO,IAAI,YAAY,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC"}
1
+ {"version":3,"file":"build_command.js","sourceRoot":"","sources":["../src/build_command.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,7 @@ type PackageManager = "npm" | "yarn" | "pnpm";
5
5
  */
6
6
  export declare function detectPackageManager(projectPath?: string): PackageManager | void;
7
7
  /**
8
- * Get the installation commands from the config file, transforms into a js object and with the options given
8
+ * Gets the required packages from the config file, transforms into a js object and with the options given
9
9
  * it modifies the object and returns it
10
10
  */
11
11
  export declare const getConfigObject: (packages: string[], options?: any) => Promise<ConfigType[] | CommandResult[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"config_reader.d.ts","sourceRoot":"","sources":["../src/config_reader.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAIlE,KAAK,cAAc,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;AAE9C;;GAEG;AAEH,wBAAgB,oBAAoB,CAClC,WAAW,GAAE,MAAsB,GAClC,cAAc,GAAG,IAAI,CAgBvB;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,GAC1B,UAAU,MAAM,EAAE,EAClB,UAAU,GAAG,KACZ,OAAO,CAAC,UAAU,EAAE,GAAG,aAAa,EAAE,CAoFxC,CAAC"}
1
+ {"version":3,"file":"config_reader.d.ts","sourceRoot":"","sources":["../src/config_reader.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAIlE,KAAK,cAAc,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;AAE9C;;GAEG;AAEH,wBAAgB,oBAAoB,CAClC,WAAW,GAAE,MAAsB,GAClC,cAAc,GAAG,IAAI,CAgBvB;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,GAC1B,UAAU,MAAM,EAAE,EAClB,UAAU,GAAG,KACZ,OAAO,CAAC,UAAU,EAAE,GAAG,aAAa,EAAE,CAsFxC,CAAC"}
@@ -22,7 +22,7 @@ export function detectPackageManager(projectPath = process.cwd()) {
22
22
  display("No Lock File Found", "error");
23
23
  }
24
24
  /**
25
- * Get the installation commands from the config file, transforms into a js object and with the options given
25
+ * Gets the required packages from the config file, transforms into a js object and with the options given
26
26
  * it modifies the object and returns it
27
27
  */
28
28
  export const getConfigObject = async (packages, options) => {
@@ -40,12 +40,15 @@ export const getConfigObject = async (packages, options) => {
40
40
  let result = Object.values(configObject);
41
41
  //filter the packages the user wants to install
42
42
  if (packages.length > 0) {
43
- result = packages.map((pkg) => {
44
- if (!configObject[pkg]) {
45
- display(`Package ${pkg} not found in the configuration file`, "warning");
43
+ result = packages
44
+ .map((pkgName) => {
45
+ const found = result.find((pkg) => pkg.name === pkgName);
46
+ if (!found) {
47
+ display(`Package '${pkgName}' not found in config`, "warning");
46
48
  }
47
- return configObject[pkg];
48
- });
49
+ return found;
50
+ })
51
+ .filter((pkg) => pkg !== undefined);
49
52
  }
50
53
  /*
51
54
  * Config object modification with the options given
@@ -1 +1 @@
1
- {"version":3,"file":"config_reader.js","sourceRoot":"","sources":["../src/config_reader.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config_reader.js","sourceRoot":"","sources":["../src/config_reader.ts"],"names":[],"mappings":"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"}
package/dist/display.d.ts CHANGED
@@ -1,5 +1,9 @@
1
1
  type DisplayType = "error" | "success" | "warning" | "info" | "loading" | "";
2
- export declare const display: (text: string, type: DisplayType) => void;
3
2
  export declare const stopSpinner: (text: string, code?: number) => void;
3
+ export declare const display: (text: string, type: DisplayType) => {
4
+ start: (msg?: string) => void;
5
+ stop: (msg?: string, code?: number) => void;
6
+ message: (msg?: string) => void;
7
+ } | undefined;
4
8
  export {};
5
9
  //# sourceMappingURL=display.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"display.d.ts","sourceRoot":"","sources":["../src/display.ts"],"names":[],"mappings":"AASA,KAAK,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,EAAE,CAAC;AAI7E,eAAO,MAAM,OAAO,GAAI,MAAM,MAAM,EAAE,MAAM,WAAW,SAuBtD,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,EAAE,OAAM,MAAU,SAMzD,CAAC"}
1
+ {"version":3,"file":"display.d.ts","sourceRoot":"","sources":["../src/display.ts"],"names":[],"mappings":"AAGA,KAAK,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,EAAE,CAAC;AAE7E,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,EAAE,OAAM,MAAU,SAIzD,CAAC;AAEF,eAAO,MAAM,OAAO,GAAI,MAAM,MAAM,EAAE,MAAM,WAAW;eA2Bu6F,CAAC;cAAiC,CAAC,cAAc,CAAC;iBAAoC,CAAC;aADpjG,CAAC"}
package/dist/display.js CHANGED
@@ -1,22 +1,19 @@
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
- const s = spinner();
3
+ export const stopSpinner = (text, code = 0) => {
4
+ const s = spinner();
5
+ if (!s || typeof s.stop !== "function")
6
+ return;
7
+ s.stop(code === 0 ? chalk.green(text) : chalk.red(text));
8
+ };
10
9
  export const display = (text, type) => {
11
10
  switch (type) {
12
11
  case "error":
13
12
  log.error(chalk.red(text));
14
13
  process.exit(1);
15
14
  case "success":
16
- if (s) {
17
- s.stop(chalk.green(text));
18
- }
19
- process.exit(0);
15
+ log.success(chalk.green(text)); // Use log.success instead
16
+ break;
20
17
  case "warning":
21
18
  log.warn(chalk.yellow(text));
22
19
  break;
@@ -24,18 +21,11 @@ export const display = (text, type) => {
24
21
  log.info(chalk.blue(text));
25
22
  break;
26
23
  case "loading":
24
+ const s = spinner();
27
25
  s.start(text);
28
- break;
26
+ return s; // Return spinner so it can be stopped later
29
27
  default:
30
28
  log.message(text);
31
29
  }
32
30
  };
33
- export const stopSpinner = (text, code = 0) => {
34
- if (code === 0) {
35
- s.stop(chalk.green(text));
36
- }
37
- else {
38
- s.stop(chalk.red(text));
39
- }
40
- };
41
31
  //# sourceMappingURL=display.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"display.js","sourceRoot":"","sources":["../src/display.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,CAAC,GAAG,OAAO,EAAE,CAAC;AAEpB,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,IAAY,EAAE,IAAiB,EAAE,EAAE;IACzD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,OAAO;YACV,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,KAAK,SAAS;YACZ,IAAI,CAAC,EAAE,CAAC;gBACN,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;YAC5B,CAAC;YAED,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,KAAK,SAAS;YACZ,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;YAC7B,MAAM;QACR,KAAK,MAAM;YACT,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAC3B,MAAM;QACR,KAAK,SAAS;YACZ,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACd,MAAM;QACR;YACE,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,OAAe,CAAC,EAAE,EAAE;IAC5D,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;QACf,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5B,CAAC;SAAM,CAAC;QACN,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC,CAAC"}
1
+ {"version":3,"file":"display.js","sourceRoot":"","sources":["../src/display.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,OAAe,CAAC,EAAE,EAAE;IAC5D,MAAM,CAAC,GAAG,OAAO,EAAE,CAAC;IACpB,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,UAAU;QAAE,OAAO;IAC/C,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3D,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,IAAY,EAAE,IAAiB,EAAE,EAAE;IACzD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,OAAO;YACV,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAElB,KAAK,SAAS;YACZ,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,0BAA0B;YAC1D,MAAM;QAER,KAAK,SAAS;YACZ,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;YAC7B,MAAM;QAER,KAAK,MAAM;YACT,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAC3B,MAAM;QAER,KAAK,SAAS;YACZ,MAAM,CAAC,GAAG,OAAO,EAAE,CAAC;YACpB,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACd,OAAO,CAAC,CAAC,CAAC,4CAA4C;QAExD;YACE,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;AACH,CAAC,CAAC"}
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ intro(chalk.inverse(" pm-auto "));
8
8
  const program = new Command();
9
9
  program
10
10
  .name("pm-auto")
11
- .version("1.0.1")
11
+ .version("1.0.4")
12
12
  .description("A CLI tool to define and install your tech stack presets with one command.");
13
13
  program
14
14
  .command("config <path>")
package/dist/install.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { CommandResult } from "./types/index.js";
2
2
  /**
3
- * Takes the interactive and non interactive command from each item in the CommandResult Array
3
+ * Install all commands
4
4
  */
5
5
  export declare function install(commands: CommandResult[]): Promise<void>;
6
6
  //# sourceMappingURL=install.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AA0BtD;;GAEG;AACH,wBAAsB,OAAO,CAAC,QAAQ,EAAE,aAAa,EAAE,iBAwBtD"}
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AA0BtD;;GAEG;AACH,wBAAsB,OAAO,CAAC,QAAQ,EAAE,aAAa,EAAE,iBAqBtD"}
package/dist/install.js CHANGED
@@ -26,7 +26,7 @@ async function runCommand(command, interactive = false) {
26
26
  }
27
27
  }
28
28
  /**
29
- * Takes the interactive and non interactive command from each item in the CommandResult Array
29
+ * Install all commands
30
30
  */
31
31
  export async function install(commands) {
32
32
  try {
@@ -34,9 +34,6 @@ export async function install(commands) {
34
34
  // Wait for all interactive commands to finish first
35
35
  if (command.interactive) {
36
36
  for (const interactiveCommand of command.interactive) {
37
- // Interactive commands need full terminal access
38
- // We don't start a spinner here, or we stop it immediately in runCommand
39
- // But better to just log info
40
37
  display(`Running interactive command: ${interactiveCommand}`, "info");
41
38
  await runCommand(interactiveCommand, true);
42
39
  }
@@ -1 +1 @@
1
- {"version":3,"file":"install.js","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAE9B,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEpD,KAAK,UAAU,UAAU,CAAC,OAAe,EAAE,cAAuB,KAAK;IACrE,IAAI,CAAC;QACH,MAAM,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAElD,IAAI,WAAW,EAAE,CAAC;YAChB,0CAA0C;YAC1C,WAAW,CAAC,iCAAiC,EAAE,CAAC,CAAC,CAAC;YAClD,MAAM,KAAK,CAAC,WAAqB,EAAE,IAAI,EAAE;gBACvC,KAAK,EAAE,SAAS;aACjB,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,MAAM,KAAK,CAAC,WAAqB,EAAE,IAAI,EAAE;gBACvC,KAAK,EAAE,SAAS;aACjB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,4CAA4C;QAC5C,IAAI,KAAK,CAAC,MAAM;YAAE,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC5C,IAAI,KAAK,CAAC,MAAM;YAAE,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACjD,OAAO,CAAC,WAAW,KAAK,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,QAAyB;IACrD,IAAI,CAAC;QACH,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,oDAAoD;YACpD,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;gBACxB,KAAK,MAAM,kBAAkB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;oBACrD,iDAAiD;oBACjD,yEAAyE;oBACzE,8BAA8B;oBAC9B,OAAO,CAAC,gCAAgC,kBAAkB,EAAE,EAAE,MAAM,CAAC,CAAC;oBACtE,MAAM,UAAU,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC;gBAC7C,CAAC;YACH,CAAC;YAED,2BAA2B;YAC3B,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;gBAC3B,yCAAyC;gBACzC,OAAO,CAAC,oBAAoB,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;gBACpE,MAAM,UAAU,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAW,EAAE,KAAK,CAAC,CAAC;YAC/D,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO,CAAC,UAAU,KAAK,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAE9B,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEpD,KAAK,UAAU,UAAU,CAAC,OAAe,EAAE,cAAuB,KAAK;IACrE,IAAI,CAAC;QACH,MAAM,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAElD,IAAI,WAAW,EAAE,CAAC;YAChB,0CAA0C;YAC1C,WAAW,CAAC,iCAAiC,EAAE,CAAC,CAAC,CAAC;YAClD,MAAM,KAAK,CAAC,WAAqB,EAAE,IAAI,EAAE;gBACvC,KAAK,EAAE,SAAS;aACjB,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,MAAM,KAAK,CAAC,WAAqB,EAAE,IAAI,EAAE;gBACvC,KAAK,EAAE,SAAS;aACjB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,4CAA4C;QAC5C,IAAI,KAAK,CAAC,MAAM;YAAE,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC5C,IAAI,KAAK,CAAC,MAAM;YAAE,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACjD,OAAO,CAAC,WAAW,KAAK,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,QAAyB;IACrD,IAAI,CAAC;QACH,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,oDAAoD;YACpD,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;gBACxB,KAAK,MAAM,kBAAkB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;oBACrD,OAAO,CAAC,gCAAgC,kBAAkB,EAAE,EAAE,MAAM,CAAC,CAAC;oBACtE,MAAM,UAAU,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC;gBAC7C,CAAC;YACH,CAAC;YAED,2BAA2B;YAC3B,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;gBAC3B,yCAAyC;gBACzC,OAAO,CAAC,oBAAoB,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;gBACpE,MAAM,UAAU,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAW,EAAE,KAAK,CAAC,CAAC;YAC/D,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO,CAAC,UAAU,KAAK,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pm-auto",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "A CLI tool to define and install your tech stack presets with one command.",
5
5
  "keywords": [
6
6
  "pm-auto",
@@ -10,12 +10,6 @@
10
10
  ],
11
11
  "license": "MIT",
12
12
  "author": "Elliot Otoijagha",
13
- "contributors": [
14
- {
15
- "name": "Triumph Aidenojie",
16
- "email": "triumphaidenojie08@gmail.com"
17
- }
18
- ],
19
13
  "type": "module",
20
14
  "main": "dist/index.js",
21
15
  "bin": {
@@ -25,7 +19,8 @@
25
19
  "build": "tsc",
26
20
  "dev": "nodemon --exec tsx src/index.ts",
27
21
  "start": "node dist/index.js",
28
- "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js"
22
+ "prepublishOnly": "npm run build",
23
+ "test": "vitest run"
29
24
  },
30
25
  "dependencies": {
31
26
  "@clack/prompts": "^0.11.0",
@@ -40,6 +35,7 @@
40
35
  "ts-jest": "^29.4.5",
41
36
  "ts-node": "^10.9.2",
42
37
  "tsx": "^4.20.6",
43
- "typescript": "^5.9.3"
38
+ "typescript": "^5.9.3",
39
+ "vitest": "^4.0.13"
44
40
  }
45
41
  }
@@ -1,119 +1,119 @@
1
- import type { ConfigType, PackageType, CommandResult } from "./types/index.js";
2
-
3
- /**
4
- * Build commands from project configurations.
5
- */
6
-
7
- export function buildCommands(projects: ConfigType[]) {
8
- // Initialize arrays properly
9
-
10
- const commandArray: CommandResult[] = [];
11
- for (const project of projects) {
12
- const { packageManager, packages } = project;
13
-
14
- const commandPrefixes = {
15
- npm: {
16
- install: "npm install",
17
- run: "npx",
18
- },
19
- pnpm: {
20
- install: "pnpm add",
21
- run: "pnpm dlx",
22
- },
23
- yarn: {
24
- install: "yarn add",
25
- run: "yarn dlx",
26
- },
27
- };
28
-
29
- const manager =
30
- commandPrefixes[packageManager as keyof typeof commandPrefixes] ||
31
- commandPrefixes.npm;
32
-
33
- const result: CommandResult = {
34
- name: project.name,
35
- interactive: [],
36
- nonInteractive: [],
37
- };
38
-
39
- // Separate interactive from non-interactive packages
40
- const nonInteractive: PackageType[] = [];
41
- const interactive: PackageType[] = [];
42
-
43
- if (packages) {
44
- packages.forEach((pkg) => {
45
- if (pkg.interactive) {
46
- interactive.push(pkg);
47
- } else {
48
- nonInteractive.push(pkg);
49
- }
50
- });
51
- }
52
-
53
- // Add interactive packages as separate commands (sequential)
54
- interactive.forEach((pkg) => {
55
- result.interactive.push(`${manager.run} ${pkg.command}`);
56
- });
57
-
58
- // Batch all non-interactive packages into ONE command
59
- if (nonInteractive.length > 0) {
60
- const packageNames = nonInteractive.map((pkg) => pkg.command).join(" ");
61
- result.nonInteractive.push(`${manager.install} ${packageNames}`);
62
- }
63
-
64
- commandArray.push(result);
65
- }
66
-
67
- return commandArray;
68
- }
69
-
70
- export function buildUninstallCommands(projects: ConfigType[]) {
71
- const commandArray: CommandResult[] = [];
72
- for (const project of projects) {
73
- const { packageManager, packages } = project;
74
-
75
- const commandPrefixes = {
76
- npm: {
77
- install: "npm uninstall",
78
- },
79
- pnpm: {
80
- install: "pnpm uninstall",
81
- },
82
- yarn: {
83
- install: "yarn remove",
84
- },
85
- };
86
-
87
- const manager =
88
- commandPrefixes[packageManager as keyof typeof commandPrefixes] ||
89
- commandPrefixes.npm;
90
-
91
- const result: CommandResult = {
92
- name: project.name,
93
- interactive: [],
94
- nonInteractive: [],
95
- };
96
-
97
- // Separate interactive from non-interactive packages
98
- const nonInteractive: PackageType[] = [];
99
- const interactive: PackageType[] = [];
100
-
101
- if (packages) {
102
- packages.forEach((pkg) => {
103
- if (!pkg.interactive) {
104
- nonInteractive.push(pkg);
105
- }
106
- });
107
- }
108
-
109
- // Batch all non-interactive packages into ONE command
110
- if (nonInteractive.length > 0) {
111
- const packageNames = nonInteractive.map((pkg) => pkg.command).join(" ");
112
- result.nonInteractive.push(`${manager.install} ${packageNames}`);
113
- }
114
-
115
- commandArray.push(result);
116
- }
117
-
118
- return commandArray;
119
- }
1
+ import type { ConfigType, PackageType, CommandResult } from "./types/index.js";
2
+
3
+ /**
4
+ * Build commands from project configurations.
5
+ */
6
+
7
+ export function buildCommands(projects: ConfigType[]) {
8
+ // Initialize arrays properly
9
+
10
+ const commandArray: CommandResult[] = [];
11
+ for (const project of projects) {
12
+ const { packageManager, packages } = project;
13
+
14
+ const commandPrefixes = {
15
+ npm: {
16
+ install: "npm install",
17
+ run: "npx",
18
+ },
19
+ pnpm: {
20
+ install: "pnpm add",
21
+ run: "pnpm dlx",
22
+ },
23
+ yarn: {
24
+ install: "yarn add",
25
+ run: "yarn dlx",
26
+ },
27
+ };
28
+
29
+ const manager =
30
+ commandPrefixes[packageManager as keyof typeof commandPrefixes] ||
31
+ commandPrefixes.npm;
32
+
33
+ const result: CommandResult = {
34
+ name: project.name,
35
+ interactive: [],
36
+ nonInteractive: [],
37
+ };
38
+
39
+ // Separate interactive from non-interactive packages
40
+ const nonInteractive: PackageType[] = [];
41
+ const interactive: PackageType[] = [];
42
+
43
+ if (packages) {
44
+ packages.forEach((pkg) => {
45
+ if (pkg.interactive) {
46
+ interactive.push(pkg);
47
+ } else {
48
+ nonInteractive.push(pkg);
49
+ }
50
+ });
51
+ }
52
+
53
+ // Add interactive packages as separate commands (sequential)
54
+ interactive.forEach((pkg) => {
55
+ result.interactive.push(`${manager.run} ${pkg.command}`);
56
+ });
57
+
58
+ // Batch all non-interactive packages into ONE command
59
+ if (nonInteractive.length > 0) {
60
+ const packageNames = nonInteractive.map((pkg) => pkg.command).join(" ");
61
+ result.nonInteractive.push(`${manager.install} ${packageNames}`);
62
+ }
63
+
64
+ commandArray.push(result);
65
+ }
66
+
67
+ return commandArray;
68
+ }
69
+
70
+ export function buildUninstallCommands(projects: ConfigType[]) {
71
+ const commandArray: CommandResult[] = [];
72
+ for (const project of projects) {
73
+ const { packageManager, packages } = project;
74
+
75
+ const commandPrefixes = {
76
+ npm: {
77
+ install: "npm uninstall",
78
+ },
79
+ pnpm: {
80
+ install: "pnpm uninstall",
81
+ },
82
+ yarn: {
83
+ install: "yarn remove",
84
+ },
85
+ };
86
+
87
+ const manager =
88
+ commandPrefixes[packageManager as keyof typeof commandPrefixes] ||
89
+ commandPrefixes.npm;
90
+
91
+ const result: CommandResult = {
92
+ name: project.name,
93
+ interactive: [],
94
+ nonInteractive: [],
95
+ };
96
+
97
+ // Separate interactive from non-interactive packages
98
+ const nonInteractive: PackageType[] = [];
99
+ // const interactive: PackageType[] = [];
100
+
101
+ if (packages) {
102
+ packages.forEach((pkg) => {
103
+ if (!pkg.interactive) {
104
+ nonInteractive.push(pkg);
105
+ }
106
+ });
107
+ }
108
+
109
+ // Batch all non-interactive packages into ONE command
110
+ if (nonInteractive.length > 0) {
111
+ const packageNames = nonInteractive.map((pkg) => pkg.command).join(" ");
112
+ result.nonInteractive.push(`${manager.install} ${packageNames}`);
113
+ }
114
+
115
+ commandArray.push(result);
116
+ }
117
+
118
+ return commandArray;
119
+ }
@@ -1,54 +1,54 @@
1
- import * as fs from "fs";
2
- import * as path from "path";
3
- import * as os from "os";
4
- import { display } from "./display.js";
5
-
6
- const SETTINGS_DIR = path.join(os.homedir(), ".pm-auto");
7
- const SETTINGS_FILE = path.join(SETTINGS_DIR, "settings.json");
8
-
9
- interface Settings {
10
- configPath?: string;
11
- }
12
-
13
- export function saveConfigPath(configPath: string): void {
14
- // Create directory if it doesn't exist
15
- if (!fs.existsSync(SETTINGS_DIR)) {
16
- fs.mkdirSync(SETTINGS_DIR, { recursive: true });
17
- }
18
-
19
- //check if file exists
20
- try {
21
- const real = fs.realpathSync(configPath);
22
- const settings: Settings = { configPath: real };
23
- fs.writeFileSync(SETTINGS_FILE, JSON.stringify(settings, null, 2));
24
-
25
- display(`Config file path saved: ${configPath}`, "success");
26
- } catch (err: any) {
27
- display(`Error saving config file: ${err.message}`, "error");
28
- }
29
- }
30
-
31
- export function getConfigPath(): string | void {
32
- //check if settings exists
33
- if (!fs.existsSync(SETTINGS_FILE)) {
34
- display(
35
- "Run `pm-auto config <path>`, where <path> is the path to your config file",
36
- "info",
37
- );
38
- display("Config file path not set", "error");
39
- }
40
-
41
- try {
42
- const data = fs.readFileSync(SETTINGS_FILE, "utf8");
43
- const settings: Settings = JSON.parse(data);
44
- return settings.configPath || "";
45
- } catch (error: any) {
46
- display(`Error reading config file path: ${error.message}`, "error");
47
- }
48
- }
49
-
50
- export function clearConfigPath(): void {
51
- if (fs.existsSync(SETTINGS_FILE)) {
52
- fs.unlinkSync(SETTINGS_FILE);
53
- }
54
- }
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ import * as os from "os";
4
+ import { display } from "./display.js";
5
+
6
+ const SETTINGS_DIR = path.join(os.homedir(), ".pm-auto");
7
+ const SETTINGS_FILE = path.join(SETTINGS_DIR, "settings.json");
8
+
9
+ interface Settings {
10
+ configPath?: string;
11
+ }
12
+
13
+ export function saveConfigPath(configPath: string): void {
14
+ // Create directory if it doesn't exist
15
+ if (!fs.existsSync(SETTINGS_DIR)) {
16
+ fs.mkdirSync(SETTINGS_DIR, { recursive: true });
17
+ }
18
+
19
+ //check if file exists
20
+ try {
21
+ const real = fs.realpathSync(configPath);
22
+ const settings: Settings = { configPath: real };
23
+ fs.writeFileSync(SETTINGS_FILE, JSON.stringify(settings, null, 2));
24
+
25
+ display(`Config file path saved: ${configPath}`, "success");
26
+ } catch (err: any) {
27
+ display(`Error saving config file: ${err.message}`, "error");
28
+ }
29
+ }
30
+
31
+ export function getConfigPath(): string | void {
32
+ //check if settings exists
33
+ if (!fs.existsSync(SETTINGS_FILE)) {
34
+ display(
35
+ "Run `pm-auto config <path>`, where <path> is the path to your config file",
36
+ "info",
37
+ );
38
+ display("Config file path not set", "error");
39
+ }
40
+
41
+ try {
42
+ const data = fs.readFileSync(SETTINGS_FILE, "utf8");
43
+ const settings: Settings = JSON.parse(data);
44
+ return settings.configPath || "";
45
+ } catch (error: any) {
46
+ display(`Error reading config file path: ${error.message}`, "error");
47
+ }
48
+ }
49
+
50
+ export function clearConfigPath(): void {
51
+ if (fs.existsSync(SETTINGS_FILE)) {
52
+ fs.unlinkSync(SETTINGS_FILE);
53
+ }
54
+ }
@@ -34,7 +34,7 @@ export function detectPackageManager(
34
34
  }
35
35
 
36
36
  /**
37
- * Get the installation commands from the config file, transforms into a js object and with the options given
37
+ * Gets the required packages from the config file, transforms into a js object and with the options given
38
38
  * it modifies the object and returns it
39
39
  */
40
40
  export const getConfigObject = async (
@@ -54,21 +54,23 @@ export const getConfigObject = async (
54
54
  "error",
55
55
  );
56
56
  }
57
+
57
58
  const configObject = JSON.parse(configContent);
58
59
  let result: ConfigType[] = Object.values(configObject);
59
60
 
60
61
  //filter the packages the user wants to install
61
62
  if (packages.length > 0) {
62
- result = packages.map((pkg) => {
63
- if (!configObject[pkg]) {
64
- display(
65
- `Package ${pkg} not found in the configuration file`,
66
- "warning",
67
- );
68
- }
69
- return configObject[pkg];
70
- });
63
+ result = packages
64
+ .map((pkgName) => {
65
+ const found = result.find((pkg) => pkg.name === pkgName);
66
+ if (!found) {
67
+ display(`Package '${pkgName}' not found in config`, "warning");
68
+ }
69
+ return found;
70
+ })
71
+ .filter((pkg) => pkg !== undefined);
71
72
  }
73
+
72
74
  /*
73
75
  * Config object modification with the options given
74
76
  */
package/src/index.ts CHANGED
@@ -12,7 +12,7 @@ const program = new Command();
12
12
 
13
13
  program
14
14
  .name("pm-auto")
15
- .version("1.0.1")
15
+ .version("1.0.4")
16
16
  .description(
17
17
  "A CLI tool to define and install your tech stack presets with one command.",
18
18
  );
package/src/install.ts CHANGED
@@ -26,7 +26,7 @@ async function runCommand(command: string, interactive: boolean = false) {
26
26
  }
27
27
 
28
28
  /**
29
- * Takes the interactive and non interactive command from each item in the CommandResult Array
29
+ * Install all commands
30
30
  */
31
31
  export async function install(commands: CommandResult[]) {
32
32
  try {
@@ -0,0 +1,37 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { buildCommands, buildUninstallCommands } from "../src/build_command.js";
3
+ import type { ConfigType } from "../src/types/index.js";
4
+
5
+ describe("buildCommand", () => {
6
+ const mockConfig: ConfigType[] = [
7
+ {
8
+ name: "vite",
9
+ packageManager: "npm",
10
+ packages: [
11
+ { command: "vite@latest", interactive: true },
12
+ { command: "gsap@latest", interactive: false },
13
+ ],
14
+ },
15
+ ];
16
+ it("builds an installation command", () => {
17
+ const command = buildCommands(mockConfig);
18
+ expect(command).toEqual([
19
+ {
20
+ name: "vite",
21
+ interactive: ["npx vite@latest"],
22
+ nonInteractive: ["npm install gsap@latest"],
23
+ },
24
+ ]);
25
+ });
26
+
27
+ it("builds an uninstallation command", () => {
28
+ const command = buildUninstallCommands(mockConfig);
29
+ expect(command).toEqual([
30
+ {
31
+ name: "vite",
32
+ interactive: [],
33
+ nonInteractive: ["npm uninstall gsap@latest"],
34
+ },
35
+ ]);
36
+ });
37
+ });
@@ -0,0 +1,142 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import * as fs from "fs";
3
+ import * as os from "os";
4
+ import {
5
+ saveConfigPath,
6
+ getConfigPath,
7
+ clearConfigPath,
8
+ } from "../src/config_path.js";
9
+ import * as display from "../src/display.js";
10
+
11
+ const mocks = vi.hoisted(() => {
12
+ return {
13
+ homedir: vi.fn(() => "/mock/home"),
14
+ };
15
+ });
16
+
17
+ // Mock modules FIRST
18
+ vi.mock("fs");
19
+ vi.mock("os", () => ({
20
+ homedir: mocks.homedir,
21
+ }));
22
+ vi.mock("../src/display.js");
23
+
24
+ // NOW import the module under test AFTER mocks are configured
25
+
26
+ describe("Config Path Management", () => {
27
+ const mockHomeDir = "/mock/home";
28
+ const mockSettingsDir = "\\mock\\home\\.pm-auto";
29
+ const mockSettingsFile = "\\mock\\home\\.pm-auto\\settings.json";
30
+
31
+ beforeEach(() => {
32
+ vi.resetAllMocks();
33
+ vi.mocked(os.homedir).mockReturnValue(mockHomeDir);
34
+ });
35
+
36
+ describe("saveConfigPath", () => {
37
+ it("creates directory and saves config path", () => {
38
+ vi.mocked(fs.existsSync).mockReturnValue(false);
39
+ vi.mocked(fs.realpathSync).mockReturnValue("\\real\\path\\config.json");
40
+
41
+ saveConfigPath("./config.json");
42
+
43
+ expect(fs.mkdirSync).toHaveBeenCalledWith(mockSettingsDir, {
44
+ recursive: true,
45
+ });
46
+ expect(fs.writeFileSync).toHaveBeenCalledWith(
47
+ mockSettingsFile,
48
+ expect.stringContaining('"configPath"'),
49
+ );
50
+ expect(display.display).toHaveBeenCalledWith(
51
+ expect.any(String),
52
+ "success",
53
+ );
54
+ });
55
+
56
+ it("skips directory creation if exists", () => {
57
+ vi.mocked(fs.existsSync).mockReturnValue(true);
58
+ vi.mocked(fs.realpathSync).mockReturnValue("/real/path");
59
+
60
+ saveConfigPath("/path");
61
+
62
+ expect(fs.mkdirSync).not.toHaveBeenCalled();
63
+ });
64
+
65
+ it("handles errors gracefully", () => {
66
+ vi.mocked(fs.realpathSync).mockImplementation(() => {
67
+ throw new Error("File not found");
68
+ });
69
+
70
+ saveConfigPath("/invalid/path");
71
+
72
+ expect(display.display).toHaveBeenCalledWith(
73
+ expect.stringContaining("File not found"),
74
+ "error",
75
+ );
76
+ });
77
+ });
78
+
79
+ describe("getConfigPath", () => {
80
+ it("returns config path when file exists", () => {
81
+ vi.mocked(fs.existsSync).mockReturnValue(true);
82
+ vi.mocked(fs.readFileSync).mockReturnValue(
83
+ JSON.stringify({ configPath: "/saved/path" }),
84
+ );
85
+
86
+ const result = getConfigPath();
87
+
88
+ expect(result).toBe("/saved/path");
89
+ });
90
+
91
+ it("shows error when settings file does not exist", () => {
92
+ vi.mocked(fs.existsSync).mockReturnValue(false);
93
+
94
+ const result = getConfigPath();
95
+
96
+ expect(display.display).toHaveBeenCalledWith(
97
+ expect.stringContaining("Config file path not set"),
98
+ "error",
99
+ );
100
+ expect(result).toBeUndefined();
101
+ });
102
+
103
+ it("handles JSON parse errors", () => {
104
+ vi.mocked(fs.existsSync).mockReturnValue(true);
105
+ vi.mocked(fs.readFileSync).mockReturnValue("invalid json");
106
+
107
+ getConfigPath();
108
+
109
+ expect(display.display).toHaveBeenCalledWith(
110
+ expect.stringContaining("Error reading"),
111
+ "error",
112
+ );
113
+ });
114
+
115
+ it("returns empty string if configPath is missing", () => {
116
+ vi.mocked(fs.existsSync).mockReturnValue(true);
117
+ vi.mocked(fs.readFileSync).mockReturnValue(JSON.stringify({}));
118
+
119
+ const result = getConfigPath();
120
+
121
+ expect(result).toBe("");
122
+ });
123
+ });
124
+
125
+ describe("clearConfigPath", () => {
126
+ it("deletes settings file if exists", () => {
127
+ vi.mocked(fs.existsSync).mockReturnValue(true);
128
+
129
+ clearConfigPath();
130
+
131
+ expect(fs.unlinkSync).toHaveBeenCalledWith(mockSettingsFile);
132
+ });
133
+
134
+ it("does nothing if file does not exist", () => {
135
+ vi.mocked(fs.existsSync).mockReturnValue(false);
136
+
137
+ clearConfigPath();
138
+
139
+ expect(fs.unlinkSync).not.toHaveBeenCalled();
140
+ });
141
+ });
142
+ });
@@ -0,0 +1,179 @@
1
+ import { beforeEach, describe, expect, it, vi } from "vitest";
2
+ import fs from "fs/promises";
3
+ import * as fsd from "fs";
4
+ import * as path from "path";
5
+ import { display } from "../src/display.js";
6
+ import { detectPackageManager, getConfigObject } from "../src/config_reader.js";
7
+ import { getConfigPath } from "../src/config_path.js";
8
+ import type { CommandResult, ConfigType } from "../src/types/index.js";
9
+ import * as clack from "@clack/prompts";
10
+
11
+ vi.mock("fs/promises");
12
+ vi.mock("fs");
13
+ vi.mock("../src/config_path.js");
14
+ vi.mock("../src/display.js");
15
+ vi.mock("@clack/prompts");
16
+ vi.mock("../src/config_path.js");
17
+
18
+ describe("detect package manager", () => {
19
+ beforeEach(() => {
20
+ vi.resetAllMocks();
21
+ });
22
+ it("should detects pnpm from lock file", () => {
23
+ vi.mocked(fsd.existsSync).mockImplementation((filePath) =>
24
+ filePath.toString().includes("pnpm-lock.yaml"),
25
+ );
26
+ const result = detectPackageManager("/test/path");
27
+
28
+ expect(result).toBe("pnpm");
29
+ });
30
+ it("should detects yarn from lock file", () => {
31
+ vi.mocked(fsd.existsSync).mockImplementation((filePath) =>
32
+ filePath.toString().includes("yarn.lock"),
33
+ );
34
+ const result = detectPackageManager("/test/path");
35
+
36
+ expect(result).toBe("yarn");
37
+ });
38
+ it("should detects npm from lock file", () => {
39
+ vi.mocked(fsd.existsSync).mockImplementation((filePath) =>
40
+ filePath.toString().includes("package-lock.json"),
41
+ );
42
+ const result = detectPackageManager("/test/path");
43
+
44
+ expect(result).toBe("npm");
45
+ });
46
+ it("should display error message when no lock file found", () => {
47
+ vi.mocked(fsd.existsSync).mockImplementation(() => false);
48
+ const result = detectPackageManager("/test/path");
49
+
50
+ expect(display).toHaveBeenCalledWith(
51
+ expect.stringContaining("No Lock File Found"),
52
+ "error",
53
+ );
54
+ expect(result).toBeUndefined();
55
+ });
56
+ });
57
+
58
+ describe("get Config Object", () => {
59
+ const mockConfig = {
60
+ react: {
61
+ name: "react",
62
+ packages: [{ command: "npm install react", interactive: false }],
63
+ },
64
+ vue: {
65
+ name: "vue",
66
+ packages: [{ command: "npm install vue", interactive: false }],
67
+ },
68
+ };
69
+
70
+ beforeEach(() => {
71
+ vi.resetAllMocks();
72
+ });
73
+
74
+ it("should get config object the user wants and display warning when package does not exist", async () => {
75
+ vi.mocked(getConfigPath).mockResolvedValue("/path/to/test");
76
+ vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify(mockConfig));
77
+
78
+ const config = await getConfigObject(["next", "react", "vue"], {});
79
+
80
+ expect(config).toEqual([
81
+ {
82
+ name: "react",
83
+ packages: [{ command: "npm install react", interactive: false }],
84
+ },
85
+ {
86
+ name: "vue",
87
+ packages: [{ command: "npm install vue", interactive: false }],
88
+ },
89
+ ]);
90
+ expect(display).toHaveBeenCalledWith(
91
+ expect.stringContaining("Package 'next' not found in config"),
92
+ "warning",
93
+ );
94
+ });
95
+
96
+ // it("should display an error on readFile error", async () => {
97
+ // vi.mocked(getConfigPath).mockReturnValue("/path/to/test");
98
+ // vi.mocked(fs.readFile).mockRejectedValue(new Error("File not found"));
99
+ // await getConfigObject([], {});
100
+ // expect(display).toHaveBeenCalledWith(
101
+ // expect.stringContaining("Try updating the config file"),
102
+ // "error",
103
+ // );
104
+ // });
105
+ //
106
+
107
+ it("adds command with addCommand option", async () => {
108
+ vi.mocked(getConfigPath).mockReturnValue("/mock/config.json");
109
+ vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify(mockConfig));
110
+
111
+ const result = (await getConfigObject(["react"], {
112
+ addCommand: "--save-dev",
113
+ })) as ConfigType[];
114
+
115
+ if (result[0]?.packages[0]?.command) {
116
+ expect(result[0].packages[0].command).toContain("--save-dev");
117
+ }
118
+ });
119
+
120
+ it("shows dry run preview and continues on confirm", async () => {
121
+ vi.mocked(getConfigPath).mockReturnValue("/mock/config.json");
122
+ vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify(mockConfig));
123
+ vi.mocked(clack.confirm).mockResolvedValue(true);
124
+ vi.mocked(clack.isCancel).mockReturnValue(false);
125
+
126
+ const result = await getConfigObject(["react"], { dryRun: true });
127
+
128
+ expect(display).toHaveBeenCalledWith("Dry Run:", "info");
129
+ expect(clack.confirm).toHaveBeenCalled();
130
+ expect(result).toHaveLength(1);
131
+ });
132
+
133
+ it("cancels on dry run cancel", async () => {
134
+ vi.mocked(getConfigPath).mockReturnValue("/mock/config.json");
135
+ vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify(mockConfig));
136
+ vi.mocked(clack.confirm).mockResolvedValue(false);
137
+ vi.mocked(clack.isCancel).mockReturnValue(true);
138
+
139
+ const mockExit = vi
140
+ .spyOn(process, "exit")
141
+ .mockImplementation(() => undefined as never);
142
+
143
+ await getConfigObject(["react"], { dryRun: true });
144
+
145
+ expect(clack.cancel).toHaveBeenCalledWith("Operation cancelled.");
146
+ expect(mockExit).toHaveBeenCalledWith(0);
147
+
148
+ mockExit.mockRestore();
149
+ });
150
+
151
+ it("generates command for package.json install", async () => {
152
+ vi.mocked(fsd.existsSync).mockImplementation((filePath) =>
153
+ filePath.toString().includes("package-lock.json"),
154
+ );
155
+
156
+ const result = await getConfigObject([], { pkgJson: true });
157
+
158
+ expect(result).toEqual([
159
+ {
160
+ name: "package.json",
161
+ interactive: [],
162
+ nonInteractive: ["npm install"],
163
+ },
164
+ ]);
165
+ });
166
+
167
+ it("uses correct package manager for package.json", async () => {
168
+ vi.mocked(fsd.existsSync).mockImplementation((filePath) =>
169
+ filePath.toString().includes("pnpm-lock.yaml"),
170
+ );
171
+
172
+ const result = (await getConfigObject([], {
173
+ pkgJson: true,
174
+ })) as CommandResult[];
175
+ if (result[0]) {
176
+ expect(result[0].nonInteractive[0]).toBe("pnpm install");
177
+ }
178
+ });
179
+ });
@@ -0,0 +1,205 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { execa } from "execa";
3
+ import { install } from "../src/install.js";
4
+ import * as display from "../src/display.js";
5
+ import type { CommandResult } from "../src/types/index.js";
6
+
7
+ // Mock dependencies
8
+ vi.mock("execa");
9
+ vi.mock("../src/display.js");
10
+
11
+ describe("install", () => {
12
+ beforeEach(() => {
13
+ vi.clearAllMocks();
14
+ });
15
+
16
+ it("runs interactive commands with inherit stdio", async () => {
17
+ const commands: CommandResult[] = [
18
+ {
19
+ name: "test",
20
+ interactive: ["npm init"],
21
+ nonInteractive: [],
22
+ },
23
+ ];
24
+
25
+ vi.mocked(execa).mockResolvedValue({} as any);
26
+
27
+ await install(commands);
28
+
29
+ expect(display.stopSpinner).toHaveBeenCalledWith(
30
+ "Starting interactive command...",
31
+ 0,
32
+ );
33
+ expect(execa).toHaveBeenCalledWith("npm", ["init"], { stdio: "inherit" });
34
+ expect(display.display).toHaveBeenCalledWith(expect.any(String), "info");
35
+ });
36
+
37
+ it("runs non-interactive commands with loading display", async () => {
38
+ const commands: CommandResult[] = [
39
+ {
40
+ name: "test",
41
+ interactive: [],
42
+ nonInteractive: ["npm install react"],
43
+ },
44
+ ];
45
+
46
+ vi.mocked(execa).mockResolvedValue({} as any);
47
+
48
+ await install(commands);
49
+
50
+ expect(display.display).toHaveBeenCalledWith(expect.any(String), "loading");
51
+ expect(execa).toHaveBeenCalledWith("npm", ["install", "react"], {
52
+ stdio: "inherit",
53
+ });
54
+ });
55
+
56
+ it("runs interactive commands before non-interactive", async () => {
57
+ const commands: CommandResult[] = [
58
+ {
59
+ name: "test",
60
+ interactive: ["npm init"],
61
+ nonInteractive: ["npm install"],
62
+ },
63
+ ];
64
+
65
+ vi.mocked(execa).mockResolvedValue({} as any);
66
+
67
+ await install(commands);
68
+
69
+ // Check interactive was called first
70
+ expect(execa).toHaveBeenNthCalledWith(1, "npm", ["init"], {
71
+ stdio: "inherit",
72
+ });
73
+ expect(execa).toHaveBeenNthCalledWith(2, "npm", ["install"], {
74
+ stdio: "inherit",
75
+ });
76
+ expect(display.stopSpinner).toHaveBeenCalled();
77
+ });
78
+
79
+ it("handles multiple interactive commands sequentially", async () => {
80
+ const commands: CommandResult[] = [
81
+ {
82
+ name: "test",
83
+ interactive: ["npm init", "npx create-app"],
84
+ nonInteractive: [],
85
+ },
86
+ ];
87
+
88
+ vi.mocked(execa).mockResolvedValue({} as any);
89
+
90
+ await install(commands);
91
+
92
+ expect(execa).toHaveBeenCalledTimes(2);
93
+ expect(execa).toHaveBeenNthCalledWith(1, "npm", ["init"], {
94
+ stdio: "inherit",
95
+ });
96
+ expect(execa).toHaveBeenNthCalledWith(2, "npx", ["create-app"], {
97
+ stdio: "inherit",
98
+ });
99
+ });
100
+
101
+ it("handles command execution errors with stdout", async () => {
102
+ const commands: CommandResult[] = [
103
+ {
104
+ name: "test",
105
+ interactive: [],
106
+ nonInteractive: ["npm install"],
107
+ },
108
+ ];
109
+
110
+ const error = new Error("Command failed");
111
+ (error as any).stdout = "stdout output";
112
+ (error as any).stderr = "stderr output";
113
+
114
+ vi.mocked(execa).mockRejectedValue(error);
115
+
116
+ await install(commands);
117
+
118
+ expect(display.display).toHaveBeenCalledWith("stdout output", "");
119
+ expect(display.display).toHaveBeenCalledWith("stderr output", "error");
120
+ expect(display.display).toHaveBeenCalledWith(
121
+ expect.stringContaining("Command failed"),
122
+ "error",
123
+ );
124
+ });
125
+
126
+ it("handles command execution errors without stdout/stderr", async () => {
127
+ const commands: CommandResult[] = [
128
+ {
129
+ name: "test",
130
+ interactive: [],
131
+ nonInteractive: ["npm install"],
132
+ },
133
+ ];
134
+
135
+ vi.mocked(execa).mockRejectedValue(new Error("Command failed"));
136
+
137
+ await install(commands);
138
+
139
+ expect(display.display).toHaveBeenCalledWith(
140
+ expect.stringContaining("Command failed"),
141
+ "error",
142
+ );
143
+ });
144
+
145
+ it("processes multiple CommandResult items in sequence", async () => {
146
+ const commands: CommandResult[] = [
147
+ {
148
+ name: "react",
149
+ interactive: [],
150
+ nonInteractive: ["npm install react"],
151
+ },
152
+ {
153
+ name: "vue",
154
+ interactive: [],
155
+ nonInteractive: ["npm install vue"],
156
+ },
157
+ ];
158
+
159
+ vi.mocked(execa).mockResolvedValue({} as any);
160
+
161
+ await install(commands);
162
+
163
+ expect(execa).toHaveBeenCalledTimes(2);
164
+ expect(execa).toHaveBeenCalledWith("npm", ["install", "react"], {
165
+ stdio: "inherit",
166
+ });
167
+ expect(execa).toHaveBeenCalledWith("npm", ["install", "vue"], {
168
+ stdio: "inherit",
169
+ });
170
+ });
171
+
172
+ it("handles empty command arrays", async () => {
173
+ const commands: CommandResult[] = [
174
+ {
175
+ name: "test",
176
+ interactive: [],
177
+ nonInteractive: [],
178
+ },
179
+ ];
180
+
181
+ await install(commands);
182
+
183
+ expect(execa).not.toHaveBeenCalled();
184
+ });
185
+
186
+ it("splits command string correctly with multiple args", async () => {
187
+ const commands: CommandResult[] = [
188
+ {
189
+ name: "test",
190
+ interactive: [],
191
+ nonInteractive: ["npm install react --save-dev"],
192
+ },
193
+ ];
194
+
195
+ vi.mocked(execa).mockResolvedValue({} as any);
196
+
197
+ await install(commands);
198
+
199
+ expect(execa).toHaveBeenCalledWith(
200
+ "npm",
201
+ ["install", "react", "--save-dev"],
202
+ { stdio: "inherit" },
203
+ );
204
+ });
205
+ });
package/tsconfig.json CHANGED
@@ -2,7 +2,6 @@
2
2
  // Visit https://aka.ms/tsconfig to read more about this file
3
3
  "compilerOptions": {
4
4
  // File Layout
5
- "rootDir": "./src",
6
5
  "outDir": "./dist",
7
6
 
8
7
  // Environment Settings
@@ -38,5 +37,7 @@
38
37
  "noUncheckedSideEffectImports": true,
39
38
  "moduleDetection": "force",
40
39
  "skipLibCheck": true
41
- }
40
+ },
41
+ "include": ["src/**/*"],
42
+ "exclude": ["node_modules", "dist", "tests/**/*"]
42
43
  }
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from "vitest/config";
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ globals: true,
6
+ environment: "node",
7
+ },
8
+ });