kaven-cli 0.1.0-alpha.1 → 0.3.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.
Files changed (36) hide show
  1. package/README.md +221 -45
  2. package/dist/commands/auth/login.js +97 -19
  3. package/dist/commands/auth/logout.js +4 -6
  4. package/dist/commands/auth/whoami.js +12 -11
  5. package/dist/commands/cache/index.js +43 -0
  6. package/dist/commands/config/index.js +128 -0
  7. package/dist/commands/init/index.js +209 -0
  8. package/dist/commands/init-ci/index.js +153 -0
  9. package/dist/commands/license/index.js +10 -0
  10. package/dist/commands/license/status.js +44 -0
  11. package/dist/commands/license/tier-table.js +46 -0
  12. package/dist/commands/marketplace/browse.js +219 -0
  13. package/dist/commands/marketplace/install.js +233 -29
  14. package/dist/commands/marketplace/list.js +94 -16
  15. package/dist/commands/module/doctor.js +143 -38
  16. package/dist/commands/module/publish.js +291 -0
  17. package/dist/commands/upgrade/check.js +162 -0
  18. package/dist/commands/upgrade/index.js +218 -0
  19. package/dist/core/AuthService.js +207 -14
  20. package/dist/core/CacheManager.js +151 -0
  21. package/dist/core/ConfigManager.js +165 -0
  22. package/dist/core/EnvManager.js +196 -0
  23. package/dist/core/ErrorRecovery.js +191 -0
  24. package/dist/core/LicenseService.js +118 -0
  25. package/dist/core/ModuleDoctor.js +286 -0
  26. package/dist/core/ModuleInstaller.js +136 -2
  27. package/dist/core/ProjectInitializer.js +117 -0
  28. package/dist/core/RegistryResolver.js +94 -0
  29. package/dist/core/ScriptRunner.js +72 -0
  30. package/dist/core/SignatureVerifier.js +72 -0
  31. package/dist/index.js +265 -20
  32. package/dist/infrastructure/MarketplaceClient.js +388 -64
  33. package/dist/infrastructure/errors.js +61 -0
  34. package/dist/types/auth.js +2 -0
  35. package/dist/types/marketplace.js +2 -0
  36. package/package.json +15 -2
package/README.md CHANGED
@@ -1,93 +1,269 @@
1
- # Kaven CLI 🚀
1
+ # Kaven CLI
2
2
 
3
3
  [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
4
- [![Version](https://img.shields.io/badge/version-0.1.0--alpha.1-orange.svg)](https://semver.org)
4
+ [![Version](https://img.shields.io/badge/version-0.2.0--alpha.1-orange.svg)](https://semver.org)
5
+ [![Node](https://img.shields.io/badge/node-%3E%3D20-brightgreen.svg)](https://nodejs.org)
5
6
 
6
- A ferramenta de linha de comando oficial para o ecossistema **Kaven**. Projetada para ser robusta, idempotente e extensível.
7
+ The official command-line tool for the **Kaven** SaaS boilerplate ecosystem.
8
+ Bootstrap projects, manage modules, and interact with the Kaven Marketplace.
7
9
 
8
- > **Note**: Este projeto está em fase **Alpha**. APIs e comandos estão sujeitos a alterações.
10
+ > **Alpha**: APIs and commands are subject to change before v1.0.0.
9
11
 
10
12
  ---
11
13
 
12
- ## 📦 Instalação
13
-
14
- A CLI pode ser instalada globalmente via npm ou pnpm:
14
+ ## Installation
15
15
 
16
16
  ```bash
17
17
  npm install -g kaven-cli@alpha
18
- # ou
18
+ # or
19
19
  pnpm add -g kaven-cli@alpha
20
20
  ```
21
21
 
22
- ## 🚀 Início Rápido
22
+ **Requirements:** Node.js >= 20, pnpm (for `kaven init`)
23
+
24
+ ---
23
25
 
24
- Consiga o seu projeto rodando em segundos:
26
+ ## Quick Start
27
+
28
+ Five commands to get productive with Kaven:
25
29
 
26
30
  ```bash
27
- # 1. Autenticação
31
+ # 1. Bootstrap a new project
32
+ kaven init my-saas-app
33
+
34
+ # 2. Authenticate with the marketplace
28
35
  kaven auth login
29
36
 
30
- # 2. Explorar Módulos
31
- kaven marketplace list
37
+ # 3. Browse available modules
38
+ kaven marketplace browse
32
39
 
33
- # 3. Instalar um Módulo
40
+ # 4. Install a module
34
41
  kaven marketplace install payments
35
42
 
36
- # 4. Verificar Saúde do Projeto
43
+ # 5. Check project health
37
44
  kaven module doctor
45
+ ```
46
+
47
+ ---
48
+
49
+ ## Command Reference
50
+
51
+ ### `kaven init [project-name]`
38
52
 
39
- # 5. Ver Telemetria Local
40
- kaven telemetry view
53
+ Bootstrap a new Kaven project from the official template.
54
+
55
+ ```
56
+ Options:
57
+ --defaults Skip interactive prompts and use default values
58
+ --skip-install Skip running pnpm install after setup
59
+ --skip-git Skip git init and initial commit
60
+ --force Overwrite existing directory
61
+
62
+ Examples:
63
+ kaven init my-app
64
+ kaven init my-app --defaults
65
+ kaven init my-app --skip-git --skip-install
41
66
  ```
42
67
 
43
- ## 🛠️ Comandos Principais
68
+ ### `kaven auth`
44
69
 
45
- A Kaven CLI organiza suas funcionalidades em grupos lógicos para uma melhor experiência:
70
+ Manage authentication and session tokens.
46
71
 
47
- ### 📦 Módulos (`module`, `m`)
72
+ ```
73
+ Commands:
74
+ login Start device code authentication flow (RFC 8628)
75
+ logout Clear the local authentication session
76
+ whoami Display info about the authenticated user
77
+ ```
48
78
 
49
- Gerenciamento local de módulos e integridade do projeto.
79
+ ### `kaven marketplace`
50
80
 
51
- - `kaven module add <path>`: Adiciona um módulo localmente via arquivo de manifest.
52
- - `kaven module remove <name>`: Remove um módulo e limpa as injeções de código.
53
- - `kaven module doctor`: Verifica a integridade dos markers, âncoras e dependências.
81
+ Explore and install modules from the Kaven Marketplace.
54
82
 
55
- ### 🔑 Autenticação (`auth`)
83
+ ```
84
+ Commands:
85
+ list List available modules
86
+ install Install a module
87
+ browse Interactive TUI module browser
88
+
89
+ Options for list:
90
+ --category <cat> Filter by category
91
+ --sort <field> Sort: newest (default), popular, name
92
+ --page <n> Page number
93
+ --limit <n> Results per page (max: 100)
94
+ --json Output raw JSON
95
+
96
+ Options for install:
97
+ --version <ver> Install specific version
98
+ --force Skip overwrite confirmation
99
+ --skip-env Skip .env injection
100
+ --env-file <path> Target .env file
101
+ ```
56
102
 
57
- Gerenciamento de sessão e tokens.
103
+ ### `kaven module`
58
104
 
59
- - `kaven auth login`: Inicia o fluxo de autenticação (Device Flow).
60
- - `kaven auth logout`: Remove as credenciais locais.
61
- - `kaven auth whoami`: Exibe informações do usuário atual.
105
+ Manage installed modules.
62
106
 
63
- ### 🏬 Marketplace (`marketplace`, `mkt`)
107
+ ```
108
+ Commands:
109
+ doctor Run health checks on the project and modules
110
+ add Install a module from a local manifest
111
+ remove Remove an installed module
112
+ publish Publish a module to the marketplace
113
+
114
+ Options for doctor:
115
+ --fix Auto-fix detected issues (pnpm install, prisma generate, env vars)
116
+ --json Output machine-readable JSON
117
+
118
+ Exit codes for doctor:
119
+ 0 All checks passed
120
+ 1 One or more errors found
121
+ 2 Warnings only (no errors)
122
+
123
+ Options for publish:
124
+ --dry-run Validate and package without uploading
125
+ --changelog <text> Release notes for this version
126
+ ```
64
127
 
65
- Descoberta e instalação de módulos oficiais.
128
+ ### `kaven upgrade`
66
129
 
67
- - `kaven marketplace list`: Lista todos os módulos disponíveis na nuvem Kaven.
68
- - `kaven marketplace install <id>`: Baixa e instala um módulo automaticamente.
130
+ Upgrade your Kaven license tier via Paddle checkout.
69
131
 
70
- ### 📊 Telemetria (`telemetry`)
132
+ ```
133
+ Options:
134
+ --no-browser Print checkout URL instead of opening browser
71
135
 
72
- Observabilidade e auditoria local.
136
+ Behavior:
137
+ - Opens a Paddle checkout in your browser
138
+ - Polls for payment confirmation (every 5s, max 10 min)
139
+ - Updates local license on success
140
+ ```
141
+
142
+ ### `kaven license`
143
+
144
+ Manage your Kaven license.
145
+
146
+ ```
147
+ Commands:
148
+ status Show current license status and tier
149
+ ```
150
+
151
+ ### `kaven cache`
152
+
153
+ Manage the local API response cache (~/.kaven/cache, max 50 MB).
154
+
155
+ ```
156
+ Commands:
157
+ status Show cache statistics (size, entries, age)
158
+ clear Delete all cached data
159
+
160
+ Cache TTLs:
161
+ Module listings: 24 hours
162
+ Module manifests: 7 days
163
+ License status: 1 hour
164
+ ```
165
+
166
+ ### `kaven telemetry`
73
167
 
74
- - `kaven telemetry view`: Exibe os últimos eventos registrados localmente.
168
+ View observability and audit logs.
169
+
170
+ ```
171
+ Commands:
172
+ view Display the most recent local telemetry events
173
+ -l, --limit <n> Number of events to show (default: 10)
174
+ ```
75
175
 
76
176
  ---
77
177
 
78
- ## 🧪 Desenvolvimento
178
+ ## Configuration
179
+
180
+ Kaven CLI stores configuration in `~/.kaven/`:
79
181
 
80
- Nós valorizamos contribuições! Antes de começar, por favor leia nosso guia de contribuição:
182
+ ```
183
+ ~/.kaven/
184
+ auth.json Authentication tokens (chmod 600)
185
+ config.json CLI configuration (apiUrl override)
186
+ license.json License key and tier
187
+ signing-key.json Module signing key pair (chmod 600)
188
+ cache/ API response cache (max 50 MB)
189
+ telemetry.log Local telemetry events
190
+ ```
81
191
 
82
- - [CONTRIBUTING.md](./CONTRIBUTING.md) - Guia de setup e padrões.
83
- - [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md) - Nosso compromisso com a comunidade.
192
+ ### Overriding the API URL
193
+
194
+ Set `KAVEN_API_URL` environment variable or add to `~/.kaven/config.json`:
195
+
196
+ ```json
197
+ {
198
+ "apiUrl": "https://api.your-kaven-instance.com"
199
+ }
200
+ ```
201
+
202
+ ### Debug Mode
203
+
204
+ ```bash
205
+ KAVEN_DEBUG=1 kaven marketplace list
206
+ ```
207
+
208
+ ### Offline Mode
209
+
210
+ ```bash
211
+ KAVEN_OFFLINE=1 kaven marketplace list # Uses cached data only
212
+ ```
213
+
214
+ ---
215
+
216
+ ## Troubleshooting
217
+
218
+ ### "Not authenticated" error
219
+
220
+ Run `kaven auth login` and complete the device code flow in your browser.
221
+
222
+ ### "module.json not found" on publish
223
+
224
+ Run `kaven module publish` from inside the module directory
225
+ (the directory containing `module.json`).
226
+
227
+ ### pnpm install fails on kaven init
228
+
229
+ Install pnpm globally: `npm install -g pnpm`
230
+ Or use `kaven init --skip-install` and run `pnpm install` manually.
231
+
232
+ ### Prisma client out of sync
233
+
234
+ Run `kaven module doctor --fix` or manually: `npx prisma generate`
235
+
236
+ ### Cache issues
237
+
238
+ Clear the cache: `kaven cache clear`
239
+
240
+ ### Permission denied on ~/.kaven/
241
+
242
+ ```bash
243
+ chmod 700 ~/.kaven
244
+ chmod 600 ~/.kaven/auth.json
245
+ ```
246
+
247
+ ---
248
+
249
+ ## Development
250
+
251
+ ```bash
252
+ git clone https://github.com/kaven-co/kaven-cli
253
+ cd kaven-cli
254
+ pnpm install # or: npm install (with legacy-peer-deps)
255
+ pnpm test # Run test suite
256
+ pnpm run typecheck # TypeScript check
257
+ pnpm run lint # ESLint
258
+ ```
259
+
260
+ ---
84
261
 
85
- ## 📄 Licença
262
+ ## License
86
263
 
87
- Este projeto é licenciado sob a **Apache-2.0 License** - veja o arquivo [LICENSE](LICENSE) para detalhes.
264
+ Apache 2.0 see [LICENSE](LICENSE)
88
265
 
89
266
  ---
90
267
 
91
- <p align="center">
92
- Feito com ❤️ pela equipe Kaven
93
- </p>
268
+ Documentation: https://docs.kaven.sh/cli
269
+ GitHub: https://github.com/kaven-co/kaven-cli
@@ -6,39 +6,117 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.authLogin = authLogin;
7
7
  const chalk_1 = __importDefault(require("chalk"));
8
8
  const ora_1 = __importDefault(require("ora"));
9
+ const open_1 = __importDefault(require("open"));
9
10
  const AuthService_1 = require("../../core/AuthService");
11
+ const MarketplaceClient_1 = require("../../infrastructure/MarketplaceClient");
10
12
  const TelemetryBuffer_1 = require("../../infrastructure/TelemetryBuffer");
13
+ /**
14
+ * Sleep helper for polling delays
15
+ */
16
+ function sleep(ms) {
17
+ return new Promise((resolve) => setTimeout(resolve, ms));
18
+ }
19
+ /**
20
+ * Poll for access token with exponential backoff
21
+ */
22
+ async function pollForToken(client, deviceCode, expiresIn, initialInterval, spinner) {
23
+ const deadline = Date.now() + expiresIn * 1000;
24
+ const backoffIntervals = [5, 10, 15, 20]; // seconds - exponential backoff
25
+ let backoffIndex = 0;
26
+ let interval = initialInterval;
27
+ while (Date.now() < deadline) {
28
+ // Update countdown spinner
29
+ const remaining = Math.ceil((deadline - Date.now()) / 1000);
30
+ const mm = Math.floor(remaining / 60);
31
+ const ss = String(remaining % 60).padStart(2, '0');
32
+ spinner.text = `Waiting for authorization... (expires in ${mm}:${ss})`;
33
+ // Wait for next poll
34
+ await sleep(interval * 1000);
35
+ try {
36
+ const result = await client.pollDeviceToken(deviceCode);
37
+ // Success - return tokens
38
+ if (result.status === 'success' && result.tokens) {
39
+ return result.tokens;
40
+ }
41
+ // Handle different status codes
42
+ switch (result.status) {
43
+ case 'slow_down':
44
+ // Increase interval by 5s as requested by server
45
+ interval += 5;
46
+ break;
47
+ case 'access_denied':
48
+ throw new Error('Authorization denied by user. Try again with \'kaven auth login\'.');
49
+ case 'expired_token':
50
+ throw new Error('Device code expired. Run \'kaven auth login\' again.');
51
+ case 'authorization_pending':
52
+ // Continue polling - apply exponential backoff
53
+ if (backoffIndex < backoffIntervals.length - 1) {
54
+ backoffIndex++;
55
+ interval = backoffIntervals[backoffIndex];
56
+ }
57
+ break;
58
+ }
59
+ }
60
+ catch (error) {
61
+ // Re-throw our custom errors
62
+ if (error.message.includes('denied') ||
63
+ error.message.includes('expired')) {
64
+ throw error;
65
+ }
66
+ // Network errors
67
+ const nodeError = error;
68
+ if (nodeError.code === 'ECONNREFUSED' || nodeError.code === 'ENOTFOUND') {
69
+ throw new Error('Network error. Check your connection and try again.');
70
+ }
71
+ // Unknown error
72
+ throw error;
73
+ }
74
+ }
75
+ // Timeout - device code expired
76
+ throw new Error('Device code expired. Run \'kaven auth login\' again.');
77
+ }
78
+ /**
79
+ * Main login command - OAuth 2.0 Device Authorization Grant (RFC 8628)
80
+ */
11
81
  async function authLogin() {
12
82
  const telemetry = TelemetryBuffer_1.TelemetryBuffer.getInstance();
13
83
  const startTime = Date.now();
14
84
  telemetry.capture("cli.auth.login.start");
85
+ const client = new MarketplaceClient_1.MarketplaceClient();
15
86
  const authService = new AuthService_1.AuthService();
16
- console.log(chalk_1.default.blue("🔐 Iniciando fluxo de autenticação...\n"));
17
- const spinner = (0, ora_1.default)("Gerando código de dispositivo...").start();
87
+ console.log(chalk_1.default.blue("🔐 Starting authentication flow...\n"));
88
+ const spinner = (0, ora_1.default)("Requesting device code from marketplace...").start();
18
89
  try {
19
- // Simulando atraso da rede
20
- await new Promise((resolve) => setTimeout(resolve, 1000));
21
- const deviceCode = "KAVEN-777-BINGO";
22
- const verificationUrl = "https://kaven.sh/device";
90
+ // Step 1: Request device code
91
+ const { device_code, user_code, verification_uri, expires_in, interval } = await client.requestDeviceCode();
23
92
  spinner.stop();
24
- console.log(chalk_1.default.yellow("Para continuar o login, acesse a URL abaixo e insira o código:"));
25
- console.log(chalk_1.default.bold(`\n URL: ${verificationUrl}`));
26
- console.log(chalk_1.default.bold(` Código: ${deviceCode}\n`));
27
- const pollSpinner = (0, ora_1.default)("Aguardando autorização no navegador...").start();
28
- // Simular polling bem-sucedido após 3 segundos
29
- await new Promise((resolve) => setTimeout(resolve, 3000));
30
- const mockToken = "jwt-mock-token-for-kaven-explorador";
31
- await authService.storeToken(mockToken);
32
- pollSpinner.succeed(chalk_1.default.green("Autenticação realizada com sucesso!"));
33
- console.log(chalk_1.default.gray("\nSeu token foi salvo com segurança em ~/.kaven/auth.json"));
34
- telemetry.capture("cli.auth.login.success", {}, Date.now() - startTime);
93
+ // Step 2: Display code and open browser
94
+ console.log(chalk_1.default.yellow("To complete login, follow these steps:\n"));
95
+ console.log(chalk_1.default.bold(` Your verification code: ${chalk_1.default.cyan(user_code)}\n`));
96
+ try {
97
+ await (0, open_1.default)(verification_uri);
98
+ console.log(chalk_1.default.dim(" ✓ Browser opened automatically"));
99
+ }
100
+ catch {
101
+ console.log(chalk_1.default.yellow(` Open this URL in your browser:`));
102
+ console.log(chalk_1.default.underline(` ${verification_uri}\n`));
103
+ }
104
+ // Step 3: Poll for token with exponential backoff
105
+ const pollSpinner = (0, ora_1.default)('Waiting for authorization...').start();
106
+ const tokens = await pollForToken(client, device_code, expires_in, interval, pollSpinner);
107
+ // Step 4: Store tokens securely
108
+ await authService.saveTokens(tokens);
109
+ pollSpinner.succeed(chalk_1.default.green(`Logged in as ${chalk_1.default.bold(tokens.user.email)}`));
110
+ console.log(chalk_1.default.dim(` Tier: ${tokens.user.tier}`));
111
+ console.log(chalk_1.default.gray("\n Your credentials were saved securely in ~/.kaven/auth.json\n"));
112
+ telemetry.capture("cli.auth.login.success", { tier: tokens.user.tier }, Date.now() - startTime);
35
113
  await telemetry.flush();
36
114
  }
37
115
  catch (error) {
38
116
  telemetry.capture("cli.auth.login.error", { error: error.message }, Date.now() - startTime);
39
117
  await telemetry.flush();
40
- spinner.fail(chalk_1.default.red("Erro ao realizar login."));
41
- console.error(error);
118
+ spinner.fail(chalk_1.default.red("Authentication failed"));
119
+ console.error(chalk_1.default.red(`\n Error: ${error.message}\n`));
42
120
  process.exit(1);
43
121
  }
44
122
  }
@@ -5,21 +5,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.authLogout = authLogout;
7
7
  const chalk_1 = __importDefault(require("chalk"));
8
- const ora_1 = __importDefault(require("ora"));
9
8
  const AuthService_1 = require("../../core/AuthService");
10
9
  async function authLogout() {
11
10
  const authService = new AuthService_1.AuthService();
12
- const spinner = (0, ora_1.default)("Encerrando sessão...").start();
13
11
  try {
14
12
  if (!(await authService.isAuthenticated())) {
15
- spinner.info(chalk_1.default.yellow("Você não está autenticado."));
13
+ console.log(chalk_1.default.yellow("You are not authenticated."));
16
14
  return;
17
15
  }
18
- await authService.clearToken();
19
- spinner.succeed(chalk_1.default.green("Sessão encerrada com sucesso!"));
16
+ await authService.logout();
17
+ console.log(chalk_1.default.green("Logged out successfully."));
20
18
  }
21
19
  catch {
22
- spinner.fail(chalk_1.default.red("Erro ao realizar logout."));
20
+ console.error(chalk_1.default.red("Error during logout."));
23
21
  process.exit(1);
24
22
  }
25
23
  }
@@ -12,24 +12,25 @@ async function authWhoami() {
12
12
  telemetry.capture("cli.auth.whoami.start");
13
13
  const authService = new AuthService_1.AuthService();
14
14
  try {
15
- const userInfo = await authService.getUserInfo();
16
- if (!userInfo) {
17
- console.log(chalk_1.default.yellow("Você não está autenticado."));
18
- console.log(chalk_1.default.gray("Use 'kaven auth login' para entrar."));
15
+ const info = await authService.getWhoamiInfo();
16
+ if (!info) {
17
+ console.log(chalk_1.default.yellow("You are not authenticated."));
18
+ console.log(chalk_1.default.gray("Use 'kaven auth login' to sign in."));
19
19
  telemetry.capture("cli.auth.whoami.not_authenticated");
20
20
  await telemetry.flush();
21
21
  return;
22
22
  }
23
23
  telemetry.capture("cli.auth.whoami.authenticated");
24
- console.log(chalk_1.default.blue("👤 Usuário logado:"));
25
- console.log(`${chalk_1.default.bold("ID:")} ${userInfo.id}`);
26
- console.log(`${chalk_1.default.bold("E-mail:")} ${userInfo.email}`);
27
- if (userInfo.name) {
28
- console.log(`${chalk_1.default.bold("Nome:")} ${userInfo.name}`);
29
- }
24
+ console.log();
25
+ console.log(` ${chalk_1.default.bold("Email:")} ${info.email}`);
26
+ console.log(` ${chalk_1.default.bold("GitHub:")} ${info.githubId}`);
27
+ console.log(` ${chalk_1.default.bold("Tier:")} ${info.tier}`);
28
+ console.log(` ${chalk_1.default.bold("Session:")} ${info.sessionExpiry}`);
29
+ console.log();
30
30
  }
31
31
  catch {
32
- console.error(chalk_1.default.red("Erro ao verificar status de autenticação."));
32
+ console.error(chalk_1.default.red("Error checking authentication status."));
33
33
  process.exit(1);
34
34
  }
35
+ await telemetry.flush();
35
36
  }
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.cacheStatus = cacheStatus;
7
+ exports.cacheClear = cacheClear;
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const CacheManager_1 = require("../../core/CacheManager");
10
+ function formatBytes(bytes) {
11
+ if (bytes === 0)
12
+ return "0 B";
13
+ const k = 1024;
14
+ const sizes = ["B", "KB", "MB", "GB"];
15
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
16
+ return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
17
+ }
18
+ async function cacheStatus() {
19
+ const manager = (0, CacheManager_1.getCacheManager)();
20
+ const stats = await manager.stats();
21
+ console.log(chalk_1.default.bold("\nKaven CLI Cache Status\n"));
22
+ console.log(` Cache directory: ${chalk_1.default.cyan(manager.cacheDir)}`);
23
+ console.log(` Total size: ${chalk_1.default.cyan(formatBytes(stats.totalSize))}`);
24
+ console.log(` Cached entries: ${chalk_1.default.cyan(stats.entries.toString())}`);
25
+ if (stats.oldest) {
26
+ console.log(` Oldest entry: ${chalk_1.default.gray(stats.oldest.toLocaleString())}`);
27
+ }
28
+ if (stats.newest) {
29
+ console.log(` Newest entry: ${chalk_1.default.gray(stats.newest.toLocaleString())}`);
30
+ }
31
+ console.log();
32
+ console.log(chalk_1.default.gray("Run 'kaven cache clear' to remove all cached data."));
33
+ }
34
+ async function cacheClear() {
35
+ const manager = (0, CacheManager_1.getCacheManager)();
36
+ const stats = await manager.stats();
37
+ if (stats.entries === 0) {
38
+ console.log(chalk_1.default.gray("Cache is already empty."));
39
+ return;
40
+ }
41
+ await manager.clear();
42
+ console.log(chalk_1.default.green(`Cache cleared: ${stats.entries} entries (${formatBytes(stats.totalSize)}) removed.`));
43
+ }