Skip to content

Commit 8d43f28

Browse files
committed
feat: add update command and version check for Ensemble CLI
- Introduced an 'update' command to allow users to update the Ensemble CLI to the latest version. - Implemented a version check that notifies users if a new version is available. - Updated the CLI versioning to reflect the version from package.json.
1 parent 37e8191 commit 8d43f28

2 files changed

Lines changed: 82 additions & 1 deletion

File tree

src/commands/update.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { exec } from 'node:child_process';
2+
3+
export async function updateCommand(): Promise<void> {
4+
return new Promise((resolve) => {
5+
const child = exec('npm install -g @ensembleui/cli', (error) => {
6+
if (error) {
7+
console.error('Failed to update @ensembleui/cli automatically.');
8+
console.error('Please run the following command manually:');
9+
console.error(' npm install -g @ensembleui/cli');
10+
}
11+
resolve();
12+
});
13+
14+
if (child.stdout) {
15+
child.stdout.pipe(process.stdout);
16+
}
17+
if (child.stderr) {
18+
child.stderr.pipe(process.stderr);
19+
}
20+
});
21+
}
22+

src/index.ts

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
11
#!/usr/bin/env node
22
import { Command } from 'commander';
3+
import https from 'node:https';
4+
5+
// eslint-disable-next-line @typescript-eslint/no-var-requires
6+
const pkg = require('../package.json') as { version: string };
7+
const LOCAL_VERSION = pkg.version;
38

49
import { loginCommand } from './commands/login.js';
510
import { logoutCommand } from './commands/logout.js';
611
import { initCommand } from './commands/init.js';
712
import { pushCommand } from './commands/push.js';
813
import { addCommand } from './commands/add.js';
914
import { pullCommand } from './commands/pull.js';
15+
import { updateCommand } from './commands/update.js';
1016
import { printCliError, resolveDebugFlag } from './core/cliError.js';
1117

1218
const program = new Command();
1319

1420
program
1521
.name('ensemble')
1622
.description('Ensemble CLI for logging in and configuring Ensemble apps.')
17-
.version('0.1.0')
23+
.version(LOCAL_VERSION)
1824
.option('--debug', 'Print full debug information and stack traces', false);
1925

2026
program
@@ -91,6 +97,59 @@ program
9197
await addCommand(normalizedKind, name);
9298
});
9399

100+
program
101+
.command('update')
102+
.description('Update the Ensemble CLI to the latest version.')
103+
.action(async () => {
104+
await updateCommand();
105+
});
106+
107+
function checkForUpdates(): void {
108+
const req = https.request(
109+
'https://npm.pkg.github.com/@ensembleui%2Fcli',
110+
{
111+
method: 'GET',
112+
headers: {
113+
Accept: 'application/vnd.npm.install-v1+json',
114+
},
115+
},
116+
(res) => {
117+
if (res.statusCode !== 200) {
118+
res.resume();
119+
return;
120+
}
121+
122+
let body = '';
123+
res.on('data', (chunk) => {
124+
body += chunk;
125+
});
126+
res.on('end', () => {
127+
try {
128+
const data = JSON.parse(body) as { 'dist-tags'?: { latest?: string } };
129+
const latest = data['dist-tags']?.latest;
130+
if (!latest || latest === LOCAL_VERSION) return;
131+
132+
// eslint-disable-next-line no-console
133+
console.warn(
134+
`A new version of @ensembleui/cli is available (${LOCAL_VERSION}${latest}).\n` +
135+
`Run "ensemble update" to upgrade.`,
136+
);
137+
} catch {
138+
// ignore JSON/parse errors
139+
}
140+
});
141+
},
142+
);
143+
144+
req.on('error', () => {
145+
// Silently ignore network errors; CLI behavior should not depend on this check.
146+
});
147+
148+
req.end();
149+
}
150+
151+
checkForUpdates();
152+
94153
program.parseAsync(process.argv).catch((err) => {
95154
const globalOptions = program.opts<{ debug?: boolean }>();
96155
const debugEnabled = resolveDebugFlag(globalOptions.debug);

0 commit comments

Comments
 (0)