diff --git a/CHANGELOG.md b/CHANGELOG.md index 65f33af1..c76a80b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,20 @@ Format: [Keep a Changelog](https://keepachangelog.com/) +## [4.3.8] - 2025-11-23 + +### Fixed +- **ora v9 Compatibility**: Fixed "ora is not a function" errors in `ccs doctor` and installer utilities +- Properly handle ora v9+ ES module format when using CommonJS `require()` +- All spinner-based operations now work correctly with ora v9.0.0 + +### Technical Details +- ora v9+ is an ES module, requiring `.default` property access in CommonJS +- Updated import: `const oraModule = require('ora'); ora = oraModule.default || oraModule` +- Fallback spinner implementation ensures graceful degradation when ora is unavailable +- Affects: `bin/management/doctor.js`, `bin/utils/claude-dir-installer.js`, `bin/utils/claude-symlink-manager.js` +- Impact: `ccs doctor` command and postinstall scripts now work correctly with latest ora version + ## [4.3.7] - 2025-11-23 ### Fixed diff --git a/VERSION b/VERSION index 7e7f33c2..3bcca128 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.3.7 +4.3.8 diff --git a/bin/management/doctor.js b/bin/management/doctor.js index 2e5c662b..1f1647b0 100644 --- a/bin/management/doctor.js +++ b/bin/management/doctor.js @@ -6,7 +6,28 @@ const os = require('os'); const { spawn } = require('child_process'); const { colored } = require('../utils/helpers'); const { detectClaudeCli } = require('../utils/claude-detector'); -const ora = require('ora'); + +// Make ora optional (might not be available during npm install postinstall) +// ora v9+ is an ES module, need to use .default for CommonJS +let ora = null; +try { + const oraModule = require('ora'); + ora = oraModule.default || oraModule; +} catch (e) { + // ora not available, create fallback spinner that uses console.log + ora = function(text) { + return { + start: () => ({ + succeed: (msg) => console.log(msg || `[OK] ${text}`), + fail: (msg) => console.log(msg || `[X] ${text}`), + warn: (msg) => console.log(msg || `[!] ${text}`), + info: (msg) => console.log(msg || `[i] ${text}`), + text: '' + }) + }; + }; +} + const Table = require('cli-table3'); /** diff --git a/bin/utils/claude-dir-installer.js b/bin/utils/claude-dir-installer.js index ed700916..51ddb4b9 100644 --- a/bin/utils/claude-dir-installer.js +++ b/bin/utils/claude-dir-installer.js @@ -6,11 +6,24 @@ const path = require('path'); const os = require('os'); // Make ora optional (might not be available during npm install postinstall) +// ora v9+ is an ES module, need to use .default for CommonJS let ora = null; try { - ora = require('ora'); + const oraModule = require('ora'); + ora = oraModule.default || oraModule; } catch (e) { - // ora not available, will use console.log instead + // ora not available, create fallback spinner that uses console.log + ora = function(text) { + return { + start: () => ({ + succeed: (msg) => console.log(msg || `[OK] ${text}`), + fail: (msg) => console.log(msg || `[X] ${text}`), + warn: (msg) => console.log(msg || `[!] ${text}`), + info: (msg) => console.log(msg || `[i] ${text}`), + text: '' + }) + }; + }; } const { colored } = require('./helpers'); diff --git a/bin/utils/claude-symlink-manager.js b/bin/utils/claude-symlink-manager.js index 5146339d..b0fdcd76 100644 --- a/bin/utils/claude-symlink-manager.js +++ b/bin/utils/claude-symlink-manager.js @@ -5,11 +5,24 @@ const path = require('path'); const os = require('os'); // Make ora optional (might not be available during npm install postinstall) +// ora v9+ is an ES module, need to use .default for CommonJS let ora = null; try { - ora = require('ora'); + const oraModule = require('ora'); + ora = oraModule.default || oraModule; } catch (e) { - // ora not available, will use console.log instead + // ora not available, create fallback spinner that uses console.log + ora = function(text) { + return { + start: () => ({ + succeed: (msg) => console.log(msg || `[OK] ${text}`), + fail: (msg) => console.log(msg || `[X] ${text}`), + warn: (msg) => console.log(msg || `[!] ${text}`), + info: (msg) => console.log(msg || `[i] ${text}`), + text: '' + }) + }; + }; } const { colored } = require('./helpers'); diff --git a/installers/install.ps1 b/installers/install.ps1 index c5bcf135..8e7c5801 100644 --- a/installers/install.ps1 +++ b/installers/install.ps1 @@ -31,7 +31,7 @@ $InstallMethod = if ($ScriptDir -and ((Test-Path "$ScriptDir\lib\ccs.ps1") -or ( # IMPORTANT: Update this version when releasing new versions! # This hardcoded version is used for standalone installations (irm | iex) # For git installations, VERSION file is read if available -$CcsVersion = "4.3.7" +$CcsVersion = "4.3.8" # Try to read VERSION file for git installations if ($ScriptDir) { diff --git a/installers/install.sh b/installers/install.sh index df5f30a8..9a135d6c 100755 --- a/installers/install.sh +++ b/installers/install.sh @@ -32,7 +32,7 @@ fi # IMPORTANT: Update this version when releasing new versions! # This hardcoded version is used for standalone installations (curl | bash) # For git installations, VERSION file is read if available -CCS_VERSION="4.3.7" +CCS_VERSION="4.3.8" # Try to read VERSION file for git installations if [[ -f "$SCRIPT_DIR/VERSION" ]]; then diff --git a/lib/ccs b/lib/ccs index fa3fd056..8091dbf8 100755 --- a/lib/ccs +++ b/lib/ccs @@ -2,7 +2,7 @@ set -euo pipefail # Version (updated by scripts/bump-version.sh) -CCS_VERSION="4.3.7" +CCS_VERSION="4.3.8" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" readonly CONFIG_FILE="${CCS_CONFIG:-$HOME/.ccs/config.json}" readonly PROFILES_JSON="$HOME/.ccs/profiles.json" diff --git a/lib/ccs.ps1 b/lib/ccs.ps1 index 5549bd05..2e5ff00e 100644 --- a/lib/ccs.ps1 +++ b/lib/ccs.ps1 @@ -12,7 +12,7 @@ param( $ErrorActionPreference = "Stop" # Version (updated by scripts/bump-version.sh) -$CcsVersion = "4.3.7" +$CcsVersion = "4.3.8" $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path $ConfigFile = if ($env:CCS_CONFIG) { $env:CCS_CONFIG } else { "$env:USERPROFILE\.ccs\config.json" } $ProfilesJson = "$env:USERPROFILE\.ccs\profiles.json" diff --git a/package-lock.json b/package-lock.json index ab868753..29e54d08 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@kaitranntt/ccs", - "version": "4.3.5", + "version": "4.3.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@kaitranntt/ccs", - "version": "4.3.5", + "version": "4.3.7", "hasInstallScript": true, "license": "MIT", "os": [ diff --git a/package.json b/package.json index 986dfc4a..aa32458f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kaitranntt/ccs", - "version": "4.3.7", + "version": "4.3.8", "description": "Claude Code Switch - Instant profile switching between Claude Sonnet 4.5 and GLM 4.6", "keywords": [ "cli",