@dawitworku/projectcli 0.2.2 → 3.0.0

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/src/preflight.js CHANGED
@@ -1,5 +1,30 @@
1
1
  const { spawn } = require("node:child_process");
2
2
 
3
+ function getInstallHint(binary) {
4
+ const bin = String(binary || "").toLowerCase();
5
+ if (bin === "git") return "Install Git: https://git-scm.com/downloads";
6
+ if (bin === "node" || bin === "npm")
7
+ return "Install Node.js (includes npm): https://nodejs.org/en/download";
8
+ if (bin === "pnpm") return "Install pnpm: https://pnpm.io/installation";
9
+ if (bin === "yarn")
10
+ return "Install Yarn: https://yarnpkg.com/getting-started/install";
11
+ if (bin === "bun") return "Install Bun: https://bun.sh/docs/installation";
12
+ if (bin === "cargo" || bin === "rustc")
13
+ return "Install Rust: https://rustup.rs";
14
+ if (bin === "go") return "Install Go: https://go.dev/dl/";
15
+ if (bin === "python" || bin === "python3")
16
+ return "Install Python: https://www.python.org/downloads/";
17
+ if (bin === "poetry")
18
+ return "Install Poetry: https://python-poetry.org/docs/#installation";
19
+ if (bin === "php") return "Install PHP: https://www.php.net/downloads";
20
+ if (bin === "dotnet")
21
+ return "Install .NET SDK: https://dotnet.microsoft.com/download";
22
+ if (bin === "java" || bin === "javac")
23
+ return "Install a JDK: https://adoptium.net/";
24
+ if (bin === "dart") return "Install Dart SDK: https://dart.dev/get-dart";
25
+ return null;
26
+ }
27
+
3
28
  function checkBinary(binary, args = ["--version"]) {
4
29
  return new Promise((resolve) => {
5
30
  const child = spawn(binary, args, {
@@ -22,4 +47,5 @@ function checkBinaries(binaries) {
22
47
  module.exports = {
23
48
  checkBinary,
24
49
  checkBinaries,
50
+ getInstallHint,
25
51
  };
package/src/preset.js ADDED
@@ -0,0 +1,59 @@
1
+ const chalk = require("chalk");
2
+
3
+ const { loadConfig, saveConfig, CONFIG_PATH } = require("./config");
4
+ const { listPresets, getPreset } = require("./presets");
5
+
6
+ function printPresetList(effectiveConfig) {
7
+ console.log(chalk.bold("\nPresets:"));
8
+ for (const id of listPresets(effectiveConfig)) {
9
+ const p = getPreset(id, effectiveConfig);
10
+ console.log(`- ${p.id}: ${chalk.dim(p.label)}`);
11
+ }
12
+ console.log("");
13
+ }
14
+
15
+ async function runPreset({ prompt, argv, effectiveConfig }) {
16
+ const args = Array.isArray(argv) ? argv : [];
17
+ const sub = args[0];
18
+
19
+ if (!sub || sub === "list") {
20
+ printPresetList(effectiveConfig);
21
+ return;
22
+ }
23
+
24
+ if (sub === "use") {
25
+ const presetArg = args[1];
26
+ const preset = getPreset(presetArg, effectiveConfig);
27
+
28
+ const config = loadConfig();
29
+
30
+ if (!presetArg) {
31
+ const { picked } = await prompt([
32
+ {
33
+ type: "list",
34
+ name: "picked",
35
+ message: "Choose a preset:",
36
+ choices: listPresets(effectiveConfig),
37
+ default: config.preset || preset.id,
38
+ },
39
+ ]);
40
+ saveConfig({ preset: picked });
41
+ console.log(chalk.green(`\n✓ Preset set to: ${picked}`));
42
+ console.log(chalk.dim(`Config: ${CONFIG_PATH}`));
43
+ return;
44
+ }
45
+
46
+ saveConfig({ preset: preset.id });
47
+ console.log(chalk.green(`\n✓ Preset set to: ${preset.id}`));
48
+ console.log(chalk.dim(`Config: ${CONFIG_PATH}`));
49
+ return;
50
+ }
51
+
52
+ throw new Error(
53
+ `Unknown preset subcommand: ${sub}. Try: projectcli preset list | projectcli preset use <name>`
54
+ );
55
+ }
56
+
57
+ module.exports = {
58
+ runPreset,
59
+ };
@@ -0,0 +1,124 @@
1
+ const PRESETS = {
2
+ minimal: {
3
+ id: "minimal",
4
+ label: "Minimal",
5
+ defaults: {
6
+ packageManager: null,
7
+ js: {
8
+ formatter: false,
9
+ linter: false,
10
+ tests: false,
11
+ },
12
+ extras: {
13
+ ci: false,
14
+ docker: false,
15
+ devcontainer: false,
16
+ license: true,
17
+ },
18
+ },
19
+ },
20
+
21
+ startup: {
22
+ id: "startup",
23
+ label: "Startup",
24
+ defaults: {
25
+ packageManager: "pnpm",
26
+ js: {
27
+ formatter: true,
28
+ linter: true,
29
+ tests: true,
30
+ },
31
+ extras: {
32
+ ci: true,
33
+ docker: true,
34
+ devcontainer: false,
35
+ license: true,
36
+ },
37
+ },
38
+ },
39
+
40
+ strict: {
41
+ id: "strict",
42
+ label: "Strict",
43
+ defaults: {
44
+ packageManager: "pnpm",
45
+ js: {
46
+ formatter: true,
47
+ linter: true,
48
+ tests: true,
49
+ },
50
+ extras: {
51
+ ci: true,
52
+ docker: true,
53
+ devcontainer: true,
54
+ license: true,
55
+ },
56
+ },
57
+ },
58
+
59
+ enterprise: {
60
+ id: "enterprise",
61
+ label: "Enterprise",
62
+ defaults: {
63
+ packageManager: "pnpm",
64
+ js: {
65
+ formatter: true,
66
+ linter: true,
67
+ tests: true,
68
+ },
69
+ extras: {
70
+ ci: true,
71
+ docker: true,
72
+ devcontainer: true,
73
+ license: true,
74
+ },
75
+ },
76
+ },
77
+ };
78
+
79
+ const { getPluginPresets } = require("../plugins/contributions");
80
+
81
+ function getAllPresets(effectiveConfig) {
82
+ const out = { ...PRESETS };
83
+
84
+ const pluginPresets = getPluginPresets(effectiveConfig);
85
+ for (const p of pluginPresets) {
86
+ if (!p || typeof p.id !== "string") continue;
87
+ const id = p.id.trim().toLowerCase();
88
+ if (!id) continue;
89
+ // Plugin presets can extend the catalog; do not override built-ins.
90
+ if (out[id]) continue;
91
+
92
+ out[id] = {
93
+ id,
94
+ label: typeof p.label === "string" ? p.label : id,
95
+ defaults: p.defaults && typeof p.defaults === "object" ? p.defaults : {},
96
+ pluginId: p.pluginId,
97
+ };
98
+ }
99
+
100
+ return out;
101
+ }
102
+
103
+ function listPresets(effectiveConfig) {
104
+ return Object.keys(getAllPresets(effectiveConfig));
105
+ }
106
+
107
+ function getPreset(presetId, effectiveConfig) {
108
+ const all = getAllPresets(effectiveConfig);
109
+ if (typeof presetId !== "string") return all.startup || PRESETS.startup;
110
+ const key = presetId.trim().toLowerCase();
111
+ return all[key] || all.startup || PRESETS.startup;
112
+ }
113
+
114
+ function describePreset(presetId, effectiveConfig) {
115
+ const p = getPreset(presetId, effectiveConfig);
116
+ return { id: p.id, label: p.label, defaults: p.defaults };
117
+ }
118
+
119
+ module.exports = {
120
+ PRESETS,
121
+ listPresets,
122
+ getPreset,
123
+ describePreset,
124
+ };
@@ -0,0 +1,91 @@
1
+ // V3 registry wrapper.
2
+ // Combines the legacy built-in registry with plugin-provided generators.
3
+
4
+ const legacy = require("../registry_legacy");
5
+ const { getPluginRegistryAdditions } = require("../plugins/contributions");
6
+
7
+ function normalizeLanguageName(name) {
8
+ return String(name || "").trim();
9
+ }
10
+
11
+ function normalizeFrameworkName(name) {
12
+ return String(name || "").trim();
13
+ }
14
+
15
+ function getPluginRegistryMap(effectiveConfig) {
16
+ const additions = getPluginRegistryAdditions(effectiveConfig);
17
+ const out = {};
18
+
19
+ for (const add of additions) {
20
+ const languages = add.languages;
21
+ if (!languages || typeof languages !== "object") continue;
22
+
23
+ for (const langKey of Object.keys(languages)) {
24
+ const langName = normalizeLanguageName(langKey);
25
+ if (!langName) continue;
26
+
27
+ const frameworks = languages[langKey];
28
+ if (!frameworks || typeof frameworks !== "object") continue;
29
+
30
+ if (!out[langName]) out[langName] = {};
31
+
32
+ for (const fwKey of Object.keys(frameworks)) {
33
+ const fwName = normalizeFrameworkName(fwKey);
34
+ if (!fwName) continue;
35
+ const gen = frameworks[fwKey];
36
+ if (!gen) continue;
37
+
38
+ // Do not override existing plugin framework entries.
39
+ if (!out[langName][fwName]) {
40
+ out[langName][fwName] = gen;
41
+ }
42
+ }
43
+ }
44
+ }
45
+
46
+ return out;
47
+ }
48
+
49
+ function getLanguages(effectiveConfig) {
50
+ const base = legacy.getLanguages();
51
+ const pluginMap = getPluginRegistryMap(effectiveConfig);
52
+
53
+ const extra = Object.keys(pluginMap);
54
+ const merged = [...base];
55
+ for (const lang of extra) {
56
+ if (!merged.includes(lang)) merged.push(lang);
57
+ }
58
+
59
+ return merged;
60
+ }
61
+
62
+ function getFrameworks(language, effectiveConfig) {
63
+ const lang = normalizeLanguageName(language);
64
+ const base = legacy.getFrameworks(lang);
65
+ const pluginMap = getPluginRegistryMap(effectiveConfig);
66
+ const pluginFrameworks = pluginMap[lang] ? Object.keys(pluginMap[lang]) : [];
67
+
68
+ const merged = [...base];
69
+ for (const fw of pluginFrameworks) {
70
+ if (!merged.includes(fw)) merged.push(fw);
71
+ }
72
+
73
+ return merged;
74
+ }
75
+
76
+ function getGenerator(language, framework, effectiveConfig) {
77
+ const lang = normalizeLanguageName(language);
78
+ const fw = normalizeFrameworkName(framework);
79
+
80
+ const base = legacy.getGenerator(lang, fw);
81
+ if (base) return base;
82
+
83
+ const pluginMap = getPluginRegistryMap(effectiveConfig);
84
+ return pluginMap[lang]?.[fw] || null;
85
+ }
86
+
87
+ module.exports = {
88
+ getLanguages,
89
+ getFrameworks,
90
+ getGenerator,
91
+ };