@kaitranntt/ccs 4.3.3 → 4.3.4
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/VERSION +1 -1
- package/bin/ccs.js +207 -15
- package/lib/ccs +1 -1
- package/lib/ccs.ps1 +1 -1
- package/package.json +1 -1
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
4.3.
|
|
1
|
+
4.3.4
|
package/bin/ccs.js
CHANGED
|
@@ -298,6 +298,150 @@ async function handleSyncCommand() {
|
|
|
298
298
|
process.exit(0);
|
|
299
299
|
}
|
|
300
300
|
|
|
301
|
+
/**
|
|
302
|
+
* Detect installation method
|
|
303
|
+
* @returns {'npm'|'direct'} - Installation method
|
|
304
|
+
*/
|
|
305
|
+
function detectInstallationMethod() {
|
|
306
|
+
const scriptPath = process.argv[1];
|
|
307
|
+
|
|
308
|
+
// Method 1: Check if script is inside node_modules
|
|
309
|
+
if (scriptPath.includes('node_modules')) {
|
|
310
|
+
return 'npm';
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Method 2: Check if script is in npm global bin directory
|
|
314
|
+
// Common patterns for npm global installations
|
|
315
|
+
const npmGlobalBinPatterns = [
|
|
316
|
+
/\.npm\/global\/bin\//, // ~/.npm/global/bin/ccs
|
|
317
|
+
/\/\.nvm\/versions\/node\/[^\/]+\/bin\//, // ~/.nvm/versions/node/v22.19.0/bin/ccs
|
|
318
|
+
/\/usr\/local\/bin\//, // /usr/local/bin/ccs (if npm global prefix is /usr/local)
|
|
319
|
+
/\/usr\/bin\// // /usr/bin/ccs (if npm global prefix is /usr)
|
|
320
|
+
];
|
|
321
|
+
|
|
322
|
+
for (const pattern of npmGlobalBinPatterns) {
|
|
323
|
+
if (pattern.test(scriptPath)) {
|
|
324
|
+
// Verify this is actually CCS by checking the linked target
|
|
325
|
+
try {
|
|
326
|
+
const binDir = path.dirname(scriptPath);
|
|
327
|
+
const nodeModulesDir = path.join(binDir, '..', 'lib', 'node_modules', '@kaitranntt', 'ccs');
|
|
328
|
+
const globalModulesDir = path.join(binDir, '..', 'node_modules', '@kaitranntt', 'ccs');
|
|
329
|
+
|
|
330
|
+
if (fs.existsSync(nodeModulesDir) || fs.existsSync(globalModulesDir)) {
|
|
331
|
+
return 'npm';
|
|
332
|
+
}
|
|
333
|
+
} catch (err) {
|
|
334
|
+
// Continue checking other patterns
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Method 3: Check if package.json exists in parent directory (development mode)
|
|
340
|
+
const packageJsonPath = path.join(__dirname, '..', 'package.json');
|
|
341
|
+
|
|
342
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
343
|
+
try {
|
|
344
|
+
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
345
|
+
// If package.json has name "@kaitranntt/ccs", it's npm install
|
|
346
|
+
if (pkg.name === '@kaitranntt/ccs') {
|
|
347
|
+
return 'npm';
|
|
348
|
+
}
|
|
349
|
+
} catch (err) {
|
|
350
|
+
// Ignore parse errors
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// Method 4: Check if script is a symlink pointing to node_modules
|
|
355
|
+
try {
|
|
356
|
+
const stats = fs.lstatSync(scriptPath);
|
|
357
|
+
if (stats.isSymbolicLink()) {
|
|
358
|
+
const targetPath = fs.readlinkSync(scriptPath);
|
|
359
|
+
if (targetPath.includes('node_modules') || targetPath.includes('@kaitranntt/ccs')) {
|
|
360
|
+
return 'npm';
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
} catch (err) {
|
|
364
|
+
// Continue to default
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Default to direct installation
|
|
368
|
+
return 'direct';
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Detect which package manager was used for installation
|
|
373
|
+
* @returns {'npm'|'yarn'|'pnpm'|'bun'|'unknown'}
|
|
374
|
+
*/
|
|
375
|
+
function detectPackageManager() {
|
|
376
|
+
const scriptPath = process.argv[1];
|
|
377
|
+
|
|
378
|
+
// Check if script path contains package manager indicators
|
|
379
|
+
if (scriptPath.includes('.pnpm')) return 'pnpm';
|
|
380
|
+
if (scriptPath.includes('yarn')) return 'yarn';
|
|
381
|
+
if (scriptPath.includes('bun')) return 'bun';
|
|
382
|
+
|
|
383
|
+
// Check parent directories for lock files
|
|
384
|
+
const binDir = path.dirname(scriptPath);
|
|
385
|
+
const fs = require('fs');
|
|
386
|
+
|
|
387
|
+
// Check global node_modules parent for lock files
|
|
388
|
+
let checkDir = binDir;
|
|
389
|
+
for (let i = 0; i < 5; i++) {
|
|
390
|
+
if (fs.existsSync(path.join(checkDir, 'pnpm-lock.yaml'))) return 'pnpm';
|
|
391
|
+
if (fs.existsSync(path.join(checkDir, 'yarn.lock'))) return 'yarn';
|
|
392
|
+
if (fs.existsSync(path.join(checkDir, 'bun.lockb'))) return 'bun';
|
|
393
|
+
checkDir = path.dirname(checkDir);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// Check if package managers are available on the system
|
|
397
|
+
const { spawnSync } = require('child_process');
|
|
398
|
+
|
|
399
|
+
// Try yarn global list to see if CCS is installed via yarn
|
|
400
|
+
try {
|
|
401
|
+
const yarnResult = spawnSync('yarn', ['global', 'list', '--pattern', '@kaitranntt/ccs'], {
|
|
402
|
+
encoding: 'utf8',
|
|
403
|
+
shell: true,
|
|
404
|
+
timeout: 5000
|
|
405
|
+
});
|
|
406
|
+
if (yarnResult.status === 0 && yarnResult.stdout.includes('@kaitranntt/ccs')) {
|
|
407
|
+
return 'yarn';
|
|
408
|
+
}
|
|
409
|
+
} catch (err) {
|
|
410
|
+
// Continue to next check
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// Try pnpm list -g to see if CCS is installed via pnpm
|
|
414
|
+
try {
|
|
415
|
+
const pnpmResult = spawnSync('pnpm', ['list', '-g', '--pattern', '@kaitranntt/ccs'], {
|
|
416
|
+
encoding: 'utf8',
|
|
417
|
+
shell: true,
|
|
418
|
+
timeout: 5000
|
|
419
|
+
});
|
|
420
|
+
if (pnpmResult.status === 0 && pnpmResult.stdout.includes('@kaitranntt/ccs')) {
|
|
421
|
+
return 'pnpm';
|
|
422
|
+
}
|
|
423
|
+
} catch (err) {
|
|
424
|
+
// Continue to next check
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// Try bun pm ls -g to see if CCS is installed via bun
|
|
428
|
+
try {
|
|
429
|
+
const bunResult = spawnSync('bun', ['pm', 'ls', '-g', '--pattern', '@kaitranntt/ccs'], {
|
|
430
|
+
encoding: 'utf8',
|
|
431
|
+
shell: true,
|
|
432
|
+
timeout: 5000
|
|
433
|
+
});
|
|
434
|
+
if (bunResult.status === 0 && bunResult.stdout.includes('@kaitranntt/ccs')) {
|
|
435
|
+
return 'bun';
|
|
436
|
+
}
|
|
437
|
+
} catch (err) {
|
|
438
|
+
// Continue to default
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// Default to npm
|
|
442
|
+
return 'npm';
|
|
443
|
+
}
|
|
444
|
+
|
|
301
445
|
async function handleUpdateCommand() {
|
|
302
446
|
const { checkForUpdates } = require('./utils/update-checker');
|
|
303
447
|
const { spawn } = require('child_process');
|
|
@@ -307,8 +451,8 @@ async function handleUpdateCommand() {
|
|
|
307
451
|
console.log('');
|
|
308
452
|
|
|
309
453
|
// Detect installation method for proper update source
|
|
310
|
-
const
|
|
311
|
-
const
|
|
454
|
+
const installMethod = detectInstallationMethod();
|
|
455
|
+
const isNpmInstall = installMethod === 'npm';
|
|
312
456
|
|
|
313
457
|
// Check for updates (force check)
|
|
314
458
|
const updateResult = await checkForUpdates(CCS_VERSION, true, installMethod);
|
|
@@ -323,7 +467,27 @@ async function handleUpdateCommand() {
|
|
|
323
467
|
console.log('');
|
|
324
468
|
console.log('Try again later or update manually:');
|
|
325
469
|
if (isNpmInstall) {
|
|
326
|
-
|
|
470
|
+
const packageManager = detectPackageManager();
|
|
471
|
+
let manualCommand;
|
|
472
|
+
|
|
473
|
+
switch (packageManager) {
|
|
474
|
+
case 'npm':
|
|
475
|
+
manualCommand = 'npm install -g @kaitranntt/ccs@latest';
|
|
476
|
+
break;
|
|
477
|
+
case 'yarn':
|
|
478
|
+
manualCommand = 'yarn global add @kaitranntt/ccs@latest';
|
|
479
|
+
break;
|
|
480
|
+
case 'pnpm':
|
|
481
|
+
manualCommand = 'pnpm add -g @kaitranntt/ccs@latest';
|
|
482
|
+
break;
|
|
483
|
+
case 'bun':
|
|
484
|
+
manualCommand = 'bun add -g @kaitranntt/ccs@latest';
|
|
485
|
+
break;
|
|
486
|
+
default:
|
|
487
|
+
manualCommand = 'npm install -g @kaitranntt/ccs@latest';
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
console.log(colored(` ${manualCommand}`, 'yellow'));
|
|
327
491
|
} else {
|
|
328
492
|
const isWindows = process.platform === 'win32';
|
|
329
493
|
if (isWindows) {
|
|
@@ -361,13 +525,38 @@ async function handleUpdateCommand() {
|
|
|
361
525
|
console.log('');
|
|
362
526
|
|
|
363
527
|
if (isNpmInstall) {
|
|
364
|
-
// npm installation -
|
|
365
|
-
|
|
528
|
+
// npm installation - detect package manager and update
|
|
529
|
+
const packageManager = detectPackageManager();
|
|
530
|
+
let updateCommand, updateArgs;
|
|
531
|
+
|
|
532
|
+
switch (packageManager) {
|
|
533
|
+
case 'npm':
|
|
534
|
+
updateCommand = 'npm';
|
|
535
|
+
updateArgs = ['install', '-g', '@kaitranntt/ccs@latest'];
|
|
536
|
+
break;
|
|
537
|
+
case 'yarn':
|
|
538
|
+
updateCommand = 'yarn';
|
|
539
|
+
updateArgs = ['global', 'add', '@kaitranntt/ccs@latest'];
|
|
540
|
+
break;
|
|
541
|
+
case 'pnpm':
|
|
542
|
+
updateCommand = 'pnpm';
|
|
543
|
+
updateArgs = ['add', '-g', '@kaitranntt/ccs@latest'];
|
|
544
|
+
break;
|
|
545
|
+
case 'bun':
|
|
546
|
+
updateCommand = 'bun';
|
|
547
|
+
updateArgs = ['add', '-g', '@kaitranntt/ccs@latest'];
|
|
548
|
+
break;
|
|
549
|
+
default:
|
|
550
|
+
updateCommand = 'npm';
|
|
551
|
+
updateArgs = ['install', '-g', '@kaitranntt/ccs@latest'];
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
console.log(colored(`Updating via ${packageManager}...`, 'cyan'));
|
|
366
555
|
console.log('');
|
|
367
556
|
|
|
368
|
-
const child = spawn(
|
|
369
|
-
stdio: 'inherit'
|
|
370
|
-
shell
|
|
557
|
+
const child = spawn(updateCommand, updateArgs, {
|
|
558
|
+
stdio: 'inherit'
|
|
559
|
+
// No shell needed for direct commands
|
|
371
560
|
});
|
|
372
561
|
|
|
373
562
|
child.on('exit', (code) => {
|
|
@@ -382,7 +571,7 @@ async function handleUpdateCommand() {
|
|
|
382
571
|
console.log(colored('[X] Update failed', 'red'));
|
|
383
572
|
console.log('');
|
|
384
573
|
console.log('Try manually:');
|
|
385
|
-
console.log(colored(
|
|
574
|
+
console.log(colored(` ${updateCommand} ${updateArgs.join(' ')}`, 'yellow'));
|
|
386
575
|
console.log('');
|
|
387
576
|
}
|
|
388
577
|
process.exit(code || 0);
|
|
@@ -390,10 +579,10 @@ async function handleUpdateCommand() {
|
|
|
390
579
|
|
|
391
580
|
child.on('error', (err) => {
|
|
392
581
|
console.log('');
|
|
393
|
-
console.log(colored(
|
|
582
|
+
console.log(colored(`[X] Failed to run ${packageManager} update`, 'red'));
|
|
394
583
|
console.log('');
|
|
395
584
|
console.log('Try manually:');
|
|
396
|
-
console.log(colored(
|
|
585
|
+
console.log(colored(` ${updateCommand} ${updateArgs.join(' ')}`, 'yellow'));
|
|
397
586
|
console.log('');
|
|
398
587
|
process.exit(1);
|
|
399
588
|
});
|
|
@@ -406,16 +595,19 @@ async function handleUpdateCommand() {
|
|
|
406
595
|
let command, args;
|
|
407
596
|
|
|
408
597
|
if (isWindows) {
|
|
598
|
+
// PowerShell
|
|
409
599
|
command = 'powershell.exe';
|
|
410
|
-
args = ['-
|
|
600
|
+
args = ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command',
|
|
601
|
+
'irm ccs.kaitran.ca/install | iex'];
|
|
411
602
|
} else {
|
|
412
|
-
|
|
603
|
+
// Unix (bash with proper shell invocation)
|
|
604
|
+
command = '/bin/bash';
|
|
413
605
|
args = ['-c', 'curl -fsSL ccs.kaitran.ca/install | bash'];
|
|
414
606
|
}
|
|
415
607
|
|
|
416
608
|
const child = spawn(command, args, {
|
|
417
|
-
stdio: 'inherit'
|
|
418
|
-
shell: true
|
|
609
|
+
stdio: 'inherit'
|
|
610
|
+
// Do NOT use shell: true
|
|
419
611
|
});
|
|
420
612
|
|
|
421
613
|
child.on('exit', (code) => {
|
package/lib/ccs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
set -euo pipefail
|
|
3
3
|
|
|
4
4
|
# Version (updated by scripts/bump-version.sh)
|
|
5
|
-
CCS_VERSION="4.3.
|
|
5
|
+
CCS_VERSION="4.3.4"
|
|
6
6
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
7
7
|
readonly CONFIG_FILE="${CCS_CONFIG:-$HOME/.ccs/config.json}"
|
|
8
8
|
readonly PROFILES_JSON="$HOME/.ccs/profiles.json"
|
package/lib/ccs.ps1
CHANGED
|
@@ -12,7 +12,7 @@ param(
|
|
|
12
12
|
$ErrorActionPreference = "Stop"
|
|
13
13
|
|
|
14
14
|
# Version (updated by scripts/bump-version.sh)
|
|
15
|
-
$CcsVersion = "4.3.
|
|
15
|
+
$CcsVersion = "4.3.4"
|
|
16
16
|
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
17
17
|
$ConfigFile = if ($env:CCS_CONFIG) { $env:CCS_CONFIG } else { "$env:USERPROFILE\.ccs\config.json" }
|
|
18
18
|
$ProfilesJson = "$env:USERPROFILE\.ccs\profiles.json"
|