@codebakers/cli 3.1.0 → 3.2.0
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/dist/config.d.ts +17 -0
- package/dist/config.js +35 -0
- package/dist/index.js +56 -2
- package/package.json +1 -1
- package/src/config.ts +41 -0
- package/src/index.ts +65 -2
package/dist/config.d.ts
CHANGED
|
@@ -43,6 +43,8 @@ interface ConfigSchema {
|
|
|
43
43
|
serviceKeys: ServiceKeys;
|
|
44
44
|
lastKeySync: string | null;
|
|
45
45
|
trial: TrialState | null;
|
|
46
|
+
lastUpdateCheck: string | null;
|
|
47
|
+
latestKnownVersion: string | null;
|
|
46
48
|
}
|
|
47
49
|
export declare function getApiKey(): string | null;
|
|
48
50
|
export declare function setApiKey(key: string): void;
|
|
@@ -105,4 +107,19 @@ export declare function hasValidAccess(): boolean;
|
|
|
105
107
|
* Get authentication mode: 'apiKey', 'trial', or 'none'
|
|
106
108
|
*/
|
|
107
109
|
export declare function getAuthMode(): 'apiKey' | 'trial' | 'none';
|
|
110
|
+
/**
|
|
111
|
+
* Get cached update info if still valid (within 24 hours)
|
|
112
|
+
*/
|
|
113
|
+
export declare function getCachedUpdateInfo(): {
|
|
114
|
+
latestVersion: string;
|
|
115
|
+
checkedAt: string;
|
|
116
|
+
} | null;
|
|
117
|
+
/**
|
|
118
|
+
* Cache the latest version from npm registry
|
|
119
|
+
*/
|
|
120
|
+
export declare function setCachedUpdateInfo(latestVersion: string): void;
|
|
121
|
+
/**
|
|
122
|
+
* Get the current CLI version from package.json
|
|
123
|
+
*/
|
|
124
|
+
export declare function getCliVersion(): string;
|
|
108
125
|
export {};
|
package/dist/config.js
CHANGED
|
@@ -32,6 +32,9 @@ exports.isTrialExpired = isTrialExpired;
|
|
|
32
32
|
exports.getTrialDaysRemaining = getTrialDaysRemaining;
|
|
33
33
|
exports.hasValidAccess = hasValidAccess;
|
|
34
34
|
exports.getAuthMode = getAuthMode;
|
|
35
|
+
exports.getCachedUpdateInfo = getCachedUpdateInfo;
|
|
36
|
+
exports.setCachedUpdateInfo = setCachedUpdateInfo;
|
|
37
|
+
exports.getCliVersion = getCliVersion;
|
|
35
38
|
const conf_1 = __importDefault(require("conf"));
|
|
36
39
|
const fs_1 = require("fs");
|
|
37
40
|
const path_1 = require("path");
|
|
@@ -126,6 +129,8 @@ const config = new conf_1.default({
|
|
|
126
129
|
serviceKeys: defaultServiceKeys,
|
|
127
130
|
lastKeySync: null,
|
|
128
131
|
trial: null,
|
|
132
|
+
lastUpdateCheck: null,
|
|
133
|
+
latestKnownVersion: null,
|
|
129
134
|
},
|
|
130
135
|
// Migration to add new keys when upgrading from old version
|
|
131
136
|
migrations: {
|
|
@@ -411,3 +416,33 @@ function getAuthMode() {
|
|
|
411
416
|
return 'trial';
|
|
412
417
|
return 'none';
|
|
413
418
|
}
|
|
419
|
+
// ============================================
|
|
420
|
+
// Update Notification Cache
|
|
421
|
+
// ============================================
|
|
422
|
+
const UPDATE_CHECK_INTERVAL_HOURS = 24;
|
|
423
|
+
/**
|
|
424
|
+
* Get cached update info if still valid (within 24 hours)
|
|
425
|
+
*/
|
|
426
|
+
function getCachedUpdateInfo() {
|
|
427
|
+
const lastCheck = config.get('lastUpdateCheck');
|
|
428
|
+
const latestVersion = config.get('latestKnownVersion');
|
|
429
|
+
if (!lastCheck || !latestVersion)
|
|
430
|
+
return null;
|
|
431
|
+
const hoursSinceCheck = (Date.now() - new Date(lastCheck).getTime()) / (1000 * 60 * 60);
|
|
432
|
+
if (hoursSinceCheck > UPDATE_CHECK_INTERVAL_HOURS)
|
|
433
|
+
return null;
|
|
434
|
+
return { latestVersion, checkedAt: lastCheck };
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Cache the latest version from npm registry
|
|
438
|
+
*/
|
|
439
|
+
function setCachedUpdateInfo(latestVersion) {
|
|
440
|
+
config.set('lastUpdateCheck', new Date().toISOString());
|
|
441
|
+
config.set('latestKnownVersion', latestVersion);
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Get the current CLI version from package.json
|
|
445
|
+
*/
|
|
446
|
+
function getCliVersion() {
|
|
447
|
+
return '3.2.0'; // Keep in sync with package.json
|
|
448
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -26,6 +26,53 @@ const push_patterns_js_1 = require("./commands/push-patterns.js");
|
|
|
26
26
|
const go_js_1 = require("./commands/go.js");
|
|
27
27
|
const extend_js_1 = require("./commands/extend.js");
|
|
28
28
|
const billing_js_1 = require("./commands/billing.js");
|
|
29
|
+
const config_js_2 = require("./config.js");
|
|
30
|
+
// ============================================
|
|
31
|
+
// Automatic Update Notification
|
|
32
|
+
// ============================================
|
|
33
|
+
const CURRENT_VERSION = '3.2.0';
|
|
34
|
+
async function checkForUpdatesInBackground() {
|
|
35
|
+
// Check if we have a valid cached result first (fast path)
|
|
36
|
+
const cached = (0, config_js_2.getCachedUpdateInfo)();
|
|
37
|
+
if (cached) {
|
|
38
|
+
if (cached.latestVersion !== CURRENT_VERSION) {
|
|
39
|
+
showUpdateBanner(CURRENT_VERSION, cached.latestVersion);
|
|
40
|
+
}
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
// Fetch from npm registry (with timeout to not block CLI)
|
|
44
|
+
try {
|
|
45
|
+
const controller = new AbortController();
|
|
46
|
+
const timeout = setTimeout(() => controller.abort(), 3000);
|
|
47
|
+
const response = await fetch('https://registry.npmjs.org/@codebakers/cli/latest', {
|
|
48
|
+
headers: { 'Accept': 'application/json' },
|
|
49
|
+
signal: controller.signal,
|
|
50
|
+
});
|
|
51
|
+
clearTimeout(timeout);
|
|
52
|
+
if (response.ok) {
|
|
53
|
+
const data = await response.json();
|
|
54
|
+
const latestVersion = data.version;
|
|
55
|
+
(0, config_js_2.setCachedUpdateInfo)(latestVersion);
|
|
56
|
+
if (latestVersion !== CURRENT_VERSION) {
|
|
57
|
+
showUpdateBanner(CURRENT_VERSION, latestVersion);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// Silently fail - don't block CLI for update check
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function showUpdateBanner(currentVersion, latestVersion) {
|
|
66
|
+
console.log(chalk_1.default.yellow(`
|
|
67
|
+
╭─────────────────────────────────────────────────────────╮
|
|
68
|
+
│ │
|
|
69
|
+
│ ${chalk_1.default.bold('Update available!')} ${chalk_1.default.gray(currentVersion)} → ${chalk_1.default.green(latestVersion)} │
|
|
70
|
+
│ │
|
|
71
|
+
│ Run ${chalk_1.default.cyan('npm i -g @codebakers/cli@latest')} to update │
|
|
72
|
+
│ │
|
|
73
|
+
╰─────────────────────────────────────────────────────────╯
|
|
74
|
+
`));
|
|
75
|
+
}
|
|
29
76
|
// Show welcome message when no command is provided
|
|
30
77
|
function showWelcome() {
|
|
31
78
|
console.log(chalk_1.default.blue(`
|
|
@@ -67,7 +114,7 @@ const program = new commander_1.Command();
|
|
|
67
114
|
program
|
|
68
115
|
.name('codebakers')
|
|
69
116
|
.description('CodeBakers CLI - Production patterns for AI-assisted development')
|
|
70
|
-
.version('3.
|
|
117
|
+
.version('3.2.0');
|
|
71
118
|
// Zero-friction trial entry (no signup required)
|
|
72
119
|
program
|
|
73
120
|
.command('go')
|
|
@@ -199,9 +246,16 @@ program
|
|
|
199
246
|
.command('mcp-uninstall')
|
|
200
247
|
.description('Remove MCP configuration from Claude Code')
|
|
201
248
|
.action(mcp_config_js_1.mcpUninstall);
|
|
249
|
+
// Add update check hook (runs before every command)
|
|
250
|
+
program.hook('preAction', async () => {
|
|
251
|
+
await checkForUpdatesInBackground();
|
|
252
|
+
});
|
|
202
253
|
// Show welcome if no command provided
|
|
203
254
|
if (process.argv.length <= 2) {
|
|
204
|
-
|
|
255
|
+
// Still check for updates when showing welcome
|
|
256
|
+
checkForUpdatesInBackground().then(() => {
|
|
257
|
+
showWelcome();
|
|
258
|
+
});
|
|
205
259
|
}
|
|
206
260
|
else {
|
|
207
261
|
program.parse();
|
package/package.json
CHANGED
package/src/config.ts
CHANGED
|
@@ -116,6 +116,9 @@ interface ConfigSchema {
|
|
|
116
116
|
lastKeySync: string | null; // ISO date of last sync with server
|
|
117
117
|
// Trial state (for zero-friction onboarding)
|
|
118
118
|
trial: TrialState | null;
|
|
119
|
+
// Update notification cache
|
|
120
|
+
lastUpdateCheck: string | null; // ISO date of last npm registry check
|
|
121
|
+
latestKnownVersion: string | null; // Cached latest version from npm
|
|
119
122
|
}
|
|
120
123
|
|
|
121
124
|
// Create default service keys object with all keys set to null
|
|
@@ -133,6 +136,8 @@ const config = new Conf<ConfigSchema>({
|
|
|
133
136
|
serviceKeys: defaultServiceKeys,
|
|
134
137
|
lastKeySync: null,
|
|
135
138
|
trial: null,
|
|
139
|
+
lastUpdateCheck: null,
|
|
140
|
+
latestKnownVersion: null,
|
|
136
141
|
},
|
|
137
142
|
// Migration to add new keys when upgrading from old version
|
|
138
143
|
migrations: {
|
|
@@ -489,3 +494,39 @@ export function getAuthMode(): 'apiKey' | 'trial' | 'none' {
|
|
|
489
494
|
|
|
490
495
|
return 'none';
|
|
491
496
|
}
|
|
497
|
+
|
|
498
|
+
// ============================================
|
|
499
|
+
// Update Notification Cache
|
|
500
|
+
// ============================================
|
|
501
|
+
|
|
502
|
+
const UPDATE_CHECK_INTERVAL_HOURS = 24;
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* Get cached update info if still valid (within 24 hours)
|
|
506
|
+
*/
|
|
507
|
+
export function getCachedUpdateInfo(): { latestVersion: string; checkedAt: string } | null {
|
|
508
|
+
const lastCheck = config.get('lastUpdateCheck');
|
|
509
|
+
const latestVersion = config.get('latestKnownVersion');
|
|
510
|
+
|
|
511
|
+
if (!lastCheck || !latestVersion) return null;
|
|
512
|
+
|
|
513
|
+
const hoursSinceCheck = (Date.now() - new Date(lastCheck).getTime()) / (1000 * 60 * 60);
|
|
514
|
+
if (hoursSinceCheck > UPDATE_CHECK_INTERVAL_HOURS) return null;
|
|
515
|
+
|
|
516
|
+
return { latestVersion, checkedAt: lastCheck };
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* Cache the latest version from npm registry
|
|
521
|
+
*/
|
|
522
|
+
export function setCachedUpdateInfo(latestVersion: string): void {
|
|
523
|
+
config.set('lastUpdateCheck', new Date().toISOString());
|
|
524
|
+
config.set('latestKnownVersion', latestVersion);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Get the current CLI version from package.json
|
|
529
|
+
*/
|
|
530
|
+
export function getCliVersion(): string {
|
|
531
|
+
return '3.2.0'; // Keep in sync with package.json
|
|
532
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -22,6 +22,61 @@ import { pushPatterns, pushPatternsInteractive } from './commands/push-patterns.
|
|
|
22
22
|
import { go } from './commands/go.js';
|
|
23
23
|
import { extend } from './commands/extend.js';
|
|
24
24
|
import { billing } from './commands/billing.js';
|
|
25
|
+
import { getCachedUpdateInfo, setCachedUpdateInfo, getCliVersion } from './config.js';
|
|
26
|
+
|
|
27
|
+
// ============================================
|
|
28
|
+
// Automatic Update Notification
|
|
29
|
+
// ============================================
|
|
30
|
+
|
|
31
|
+
const CURRENT_VERSION = '3.2.0';
|
|
32
|
+
|
|
33
|
+
async function checkForUpdatesInBackground(): Promise<void> {
|
|
34
|
+
// Check if we have a valid cached result first (fast path)
|
|
35
|
+
const cached = getCachedUpdateInfo();
|
|
36
|
+
if (cached) {
|
|
37
|
+
if (cached.latestVersion !== CURRENT_VERSION) {
|
|
38
|
+
showUpdateBanner(CURRENT_VERSION, cached.latestVersion);
|
|
39
|
+
}
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Fetch from npm registry (with timeout to not block CLI)
|
|
44
|
+
try {
|
|
45
|
+
const controller = new AbortController();
|
|
46
|
+
const timeout = setTimeout(() => controller.abort(), 3000);
|
|
47
|
+
|
|
48
|
+
const response = await fetch('https://registry.npmjs.org/@codebakers/cli/latest', {
|
|
49
|
+
headers: { 'Accept': 'application/json' },
|
|
50
|
+
signal: controller.signal,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
clearTimeout(timeout);
|
|
54
|
+
|
|
55
|
+
if (response.ok) {
|
|
56
|
+
const data = await response.json();
|
|
57
|
+
const latestVersion = data.version;
|
|
58
|
+
setCachedUpdateInfo(latestVersion);
|
|
59
|
+
|
|
60
|
+
if (latestVersion !== CURRENT_VERSION) {
|
|
61
|
+
showUpdateBanner(CURRENT_VERSION, latestVersion);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
} catch {
|
|
65
|
+
// Silently fail - don't block CLI for update check
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function showUpdateBanner(currentVersion: string, latestVersion: string): void {
|
|
70
|
+
console.log(chalk.yellow(`
|
|
71
|
+
╭─────────────────────────────────────────────────────────╮
|
|
72
|
+
│ │
|
|
73
|
+
│ ${chalk.bold('Update available!')} ${chalk.gray(currentVersion)} → ${chalk.green(latestVersion)} │
|
|
74
|
+
│ │
|
|
75
|
+
│ Run ${chalk.cyan('npm i -g @codebakers/cli@latest')} to update │
|
|
76
|
+
│ │
|
|
77
|
+
╰─────────────────────────────────────────────────────────╯
|
|
78
|
+
`));
|
|
79
|
+
}
|
|
25
80
|
|
|
26
81
|
// Show welcome message when no command is provided
|
|
27
82
|
function showWelcome(): void {
|
|
@@ -72,7 +127,7 @@ const program = new Command();
|
|
|
72
127
|
program
|
|
73
128
|
.name('codebakers')
|
|
74
129
|
.description('CodeBakers CLI - Production patterns for AI-assisted development')
|
|
75
|
-
.version('3.
|
|
130
|
+
.version('3.2.0');
|
|
76
131
|
|
|
77
132
|
// Zero-friction trial entry (no signup required)
|
|
78
133
|
program
|
|
@@ -225,9 +280,17 @@ program
|
|
|
225
280
|
.description('Remove MCP configuration from Claude Code')
|
|
226
281
|
.action(mcpUninstall);
|
|
227
282
|
|
|
283
|
+
// Add update check hook (runs before every command)
|
|
284
|
+
program.hook('preAction', async () => {
|
|
285
|
+
await checkForUpdatesInBackground();
|
|
286
|
+
});
|
|
287
|
+
|
|
228
288
|
// Show welcome if no command provided
|
|
229
289
|
if (process.argv.length <= 2) {
|
|
230
|
-
|
|
290
|
+
// Still check for updates when showing welcome
|
|
291
|
+
checkForUpdatesInBackground().then(() => {
|
|
292
|
+
showWelcome();
|
|
293
|
+
});
|
|
231
294
|
} else {
|
|
232
295
|
program.parse();
|
|
233
296
|
}
|