kaven-cli 0.1.0-alpha.1 → 0.3.5

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 (50) hide show
  1. package/README.md +284 -45
  2. package/README.pt-BR.md +334 -0
  3. package/dist/commands/auth/login.js +97 -19
  4. package/dist/commands/auth/logout.js +4 -6
  5. package/dist/commands/auth/whoami.js +12 -11
  6. package/dist/commands/cache/index.js +43 -0
  7. package/dist/commands/config/index.js +128 -0
  8. package/dist/commands/init/index.js +209 -0
  9. package/dist/commands/init-ci/index.js +153 -0
  10. package/dist/commands/license/index.js +10 -0
  11. package/dist/commands/license/status.js +44 -0
  12. package/dist/commands/license/tier-table.js +46 -0
  13. package/dist/commands/marketplace/browse.js +219 -0
  14. package/dist/commands/marketplace/install.js +233 -29
  15. package/dist/commands/marketplace/list.js +94 -16
  16. package/dist/commands/module/doctor.js +143 -38
  17. package/dist/commands/module/publish.js +291 -0
  18. package/dist/commands/upgrade/check.js +162 -0
  19. package/dist/commands/upgrade/index.js +218 -0
  20. package/dist/core/AuthService.js +207 -14
  21. package/dist/core/CacheManager.js +151 -0
  22. package/dist/core/ConfigManager.js +165 -0
  23. package/dist/core/EnvManager.js +196 -0
  24. package/dist/core/ErrorRecovery.js +191 -0
  25. package/dist/core/LicenseService.js +118 -0
  26. package/dist/core/ModuleDoctor.js +290 -4
  27. package/dist/core/ModuleInstaller.js +136 -2
  28. package/dist/core/ProjectInitializer.js +154 -0
  29. package/dist/core/RegistryResolver.js +94 -0
  30. package/dist/core/ScriptRunner.js +72 -0
  31. package/dist/core/SignatureVerifier.js +75 -0
  32. package/dist/index.js +265 -20
  33. package/dist/infrastructure/MarketplaceClient.js +388 -64
  34. package/dist/infrastructure/errors.js +61 -0
  35. package/dist/types/auth.js +2 -0
  36. package/dist/types/marketplace.js +2 -0
  37. package/package.json +23 -4
  38. package/dist/commands/modules/add.js +0 -53
  39. package/dist/commands/modules/list.js +0 -40
  40. package/dist/commands/modules/remove.js +0 -54
  41. package/dist/core/api/KavenApiClient.js +0 -61
  42. package/dist/core/auth/AuthManager.js +0 -91
  43. package/dist/core/modules/Injector.js +0 -86
  44. package/dist/core/modules/ModuleInstaller.js +0 -63
  45. package/dist/core/modules/ModuleManager.js +0 -59
  46. package/dist/core/modules/ModuleRemover.js +0 -60
  47. package/dist/lib/config.js +0 -66
  48. package/dist/lib/errors.js +0 -32
  49. package/dist/lib/logger.js +0 -70
  50. package/dist/types/module.js +0 -49
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RegistryResolver = void 0;
4
+ const ConfigManager_1 = require("./ConfigManager");
5
+ const MarketplaceClient_1 = require("../infrastructure/MarketplaceClient");
6
+ const AuthService_1 = require("./AuthService");
7
+ /**
8
+ * C2.5: Registry resolver — handles both official and custom registries
9
+ */
10
+ class RegistryResolver {
11
+ constructor(authService) {
12
+ this.authService = authService || new AuthService_1.AuthService();
13
+ }
14
+ /**
15
+ * Get the active registry URL (custom or default)
16
+ */
17
+ async getActiveRegistry() {
18
+ await ConfigManager_1.configManager.initialize();
19
+ return ConfigManager_1.configManager.getRegistry();
20
+ }
21
+ /**
22
+ * Get marketplace client for active registry
23
+ */
24
+ async getMarketplaceClient() {
25
+ const registry = await this.getActiveRegistry();
26
+ const client = new MarketplaceClient_1.MarketplaceClient(this.authService);
27
+ // Set custom registry if configured
28
+ if (registry !== "https://marketplace.kaven.sh") {
29
+ client.baseUrl = registry;
30
+ }
31
+ return client;
32
+ }
33
+ /**
34
+ * Validate registry URL is accessible
35
+ */
36
+ async validateRegistry(url) {
37
+ try {
38
+ const response = await fetch(`${url}/health`);
39
+ if (!response.ok) {
40
+ return {
41
+ valid: false,
42
+ error: `Registry returned ${response.status} ${response.statusText}`,
43
+ };
44
+ }
45
+ return { valid: true };
46
+ }
47
+ catch (error) {
48
+ return {
49
+ valid: false,
50
+ error: `Failed to connect: ${error instanceof Error ? error.message : String(error)}`,
51
+ };
52
+ }
53
+ }
54
+ /**
55
+ * Set custom registry
56
+ */
57
+ async setCustomRegistry(url) {
58
+ // Validate URL format
59
+ try {
60
+ new URL(url);
61
+ }
62
+ catch {
63
+ throw new Error(`Invalid URL format: ${url}`);
64
+ }
65
+ // Validate registry is accessible
66
+ const validation = await this.validateRegistry(url);
67
+ if (!validation.valid) {
68
+ throw new Error(`Registry validation failed: ${validation.error}`);
69
+ }
70
+ // Save to config
71
+ await ConfigManager_1.configManager.initialize();
72
+ await ConfigManager_1.configManager.set("customRegistry", url);
73
+ }
74
+ /**
75
+ * Reset to default registry
76
+ */
77
+ async resetToDefaultRegistry() {
78
+ await ConfigManager_1.configManager.initialize();
79
+ await ConfigManager_1.configManager.set("customRegistry", undefined);
80
+ }
81
+ /**
82
+ * List all available registries (default + custom)
83
+ */
84
+ async listRegistries() {
85
+ await ConfigManager_1.configManager.initialize();
86
+ const config = ConfigManager_1.configManager.getAll();
87
+ return {
88
+ default: config.registry || "https://marketplace.kaven.sh",
89
+ custom: config.customRegistry,
90
+ active: await this.getActiveRegistry(),
91
+ };
92
+ }
93
+ }
94
+ exports.RegistryResolver = RegistryResolver;
@@ -0,0 +1,72 @@
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.ScriptRunner = void 0;
7
+ const child_process_1 = require("child_process");
8
+ const readline_1 = __importDefault(require("readline"));
9
+ const chalk_1 = __importDefault(require("chalk"));
10
+ class ScriptRunner {
11
+ constructor(timeoutMs = 60000) {
12
+ this.timeoutMs = timeoutMs;
13
+ }
14
+ async runScript(script, label, skipConfirmation = false) {
15
+ if (!skipConfirmation) {
16
+ const confirmed = await this.confirm(`Run ${label} script: ${script.command} ${(script.args ?? []).join(' ')}?`);
17
+ if (!confirmed) {
18
+ console.log(chalk_1.default.dim(` Skipping ${label} script.`));
19
+ return;
20
+ }
21
+ }
22
+ return new Promise((resolve, reject) => {
23
+ const child = (0, child_process_1.spawn)(script.command, script.args ?? [], {
24
+ cwd: script.cwd,
25
+ stdio: ['ignore', 'pipe', 'pipe'],
26
+ shell: true,
27
+ });
28
+ const prefix = chalk_1.default.dim(`[${label}] `);
29
+ child.stdout?.on('data', (data) => {
30
+ process.stdout.write(prefix + data.toString());
31
+ });
32
+ child.stderr?.on('data', (data) => {
33
+ process.stderr.write(prefix + chalk_1.default.yellow(data.toString()));
34
+ });
35
+ const timer = setTimeout(() => {
36
+ console.warn(chalk_1.default.yellow(`\n ⚠ ${label} script timed out after ${this.timeoutMs / 1000}s, sending SIGTERM...`));
37
+ child.kill('SIGTERM');
38
+ setTimeout(() => {
39
+ child.kill('SIGKILL');
40
+ }, 5000);
41
+ }, this.timeoutMs);
42
+ child.on('close', (code) => {
43
+ clearTimeout(timer);
44
+ if (code === 0 || code === null) {
45
+ resolve();
46
+ }
47
+ else {
48
+ reject(new Error(`${label} script exited with code ${code}`));
49
+ }
50
+ });
51
+ child.on('error', (err) => {
52
+ clearTimeout(timer);
53
+ reject(err);
54
+ });
55
+ });
56
+ }
57
+ async runScripts(scripts, label, skipConfirmation = false) {
58
+ for (const script of scripts) {
59
+ await this.runScript(script, label, skipConfirmation);
60
+ }
61
+ }
62
+ confirm(message) {
63
+ return new Promise((resolve) => {
64
+ const rl = readline_1.default.createInterface({ input: process.stdin, output: process.stdout });
65
+ rl.question(`\n ${message} [y/N] `, (answer) => {
66
+ rl.close();
67
+ resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
68
+ });
69
+ });
70
+ }
71
+ }
72
+ exports.ScriptRunner = ScriptRunner;
@@ -0,0 +1,75 @@
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.computeFileChecksum = computeFileChecksum;
7
+ exports.verifyEd25519Signature = verifyEd25519Signature;
8
+ exports.verifyDownload = verifyDownload;
9
+ const crypto_1 = __importDefault(require("crypto"));
10
+ const fs_extra_1 = __importDefault(require("fs-extra"));
11
+ const errors_1 = require("../infrastructure/errors");
12
+ /**
13
+ * Compute SHA-256 hex checksum of a file.
14
+ */
15
+ async function computeFileChecksum(filePath) {
16
+ const data = await fs_extra_1.default.readFile(filePath);
17
+ return crypto_1.default.createHash("sha256").update(data).digest("hex");
18
+ }
19
+ const HEX_PATTERN = /^[0-9a-fA-F]+$/;
20
+ /**
21
+ * Decode a signature string that may be hex or base64 encoded.
22
+ * Ed25519 signatures are always 64 bytes:
23
+ * - hex: 128 chars, only [0-9a-fA-F]
24
+ * - base64: 88 chars, may contain +/=
25
+ */
26
+ function decodeSignature(encoded) {
27
+ if (HEX_PATTERN.test(encoded) && encoded.length === 128) {
28
+ return Buffer.from(encoded, "hex");
29
+ }
30
+ return Buffer.from(encoded, "base64");
31
+ }
32
+ /**
33
+ * Verify Ed25519 signature against a SHA-256 checksum.
34
+ *
35
+ * Accepts signature in either hex or base64 encoding.
36
+ * Tolerates signatures made over checksum with trailing newline
37
+ * (common when signing via `echo checksum > file && openssl sign`).
38
+ */
39
+ function verifyEd25519Signature(checksum, signature, publicKeyBase64) {
40
+ try {
41
+ const publicKey = crypto_1.default.createPublicKey({
42
+ key: Buffer.from(publicKeyBase64, "base64"),
43
+ type: "spki",
44
+ format: "der",
45
+ });
46
+ const sigBuffer = decodeSignature(signature);
47
+ if (crypto_1.default.verify(null, Buffer.from(checksum), publicKey, sigBuffer)) {
48
+ return true;
49
+ }
50
+ // Tolerate trailing newline from shell-based signing
51
+ return crypto_1.default.verify(null, Buffer.from(checksum + "\n"), publicKey, sigBuffer);
52
+ }
53
+ catch {
54
+ return false;
55
+ }
56
+ }
57
+ /**
58
+ * Verify a downloaded module tarball:
59
+ * 1. Compute SHA-256 checksum and compare to expected
60
+ * 2. Verify Ed25519 signature of checksum with publisher key
61
+ *
62
+ * Throws SignatureVerificationError on failure.
63
+ */
64
+ async function verifyDownload(opts) {
65
+ const actualChecksum = await computeFileChecksum(opts.filePath);
66
+ if (actualChecksum !== opts.expectedChecksum) {
67
+ throw new errors_1.SignatureVerificationError(`Checksum mismatch: expected ${opts.expectedChecksum.substring(0, 16)}..., ` +
68
+ `got ${actualChecksum.substring(0, 16)}...`);
69
+ }
70
+ const valid = verifyEd25519Signature(opts.expectedChecksum, opts.signature, opts.publicKeyBase64);
71
+ if (!valid) {
72
+ throw new errors_1.SignatureVerificationError("Ed25519 signature verification failed. " +
73
+ "The package may have been tampered with.");
74
+ }
75
+ }
package/dist/index.js CHANGED
@@ -6,55 +6,152 @@ const commander_1 = require("commander");
6
6
  const doctor_1 = require("./commands/module/doctor");
7
7
  const add_1 = require("./commands/module/add");
8
8
  const remove_1 = require("./commands/module/remove");
9
+ const publish_1 = require("./commands/module/publish");
9
10
  const login_1 = require("./commands/auth/login");
10
11
  const logout_1 = require("./commands/auth/logout");
11
12
  const whoami_1 = require("./commands/auth/whoami");
12
13
  const list_1 = require("./commands/marketplace/list");
13
14
  const install_1 = require("./commands/marketplace/install");
15
+ const browse_1 = require("./commands/marketplace/browse");
14
16
  const view_1 = require("./commands/telemetry/view");
17
+ const index_js_1 = require("./commands/license/index.js");
18
+ const index_1 = require("./commands/init/index");
19
+ const index_2 = require("./commands/upgrade/index");
20
+ const index_3 = require("./commands/cache/index");
21
+ const index_4 = require("./commands/config/index");
22
+ const index_5 = require("./commands/init-ci/index");
15
23
  const main = () => {
16
24
  const program = new commander_1.Command();
17
25
  program
18
26
  .name("kaven")
19
- .description("CLI oficial para o ecossistema Kaven")
20
- .version("0.1.0-alpha.1");
27
+ .description("The official CLI for the Kaven SaaS boilerplate ecosystem")
28
+ .version("0.2.0-alpha.1")
29
+ .addHelpText("after", `
30
+ Examples:
31
+ $ kaven init my-saas-app Bootstrap a new Kaven project
32
+ $ kaven auth login Authenticate with Kaven Marketplace
33
+ $ kaven marketplace list Browse available modules
34
+ $ kaven marketplace install auth Install the auth module
35
+ $ kaven upgrade Upgrade your license tier
36
+ $ kaven module doctor Check project health
37
+
38
+ Documentation: https://docs.kaven.sh/cli
39
+ Support: https://github.com/kaven-co/kaven-cli/issues
40
+ `);
41
+ /**
42
+ * Init command — Bootstrap a new Kaven project
43
+ */
44
+ program
45
+ .command("init [project-name]")
46
+ .description("Bootstrap a new Kaven project from the official template")
47
+ .option("--defaults", "Skip interactive prompts and use default values")
48
+ .option("--skip-install", "Skip running pnpm install after setup")
49
+ .option("--skip-git", "Skip git init and initial commit")
50
+ .option("--force", "Overwrite existing directory if it exists")
51
+ .addHelpText("after", `
52
+ Examples:
53
+ $ kaven init my-app Interactive setup
54
+ $ kaven init my-app --defaults Use defaults (no prompts)
55
+ $ kaven init my-app --skip-git Skip git initialization
56
+ `)
57
+ .action((name, opts) => (0, index_1.initProject)(name, {
58
+ defaults: opts.defaults,
59
+ skipInstall: opts.skipInstall,
60
+ skipGit: opts.skipGit,
61
+ force: opts.force,
62
+ }));
21
63
  /**
22
64
  * Modules Group
23
65
  */
24
66
  const moduleCommand = program
25
67
  .command("module")
26
68
  .alias("m")
27
- .description("Gerenciamento de módulos e integridade");
69
+ .description("Manage Kaven modules: install, remove, publish, and diagnose")
70
+ .addHelpText("after", `
71
+ Examples:
72
+ $ kaven module doctor Check module integrity
73
+ $ kaven module doctor --fix Auto-fix detected issues
74
+ $ kaven module add ./my-module Install a local module
75
+ $ kaven module remove payments Remove a module
76
+ $ kaven module publish Publish module to marketplace
77
+ `);
28
78
  moduleCommand
29
79
  .command("doctor")
30
- .description("Verifica integridade do projeto e dos módulos instalados")
31
- .option("--fix", "Attempt to fix issues")
32
- .action((options) => (0, doctor_1.moduleDoctor)(options));
80
+ .description("Run comprehensive project and module health checks")
81
+ .option("--fix", "Attempt to auto-fix detected issues (pnpm install, prisma generate, env vars)")
82
+ .option("--json", "Output results as machine-readable JSON")
83
+ .addHelpText("after", `
84
+ Exit codes:
85
+ 0 All checks passed
86
+ 1 One or more errors found
87
+ 2 Warnings only (no errors)
88
+
89
+ Examples:
90
+ $ kaven module doctor
91
+ $ kaven module doctor --fix
92
+ $ kaven module doctor --json
93
+ `)
94
+ .action((options) => (0, doctor_1.moduleDoctor)({ fix: options.fix, json: options.json }));
33
95
  moduleCommand
34
96
  .command("add <path>")
35
- .description("Instala um módulo a partir de um manifest local")
97
+ .description("Install a module from a local manifest file")
98
+ .addHelpText("after", `
99
+ Examples:
100
+ $ kaven module add ./modules/payments/module.json
101
+ $ kaven module add /absolute/path/to/module.json
102
+ `)
36
103
  .action((path) => (0, add_1.moduleAdd)(path));
37
104
  moduleCommand
38
105
  .command("remove <name>")
39
- .description("Remove um módulo e limpa injeções de código")
106
+ .description("Remove an installed module and clean up injected code")
107
+ .addHelpText("after", `
108
+ Examples:
109
+ $ kaven module remove payments
110
+ $ kaven module remove notifications
111
+ `)
40
112
  .action((name) => (0, remove_1.moduleRemove)(name));
113
+ moduleCommand
114
+ .command("publish")
115
+ .description("Publish the current directory as a module to Kaven Marketplace")
116
+ .option("--dry-run", "Validate and package the module without uploading")
117
+ .option("--changelog <text>", "Release notes for this version")
118
+ .addHelpText("after", `
119
+ Requirements:
120
+ - module.json must exist in the current directory
121
+ - Must be authenticated: run 'kaven auth login' first
122
+
123
+ Examples:
124
+ $ kaven module publish
125
+ $ kaven module publish --dry-run
126
+ $ kaven module publish --changelog "Added dark mode support"
127
+ `)
128
+ .action((opts) => (0, publish_1.modulePublish)({
129
+ dryRun: opts.dryRun,
130
+ changelog: opts.changelog,
131
+ }));
41
132
  /**
42
133
  * Auth Group
43
134
  */
44
135
  const authCommand = program
45
136
  .command("auth")
46
- .description("Autenticação e gerenciamento de sessão");
137
+ .description("Manage authentication and session tokens")
138
+ .addHelpText("after", `
139
+ Examples:
140
+ $ kaven auth login Start device code authentication flow
141
+ $ kaven auth whoami Show current user info
142
+ $ kaven auth logout End the local session
143
+ `);
47
144
  authCommand
48
145
  .command("login")
49
- .description("Inicia o fluxo de login interativo")
146
+ .description("Start the interactive device code authentication flow (RFC 8628)")
50
147
  .action(() => (0, login_1.authLogin)());
51
148
  authCommand
52
149
  .command("logout")
53
- .description("Encerra a sessão local")
150
+ .description("Clear the local authentication session")
54
151
  .action(() => (0, logout_1.authLogout)());
55
152
  authCommand
56
153
  .command("whoami")
57
- .description("Exibe informações do usuário autenticado")
154
+ .description("Display information about the currently authenticated user")
58
155
  .action(() => (0, whoami_1.authWhoami)());
59
156
  /**
60
157
  * Marketplace Group
@@ -63,26 +160,174 @@ const main = () => {
63
160
  .command("marketplace")
64
161
  .alias("mkt")
65
162
  .alias("market")
66
- .description("Explorar e instalar módulos do Marketplace oficial");
163
+ .description("Explore, browse, and install modules from the Kaven Marketplace")
164
+ .addHelpText("after", `
165
+ Examples:
166
+ $ kaven marketplace list
167
+ $ kaven marketplace list --category auth --sort popular
168
+ $ kaven marketplace install payments
169
+ $ kaven marketplace browse
170
+ `);
67
171
  marketplaceCommand
68
172
  .command("list")
69
- .description("Lista todos os módulos disponíveis no marketplace")
70
- .action(() => (0, list_1.marketplaceList)());
173
+ .description("List all modules available in the marketplace")
174
+ .option("--category <category>", "Filter modules by category")
175
+ .option("--sort <field>", "Sort order: newest (default), popular, name", "newest")
176
+ .option("--page <n>", "Page number (default: 1)", "1")
177
+ .option("--limit <n>", "Results per page (default: 20, max: 100)", "20")
178
+ .option("--json", "Output raw JSON instead of formatted table")
179
+ .action((options) => (0, list_1.marketplaceList)({
180
+ category: options.category,
181
+ sort: options.sort,
182
+ page: parseInt(options.page, 10),
183
+ limit: parseInt(options.limit, 10),
184
+ json: options.json ?? false,
185
+ }));
71
186
  marketplaceCommand
72
187
  .command("install <moduleId>")
73
- .description("Baixa e instala um módulo via Marketplace")
74
- .action((moduleId) => (0, install_1.marketplaceInstall)(moduleId));
188
+ .description("Download and install a module from the Kaven Marketplace")
189
+ .option("--version <ver>", "Install a specific version (default: latest)")
190
+ .option("--force", "Skip overwrite confirmation")
191
+ .option("--skip-env", "Skip environment variable injection")
192
+ .option("--skip-verify", "Skip Ed25519 signature verification (dev only)")
193
+ .option("--env-file <path>", "Target .env file (default: .env)")
194
+ .addHelpText("after", `
195
+ Examples:
196
+ $ kaven marketplace install payments
197
+ $ kaven marketplace install payments --version 1.2.0
198
+ $ kaven marketplace install auth --skip-env
199
+ $ kaven marketplace install my-module --skip-verify
200
+ `)
201
+ .action((moduleId, options) => (0, install_1.marketplaceInstall)(moduleId, {
202
+ version: options.version,
203
+ force: options.force ?? false,
204
+ skipEnv: options.skipEnv ?? false,
205
+ skipVerify: options.skipVerify ?? false,
206
+ envFile: options.envFile,
207
+ }));
208
+ marketplaceCommand
209
+ .command("browse")
210
+ .description("Interactive TUI module browser — explore modules by category")
211
+ .addHelpText("after", `
212
+ Navigate with arrow keys, press Enter to select.
213
+ Supports category filtering and pagination.
214
+ `)
215
+ .action(() => (0, browse_1.marketplaceBrowse)());
216
+ /**
217
+ * Upgrade Group — License tier upgrades and CLI updates
218
+ */
219
+ const upgradeCommandGroup = program
220
+ .command("upgrade")
221
+ .description("Upgrade your license tier or CLI version")
222
+ .addHelpText("after", `
223
+ Examples:
224
+ $ kaven upgrade Upgrade license tier
225
+ $ kaven upgrade check Check for CLI updates
226
+ $ kaven upgrade install Install latest CLI version
227
+ `);
228
+ upgradeCommandGroup
229
+ .command("tier")
230
+ .description("Upgrade your Kaven license to a higher tier (default)")
231
+ .option("--no-browser", "Print the checkout URL instead of opening the browser")
232
+ .action((opts) => (0, index_2.upgradeCommand)({
233
+ browser: opts.browser !== false,
234
+ }));
235
+ upgradeCommandGroup
236
+ .command("check")
237
+ .description("Check for Kaven CLI updates")
238
+ .action(() => (0, index_2.upgradeCheck)());
239
+ upgradeCommandGroup
240
+ .command("install")
241
+ .description("Install the latest Kaven CLI version")
242
+ .action(() => (0, index_2.upgradeInstall)());
75
243
  /**
76
244
  * Telemetry Group
77
245
  */
78
246
  const telemetryCommand = program
79
247
  .command("telemetry")
80
- .description("Observabilidade e auditoria de comandos");
248
+ .description("View observability and command audit logs");
81
249
  telemetryCommand
82
250
  .command("view")
83
- .description("Visualiza os últimos eventos de telemetria locais")
84
- .option("-l, --limit <number>", "Número de eventos a exibir", "10")
251
+ .description("Display the most recent local telemetry events")
252
+ .option("-l, --limit <number>", "Number of events to display", "10")
85
253
  .action((options) => (0, view_1.telemetryView)(parseInt(options.limit)));
254
+ /**
255
+ * License Group
256
+ */
257
+ program.addCommand((0, index_js_1.buildLicenseCommand)());
258
+ /**
259
+ * Cache Group
260
+ */
261
+ const cacheCommand = program
262
+ .command("cache")
263
+ .description("Manage the local API response cache")
264
+ .addHelpText("after", `
265
+ Cache directory: ~/.kaven/cache (max 50 MB)
266
+ Cached data: module listings (24h TTL), manifests (7d), license status (1h)
267
+
268
+ Examples:
269
+ $ kaven cache status
270
+ $ kaven cache clear
271
+ `);
272
+ cacheCommand
273
+ .command("status")
274
+ .description("Show cache statistics (size, entry count, age)")
275
+ .action(() => (0, index_3.cacheStatus)());
276
+ cacheCommand
277
+ .command("clear")
278
+ .description("Delete all locally cached API responses")
279
+ .action(() => (0, index_3.cacheClear)());
280
+ /**
281
+ * Config Group — Manage Kaven CLI configuration
282
+ */
283
+ const configCommand = program
284
+ .command("config")
285
+ .description("Manage Kaven CLI configuration")
286
+ .addHelpText("after", `
287
+ Config file: ~/.kaven/config.json
288
+
289
+ Examples:
290
+ $ kaven config set registry https://custom.registry.sh
291
+ $ kaven config get registry
292
+ $ kaven config view
293
+ $ kaven config reset
294
+ `);
295
+ configCommand
296
+ .command("set <key> <value>")
297
+ .description("Set a configuration value")
298
+ .action((key, value) => (0, index_4.configSet)(key, value));
299
+ configCommand
300
+ .command("get <key>")
301
+ .description("Get a configuration value")
302
+ .option("--json", "Output as JSON")
303
+ .action((key, opts) => (0, index_4.configGet)(key, { json: opts.json }));
304
+ configCommand
305
+ .command("view")
306
+ .description("Display all configuration")
307
+ .option("--json", "Output as JSON")
308
+ .action((opts) => (0, index_4.configView)({ json: opts.json }));
309
+ configCommand
310
+ .command("reset")
311
+ .description("Reset configuration to defaults")
312
+ .action(() => (0, index_4.configReset)());
313
+ /**
314
+ * Init CI — Initialize CI/CD workflows
315
+ */
316
+ program
317
+ .command("init-ci")
318
+ .description("Initialize GitHub Actions CI/CD workflows")
319
+ .option("--dry-run", "Show what would be created without writing files")
320
+ .addHelpText("after", `
321
+ Creates:
322
+ - .github/workflows/test.yml Run tests on push/PR
323
+ - .github/workflows/publish.yml Publish modules on git tags
324
+ - .husky/pre-commit Local pre-commit validation
325
+
326
+ Examples:
327
+ $ kaven init-ci Interactive setup
328
+ $ kaven init-ci --dry-run Show what would be created
329
+ `)
330
+ .action((opts) => (0, index_5.initCi)({ dryRun: opts.dryRun }));
86
331
  program.parse();
87
332
  };
88
333
  exports.main = main;