kaven-cli 0.4.0 → 0.4.2-alpha.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 (57) hide show
  1. package/README.md +181 -207
  2. package/dist/EnvManager-NMS3NMIE.js +15 -0
  3. package/dist/MarketplaceClient-YCFH2VU4.js +1 -0
  4. package/dist/chunk-JHLQ46NG.js +1 -0
  5. package/dist/index.d.ts +4 -0
  6. package/dist/index.js +243 -289
  7. package/dist/tier-table-DQMPQSI2.js +6 -0
  8. package/package.json +26 -10
  9. package/dist/commands/auth/login.js +0 -122
  10. package/dist/commands/auth/logout.js +0 -23
  11. package/dist/commands/auth/whoami.js +0 -36
  12. package/dist/commands/cache/index.js +0 -43
  13. package/dist/commands/config/features.js +0 -1026
  14. package/dist/commands/config/index.js +0 -95
  15. package/dist/commands/index.js +0 -2
  16. package/dist/commands/init/index.js +0 -197
  17. package/dist/commands/init-ci/index.js +0 -153
  18. package/dist/commands/license/index.js +0 -10
  19. package/dist/commands/license/status.js +0 -44
  20. package/dist/commands/license/tier-table.js +0 -46
  21. package/dist/commands/marketplace/browse.js +0 -186
  22. package/dist/commands/marketplace/install.js +0 -263
  23. package/dist/commands/marketplace/list.js +0 -122
  24. package/dist/commands/module/activate.js +0 -206
  25. package/dist/commands/module/add.js +0 -69
  26. package/dist/commands/module/doctor.js +0 -175
  27. package/dist/commands/module/publish.js +0 -258
  28. package/dist/commands/module/remove.js +0 -58
  29. package/dist/commands/telemetry/view.js +0 -27
  30. package/dist/commands/upgrade/check.js +0 -162
  31. package/dist/commands/upgrade/index.js +0 -185
  32. package/dist/core/AuthService.js +0 -222
  33. package/dist/core/CacheManager.js +0 -154
  34. package/dist/core/ConfigManager.js +0 -166
  35. package/dist/core/EnvManager.js +0 -196
  36. package/dist/core/ErrorRecovery.js +0 -192
  37. package/dist/core/LicenseService.js +0 -83
  38. package/dist/core/ManifestParser.js +0 -52
  39. package/dist/core/MarkerService.js +0 -62
  40. package/dist/core/ModuleDoctor.js +0 -451
  41. package/dist/core/ModuleInstaller.js +0 -169
  42. package/dist/core/ProjectInitializer.js +0 -166
  43. package/dist/core/RegistryResolver.js +0 -95
  44. package/dist/core/SchemaActivator.js +0 -270
  45. package/dist/core/ScriptRunner.js +0 -73
  46. package/dist/core/SignatureVerifier.js +0 -75
  47. package/dist/core/index.js +0 -2
  48. package/dist/infrastructure/Container.js +0 -37
  49. package/dist/infrastructure/MarketplaceClient.js +0 -399
  50. package/dist/infrastructure/TelemetryBuffer.js +0 -73
  51. package/dist/infrastructure/TransactionalFileSystem.js +0 -77
  52. package/dist/infrastructure/errors.js +0 -63
  53. package/dist/infrastructure/index.js +0 -2
  54. package/dist/types/auth.js +0 -2
  55. package/dist/types/manifest.js +0 -45
  56. package/dist/types/markers.js +0 -10
  57. package/dist/types/marketplace.js +0 -2
@@ -1,186 +0,0 @@
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.marketplaceBrowse = marketplaceBrowse;
7
- const chalk_1 = __importDefault(require("chalk"));
8
- const ora_1 = __importDefault(require("ora"));
9
- const AuthService_1 = require("../../core/AuthService");
10
- const MarketplaceClient_1 = require("../../infrastructure/MarketplaceClient");
11
- const install_1 = require("./install");
12
- const PAGE_SIZE = 10;
13
- function tierBadge(tier) {
14
- switch (tier.toUpperCase()) {
15
- case "FREE":
16
- return chalk_1.default.gray("[FREE]");
17
- case "STARTER":
18
- return chalk_1.default.green("[STARTER]");
19
- case "COMPLETE":
20
- return chalk_1.default.yellow("[COMPLETE]");
21
- case "PRO":
22
- return chalk_1.default.magenta("[PRO]");
23
- case "ENTERPRISE":
24
- return chalk_1.default.cyan("[ENTERPRISE]");
25
- default:
26
- return chalk_1.default.gray(`[${tier}]`);
27
- }
28
- }
29
- async function marketplaceBrowse() {
30
- const authService = new AuthService_1.AuthService();
31
- const client = new MarketplaceClient_1.MarketplaceClient(authService);
32
- const state = {
33
- category: null,
34
- page: 1,
35
- selectedModule: null,
36
- screen: "categories",
37
- };
38
- const { select } = await import("@inquirer/prompts");
39
- while (state.screen !== "exit") {
40
- if (state.screen === "categories") {
41
- // Step 1: Category selection
42
- const spinner = (0, ora_1.default)("Loading categories...").start();
43
- let categories = [];
44
- try {
45
- categories = await client.getCategories();
46
- spinner.stop();
47
- }
48
- catch {
49
- spinner.stop();
50
- console.log(chalk_1.default.yellow("Could not load categories — showing all modules."));
51
- }
52
- const categoryChoices = [
53
- { name: "All modules", value: "__all__" },
54
- ...categories.map((c) => ({ name: c, value: c })),
55
- { name: chalk_1.default.red("Exit"), value: "__exit__" },
56
- ];
57
- const selected = await select({
58
- message: "Browse by category:",
59
- choices: categoryChoices,
60
- });
61
- if (selected === "__exit__") {
62
- state.screen = "exit";
63
- break;
64
- }
65
- state.category = selected === "__all__" ? null : selected;
66
- state.page = 1;
67
- state.screen = "list";
68
- continue;
69
- }
70
- if (state.screen === "list") {
71
- // Step 2: Module listing with pagination
72
- const spinner = (0, ora_1.default)("Loading modules...").start();
73
- let modules = [];
74
- let totalPages = 1;
75
- try {
76
- const result = await client.listModules({
77
- category: state.category || undefined,
78
- page: state.page,
79
- pageSize: PAGE_SIZE,
80
- });
81
- modules = result.data;
82
- totalPages = Math.ceil(result.total / PAGE_SIZE) || 1;
83
- spinner.stop();
84
- }
85
- catch (error) {
86
- spinner.stop();
87
- console.error(chalk_1.default.red(`Error loading modules: ${error instanceof Error ? error.message : String(error)}`));
88
- state.screen = "categories";
89
- continue;
90
- }
91
- if (modules.length === 0) {
92
- console.log(chalk_1.default.yellow(`No modules found${state.category ? ` in category: ${state.category}` : ""}.`));
93
- state.screen = "categories";
94
- continue;
95
- }
96
- const categoryLabel = state.category ? ` [${state.category}]` : "";
97
- const pageLabel = totalPages > 1 ? ` (page ${state.page}/${totalPages})` : "";
98
- const moduleChoices = [
99
- ...modules.map((m) => ({
100
- name: `${m.name} ${tierBadge(m.requiredTier ?? m.tier ?? "")} — ${m.description}`,
101
- value: m.slug,
102
- })),
103
- ];
104
- // Navigation options at bottom
105
- if (state.page < totalPages) {
106
- moduleChoices.push({ name: chalk_1.default.cyan("→ Next page"), value: "__next__" });
107
- }
108
- if (state.page > 1) {
109
- moduleChoices.push({ name: chalk_1.default.cyan("← Previous page"), value: "__prev__" });
110
- }
111
- moduleChoices.push({ name: chalk_1.default.dim("↑ Back to categories"), value: "__back__" });
112
- moduleChoices.push({ name: chalk_1.default.red("Exit"), value: "__exit__" });
113
- const selected = await select({
114
- message: `Modules${categoryLabel}${pageLabel}:`,
115
- choices: moduleChoices,
116
- });
117
- if (selected === "__exit__") {
118
- state.screen = "exit";
119
- break;
120
- }
121
- if (selected === "__back__") {
122
- state.screen = "categories";
123
- continue;
124
- }
125
- if (selected === "__next__") {
126
- state.page++;
127
- continue;
128
- }
129
- if (selected === "__prev__") {
130
- state.page = Math.max(1, state.page - 1);
131
- continue;
132
- }
133
- // Find selected module
134
- const module = modules.find((m) => m.slug === selected);
135
- if (module) {
136
- state.selectedModule = module;
137
- state.screen = "detail";
138
- }
139
- continue;
140
- }
141
- if (state.screen === "detail" && state.selectedModule) {
142
- const m = state.selectedModule;
143
- // Step 3: Module detail view
144
- console.log();
145
- console.log(chalk_1.default.bold(`${m.name}`), tierBadge(m.requiredTier ?? m.tier ?? ""));
146
- console.log(chalk_1.default.gray(`Version: ${m.latestVersion || "latest"}`));
147
- if (m.installCount !== undefined) {
148
- console.log(chalk_1.default.gray(`Installs: ${m.installCount.toLocaleString()}`));
149
- }
150
- if (m.description) {
151
- console.log();
152
- console.log(m.description);
153
- }
154
- console.log();
155
- const action = await select({
156
- message: "What would you like to do?",
157
- choices: [
158
- { name: `Install ${m.name}`, value: "install" },
159
- { name: "Back to module list", value: "back" },
160
- { name: chalk_1.default.red("Exit"), value: "exit" },
161
- ],
162
- });
163
- if (action === "exit") {
164
- state.screen = "exit";
165
- break;
166
- }
167
- if (action === "back") {
168
- state.selectedModule = null;
169
- state.screen = "list";
170
- continue;
171
- }
172
- if (action === "install") {
173
- console.log();
174
- await (0, install_1.marketplaceInstall)(m.slug, {
175
- force: false,
176
- skipEnv: false,
177
- });
178
- state.screen = "exit";
179
- break;
180
- }
181
- }
182
- }
183
- if (state.screen === "exit") {
184
- console.log(chalk_1.default.gray("Browse session ended."));
185
- }
186
- }
@@ -1,263 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.marketplaceInstall = marketplaceInstall;
40
- const chalk_1 = __importDefault(require("chalk"));
41
- const ora_1 = __importDefault(require("ora"));
42
- const fs_extra_1 = __importDefault(require("fs-extra"));
43
- const path_1 = __importDefault(require("path"));
44
- const os_1 = __importDefault(require("os"));
45
- const tar = __importStar(require("tar"));
46
- const MarketplaceClient_1 = require("../../infrastructure/MarketplaceClient");
47
- const AuthService_1 = require("../../core/AuthService");
48
- const ModuleInstaller_1 = require("../../core/ModuleInstaller");
49
- const MarkerService_1 = require("../../core/MarkerService");
50
- const TelemetryBuffer_1 = require("../../infrastructure/TelemetryBuffer");
51
- const errors_1 = require("../../infrastructure/errors");
52
- const SignatureVerifier_1 = require("../../core/SignatureVerifier");
53
- /** Create a unique temp directory for this install session. */
54
- async function makeTempDir() {
55
- const base = path_1.default.join(os_1.default.tmpdir(), "kaven-install-");
56
- return fs_extra_1.default.mkdtemp(base);
57
- }
58
- /** Format bytes into a human-readable string like "245 KB". */
59
- function formatBytes(bytes) {
60
- if (bytes < 1024)
61
- return `${bytes} B`;
62
- if (bytes < 1024 * 1024)
63
- return `${Math.round(bytes / 1024)} KB`;
64
- return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
65
- }
66
- async function marketplaceInstall(slug, options = {}) {
67
- const telemetry = TelemetryBuffer_1.TelemetryBuffer.getInstance();
68
- const startTime = Date.now();
69
- telemetry.capture("cli.marketplace.install.start", { slug });
70
- const authService = new AuthService_1.AuthService();
71
- const client = new MarketplaceClient_1.MarketplaceClient(authService);
72
- const projectRoot = process.cwd();
73
- // 1. Verify authentication — required for downloads
74
- let accessToken;
75
- try {
76
- accessToken = await authService.getValidToken();
77
- }
78
- catch {
79
- console.error(chalk_1.default.red("Authentication required. Run: kaven auth login"));
80
- telemetry.capture("cli.marketplace.install.error", { slug, error: "not_authenticated" }, Date.now() - startTime);
81
- await telemetry.flush();
82
- process.exit(1);
83
- return; // Unreachable but satisfies TS control flow
84
- }
85
- void accessToken; // used implicitly via authService in client
86
- const spinner = (0, ora_1.default)(`Preparing installation of '${slug}'...`).start();
87
- let tempDir = null;
88
- try {
89
- // 2. Get module metadata
90
- spinner.text = `Fetching module '${slug}' from Marketplace...`;
91
- let moduleData;
92
- try {
93
- moduleData = await client.getModule(slug);
94
- }
95
- catch (error) {
96
- if (error instanceof errors_1.NotFoundError) {
97
- spinner.fail(chalk_1.default.red(`Module '${slug}' not found in Marketplace.`));
98
- process.exit(1);
99
- return;
100
- }
101
- throw error;
102
- }
103
- const latestVersion = moduleData.latestVersion
104
- ?? moduleData.releases?.[0]?.version;
105
- const installVersion = options.version ?? latestVersion;
106
- if (!installVersion) {
107
- spinner.fail(chalk_1.default.red(`No published version found for '${slug}'.`));
108
- process.exit(1);
109
- return;
110
- }
111
- // 3. Check for conflict before downloading
112
- const markerService = new MarkerService_1.MarkerService();
113
- const installer = new ModuleInstaller_1.ModuleInstaller(projectRoot, markerService);
114
- // Check if already installed by looking at marker files
115
- const isInstalled = await installer.isModuleInstalled(slug);
116
- if (isInstalled && !options.force) {
117
- spinner.stop();
118
- console.log(chalk_1.default.yellow(`Module '${slug}' is already installed. Use --force to overwrite.`));
119
- telemetry.capture("cli.marketplace.install.skipped", { slug, reason: "already_installed" }, Date.now() - startTime);
120
- await telemetry.flush();
121
- return;
122
- }
123
- // 4. Create download token
124
- spinner.text = `Creating download token for '${slug}@${installVersion}'...`;
125
- const downloadToken = await client.createDownloadToken(slug, installVersion);
126
- // 5. Download the tarball to a temp directory
127
- tempDir = await makeTempDir();
128
- const tarPath = path_1.default.join(tempDir, "module.tar.gz");
129
- const extractDir = path_1.default.join(tempDir, "extracted");
130
- await fs_extra_1.default.ensureDir(extractDir);
131
- // Fetch with size reporting
132
- spinner.text = `Downloading ${slug} v${installVersion}...`;
133
- const absoluteUrl = await client.resolveUrl(downloadToken.downloadUrl);
134
- const response = await fetch(absoluteUrl);
135
- if (!response.ok) {
136
- throw new Error(`Download failed: ${response.status} ${response.statusText}`);
137
- }
138
- const contentLength = response.headers.get("content-length");
139
- const sizeStr = contentLength
140
- ? ` (${formatBytes(parseInt(contentLength, 10))})`
141
- : "";
142
- spinner.text = `Downloading ${slug} v${installVersion}${sizeStr}...`;
143
- if (!response.body) {
144
- throw new Error("No response body received for download");
145
- }
146
- // Stream download to file
147
- const fileStream = fs_extra_1.default.createWriteStream(tarPath);
148
- const reader = response.body.getReader();
149
- await new Promise((resolve, reject) => {
150
- const pump = async () => {
151
- try {
152
- let reading = true;
153
- while (reading) {
154
- const { done, value } = await reader.read();
155
- if (done) {
156
- fileStream.end();
157
- reading = false;
158
- }
159
- else {
160
- if (!fileStream.write(value)) {
161
- await new Promise((r) => fileStream.once("drain", r));
162
- }
163
- }
164
- }
165
- fileStream.once("finish", resolve);
166
- fileStream.once("error", reject);
167
- }
168
- catch (err) {
169
- reject(err);
170
- }
171
- };
172
- pump();
173
- });
174
- // 6. Verify Ed25519 signature and SHA-256 checksum
175
- const stat = await fs_extra_1.default.stat(tarPath);
176
- if (stat.size === 0) {
177
- throw new Error("Downloaded file is empty");
178
- }
179
- if (!options.skipVerify) {
180
- spinner.text = `Verifying signature for ${slug} v${installVersion}...`;
181
- const releaseInfo = await client.getReleaseInfo(slug, installVersion);
182
- if (releaseInfo.checksum &&
183
- releaseInfo.signature &&
184
- releaseInfo.publicKey) {
185
- await (0, SignatureVerifier_1.verifyDownload)({
186
- filePath: tarPath,
187
- expectedChecksum: releaseInfo.checksum,
188
- signature: releaseInfo.signature,
189
- publicKeyBase64: releaseInfo.publicKey,
190
- });
191
- spinner.text = `Signature verified for ${slug} v${installVersion}`;
192
- }
193
- else {
194
- spinner.text = `No signature data for ${slug} v${installVersion} — skipping verification`;
195
- }
196
- }
197
- // 7. Extract tarball
198
- spinner.text = `Extracting ${slug} v${installVersion}...`;
199
- await tar.x({ file: tarPath, cwd: extractDir });
200
- // 8. Read module.json manifest from extracted dir
201
- const manifestPath = path_1.default.join(extractDir, "module.json");
202
- const manifestExists = await fs_extra_1.default.pathExists(manifestPath);
203
- if (!manifestExists) {
204
- throw new Error(`module.json not found in extracted archive for '${slug}'`);
205
- }
206
- const manifest = await fs_extra_1.default.readJson(manifestPath);
207
- // 9. Delegate to ModuleInstaller
208
- spinner.text = `Installing ${slug} v${installVersion}...`;
209
- await installer.install(manifest);
210
- spinner.succeed(chalk_1.default.green(`Module '${slug}@${installVersion}' installed successfully.`));
211
- console.log(chalk_1.default.gray(`Use 'kaven module doctor' to verify the installation.`));
212
- telemetry.capture("cli.marketplace.install.success", { slug, version: installVersion }, Date.now() - startTime);
213
- await telemetry.flush();
214
- }
215
- catch (error) {
216
- spinner.stop();
217
- if (error instanceof errors_1.SignatureVerificationError) {
218
- console.error(chalk_1.default.red(`Signature verification failed for '${slug}': ${error.message}`));
219
- console.error(chalk_1.default.yellow("Use --skip-verify to bypass (not recommended)."));
220
- telemetry.capture("cli.marketplace.install.error", { slug, error: "signature_verification_failed" }, Date.now() - startTime);
221
- await telemetry.flush();
222
- process.exit(1);
223
- return;
224
- }
225
- if (error instanceof errors_1.LicenseRequiredError) {
226
- console.error(chalk_1.default.red(`License required: '${slug}' requires a '${error.requiredTier}' license.`));
227
- console.error(chalk_1.default.yellow(`Run: kaven upgrade ${error.requiredTier}`));
228
- telemetry.capture("cli.marketplace.install.error", { slug, error: "license_required", tier: error.requiredTier }, Date.now() - startTime);
229
- await telemetry.flush();
230
- process.exit(1);
231
- return;
232
- }
233
- if (error instanceof errors_1.AuthenticationError ||
234
- (error instanceof Error &&
235
- error.message.includes("Not authenticated"))) {
236
- console.error(chalk_1.default.red("Authentication required. Run: kaven auth login"));
237
- telemetry.capture("cli.marketplace.install.error", { slug, error: "auth_error" }, Date.now() - startTime);
238
- await telemetry.flush();
239
- process.exit(1);
240
- return;
241
- }
242
- if (error instanceof errors_1.NetworkError) {
243
- console.error(chalk_1.default.red("Could not reach marketplace. Check your connection."));
244
- telemetry.capture("cli.marketplace.install.error", { slug, error: "network_error" }, Date.now() - startTime);
245
- await telemetry.flush();
246
- process.exit(1);
247
- return;
248
- }
249
- telemetry.capture("cli.marketplace.install.error", { slug, error: error.message }, Date.now() - startTime);
250
- await telemetry.flush();
251
- spinner.fail(chalk_1.default.red(`Failed to install module '${slug}'.`));
252
- console.error(error);
253
- process.exit(1);
254
- }
255
- finally {
256
- // 10. Always cleanup temp dir
257
- if (tempDir) {
258
- await fs_extra_1.default.remove(tempDir).catch(() => {
259
- // Ignore cleanup errors
260
- });
261
- }
262
- }
263
- }
@@ -1,122 +0,0 @@
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.marketplaceList = marketplaceList;
7
- const chalk_1 = __importDefault(require("chalk"));
8
- const ora_1 = __importDefault(require("ora"));
9
- const cli_table3_1 = __importDefault(require("cli-table3"));
10
- const MarketplaceClient_1 = require("../../infrastructure/MarketplaceClient");
11
- const AuthService_1 = require("../../core/AuthService");
12
- const errors_1 = require("../../infrastructure/errors");
13
- const TelemetryBuffer_1 = require("../../infrastructure/TelemetryBuffer");
14
- function colorTier(tier) {
15
- switch (tier.toLowerCase()) {
16
- case "starter":
17
- return chalk_1.default.green(tier.toLowerCase());
18
- case "complete":
19
- return chalk_1.default.yellow(tier.toLowerCase());
20
- case "pro":
21
- return chalk_1.default.magenta(tier.toLowerCase());
22
- case "enterprise":
23
- return chalk_1.default.blue(tier.toLowerCase());
24
- default:
25
- return tier;
26
- }
27
- }
28
- async function marketplaceList(options = {}) {
29
- const telemetry = TelemetryBuffer_1.TelemetryBuffer.getInstance();
30
- const startTime = Date.now();
31
- telemetry.capture("cli.marketplace.list.start");
32
- const authService = new AuthService_1.AuthService();
33
- const client = new MarketplaceClient_1.MarketplaceClient(authService);
34
- const page = options.page ?? 1;
35
- const pageSize = Math.min(options.limit ?? 20, 100);
36
- const sort = options.sort ?? "newest";
37
- // Check auth — warn but don't block
38
- const isAuth = await authService.isAuthenticated();
39
- if (!isAuth) {
40
- console.log(chalk_1.default.yellow("Warning: Not authenticated. Only public modules will be shown. Run: kaven auth login"));
41
- }
42
- const spinner = (0, ora_1.default)("Fetching modules from Marketplace...").start();
43
- try {
44
- const result = await client.listModules({
45
- category: options.category,
46
- page,
47
- pageSize,
48
- q: sort === "newest" ? undefined : undefined,
49
- });
50
- spinner.stop();
51
- const modules = result.data;
52
- const meta = result.meta;
53
- const total = result.total ?? meta?.total ?? modules.length;
54
- if (options.json) {
55
- console.log(JSON.stringify(result, null, 2));
56
- telemetry.capture("cli.marketplace.list.success", { count: modules.length, json: true }, Date.now() - startTime);
57
- await telemetry.flush();
58
- return;
59
- }
60
- if (modules.length === 0) {
61
- console.log(chalk_1.default.yellow("No modules found matching your criteria."));
62
- telemetry.capture("cli.marketplace.list.success", { count: 0 }, Date.now() - startTime);
63
- await telemetry.flush();
64
- return;
65
- }
66
- const table = new cli_table3_1.default({
67
- head: [
68
- chalk_1.default.white.bold("Slug"),
69
- chalk_1.default.white.bold("Name"),
70
- chalk_1.default.white.bold("Version"),
71
- chalk_1.default.white.bold("Tier"),
72
- chalk_1.default.white.bold("Installs"),
73
- ],
74
- style: {
75
- head: [],
76
- border: ["gray"],
77
- },
78
- });
79
- // Sort modules client-side based on sort option
80
- const sorted = [...modules];
81
- if (sort === "popular") {
82
- sorted.sort((a, b) => b.installCount - a.installCount);
83
- }
84
- else if (sort === "name") {
85
- sorted.sort((a, b) => a.name.localeCompare(b.name));
86
- }
87
- // newest = default server-side order
88
- for (const mod of sorted) {
89
- table.push([
90
- chalk_1.default.cyan(mod.slug),
91
- chalk_1.default.white(mod.name),
92
- chalk_1.default.green(mod.latestVersion ?? "—"),
93
- colorTier(mod.requiredTier ?? mod.tier ?? ""),
94
- chalk_1.default.gray(String(mod.installCount)),
95
- ]);
96
- }
97
- console.log(chalk_1.default.blue.bold("\nAvailable Marketplace Modules:\n"));
98
- console.log(table.toString());
99
- // Pagination footer
100
- const totalPages = Math.ceil(total / pageSize);
101
- const startItem = (page - 1) * pageSize + 1;
102
- const endItem = Math.min(page * pageSize, total);
103
- console.log(chalk_1.default.gray(`\nShowing ${startItem}-${endItem} of ${total} modules (page ${page}/${totalPages})`));
104
- console.log(chalk_1.default.gray("Use 'kaven marketplace install <slug>' to install a module."));
105
- telemetry.capture("cli.marketplace.list.success", { count: modules.length, total }, Date.now() - startTime);
106
- await telemetry.flush();
107
- }
108
- catch (error) {
109
- spinner.stop();
110
- if (error instanceof errors_1.NetworkError) {
111
- console.error(chalk_1.default.red("Could not reach marketplace. Check your connection."));
112
- telemetry.capture("cli.marketplace.list.error", { error: "network_error" }, Date.now() - startTime);
113
- await telemetry.flush();
114
- process.exit(1);
115
- }
116
- telemetry.capture("cli.marketplace.list.error", { error: error.message }, Date.now() - startTime);
117
- await telemetry.flush();
118
- console.error(chalk_1.default.red("Error fetching modules from Marketplace."));
119
- console.error(error);
120
- process.exit(1);
121
- }
122
- }