pro-cpp-cli-core 1.0.5 → 1.0.7

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.
Files changed (3) hide show
  1. package/README.md +6 -0
  2. package/index.js +85 -73
  3. package/package.json +7 -16
package/README.md CHANGED
@@ -56,6 +56,12 @@ Now `cl.exe` is recognized, and `procpp` can build your code!
56
56
 
57
57
  ---
58
58
 
59
+ 🧐 Why this package?
60
+
61
+ Tired of configuring CMake and tasks.json for days just to test a simple C++ idea? pro-cpp-cli brings modern Web Development DX (like Vite/Nodemon) to the C++ world. Zero configuration. Native C++20 Modules support. Just write code.
62
+
63
+ ---
64
+
59
65
  🐞 Debugging
60
66
 
61
67
  Just press F5! Our `init` command sets up a "Bulletproof" debugger configuration that won't conflict with the watcher.
package/index.js CHANGED
@@ -1,21 +1,48 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * PRO C++ CLI Core (With C++20 Modules Topological Sorter)
5
- * FIX: Restored initProject!
6
- * FIX: Smart post-build artifact routing to .build/ directory!
4
+ * PRO C++ CLI Core (V1.0.7)
5
+ * - Added Environment Check (cl.exe validation)
6
+ * - Added Versioning (-v, --version)
7
+ * - Improved 'init' template for 100% success rate
8
+ * - Native ANSI Colors & Performance Tracking
7
9
  */
8
10
 
9
11
  const { execSync, spawn } = require('child_process');
10
12
  const fs = require('fs');
11
13
  const path = require('path');
14
+ const { performance } = require('perf_hooks');
12
15
 
13
- const [,, command, ...args] = process.argv;
16
+ const packageJson = require('./package.json');
17
+ const [,, command] = process.argv;
14
18
  let currentAppProcess = null;
15
19
  let watchTimeout = null;
16
20
 
17
21
  const BUILD_DIR = path.join(process.cwd(), '.build');
18
22
 
23
+ const colors = {
24
+ reset: "\x1b[0m",
25
+ cyan: "\x1b[36m",
26
+ green: "\x1b[32m",
27
+ yellow: "\x1b[33m",
28
+ red: "\x1b[31m",
29
+ gray: "\x1b[90m",
30
+ bold: "\x1b[1m"
31
+ };
32
+
33
+ // --- UTILS ---
34
+
35
+ function checkEnv() {
36
+ try {
37
+ execSync('cl.exe', { stdio: 'ignore' });
38
+ return true;
39
+ } catch (e) {
40
+ console.error(`\n${colors.red}${colors.bold}❌ MSVC Compiler (cl.exe) NOT FOUND!${colors.reset}`);
41
+ console.log(`${colors.yellow}💡 Fix: Please use "Developer PowerShell for VS 2022" or "Developer Command Prompt".${colors.reset}\n`);
42
+ return false;
43
+ }
44
+ }
45
+
19
46
  function runSyncCommand(cmd) {
20
47
  try {
21
48
  execSync(cmd, { stdio: 'inherit' });
@@ -26,34 +53,26 @@ function runSyncCommand(cmd) {
26
53
  }
27
54
 
28
55
  function cleanupOldBuilds() {
29
- // 1. Clean .build folder
30
56
  if (fs.existsSync(BUILD_DIR)) {
31
57
  const files = fs.readdirSync(BUILD_DIR);
32
58
  files.forEach(file => {
33
- if (file.endsWith('.obj') || file.endsWith('.pdb') || file.endsWith('.ilk') || file.endsWith('.ifc') || file.startsWith('app_build_')) {
59
+ if (['.obj', '.pdb', '.ilk', '.ifc'].some(ext => file.endsWith(ext)) || file.startsWith('app_build_')) {
34
60
  try { fs.unlinkSync(path.join(BUILD_DIR, file)); } catch (err) {}
35
61
  }
36
62
  });
37
63
  }
38
- // 2. Clean root folder (just in case)
39
- const rootFiles = fs.readdirSync(process.cwd());
40
- rootFiles.forEach(file => {
41
- if (file.endsWith('.obj') || file.endsWith('.pdb') || file.endsWith('.ilk') || file.endsWith('.ifc') || (file.startsWith('app_build_') && file.endsWith('.exe'))) {
42
- try { fs.unlinkSync(path.join(process.cwd(), file)); } catch (err) {}
43
- }
44
- });
45
64
  }
46
65
 
47
66
  function getSortedCppFiles() {
48
67
  const fileList = [];
49
-
50
68
  function scanDir(dir) {
69
+ if (!fs.existsSync(dir)) return;
51
70
  const files = fs.readdirSync(dir);
52
71
  for (const file of files) {
53
72
  const filePath = path.join(dir, file);
54
- if (fs.statSync(filePath).isDirectory()) {
55
- // ИГНОРИРУЕМ ПАПКУ .build, ЧТОБЫ ВОЧЕР НЕ СОШЕЛ С УМА
56
- if (file !== 'node_modules' && file !== '.vscode' && file !== '.build') {
73
+ const stat = fs.statSync(filePath);
74
+ if (stat.isDirectory()) {
75
+ if (file !== 'node_modules' && file !== '.vscode' && file !== '.build' && !file.startsWith('.')) {
57
76
  scanDir(filePath);
58
77
  }
59
78
  } else if (filePath.endsWith('.cpp') || filePath.endsWith('.ixx')) {
@@ -63,11 +82,12 @@ function getSortedCppFiles() {
63
82
  }
64
83
  scanDir(process.cwd());
65
84
 
85
+ if (fileList.length === 0) return null;
86
+
66
87
  const fileData = fileList.map(file => {
67
88
  const content = fs.readFileSync(file, 'utf8');
68
89
  const exportsMatch = content.match(/export\s+module\s+([a-zA-Z0-9_]+)\s*;/);
69
90
  const importsMatches = [...content.matchAll(/import\s+([a-zA-Z0-9_]+)\s*;/g)].map(m => m[1]);
70
-
71
91
  return { file, exports: exportsMatch ? exportsMatch[1] : null, imports: importsMatches };
72
92
  });
73
93
 
@@ -79,12 +99,10 @@ function getSortedCppFiles() {
79
99
  if (visited.has(node.file)) return;
80
100
  if (processing.has(node.file)) return;
81
101
  processing.add(node.file);
82
-
83
102
  node.imports.forEach(imp => {
84
103
  const dep = fileData.find(f => f.exports === imp);
85
104
  if (dep) visit(dep);
86
105
  });
87
-
88
106
  processing.delete(node.file);
89
107
  visited.add(node.file);
90
108
  sortedFiles.push(`"${node.file}"`);
@@ -94,68 +112,52 @@ function getSortedCppFiles() {
94
112
  return sortedFiles.join(' ');
95
113
  }
96
114
 
115
+ // --- COMMANDS ---
116
+
97
117
  function initProject() {
98
- console.log("🚀 Initializing PRO C++ Project (C++20 Modules)...");
118
+ console.log(`${colors.cyan}${colors.bold}🚀 Initializing PRO C++ Project...${colors.reset}`);
99
119
  const vscodeDir = path.join(process.cwd(), '.vscode');
100
120
  if (!fs.existsSync(vscodeDir)) fs.mkdirSync(vscodeDir);
101
121
 
102
- // 1. tasks.json
103
- const tasksContent = {
122
+ const tasks = {
104
123
  "version": "2.0.0",
105
124
  "tasks": [{
106
- "type": "cppbuild",
107
- "label": "DEBUG-BUILD-MSVC",
108
- "command": "cl.exe",
109
- "args": ["/std:c++20", "/Zi", "/EHsc", "/nologo", "/Fe${fileDirname}\\.build\\debug_build.exe", "${file}"],
110
- "problemMatcher": ["$msCompile"],
111
- "group": "build"
125
+ "label": "PRO-CPP-BUILD",
126
+ "type": "shell",
127
+ "command": "procpp run",
128
+ "group": { "kind": "build", "isDefault": true }
112
129
  }]
113
130
  };
114
- fs.writeFileSync(path.join(vscodeDir, 'tasks.json'), JSON.stringify(tasksContent, null, 4));
131
+ fs.writeFileSync(path.join(vscodeDir, 'tasks.json'), JSON.stringify(tasks, null, 4));
115
132
 
116
- // 2. c_cpp_properties.json (FIX FOR IDE SQUIGGLES!)
117
- const propertiesContent = {
133
+ const props = {
118
134
  "configurations": [{
119
135
  "name": "Win32",
120
136
  "includePath": ["${workspaceFolder}/**"],
121
137
  "compilerPath": "cl.exe",
122
- "cStandard": "c17",
123
138
  "cppStandard": "c++20",
124
139
  "intelliSenseMode": "windows-msvc-x64",
125
- "compilerArgs": [
126
- "/std:c++20",
127
- "/experimental:module",
128
- "/ifcSearchDir", // Указываем IDE, где искать .ifc файлы!
129
- "${workspaceFolder}/.build"
130
- ]
140
+ "compilerArgs": ["/std:c++20", "/experimental:module", "/ifcSearchDir", "${workspaceFolder}/.build"]
131
141
  }],
132
142
  "version": 4
133
143
  };
134
- fs.writeFileSync(path.join(vscodeDir, 'c_cpp_properties.json'), JSON.stringify(propertiesContent, null, 4));
135
-
136
- // 3. settings.json (Hide .build folder from UI)
137
- const settingsContent = {
138
- "files.exclude": {
139
- ".build": true,
140
- "**/.build": true
141
- },
142
- "C_Cpp.errorSquiggles": "disabled"
143
- };
144
- fs.writeFileSync(path.join(vscodeDir, 'settings.json'), JSON.stringify(settingsContent, null, 4));
144
+ fs.writeFileSync(path.join(vscodeDir, 'c_cpp_properties.json'), JSON.stringify(props, null, 4));
145
145
 
146
- // 4. main.cpp template
147
146
  const mainCppPath = path.join(process.cwd(), 'main.cpp');
148
147
  if (!fs.existsSync(mainCppPath)) {
149
- fs.writeFileSync(mainCppPath, `import std.core;\n// C++20 Modules ready!\nint main() { return 0; }`);
148
+ // Using standard include for max compatibility in template
149
+ fs.writeFileSync(mainCppPath, `#include <iostream>\n\nint main() {\n std::cout << "🚀 PRO C++ is running!" << std::endl;\n return 0;\n}`);
150
150
  }
151
151
 
152
- console.log("✅ Ready! .vscode configs created. IntelliSense is pointed to .build/");
152
+ console.log(`${colors.green}✅ Ready! Use 'procpp watch' to start developing.${colors.reset}`);
153
153
  }
154
154
 
155
155
  function buildAndRun() {
156
+ if (!checkEnv()) return;
157
+
156
158
  const cppFiles = getSortedCppFiles();
157
159
  if (!cppFiles) {
158
- console.error("❌ Error: No .cpp or .ixx files found!");
160
+ console.error(`${colors.red}❌ Error: No .cpp or .ixx files found!${colors.reset}`);
159
161
  return;
160
162
  }
161
163
 
@@ -164,55 +166,65 @@ function buildAndRun() {
164
166
  if (!fs.existsSync(BUILD_DIR)) fs.mkdirSync(BUILD_DIR);
165
167
 
166
168
  const outputExeName = `app_build_${Date.now()}.exe`;
169
+ console.log(`\n${colors.cyan}🔨 Compiling...${colors.reset}`);
167
170
 
168
- console.log(`\n🔨 Compiling with SMART DEPENDENCY GRAPH...`);
169
-
170
- // Компилируем чисто, без странных флагов
171
- const compileCmd = `cl.exe /std:c++20 /nologo /EHsc ${cppFiles} /Fe"${outputExeName}"`;
171
+ const startTime = performance.now();
172
+ const compileCmd = `cl.exe /std:c++20 /nologo /EHsc /Zi ${cppFiles} /Fe"${outputExeName}"`;
172
173
 
173
174
  if (runSyncCommand(compileCmd)) {
174
- // МАГИЯ ПЕРЕНОСА: Двигаем все созданные файлы в папку .build
175
- const files = fs.readdirSync(process.cwd());
176
- files.forEach(file => {
177
- if (file.endsWith('.obj') || file.endsWith('.ifc') || file.endsWith('.pdb') || file.endsWith('.ilk') || file === outputExeName) {
178
- try {
179
- fs.renameSync(path.join(process.cwd(), file), path.join(BUILD_DIR, file));
180
- } catch(e) {}
175
+ const buildTime = ((performance.now() - startTime) / 1000).toFixed(2);
176
+
177
+ // Move artifacts to .build
178
+ fs.readdirSync(process.cwd()).forEach(file => {
179
+ if (['.obj', '.ifc', '.pdb', '.ilk'].some(ext => file.endsWith(ext)) || file === outputExeName) {
180
+ try { fs.renameSync(path.join(process.cwd(), file), path.join(BUILD_DIR, file)); } catch(e) {}
181
181
  }
182
182
  });
183
183
 
184
- console.log(`🟢 RUNNING -> .build\\${outputExeName}\n` + "-".repeat(40));
184
+ console.log(`${colors.green}${colors.bold}⚡ [Success] Compiled in ${buildTime}s${colors.reset}`);
185
+ console.log(`${colors.yellow}🟢 RUNNING -> ${outputExeName}${colors.reset}\n` + `${colors.gray}${"-".repeat(40)}${colors.reset}`);
185
186
 
186
- // Запускаем из папки .build
187
187
  currentAppProcess = spawn(`.\\.build\\${outputExeName}`, [], { shell: true, stdio: 'inherit' });
188
188
  currentAppProcess.on('close', (code) => {
189
- if (code !== null) console.log("-".repeat(40) + `\n🛑 Process exited with code ${code}`);
189
+ if (code !== null) console.log(`${colors.gray}${"-".repeat(40)}${colors.reset}\n${colors.red}🛑 Process exited (code ${code})${colors.reset}`);
190
190
  });
191
191
  } else {
192
- console.log(`\n❌ BUILD FAILED`);
192
+ console.log(`\n${colors.red}${colors.bold}❌ BUILD FAILED${colors.reset}`);
193
193
  }
194
194
  }
195
195
 
196
196
  function watchProject() {
197
- console.log("👀 PRO C++ Watcher Started (Mode: Smart C++20 Modules)");
197
+ if (!checkEnv()) return;
198
+ console.clear();
199
+ console.log(`${colors.cyan}${colors.bold}👀 PRO C++ Watcher Started${colors.reset}`);
198
200
  buildAndRun();
199
201
 
200
202
  fs.watch(process.cwd(), { recursive: true }, (eventType, filename) => {
201
- // Игнорируем всё, что происходит внутри папки .build
202
203
  if (filename && (filename.endsWith('.cpp') || filename.endsWith('.ixx') || filename.endsWith('.h')) && !filename.includes('.build')) {
203
204
  clearTimeout(watchTimeout);
204
205
  watchTimeout = setTimeout(() => {
205
206
  console.clear();
206
- console.log(`[${new Date().toLocaleTimeString()}] Change detected: ${filename}`);
207
+ console.log(`${colors.gray}[${new Date().toLocaleTimeString()}] Change detected: ${filename}${colors.reset}`);
207
208
  buildAndRun();
208
209
  }, 300);
209
210
  }
210
211
  });
211
212
  }
212
213
 
214
+ // --- CLI ROUTER ---
215
+
216
+ const versionFlags = ['-v', '--version', 'version'];
217
+ if (versionFlags.includes(command)) {
218
+ console.log(`${colors.bold}pro-cpp-cli-core v${packageJson.version}${colors.reset}`);
219
+ process.exit(0);
220
+ }
221
+
213
222
  switch (command) {
214
223
  case 'init': initProject(); break;
215
224
  case 'run': buildAndRun(); break;
216
225
  case 'watch': watchProject(); break;
217
- default: console.log("🛠️ PRO CPP CLI\nUsage: procpp <init|run|watch>"); break;
226
+ default:
227
+ console.log(`${colors.bold}🛠️ PRO CPP CLI v${packageJson.version}${colors.reset}`);
228
+ console.log(`Usage: procpp <init|run|watch|version>`);
229
+ break;
218
230
  }
package/package.json CHANGED
@@ -1,29 +1,20 @@
1
1
  {
2
2
  "name": "pro-cpp-cli-core",
3
- "version": "1.0.5",
4
- "repository": {
5
- "type": "git",
6
- "url": "git+https://github.com/anton-po-github/pro-cpp-cli-core.git"
7
- },
8
- "bugs": {
9
- "url": "https://github.com/anton-po-github/pro-cpp-cli-core/issues"
10
- },
11
- "homepage": "https://github.com/anton-po-github/pro-cpp-cli-core#readme",
12
- "description": "The ultimate C++ Developer Experience for Windows",
3
+ "version": "1.0.7",
4
+ "description": "The ultimate C++ Developer Experience for Windows.",
13
5
  "main": "index.js",
14
6
  "bin": {
15
- "procpp": "index.js"
16
- },
17
- "scripts": {
18
- "start": "node index.js"
7
+ "procpp": "./index.js"
19
8
  },
20
9
  "keywords": [
21
10
  "cpp",
22
11
  "c++",
23
12
  "cli",
24
13
  "watch",
25
- "build"
14
+ "hot-reload",
15
+ "c++20",
16
+ "msvc"
26
17
  ],
27
18
  "author": "PRO Developer",
28
19
  "license": "MIT"
29
- }
20
+ }