@fredlackey/devutils 0.0.13 → 0.0.15

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 CHANGED
@@ -27,11 +27,38 @@ That's it. DevUtils CLI detects your operating system and installs everything yo
27
27
 
28
28
  ## Installation
29
29
 
30
+ ### If You Have Node.js Installed
31
+
32
+ If you already have Node.js 18+ on your machine, install DevUtils CLI as a global npm package:
33
+
30
34
  ```bash
31
35
  npm install -g @fredlackey/devutils
32
36
  ```
33
37
 
34
- **Requirements:** Node.js 18+
38
+ ### Fresh Machine (No Node.js)
39
+
40
+ For a fresh machine without Node.js, run the bootstrap script. It installs everything you need: build tools, nvm, Node.js LTS, and DevUtils CLI.
41
+
42
+ **macOS:**
43
+ ```bash
44
+ bash -c "$(curl -LsS https://raw.github.com/fredlackey/devutils-cli/main/setup.sh)"
45
+ ```
46
+
47
+ **Ubuntu / Debian / Raspberry Pi OS:**
48
+ ```bash
49
+ bash -c "$(wget -qO - https://raw.github.com/fredlackey/devutils-cli/main/setup.sh)"
50
+ ```
51
+
52
+ **Amazon Linux / RHEL / Fedora:**
53
+ ```bash
54
+ bash -c "$(curl -LsS https://raw.github.com/fredlackey/devutils-cli/main/setup.sh)"
55
+ ```
56
+
57
+ The script is interactive by default. For automated/CI environments, add `--no-prompt`:
58
+
59
+ ```bash
60
+ bash -c "$(curl -LsS https://raw.github.com/fredlackey/devutils-cli/main/setup.sh)" -- --no-prompt
61
+ ```
35
62
 
36
63
  ## Quick Start
37
64
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fredlackey/devutils",
3
- "version": "0.0.13",
3
+ "version": "0.0.15",
4
4
  "description": "A globally-installable Node.js CLI toolkit for bootstrapping and configuring development environments across any machine.",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/cli.js CHANGED
@@ -13,6 +13,8 @@ const statusCommand = require('./commands/status');
13
13
  const identityCommand = require('./commands/identity');
14
14
  const ignoreCommand = require('./commands/ignore');
15
15
  const installCommand = require('./commands/install');
16
+ const versionCommand = require('./commands/version');
17
+ const updateCommand = require('./commands/update');
16
18
  const { installCompletion, uninstallCompletion } = require('./completion');
17
19
 
18
20
  /**
@@ -36,6 +38,8 @@ function run() {
36
38
  program.addCommand(identityCommand);
37
39
  program.addCommand(ignoreCommand);
38
40
  program.addCommand(installCommand);
41
+ program.addCommand(versionCommand);
42
+ program.addCommand(updateCommand);
39
43
 
40
44
  // Setup command - install essential tools
41
45
  const setupCommand = require('./commands/setup');
@@ -0,0 +1,142 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * @fileoverview Update command - Update this package to the latest version.
5
+ * Queries the NPM registry and installs the latest version globally.
6
+ */
7
+
8
+ const { Command } = require('commander');
9
+ const { execSync, spawn } = require('child_process');
10
+ const pkg = require('../../package.json');
11
+
12
+ /**
13
+ * The name of this package on NPM
14
+ */
15
+ const PACKAGE_NAME = pkg.name;
16
+
17
+ /**
18
+ * Get the latest version of this package from the NPM registry
19
+ * @returns {string|null} The latest version string, or null if unable to fetch
20
+ */
21
+ function getLatestVersion() {
22
+ try {
23
+ const result = execSync(`npm view ${PACKAGE_NAME} version`, {
24
+ encoding: 'utf8',
25
+ stdio: ['pipe', 'pipe', 'pipe']
26
+ });
27
+ return result.trim();
28
+ } catch {
29
+ return null;
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Compare two semantic version strings
35
+ * @param {string} current - Current version (e.g., "1.2.3")
36
+ * @param {string} latest - Latest version (e.g., "1.2.4")
37
+ * @returns {boolean} True if latest is newer than current
38
+ */
39
+ function isNewerVersion(current, latest) {
40
+ if (!current || !latest) {
41
+ return false;
42
+ }
43
+
44
+ const currentParts = current.split('.').map(Number);
45
+ const latestParts = latest.split('.').map(Number);
46
+
47
+ for (let i = 0; i < 3; i++) {
48
+ const currentPart = currentParts[i] || 0;
49
+ const latestPart = latestParts[i] || 0;
50
+
51
+ if (latestPart > currentPart) {
52
+ return true;
53
+ }
54
+ if (latestPart < currentPart) {
55
+ return false;
56
+ }
57
+ }
58
+
59
+ return false;
60
+ }
61
+
62
+ /**
63
+ * Install the latest version of this package globally
64
+ * @returns {Promise<boolean>} True if installation succeeded
65
+ */
66
+ function installLatestVersion() {
67
+ return new Promise((resolve) => {
68
+ console.log(`\nInstalling ${PACKAGE_NAME}@latest globally...`);
69
+ console.log('─'.repeat(40));
70
+
71
+ const npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm';
72
+ const child = spawn(npmCommand, ['install', '-g', `${PACKAGE_NAME}@latest`], {
73
+ stdio: 'inherit'
74
+ });
75
+
76
+ child.on('close', (code) => {
77
+ if (code === 0) {
78
+ resolve(true);
79
+ } else {
80
+ resolve(false);
81
+ }
82
+ });
83
+
84
+ child.on('error', () => {
85
+ resolve(false);
86
+ });
87
+ });
88
+ }
89
+
90
+ /**
91
+ * Check for updates and install if available
92
+ * @param {object} options - Command options
93
+ */
94
+ async function runUpdate(options) {
95
+ const currentVersion = pkg.version;
96
+
97
+ console.log(`\n${pkg.name}`);
98
+ console.log('─'.repeat(40));
99
+ console.log(`Current version: ${currentVersion}`);
100
+
101
+ // Check for updates
102
+ console.log('\nChecking for updates...');
103
+ const latestVersion = getLatestVersion();
104
+
105
+ if (!latestVersion) {
106
+ console.log('Unable to check for updates (NPM registry unreachable)');
107
+ console.log('');
108
+ return;
109
+ }
110
+
111
+ console.log(`Latest version: ${latestVersion}`);
112
+
113
+ if (!isNewerVersion(currentVersion, latestVersion)) {
114
+ console.log('\nYou are already running the latest version.');
115
+ console.log('');
116
+ return;
117
+ }
118
+
119
+ console.log(`\nUpdate available: ${currentVersion} -> ${latestVersion}`);
120
+
121
+ // Perform the update
122
+ const success = await installLatestVersion();
123
+
124
+ if (success) {
125
+ console.log('─'.repeat(40));
126
+ console.log(`\nSuccessfully updated to version ${latestVersion}`);
127
+ console.log('');
128
+ } else {
129
+ console.log('─'.repeat(40));
130
+ console.log('\nUpdate failed. Try running manually:');
131
+ console.log(` npm install -g ${PACKAGE_NAME}@latest`);
132
+ console.log('');
133
+ process.exit(1);
134
+ }
135
+ }
136
+
137
+ // Create and configure the command
138
+ const update = new Command('update')
139
+ .description('Update this package to the latest version')
140
+ .action(runUpdate);
141
+
142
+ module.exports = update;
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * @fileoverview Version command - Display current version and check for updates.
5
+ * Queries the NPM registry to determine if a newer version is available.
6
+ */
7
+
8
+ const { Command } = require('commander');
9
+ const { execSync } = require('child_process');
10
+ const pkg = require('../../package.json');
11
+
12
+ /**
13
+ * The name of this package on NPM
14
+ */
15
+ const PACKAGE_NAME = pkg.name;
16
+
17
+ /**
18
+ * Get the latest version of this package from the NPM registry
19
+ * @returns {string|null} The latest version string, or null if unable to fetch
20
+ */
21
+ function getLatestVersion() {
22
+ try {
23
+ const result = execSync(`npm view ${PACKAGE_NAME} version`, {
24
+ encoding: 'utf8',
25
+ stdio: ['pipe', 'pipe', 'pipe']
26
+ });
27
+ return result.trim();
28
+ } catch {
29
+ return null;
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Compare two semantic version strings
35
+ * @param {string} current - Current version (e.g., "1.2.3")
36
+ * @param {string} latest - Latest version (e.g., "1.2.4")
37
+ * @returns {boolean} True if latest is newer than current
38
+ */
39
+ function isNewerVersion(current, latest) {
40
+ if (!current || !latest) {
41
+ return false;
42
+ }
43
+
44
+ const currentParts = current.split('.').map(Number);
45
+ const latestParts = latest.split('.').map(Number);
46
+
47
+ for (let i = 0; i < 3; i++) {
48
+ const currentPart = currentParts[i] || 0;
49
+ const latestPart = latestParts[i] || 0;
50
+
51
+ if (latestPart > currentPart) {
52
+ return true;
53
+ }
54
+ if (latestPart < currentPart) {
55
+ return false;
56
+ }
57
+ }
58
+
59
+ return false;
60
+ }
61
+
62
+ /**
63
+ * Display version information and check for updates
64
+ * @param {object} options - Command options
65
+ */
66
+ async function runVersion(options) {
67
+ const currentVersion = pkg.version;
68
+
69
+ console.log(`\n${pkg.name}`);
70
+ console.log('─'.repeat(40));
71
+ console.log(`Current version: ${currentVersion}`);
72
+
73
+ // Check for updates
74
+ console.log('\nChecking for updates...');
75
+ const latestVersion = getLatestVersion();
76
+
77
+ if (!latestVersion) {
78
+ console.log('Unable to check for updates (NPM registry unreachable)');
79
+ console.log('');
80
+ return;
81
+ }
82
+
83
+ if (isNewerVersion(currentVersion, latestVersion)) {
84
+ console.log(`\nUpdate available: ${currentVersion} -> ${latestVersion}`);
85
+ console.log('\nTo update, run:');
86
+ console.log(' dev update');
87
+ console.log('');
88
+ } else {
89
+ console.log(`Latest version: ${latestVersion}`);
90
+ console.log('\nYou are running the latest version.');
91
+ console.log('');
92
+ }
93
+ }
94
+
95
+ // Create and configure the command
96
+ const version = new Command('version')
97
+ .description('Display current version and check for updates')
98
+ .action(runVersion);
99
+
100
+ module.exports = version;