1
1
const fs = require("fs");
2
2
const path = require("path");
3
- const os = require("os");
4
3
const { spawn } = require("child_process");
5
4
const { Command } = require("commander");
6
5
const { fetch } = require("undici");
7
6
const chalk = require("chalk");
8
7
const inquirer = require("inquirer");
9
8
const { success, log, warn, error, hint, actionRunner, commandDescriptions } = require("../parser");
9
+ const { getLatestVersion, compareVersions } = require("../utils");
10
10
const { version } = require("../../package.json");
11
11
12
12
/**
@@ -15,13 +15,11 @@ const { version } = require("../../package.json");
15
15
const isInstalledViaNpm = () => {
16
16
try {
17
17
const scriptPath = process.argv[1];
18
-
19
- // Common indicators of npm global installation
18
+
20
19
if (scriptPath.includes('node_modules') && scriptPath.includes('appwrite-cli')) {
21
20
return true;
22
21
}
23
-
24
- // Check for npm global paths
22
+
25
23
if (scriptPath.includes('/usr/local/lib/node_modules/') ||
26
24
scriptPath.includes('/opt/homebrew/lib/node_modules/') ||
27
25
scriptPath.includes('/.npm-global/') ||
@@ -47,39 +45,7 @@ const isInstalledViaHomebrew = () => {
47
45
}
48
46
};
49
47
50
- /**
51
- * Get the latest version from npm registry
52
- */
53
- const getLatestVersion = async () => {
54
- try {
55
- const response = await fetch('https://registry.npmjs.org/{{ language .params .npmPackage | caseDash }}/latest');
56
- if (!response.ok) {
57
- throw new Error(`HTTP ${response.status}`);
58
- }
59
- const data = await response.json();
60
- return data.version;
61
- } catch (e) {
62
- throw new Error(`Failed to fetch latest version: ${e.message}`);
63
- }
64
- };
65
48
66
- /**
67
- * Compare versions using semantic versioning
68
- */
69
- const compareVersions = (current, latest) => {
70
- const currentParts = current.split('.').map(Number);
71
- const latestParts = latest.split('.').map(Number);
72
-
73
- for (let i = 0; i < Math.max(currentParts.length, latestParts.length); i++) {
74
- const currentPart = currentParts[i] || 0;
75
- const latestPart = latestParts[i] || 0;
76
-
77
- if (latestPart > currentPart) return 1; // Latest is newer
78
- if (latestPart < currentPart) return -1; // Current is newer
79
- }
80
-
81
- return 0; // Same version
82
- };
83
49
84
50
/**
85
51
* Execute command and return promise
@@ -115,7 +81,6 @@ const updateViaNpm = async () => {
115
81
success("Updated to latest version via npm!");
116
82
hint("Run '{{ language .params .executableName | caseLower }} --version' to verify the new version.");
117
83
} catch (e) {
118
- // Check if error is due to file already existing (likely already latest version)
119
84
if (e.message.includes('EEXIST') || e.message.includes('file already exists')) {
120
85
success("Latest version is already installed via npm!");
121
86
hint("The CLI is up to date. Run '{{ language .params .executableName | caseLower }} --version' to verify.");
@@ -135,7 +100,6 @@ const updateViaHomebrew = async () => {
135
100
success("Updated to latest version via Homebrew!");
136
101
hint("Run '{{ language .params .executableName | caseLower }} --version' to verify the new version.");
137
102
} catch (e) {
138
- // Check if error is due to package already being up-to-date
139
103
if (e.message.includes('already installed') || e.message.includes('up-to-date')) {
140
104
success("Latest version is already installed via Homebrew!");
141
105
hint("The CLI is up to date. Run '{{ language .params .executableName | caseLower }} --version' to verify.");
@@ -146,42 +110,11 @@ const updateViaHomebrew = async () => {
146
110
}
147
111
};
148
112
149
- /**
150
- * Update via installation script
151
- */
152
- const updateViaScript = async () => {
153
- const platform = os.platform();
154
-
155
- try {
156
- if (platform === 'win32') {
157
- // Windows PowerShell script
158
- await execCommand('powershell', ['-Command', 'iwr -useb https://appwrite.io/cli/install.ps1 | iex']);
159
- } else {
160
- // Linux/macOS bash script
161
- await execCommand('sh', ['-c', 'wget -q https://appwrite.io/cli/install.sh -O - | /bin/bash']);
162
- }
163
- success("Updated to latest version via installation script!");
164
- hint("Run '{{ language .params .executableName | caseLower }} --version' to verify the new version.");
165
- } catch (e) {
166
- // Check if error indicates already up-to-date
167
- if (e.message.includes('already exists') || e.message.includes('up-to-date')) {
168
- success("Latest version is already installed!");
169
- hint("The CLI is up to date. Run '{{ language .params .executableName | caseLower }} --version' to verify.");
170
- } else {
171
- error(`Failed to update via installation script: ${e.message}`);
172
- if (platform === 'win32') {
173
- hint("Try running: iwr -useb https://appwrite.io/cli/install.ps1 | iex");
174
- } else {
175
- hint("Try running: wget -q https://appwrite.io/cli/install.sh -O - | /bin/bash");
176
- }
177
- }
178
- }
179
- };
180
-
181
113
/**
182
114
* Show manual update instructions
183
115
*/
184
116
const showManualInstructions = (latestVersion) => {
117
+ console.log("");
185
118
log("Manual update options:");
186
119
console.log("");
187
120
@@ -193,17 +126,40 @@ const showManualInstructions = (latestVersion) => {
193
126
console.log(` brew upgrade {{ language .params .executableName | caseLower }}`);
194
127
console.log("");
195
128
196
- log(`${chalk.bold("Option 3: Installation Script")}`);
197
- if (os.platform() === 'win32') {
198
- console.log(` iwr -useb https://appwrite.io/cli/install.ps1 | iex`);
199
- } else {
200
- console.log(` wget -q https://appwrite.io/cli/install.sh -O - | /bin/bash`);
129
+ log(`${chalk.bold("Option 3: Download Binary")}`);
130
+ console.log(` Visit: https://github.com/{{ language .params .npmPackage | caseDash }}/releases/tag/${latestVersion}`);
131
+ };
132
+
133
+ /**
134
+ * Show interactive menu for choosing update method
135
+ */
136
+ const chooseUpdateMethod = async (latestVersion) => {
137
+ const choices = [
138
+ { name: 'NPM', value: 'npm' },
139
+ { name: 'Homebrew (macOS)', value: 'homebrew' },
140
+ { name: 'Show manual instructions', value: 'manual' }
141
+ ];
142
+
143
+ const { method } = await inquirer.prompt([
144
+ {
145
+ type: 'list',
146
+ name: 'method',
147
+ message: 'Could not detect installation method. How would you like to update?',
148
+ choices: choices
149
+ }
150
+ ]);
151
+
152
+ switch (method) {
153
+ case 'npm':
154
+ await updateViaNpm();
155
+ break;
156
+ case 'homebrew':
157
+ await updateViaHomebrew();
158
+ break;
159
+ case 'manual':
160
+ showManualInstructions(latestVersion);
161
+ break;
201
162
}
202
- console.log("");
203
-
204
- log(`${chalk.bold("Option 4: Download Binary")}`);
205
- console.log(` Visit: https://github.com/appwrite/sdk-for-cli/releases/tag/${latestVersion}`);
206
- console.log("");
207
163
};
208
164
209
165
/**
@@ -225,35 +181,23 @@ const updateCli = async ({ manual } = {}) => {
225
181
}
226
182
227
183
log(`Updating from ${chalk.blue(version)} to ${chalk.green(latestVersion)}...`);
228
- console.log("");
229
184
230
185
if (manual) {
231
186
showManualInstructions(latestVersion);
232
187
return;
233
188
}
234
189
235
- // Auto-detect installation method and update automatically
236
190
if (isInstalledViaNpm()) {
237
191
await updateViaNpm();
238
192
} else if (isInstalledViaHomebrew()) {
239
193
await updateViaHomebrew();
240
194
} else {
241
- // Unknown installation method - try npm first, then show manual instructions
242
- try {
243
- await updateViaNpm();
244
- } catch (e) {
245
- // If npm failed and it's not because the version is already installed
246
- if (!e.message.includes('EEXIST') && !e.message.includes('file already exists')) {
247
- error("Could not detect installation method or update failed.");
248
- showManualInstructions(latestVersion);
249
- }
250
- // If it's EEXIST error, updateViaNpm already handled it with success message
251
- }
195
+ await chooseUpdateMethod(latestVersion);
252
196
}
253
197
254
198
} catch (e) {
255
199
error(`Failed to check for updates: ${e.message}`);
256
- hint("You can manually check for updates at: https://github.com/appwrite/sdk-for-cli /releases");
200
+ hint("You can manually check for updates at: https://github.com/{{ language . params . npmPackage | caseDash }} /releases");
257
201
}
258
202
};
259
203
@@ -264,4 +208,4 @@ const update = new Command("update")
264
208
265
209
module.exports = {
266
210
update
267
- };
211
+ };
0 commit comments