This guide covers the sophisticated version handling capabilities of @cloud-copilot/cli, including automatic update checking and custom version logic.
The simplest way to add version support is with a static string:
const cli = await parseCliArguments(
'my-app',
{},
{},
{
version: '1.0.0'
}
)Users can now run:
my-app --version
# 1.0.0Load version information from your package.json file:
import { createPackageFileReader } from '@cloud-copilot/cli'
//Create a reader that can read files relative to the root of your project
const relativeFileReader = createPackageFileReader(import.meta.url, 2)
// Read the package.json file in your project root
const contents = await relativeFileReader.readFile(['package.json'])
const version = JSON.parse(contents).version
const cli = await parseCliArguments(
'my-app',
{},
{},
{
version: version
}
)Or use a function for lazy loading:
import { createPackageFileReader } from '@cloud-copilot/cli'
const cli = await parseCliArguments(
'my-app',
{},
{},
{
version: {
currentVersion: () => {
//Create a reader that can read files relative to the root of your project
const relativeFileReader = createPackageFileReader(import.meta.url, 2)
// Read the package.json file in your project root
const contents = await relativeFileReader.readFile(['package.json'])
return JSON.parse(contents).version
}
}
}
)Enable automatic update checking by specifying an npm package name:
const cli = await parseCliArguments(
'my-app',
{},
{},
{
version: {
currentVersion: '1.0.0',
checkForUpdates: '@my-org/my-package' // npm package name
}
}
)When users run --version, the CLI will:
- Display the current version
- Check npm for the latest published version
- Show an update message if a newer version is available
my-app --version
# Output:
# my-app version 1.0.0
#
# Update available: 1.0.0 → 1.2.3
# Run: npm install -g my-npm-packageCustomize the update notification message:
const cli = await parseCliArguments(
'my-app',
{},
{},
{
version: {
currentVersion: '1.0.0',
checkForUpdates: 'my-npm-package',
updateMessage: (current, latest) =>
`🎉 New version available!\n` +
`Current: ${current}\n` +
`Latest: ${latest}\n` +
`\n` +
`Update with: npm install -g my-npm-package@${latest}\n` +
`Changelog: https://github.com/my-org/my-package/releases/tag/v${latest}`
}
}
)Implement your own update checking logic:
const cli = await parseCliArguments(
'my-app',
{},
{},
{
version: {
currentVersion: '1.0.0',
checkForUpdates: async () => {
try {
const response = await fetch(
'https://api.github.com/repos/my-org/my-repo/releases/latest'
)
const data = await response.json()
return data.tag_name.replace(/^v/, '') // Remove 'v' prefix
} catch (error) {
console.warn('Failed to check for updates:', error.message)
return null // Return null to indicate no update available
}
},
updateMessage: (current, latest) =>
`Update available: ${current} → ${latest}\n` +
`Download: https://github.com/my-org/my-repo/releases/tag/v${latest}`
}
}
)Both currentVersion and checkForUpdates can be async functions:
const cli = await parseCliArguments(
'my-app',
{},
{},
{
version: {
currentVersion: async () => {
// Maybe read from a database, API, or computed value
const buildInfo = await fetch('https://api.example.com/build-info')
const data = await buildInfo.json()
return `${data.version}-${data.buildNumber}`
},
checkForUpdates: async () => {
// Custom update check logic
const response = await fetch('https://api.example.com/latest-version')
const data = await response.json()
return data.version
}
}
}
)import semver from 'semver'
const cli = await parseCliArguments(
'my-app',
{},
{},
{
version: {
currentVersion: '1.2.0',
checkForUpdates: async () => {
const response = await fetch('https://registry.npmjs.org/my-package/latest')
const data = await response.json()
return data.version
},
updateMessage: (current, latest) => {
const updateType = semver.diff(current, latest)
const urgency =
updateType === 'major' ? '⚠️ MAJOR' : updateType === 'minor' ? '✨ MINOR' : '🐛 PATCH'
return (
`${urgency} update available: ${current} → ${latest}\n` +
`Run: npm install -g my-package@${latest}`
)
}
}
}
)const isDevelopment = process.env.NODE_ENV === 'development'
const cli = await parseCliArguments(
'my-app',
{},
{},
{
version: {
currentVersion: () => {
const pkg = JSON.parse(readFileSync('./package.json', 'utf8'))
if (isDevelopment) {
const gitHash = require('child_process')
.execSync('git rev-parse --short HEAD')
.toString()
.trim()
return `${pkg.version}-dev-${gitHash}`
}
return pkg.version
},
// Only check for updates in production
checkForUpdates: isDevelopment ? undefined : 'my-npm-package'
}
}
)Include build information in version output:
const cli = await parseCliArguments(
'my-app',
{},
{},
{
version: {
currentVersion: () => {
const pkg = JSON.parse(readFileSync('./package.json', 'utf8'))
const buildDate = new Date().toISOString()
const nodeVersion = process.version
return [
`Version: ${pkg.version}`,
`Built: ${buildDate}`,
`Node: ${nodeVersion}`,
`Platform: ${process.platform}-${process.arch}`
].join('\n')
}
}
}
)Support different update channels (stable, beta, nightly):
const updateChannel = process.env.UPDATE_CHANNEL || 'stable'
const cli = await parseCliArguments(
'my-app',
{},
{},
{
version: {
currentVersion: '1.0.0',
checkForUpdates: async () => {
const response = await fetch(`https://api.example.com/releases/${updateChannel}`)
const data = await response.json()
return data.version
},
updateMessage: (current, latest) =>
`Update available on ${updateChannel} channel: ${current} → ${latest}\n` +
`Run: npm install -g my-package@${updateChannel}`
}
}
)