pm-auto 1.0.3 → 1.0.5
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.
- package/README.md +91 -36
- package/dist/build_command.js +1 -1
- package/dist/build_command.js.map +1 -1
- package/dist/config_path.d.ts +0 -1
- package/dist/config_path.d.ts.map +1 -1
- package/dist/config_path.js +0 -5
- package/dist/config_path.js.map +1 -1
- package/dist/config_reader.d.ts +3 -1
- package/dist/config_reader.d.ts.map +1 -1
- package/dist/config_reader.js +54 -6
- package/dist/config_reader.js.map +1 -1
- package/dist/display.d.ts +5 -2
- package/dist/display.d.ts.map +1 -1
- package/dist/display.js +5 -21
- package/dist/display.js.map +1 -1
- package/dist/index.js +30 -2
- package/dist/index.js.map +1 -1
- package/dist/install.d.ts +1 -1
- package/dist/install.d.ts.map +1 -1
- package/dist/install.js +3 -8
- package/dist/install.js.map +1 -1
- package/dist/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator.js +4 -5
- package/dist/orchestrator.js.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +5 -3
- package/src/build_command.ts +119 -119
- package/src/config_path.ts +48 -54
- package/src/config_reader.ts +68 -10
- package/src/display.ts +1 -7
- package/src/index.ts +33 -2
- package/src/install.ts +3 -5
- package/src/orchestrator.ts +5 -6
- package/src/types/index.ts +17 -16
- package/test.json +87 -94
- package/tests/build_command.test.ts +37 -0
- package/tests/config_path.test.ts +120 -0
- package/tests/config_reader.test.ts +179 -0
- package/tests/display.test.ts +83 -0
- package/tests/install.test.ts +200 -0
- package/tsconfig.json +3 -2
- package/vitest.config.js +8 -0
package/dist/orchestrator.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../src/orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../src/orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEvC,sDAAsD;AACtD,SAAS,iBAAiB,CAAC,KAAc;IACvC,OAAO,CACL,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACpB,KAAK,CAAC,KAAK,CACT,CAAC,IAAI,EAAE,EAAE,CACP,OAAO,IAAI,KAAK,QAAQ;YACxB,IAAI,KAAK,IAAI;YACb,UAAU,IAAI,IAAI;YAClB,KAAK,CAAC,OAAO,CAAE,IAAY,CAAC,QAAQ,CAAC,CACxC,CACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,OAAe,EACf,QAAkB,EAClB,OAAa,EACb,EAAE;IACF,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,CACL,0BAA0B,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAE,QAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EACrG,MAAM,CACP,CAAC;QAEF,eAAe,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;YACvD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxB,OAAO,CAAC,wBAAwB,EAAE,OAAO,CAAC,CAAC;gBAC3C,OAAO;YACT,CAAC;YAED,IAAI,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC9B,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;gBAEvC,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC;gBACxB,OAAO,CAAC,iCAAiC,EAAE,SAAS,CAAC,CAAC;gBACtD,KAAK,CAAC,OAAO,CAAC,CAAC;YACjB,CAAC;iBAAM,CAAC;gBACN,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;gBACtB,OAAO,CAAC,mDAAmD,EAAE,SAAS,CAAC,CAAC;gBACxE,KAAK,CAAC,OAAO,CAAC,CAAC;YACjB,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,OAAO,CACL,4BAA6B,QAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAC/D,MAAM,CACP,CAAC;QAEF,eAAe,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;YACvD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxB,OAAO,CAAC,wBAAwB,EAAE,OAAO,CAAC,CAAC;gBAC3C,OAAO;YACT,CAAC;YAED,IAAI,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC9B,MAAM,QAAQ,GAAG,sBAAsB,CAAC,MAAM,CAAC,CAAC;gBAChD,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC;gBACxB,OAAO,CAAC,mCAAmC,EAAE,SAAS,CAAC,CAAC;gBACxD,KAAK,CAAC,OAAO,CAAC,CAAC;YACjB,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;CACvD;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;CACvD;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pm-auto",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "A CLI tool to define and install your tech stack presets with one command.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pm-auto",
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
"build": "tsc",
|
|
20
20
|
"dev": "nodemon --exec tsx src/index.ts",
|
|
21
21
|
"start": "node dist/index.js",
|
|
22
|
-
"
|
|
22
|
+
"prepublishOnly": "npm run build",
|
|
23
|
+
"test": "vitest run"
|
|
23
24
|
},
|
|
24
25
|
"dependencies": {
|
|
25
26
|
"@clack/prompts": "^0.11.0",
|
|
@@ -34,6 +35,7 @@
|
|
|
34
35
|
"ts-jest": "^29.4.5",
|
|
35
36
|
"ts-node": "^10.9.2",
|
|
36
37
|
"tsx": "^4.20.6",
|
|
37
|
-
"typescript": "^5.9.3"
|
|
38
|
+
"typescript": "^5.9.3",
|
|
39
|
+
"vitest": "^4.0.13"
|
|
38
40
|
}
|
|
39
41
|
}
|
package/src/build_command.ts
CHANGED
|
@@ -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
|
+
}
|
package/src/config_path.ts
CHANGED
|
@@ -1,54 +1,48 @@
|
|
|
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
|
+
}
|
package/src/config_reader.ts
CHANGED
|
@@ -34,7 +34,7 @@ export function detectPackageManager(
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
|
-
*
|
|
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
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
"warning"
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
*/
|
|
@@ -125,3 +127,59 @@ export const getConfigObject = async (
|
|
|
125
127
|
return result;
|
|
126
128
|
}
|
|
127
129
|
};
|
|
130
|
+
|
|
131
|
+
export const getConfigKeys = async (options: any) => {
|
|
132
|
+
const configPath = getConfigPath();
|
|
133
|
+
|
|
134
|
+
//read config file content
|
|
135
|
+
let configContent = "";
|
|
136
|
+
try {
|
|
137
|
+
configContent = await fs.readFile(configPath as string, "utf8");
|
|
138
|
+
} catch (error) {
|
|
139
|
+
display(
|
|
140
|
+
`File not found ${error} Try updating the config file path`,
|
|
141
|
+
"error",
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const configObject = JSON.parse(configContent);
|
|
146
|
+
let keys = Object.keys(configObject);
|
|
147
|
+
|
|
148
|
+
keys.forEach((key) => {
|
|
149
|
+
if (options.desc) {
|
|
150
|
+
const description = !configObject[key].description
|
|
151
|
+
? "No description"
|
|
152
|
+
: configObject[key].description;
|
|
153
|
+
display(`${key} - ${description}`, "info");
|
|
154
|
+
} else {
|
|
155
|
+
display(`${key}`, "info");
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
export const getPackageDescription = async (packageName: string) => {
|
|
161
|
+
const configPath = getConfigPath();
|
|
162
|
+
|
|
163
|
+
//read config file content
|
|
164
|
+
let configContent = "";
|
|
165
|
+
try {
|
|
166
|
+
configContent = await fs.readFile(configPath as string, "utf8");
|
|
167
|
+
} catch (error) {
|
|
168
|
+
display(
|
|
169
|
+
`File not found ${error} Try updating the config file path`,
|
|
170
|
+
"error",
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const configObject = JSON.parse(configContent);
|
|
175
|
+
let keys = Object.keys(configObject);
|
|
176
|
+
|
|
177
|
+
keys.forEach((key) => {
|
|
178
|
+
if (key === packageName) {
|
|
179
|
+
const description = !configObject[key].description
|
|
180
|
+
? "No description"
|
|
181
|
+
: configObject[key].description;
|
|
182
|
+
display(`${packageName} - ${description}`, "info");
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
};
|
package/src/display.ts
CHANGED
|
@@ -3,17 +3,11 @@ import chalk from "chalk";
|
|
|
3
3
|
|
|
4
4
|
type DisplayType = "error" | "success" | "warning" | "info" | "loading" | "";
|
|
5
5
|
|
|
6
|
-
export const stopSpinner = (text: string, code: number = 0) => {
|
|
7
|
-
const s = spinner();
|
|
8
|
-
if (!s || typeof s.stop !== "function") return;
|
|
9
|
-
s.stop(code === 0 ? chalk.green(text) : chalk.red(text));
|
|
10
|
-
};
|
|
11
|
-
|
|
12
6
|
export const display = (text: string, type: DisplayType) => {
|
|
13
7
|
switch (type) {
|
|
14
8
|
case "error":
|
|
15
9
|
log.error(chalk.red(text));
|
|
16
|
-
process.exit(
|
|
10
|
+
process.exit(0);
|
|
17
11
|
|
|
18
12
|
case "success":
|
|
19
13
|
log.success(chalk.green(text)); // Use log.success instead
|
package/src/index.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { Command } from "commander";
|
|
4
|
-
import { saveConfigPath } from "./config_path.js";
|
|
4
|
+
import { getConfigPath, saveConfigPath } from "./config_path.js";
|
|
5
5
|
import { intro } from "@clack/prompts";
|
|
6
6
|
import { orchestrator } from "./orchestrator.js";
|
|
7
7
|
import chalk from "chalk";
|
|
8
|
+
import { getConfigKeys, getPackageDescription } from "./config_reader.js";
|
|
9
|
+
import { display } from "./display.js";
|
|
8
10
|
|
|
9
11
|
intro(chalk.inverse(" pm-auto "));
|
|
10
12
|
|
|
@@ -12,7 +14,7 @@ const program = new Command();
|
|
|
12
14
|
|
|
13
15
|
program
|
|
14
16
|
.name("pm-auto")
|
|
15
|
-
.version("1.0.
|
|
17
|
+
.version("1.0.5")
|
|
16
18
|
.description(
|
|
17
19
|
"A CLI tool to define and install your tech stack presets with one command.",
|
|
18
20
|
);
|
|
@@ -57,4 +59,33 @@ program
|
|
|
57
59
|
orchestrator("uninstall", packages, options);
|
|
58
60
|
});
|
|
59
61
|
|
|
62
|
+
//Listing config packages
|
|
63
|
+
program
|
|
64
|
+
.command("list")
|
|
65
|
+
.alias("ls")
|
|
66
|
+
.description("List all packages from the config file")
|
|
67
|
+
.option("-D, --desc", "Display packages description", false)
|
|
68
|
+
.action((options) => {
|
|
69
|
+
getConfigKeys(options);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
//Displaying config details
|
|
73
|
+
program
|
|
74
|
+
.command("describe <package>")
|
|
75
|
+
.alias("desc")
|
|
76
|
+
.description("Display description of the package")
|
|
77
|
+
.action((packages) => {
|
|
78
|
+
getPackageDescription(packages);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
//get config path
|
|
82
|
+
program
|
|
83
|
+
.command("config-path")
|
|
84
|
+
.alias("cp")
|
|
85
|
+
.description("Display the path to the configuration file")
|
|
86
|
+
.action(() => {
|
|
87
|
+
const path = getConfigPath();
|
|
88
|
+
display(`Config Path: ${path}`, "info");
|
|
89
|
+
});
|
|
90
|
+
|
|
60
91
|
program.parse();
|
package/src/install.ts
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { execa } from "execa";
|
|
2
2
|
import type { CommandResult } from "./types/index.js";
|
|
3
|
-
import { display
|
|
3
|
+
import { display } from "./display.js";
|
|
4
4
|
|
|
5
5
|
async function runCommand(command: string, interactive: boolean = false) {
|
|
6
6
|
try {
|
|
7
7
|
const [commandName, ...args] = command.split(" ");
|
|
8
8
|
|
|
9
9
|
if (interactive) {
|
|
10
|
-
// Stop spinner before interactive command
|
|
11
|
-
stopSpinner("Starting interactive command...", 0);
|
|
12
10
|
await execa(commandName as string, args, {
|
|
13
11
|
stdio: "inherit",
|
|
14
12
|
});
|
|
@@ -26,7 +24,7 @@ async function runCommand(command: string, interactive: boolean = false) {
|
|
|
26
24
|
}
|
|
27
25
|
|
|
28
26
|
/**
|
|
29
|
-
*
|
|
27
|
+
* Install all commands
|
|
30
28
|
*/
|
|
31
29
|
export async function install(commands: CommandResult[]) {
|
|
32
30
|
try {
|
|
@@ -40,7 +38,7 @@ export async function install(commands: CommandResult[]) {
|
|
|
40
38
|
}
|
|
41
39
|
|
|
42
40
|
// Then run non-interactive
|
|
43
|
-
if (command.nonInteractive) {
|
|
41
|
+
if (command.nonInteractive.length > 0) {
|
|
44
42
|
// For non-interactive, we show a spinner
|
|
45
43
|
display(`Running command: ${command.nonInteractive[0]}`, "loading");
|
|
46
44
|
await runCommand(command.nonInteractive[0] as string, false);
|
package/src/orchestrator.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { buildCommands, buildUninstallCommands } from "./build_command.js";
|
|
2
2
|
import { getConfigObject } from "./config_reader.js";
|
|
3
|
-
import { display
|
|
3
|
+
import { display } from "./display.js";
|
|
4
4
|
import { install } from "./install.js";
|
|
5
5
|
import type { ConfigType } from "./types/index.js";
|
|
6
6
|
import { outro } from "@clack/prompts";
|
|
@@ -38,14 +38,13 @@ export const orchestrator = (
|
|
|
38
38
|
|
|
39
39
|
if (isConfigTypeArray(config)) {
|
|
40
40
|
const commands = buildCommands(config);
|
|
41
|
+
|
|
41
42
|
await install(commands);
|
|
42
|
-
|
|
43
|
-
process.stdout.write("\x07");
|
|
43
|
+
display("Packages installed successfully", "success");
|
|
44
44
|
outro("Done!");
|
|
45
45
|
} else {
|
|
46
46
|
await install(config);
|
|
47
|
-
|
|
48
|
-
stopSpinner("Packages from package.json installed successfully");
|
|
47
|
+
display("Packages from package.json installed successfully", "success");
|
|
49
48
|
outro("Done!");
|
|
50
49
|
}
|
|
51
50
|
});
|
|
@@ -64,7 +63,7 @@ export const orchestrator = (
|
|
|
64
63
|
if (isConfigTypeArray(config)) {
|
|
65
64
|
const commands = buildUninstallCommands(config);
|
|
66
65
|
await install(commands);
|
|
67
|
-
|
|
66
|
+
display("Packages uninstalled successfully", "success");
|
|
68
67
|
outro("Done!");
|
|
69
68
|
}
|
|
70
69
|
});
|
package/src/types/index.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
export interface ConfigType {
|
|
2
|
-
name: string;
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
export interface ConfigType {
|
|
2
|
+
name: string;
|
|
3
|
+
description?: string;
|
|
4
|
+
packageManager: string;
|
|
5
|
+
packages: { command: string; interactive: boolean }[];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface PackageType {
|
|
9
|
+
command: string;
|
|
10
|
+
interactive: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface CommandResult {
|
|
14
|
+
name: string;
|
|
15
|
+
interactive: string[];
|
|
16
|
+
nonInteractive: string[];
|
|
17
|
+
}
|