mnm-node-manager 0.1.0__py3-none-any.whl
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.
mnm/__init__.py
ADDED
|
File without changes
|
mnm/main.py
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import subprocess
|
|
4
|
+
import shutil
|
|
5
|
+
import json
|
|
6
|
+
|
|
7
|
+
# Ensure questionary is installed
|
|
8
|
+
try:
|
|
9
|
+
import questionary
|
|
10
|
+
except ImportError:
|
|
11
|
+
# In a packaged environment, dependencies should be handled by setup.py/pip.
|
|
12
|
+
# But we keep this as a fallback if run directly.
|
|
13
|
+
print("Module 'questionary' not found. Installing...")
|
|
14
|
+
subprocess.check_call([sys.executable, "-m", "pip", "install", "questionary"])
|
|
15
|
+
import questionary
|
|
16
|
+
|
|
17
|
+
def get_nvm_path():
|
|
18
|
+
# Try to find NVM directory
|
|
19
|
+
potential_paths = [
|
|
20
|
+
os.environ.get('NVM_HOME'),
|
|
21
|
+
os.environ.get('NVM_SYMLINK'),
|
|
22
|
+
r"D:\program\nvm",
|
|
23
|
+
r"C:\Users\HP\AppData\Roaming\nvm",
|
|
24
|
+
os.path.expanduser("~\\AppData\\Roaming\\nvm")
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
for path in potential_paths:
|
|
28
|
+
if path and os.path.exists(path) and os.path.isdir(path):
|
|
29
|
+
return path
|
|
30
|
+
return None
|
|
31
|
+
|
|
32
|
+
def get_installed_node_versions(nvm_path):
|
|
33
|
+
if not nvm_path:
|
|
34
|
+
return []
|
|
35
|
+
|
|
36
|
+
versions = []
|
|
37
|
+
try:
|
|
38
|
+
for item in os.listdir(nvm_path):
|
|
39
|
+
if item.startswith('v') and os.path.isdir(os.path.join(nvm_path, item)):
|
|
40
|
+
parts = item[1:].split('.')
|
|
41
|
+
if len(parts) >= 1 and parts[0].isdigit():
|
|
42
|
+
versions.append(item)
|
|
43
|
+
except Exception as e:
|
|
44
|
+
print(f"Error reading versions: {e}")
|
|
45
|
+
|
|
46
|
+
return sorted(versions, key=lambda s: [int(u) for u in s[1:].split('.')], reverse=True)
|
|
47
|
+
|
|
48
|
+
def show_header():
|
|
49
|
+
os.system('cls' if os.name == 'nt' else 'clear')
|
|
50
|
+
print("\n 🚀 \033[1;36mMNM - My Node Manager\033[0m")
|
|
51
|
+
print(" \033[90mInteractive Node.js, NPM & Angular Switcher\033[0m\n")
|
|
52
|
+
|
|
53
|
+
def get_node_modules_path():
|
|
54
|
+
# Attempt to find global node_modules
|
|
55
|
+
try:
|
|
56
|
+
# 1. Try to deduce from node executable location
|
|
57
|
+
node_path = shutil.which('node')
|
|
58
|
+
if node_path:
|
|
59
|
+
# Common structure:
|
|
60
|
+
# Windows: <prefix>/node.exe -> <prefix>/node_modules
|
|
61
|
+
# Linux/Unix: <prefix>/bin/node -> <prefix>/lib/node_modules
|
|
62
|
+
base_dir = os.path.dirname(node_path)
|
|
63
|
+
|
|
64
|
+
# Windows check
|
|
65
|
+
win_modules = os.path.join(base_dir, 'node_modules')
|
|
66
|
+
if os.path.exists(win_modules):
|
|
67
|
+
return win_modules
|
|
68
|
+
|
|
69
|
+
# Unix check
|
|
70
|
+
unix_modules = os.path.join(os.path.dirname(base_dir), 'lib', 'node_modules')
|
|
71
|
+
if os.path.exists(unix_modules):
|
|
72
|
+
return unix_modules
|
|
73
|
+
|
|
74
|
+
# 2. Fallback to npm root -g (slower but reliable)
|
|
75
|
+
# Only run if we really have to
|
|
76
|
+
return subprocess.check_output("npm root -g", shell=True).decode().strip()
|
|
77
|
+
except:
|
|
78
|
+
return None
|
|
79
|
+
|
|
80
|
+
def get_package_version(package_name):
|
|
81
|
+
try:
|
|
82
|
+
modules_path = get_node_modules_path()
|
|
83
|
+
if not modules_path:
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
pkg_json_path = os.path.join(modules_path, package_name, 'package.json')
|
|
87
|
+
if os.path.exists(pkg_json_path):
|
|
88
|
+
with open(pkg_json_path, 'r', encoding='utf-8') as f:
|
|
89
|
+
data = json.load(f)
|
|
90
|
+
return data.get('version')
|
|
91
|
+
except:
|
|
92
|
+
pass
|
|
93
|
+
return None
|
|
94
|
+
|
|
95
|
+
def show_versions():
|
|
96
|
+
print("\n 🔍 \033[1;36mCurrent Environment Versions:\033[0m")
|
|
97
|
+
try:
|
|
98
|
+
print(" \033[33mNode.js:\033[0m ", end="")
|
|
99
|
+
sys.stdout.flush()
|
|
100
|
+
os.system("node --version")
|
|
101
|
+
|
|
102
|
+
print(" \033[33mNPM:\033[0m ", end="")
|
|
103
|
+
sys.stdout.flush()
|
|
104
|
+
# npm -v is usually fast enough, reading package.json for npm is tricky as it's often nested in node dict
|
|
105
|
+
os.system("npm --version")
|
|
106
|
+
|
|
107
|
+
print(" \033[33mAngular:\033[0m ", end="")
|
|
108
|
+
sys.stdout.flush()
|
|
109
|
+
|
|
110
|
+
# Fast check
|
|
111
|
+
ng_ver = get_package_version('@angular/cli')
|
|
112
|
+
if ng_ver:
|
|
113
|
+
print(ng_ver)
|
|
114
|
+
else:
|
|
115
|
+
# Fallback
|
|
116
|
+
try:
|
|
117
|
+
# Check if ng is installed
|
|
118
|
+
if shutil.which('ng'):
|
|
119
|
+
# Run full command if we can't find package.json (rare)
|
|
120
|
+
os.system("ng version")
|
|
121
|
+
else:
|
|
122
|
+
print("Not Installed")
|
|
123
|
+
except:
|
|
124
|
+
print("Not Found")
|
|
125
|
+
|
|
126
|
+
except Exception as e:
|
|
127
|
+
print(f"Error checking versions: {e}")
|
|
128
|
+
|
|
129
|
+
def list_node_versions(nvm_path):
|
|
130
|
+
versions = get_installed_node_versions(nvm_path)
|
|
131
|
+
print("\n 📦 \033[1;36mInstalled Node Versions:\033[0m")
|
|
132
|
+
if not versions:
|
|
133
|
+
print(" (No versions found in NVM directory)")
|
|
134
|
+
else:
|
|
135
|
+
for v in versions:
|
|
136
|
+
print(f" - \033[32m{v}\033[0m")
|
|
137
|
+
print("")
|
|
138
|
+
|
|
139
|
+
def interactive_mode(nvm_path):
|
|
140
|
+
show_header()
|
|
141
|
+
|
|
142
|
+
if not nvm_path:
|
|
143
|
+
print("\033[91m[!] Could not locate NVM directory.\033[0m")
|
|
144
|
+
return
|
|
145
|
+
|
|
146
|
+
node_versions = get_installed_node_versions(nvm_path)
|
|
147
|
+
if not node_versions:
|
|
148
|
+
print("\033[91m[!] No Node.js versions found in NVM.\033[0m")
|
|
149
|
+
return
|
|
150
|
+
|
|
151
|
+
# --- Menu 1: Node Version ---
|
|
152
|
+
selected_node = questionary.select(
|
|
153
|
+
"Choose Node.js Version:",
|
|
154
|
+
choices=node_versions
|
|
155
|
+
).ask()
|
|
156
|
+
|
|
157
|
+
if not selected_node: return
|
|
158
|
+
|
|
159
|
+
print(f"\033[32m✔ Selected Node: {selected_node}\033[0m")
|
|
160
|
+
|
|
161
|
+
# --- Menu 2: NPM Version ---
|
|
162
|
+
npm_choices = ["Keep Default (Don't Change)", "Latest", "6.14.17 (For Node 14)", "8.x", "9.x", "Custom Input"]
|
|
163
|
+
selected_npm = questionary.select(
|
|
164
|
+
"Choose NPM Version:",
|
|
165
|
+
choices=npm_choices
|
|
166
|
+
).ask()
|
|
167
|
+
|
|
168
|
+
if not selected_npm: return
|
|
169
|
+
|
|
170
|
+
npm_version_arg = ""
|
|
171
|
+
if selected_npm == "Custom Input":
|
|
172
|
+
npm_version_arg = questionary.text("Enter NPM Version:").ask()
|
|
173
|
+
elif "Keep Default" in selected_npm:
|
|
174
|
+
npm_version_arg = None
|
|
175
|
+
elif "Latest" in selected_npm:
|
|
176
|
+
npm_version_arg = "latest"
|
|
177
|
+
elif "6.14.17" in selected_npm:
|
|
178
|
+
npm_version_arg = "6.14.17"
|
|
179
|
+
else:
|
|
180
|
+
npm_version_arg = selected_npm
|
|
181
|
+
|
|
182
|
+
if npm_version_arg:
|
|
183
|
+
print(f"\033[33m✔ Selected NPM: {npm_version_arg}\033[0m")
|
|
184
|
+
else:
|
|
185
|
+
print(f"\033[33m✔ Selected NPM: Default\033[0m")
|
|
186
|
+
|
|
187
|
+
# --- Menu 3: Angular Version ---
|
|
188
|
+
ng_choices = ["Skip (Don't Install)", "12.2.11 (HRS Project)", "Latest", "13.3.11", "14.2.13", "15.2.10", "16.2.12", "17.3.0", "Custom Input"]
|
|
189
|
+
selected_ng = questionary.select(
|
|
190
|
+
"Choose Angular CLI Version:",
|
|
191
|
+
choices=ng_choices
|
|
192
|
+
).ask()
|
|
193
|
+
|
|
194
|
+
if not selected_ng: return
|
|
195
|
+
|
|
196
|
+
ng_version_arg = ""
|
|
197
|
+
if selected_ng == "Custom Input":
|
|
198
|
+
ng_version_arg = questionary.text("Enter Angular CLI Version:").ask()
|
|
199
|
+
elif "12.2.11" in selected_ng:
|
|
200
|
+
ng_version_arg = "12.2.11"
|
|
201
|
+
elif "Latest" in selected_ng:
|
|
202
|
+
ng_version_arg = "latest"
|
|
203
|
+
elif "Skip" in selected_ng:
|
|
204
|
+
ng_version_arg = None
|
|
205
|
+
else:
|
|
206
|
+
ng_version_arg = selected_ng.split(' ')[0]
|
|
207
|
+
|
|
208
|
+
if ng_version_arg:
|
|
209
|
+
print(f"\033[31m✔ Selected Angular: {ng_version_arg}\033[0m")
|
|
210
|
+
else:
|
|
211
|
+
print(f"\033[31m✔ Selected Angular: Skipped\033[0m")
|
|
212
|
+
|
|
213
|
+
# --- Execution ---
|
|
214
|
+
print("\n" + "="*40)
|
|
215
|
+
print("⚡ Configuring Environment...")
|
|
216
|
+
print("="*40 + "\n")
|
|
217
|
+
|
|
218
|
+
cmds = []
|
|
219
|
+
clean_version = selected_node.replace('v', '')
|
|
220
|
+
|
|
221
|
+
# 1. NVM Use
|
|
222
|
+
cmds.append(f"nvm use {clean_version}")
|
|
223
|
+
|
|
224
|
+
# 2. NPM Install
|
|
225
|
+
if npm_version_arg:
|
|
226
|
+
cmds.append(f"npm install -g npm@{npm_version_arg} --force")
|
|
227
|
+
|
|
228
|
+
# 3. Angular Install
|
|
229
|
+
if ng_version_arg:
|
|
230
|
+
cmds.append(f"npm install -g @angular/cli@{ng_version_arg} --force")
|
|
231
|
+
|
|
232
|
+
# 4. Verify
|
|
233
|
+
# Note: We can't easily verify within the same python process if nvm use changes shell env.
|
|
234
|
+
# But nvm use usually changes symlink, so subsequent calls might work.
|
|
235
|
+
|
|
236
|
+
final_cmd = " && ".join(cmds)
|
|
237
|
+
print(f"\033[90mExecuting: {final_cmd}\033[0m\n")
|
|
238
|
+
|
|
239
|
+
# Execute command
|
|
240
|
+
os.system(final_cmd)
|
|
241
|
+
|
|
242
|
+
# Print versions after update
|
|
243
|
+
print("\n" + "="*40 + "\n")
|
|
244
|
+
show_versions()
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def show_help():
|
|
248
|
+
show_header()
|
|
249
|
+
print(" \033[1;33mUsage:\033[0m")
|
|
250
|
+
print(" mnm For interactive mode")
|
|
251
|
+
print(" mnm use <version> Switch Node.js version directly (e.g. mnm use 14)")
|
|
252
|
+
print(" mnm -l, --list List installed Node.js versions")
|
|
253
|
+
print(" mnm -v, --version Show current Node, NPM, and Angular versions")
|
|
254
|
+
print(" mnm help Show this help message")
|
|
255
|
+
print("\n")
|
|
256
|
+
|
|
257
|
+
def main():
|
|
258
|
+
args = sys.argv[1:]
|
|
259
|
+
|
|
260
|
+
# Handle commands
|
|
261
|
+
if args:
|
|
262
|
+
cmd = args[0].lower()
|
|
263
|
+
|
|
264
|
+
if cmd in ['-v', '--version', 'version']:
|
|
265
|
+
show_versions()
|
|
266
|
+
return
|
|
267
|
+
|
|
268
|
+
if cmd in ['-l', '--list', 'list']:
|
|
269
|
+
nvm_path = get_nvm_path()
|
|
270
|
+
list_node_versions(nvm_path)
|
|
271
|
+
return
|
|
272
|
+
|
|
273
|
+
# Flexible "use" command: mnm use 14
|
|
274
|
+
if cmd == 'use' and len(args) > 1:
|
|
275
|
+
target = args[1]
|
|
276
|
+
# remove 'v' if user typed it
|
|
277
|
+
if target.startswith('v'):
|
|
278
|
+
target = target[1:]
|
|
279
|
+
|
|
280
|
+
print(f"Switching to Node {target}...")
|
|
281
|
+
os.system(f"nvm use {target}")
|
|
282
|
+
return
|
|
283
|
+
|
|
284
|
+
if cmd in ['help', '--help', '-h']:
|
|
285
|
+
show_help()
|
|
286
|
+
return
|
|
287
|
+
|
|
288
|
+
# Default to interactive
|
|
289
|
+
nvm_path = get_nvm_path()
|
|
290
|
+
interactive_mode(nvm_path)
|
|
291
|
+
|
|
292
|
+
if __name__ == "__main__":
|
|
293
|
+
main()
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mnm-node-manager
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Interactive Node.js, NPM, and Angular CLI Version Manager
|
|
5
|
+
Home-page: https://github.com/yourusername/mnm
|
|
6
|
+
Author: CodeX
|
|
7
|
+
Author-email: your.email@example.com
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.6
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
Requires-Dist: questionary
|
|
14
|
+
Dynamic: author
|
|
15
|
+
Dynamic: author-email
|
|
16
|
+
Dynamic: classifier
|
|
17
|
+
Dynamic: description
|
|
18
|
+
Dynamic: description-content-type
|
|
19
|
+
Dynamic: home-page
|
|
20
|
+
Dynamic: requires-dist
|
|
21
|
+
Dynamic: requires-python
|
|
22
|
+
Dynamic: summary
|
|
23
|
+
|
|
24
|
+
# MNM - My Node Manager
|
|
25
|
+
|
|
26
|
+
**[English](#english) | [Bahasa Indonesia](#bahasa-indonesia)**
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## English
|
|
31
|
+
|
|
32
|
+
**MNM** (My Node Manager) is a simple, interactive CLI tool to manage and switch between different versions of Node.js, NPM, and Angular CLI on Windows (via NVM).
|
|
33
|
+
|
|
34
|
+
It is designed to wrap `nvm-windows` with a friendlier, interactive menu interface.
|
|
35
|
+
|
|
36
|
+
### Features
|
|
37
|
+
- 🚀 Interactive menu to select Node.js versions.
|
|
38
|
+
- 📦 Easily switch NPM versions (including ancient versions for legacy projects).
|
|
39
|
+
- 🅰️ Manage Angular CLI versions globally per project requirements.
|
|
40
|
+
- ⚡ Fast execution.
|
|
41
|
+
|
|
42
|
+
### Requirements
|
|
43
|
+
- Windows
|
|
44
|
+
- `nvm-windows` installed and configured.
|
|
45
|
+
- Python 3.6+
|
|
46
|
+
|
|
47
|
+
### Installation
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install mnm-node-manager
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Usage
|
|
54
|
+
|
|
55
|
+
Simply run:
|
|
56
|
+
```bash
|
|
57
|
+
mnm
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Or for specific commands:
|
|
61
|
+
```bash
|
|
62
|
+
mnm -v # Check current versions
|
|
63
|
+
mnm -l # List installed Node versions
|
|
64
|
+
mnm use <ver> # Switch Node version immediately
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Bahasa Indonesia
|
|
70
|
+
|
|
71
|
+
**MNM** (My Node Manager) adalah alat CLI interaktif sederhana untuk mengelola dan berpindah antar versi Node.js, NPM, dan Angular CLI di Windows (menggunakan NVM).
|
|
72
|
+
|
|
73
|
+
Alat ini dirancang untuk membungkus `nvm-windows` dengan antarmuka menu yang lebih ramah pengguna.
|
|
74
|
+
|
|
75
|
+
### Fitur
|
|
76
|
+
- 🚀 Menu interaktif untuk memilih versi Node.js.
|
|
77
|
+
- 📦 Mudah mengganti versi NPM (termasuk versi lama untuk proyek lawas).
|
|
78
|
+
- 🅰️ Mengelola versi Angular CLI secara global sesuai kebutuhan proyek.
|
|
79
|
+
- ⚡ Eksekusi cepat.
|
|
80
|
+
|
|
81
|
+
### Persyaratan
|
|
82
|
+
- Windows
|
|
83
|
+
- `nvm-windows` sudah terinstall dan dikonfigurasi.
|
|
84
|
+
- Python 3.6+
|
|
85
|
+
|
|
86
|
+
### Instalasi
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
pip install mnm-node-manager
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Penggunaan
|
|
93
|
+
|
|
94
|
+
Cukup jalankan:
|
|
95
|
+
```bash
|
|
96
|
+
mnm
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Atau untuk perintah spesifik:
|
|
100
|
+
```bash
|
|
101
|
+
mnm -v # Cek versi saat ini
|
|
102
|
+
mnm -l # Lihat daftar versi Node yang terinstall
|
|
103
|
+
mnm use <ver> # Ganti versi Node secara langsung
|
|
104
|
+
```
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
mnm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
mnm/main.py,sha256=JMK6tVM_SQwJuM2xT8VkVkm7jp2dsveyYZtQ4n66jPg,9586
|
|
3
|
+
mnm_node_manager-0.1.0.dist-info/METADATA,sha256=mUqTXF4bPbpnFsAzrPKQ5ym4Azvvo3jmjBcySztnHtA,2641
|
|
4
|
+
mnm_node_manager-0.1.0.dist-info/WHEEL,sha256=YCfwYGOYMi5Jhw2fU4yNgwErybb2IX5PEwBKV4ZbdBo,91
|
|
5
|
+
mnm_node_manager-0.1.0.dist-info/entry_points.txt,sha256=WZ9acbefvrBMCPcbRvbFDMK3FZDt9K-zqAOtgUY34qA,38
|
|
6
|
+
mnm_node_manager-0.1.0.dist-info/top_level.txt,sha256=OzgWNkuE-bX9XJp9nDy8RFDoQQkbP82L9KkXMy6epI8,4
|
|
7
|
+
mnm_node_manager-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
mnm
|