prpm 0.1.17 → 1.0.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 (46) hide show
  1. package/dist/index.js +14257 -107
  2. package/package.json +11 -9
  3. package/dist/__tests__/e2e/test-helpers.js +0 -151
  4. package/dist/commands/buy-credits.js +0 -224
  5. package/dist/commands/catalog.js +0 -365
  6. package/dist/commands/collections.js +0 -655
  7. package/dist/commands/config.js +0 -161
  8. package/dist/commands/credits.js +0 -186
  9. package/dist/commands/index.js +0 -184
  10. package/dist/commands/info.js +0 -78
  11. package/dist/commands/init.js +0 -684
  12. package/dist/commands/install.js +0 -789
  13. package/dist/commands/list.js +0 -189
  14. package/dist/commands/login.js +0 -316
  15. package/dist/commands/outdated.js +0 -130
  16. package/dist/commands/playground.js +0 -570
  17. package/dist/commands/popular.js +0 -33
  18. package/dist/commands/publish.js +0 -803
  19. package/dist/commands/schema.js +0 -41
  20. package/dist/commands/search.js +0 -446
  21. package/dist/commands/subscribe.js +0 -211
  22. package/dist/commands/telemetry.js +0 -104
  23. package/dist/commands/trending.js +0 -86
  24. package/dist/commands/uninstall.js +0 -120
  25. package/dist/commands/update.js +0 -121
  26. package/dist/commands/upgrade.js +0 -121
  27. package/dist/commands/whoami.js +0 -83
  28. package/dist/core/claude-config.js +0 -91
  29. package/dist/core/cursor-config.js +0 -130
  30. package/dist/core/downloader.js +0 -64
  31. package/dist/core/errors.js +0 -29
  32. package/dist/core/filesystem.js +0 -242
  33. package/dist/core/lockfile.js +0 -292
  34. package/dist/core/marketplace-converter.js +0 -224
  35. package/dist/core/registry-client.js +0 -305
  36. package/dist/core/schema-validator.js +0 -74
  37. package/dist/core/telemetry.js +0 -253
  38. package/dist/core/user-config.js +0 -147
  39. package/dist/types/registry.js +0 -12
  40. package/dist/types.js +0 -36
  41. package/dist/utils/license-extractor.js +0 -122
  42. package/dist/utils/multi-package.js +0 -117
  43. package/dist/utils/parallel-publisher.js +0 -144
  44. package/dist/utils/script-executor.js +0 -72
  45. package/dist/utils/snippet-extractor.js +0 -77
  46. package/dist/utils/webapp-url.js +0 -44
@@ -1,189 +0,0 @@
1
- "use strict";
2
- /**
3
- * List command implementation
4
- */
5
- var __importDefault = (this && this.__importDefault) || function (mod) {
6
- return (mod && mod.__esModule) ? mod : { "default": mod };
7
- };
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.handleList = handleList;
10
- exports.createListCommand = createListCommand;
11
- const commander_1 = require("commander");
12
- const lockfile_1 = require("../core/lockfile");
13
- const telemetry_1 = require("../core/telemetry");
14
- const fs_1 = require("fs");
15
- const path_1 = __importDefault(require("path"));
16
- const errors_1 = require("../core/errors");
17
- /**
18
- * Get destination directory based on package type
19
- */
20
- function getDestinationDir(type) {
21
- switch (type) {
22
- case 'cursor':
23
- return '.cursor/rules';
24
- case 'claude':
25
- return '.claude/agents';
26
- case 'claude-agent':
27
- return '.claude/agents';
28
- case 'claude-skill':
29
- return '.claude/skills';
30
- case 'claude-slash-command':
31
- return '.claude/commands';
32
- case 'continue':
33
- return '.continue/rules';
34
- case 'windsurf':
35
- return '.windsurf/rules';
36
- case 'agents.md':
37
- return '.agents';
38
- case 'generic':
39
- return '.prompts';
40
- case 'mcp':
41
- return '.mcp';
42
- default:
43
- return '.prompts';
44
- }
45
- }
46
- /**
47
- * Strip author namespace from package ID
48
- */
49
- function stripAuthorNamespace(packageId) {
50
- const parts = packageId.split('/');
51
- return parts[parts.length - 1];
52
- }
53
- /**
54
- * Find the actual file location for a package
55
- */
56
- async function findPackageLocation(id, format, subtype) {
57
- if (!format)
58
- return null;
59
- const baseDir = getDestinationDir(format);
60
- // Strip author namespace to get actual package name used in file system
61
- const packageName = stripAuthorNamespace(id);
62
- // Try different file extensions based on format
63
- const extensions = format === 'cursor' ? ['.mdc', '.md'] : ['.md'];
64
- // Try direct file: <dir>/<packageName>.ext
65
- for (const ext of extensions) {
66
- const directPath = path_1.default.join(baseDir, `${packageName}${ext}`);
67
- try {
68
- await fs_1.promises.access(directPath);
69
- return directPath;
70
- }
71
- catch {
72
- // File doesn't exist, continue
73
- }
74
- }
75
- // Try subdirectory: <dir>/<packageName>/SKILL.md or <dir>/<packageName>/AGENT.md
76
- if (subtype === 'skill') {
77
- const skillPath = path_1.default.join(baseDir, packageName, 'SKILL.md');
78
- try {
79
- await fs_1.promises.access(skillPath);
80
- return skillPath;
81
- }
82
- catch {
83
- // Not found
84
- }
85
- }
86
- if (subtype === 'agent' || format === 'claude') {
87
- const agentPath = path_1.default.join(baseDir, packageName, 'AGENT.md');
88
- try {
89
- await fs_1.promises.access(agentPath);
90
- return agentPath;
91
- }
92
- catch {
93
- // Not found
94
- }
95
- }
96
- return null;
97
- }
98
- /**
99
- * Display packages in a formatted table
100
- */
101
- async function displayPackages(packages) {
102
- if (packages.length === 0) {
103
- console.log('šŸ“¦ No packages installed');
104
- return;
105
- }
106
- console.log('šŸ“¦ Installed packages:');
107
- console.log('');
108
- // Find file locations
109
- const packagesWithLocations = await Promise.all(packages.map(async (pkg) => ({
110
- ...pkg,
111
- location: await findPackageLocation(pkg.id, pkg.format, pkg.subtype)
112
- })));
113
- // Helper to format type display
114
- const formatType = (format, subtype) => {
115
- if (!format)
116
- return '';
117
- return subtype ? `${format}/${subtype}` : format;
118
- };
119
- // Calculate column widths
120
- const idWidth = Math.max(8, ...packagesWithLocations.map(p => p.id.length));
121
- const versionWidth = Math.max(7, ...packagesWithLocations.map(p => p.version.length));
122
- const typeWidth = Math.max(6, ...packagesWithLocations.map(p => formatType(p.format, p.subtype).length));
123
- const locationWidth = Math.max(8, ...packagesWithLocations.map(p => (p.installedPath || 'N/A').length));
124
- // Header
125
- const header = [
126
- 'ID'.padEnd(idWidth),
127
- 'VERSION'.padEnd(versionWidth),
128
- 'TYPE'.padEnd(typeWidth),
129
- 'LOCATION'.padEnd(locationWidth)
130
- ].join(' | ');
131
- console.log(header);
132
- console.log('-'.repeat(header.length));
133
- // Rows
134
- packagesWithLocations.forEach(pkg => {
135
- const row = [
136
- pkg.id.padEnd(idWidth),
137
- pkg.version.padEnd(versionWidth),
138
- formatType(pkg.format, pkg.subtype).padEnd(typeWidth),
139
- (pkg.installedPath || 'N/A').padEnd(locationWidth)
140
- ].join(' | ');
141
- console.log(row);
142
- });
143
- console.log('');
144
- console.log(`Total: ${packages.length} package${packages.length === 1 ? '' : 's'}`);
145
- }
146
- /**
147
- * Handle the list command
148
- */
149
- async function handleList() {
150
- const startTime = Date.now();
151
- let success = false;
152
- let error;
153
- let packageCount = 0;
154
- try {
155
- const packages = await (0, lockfile_1.listPackages)();
156
- packageCount = packages.length;
157
- await displayPackages(packages);
158
- success = true;
159
- }
160
- catch (err) {
161
- error = err instanceof Error ? err.message : String(err);
162
- throw new errors_1.CLIError(`āŒ Failed to list packages: ${error}`, 1);
163
- }
164
- finally {
165
- // Track telemetry
166
- await telemetry_1.telemetry.track({
167
- command: 'list',
168
- success,
169
- error,
170
- duration: Date.now() - startTime,
171
- data: {
172
- packageCount,
173
- },
174
- });
175
- await telemetry_1.telemetry.shutdown();
176
- }
177
- }
178
- /**
179
- * Create the list command
180
- */
181
- function createListCommand() {
182
- const command = new commander_1.Command('list');
183
- command
184
- .description('List all installed prompt packages')
185
- .action(async () => {
186
- await handleList();
187
- });
188
- return command;
189
- }
@@ -1,316 +0,0 @@
1
- "use strict";
2
- /**
3
- * Login command implementation
4
- */
5
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
- if (k2 === undefined) k2 = k;
7
- var desc = Object.getOwnPropertyDescriptor(m, k);
8
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
- desc = { enumerable: true, get: function() { return m[k]; } };
10
- }
11
- Object.defineProperty(o, k2, desc);
12
- }) : (function(o, m, k, k2) {
13
- if (k2 === undefined) k2 = k;
14
- o[k2] = m[k];
15
- }));
16
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
- Object.defineProperty(o, "default", { enumerable: true, value: v });
18
- }) : function(o, v) {
19
- o["default"] = v;
20
- });
21
- var __importStar = (this && this.__importStar) || (function () {
22
- var ownKeys = function(o) {
23
- ownKeys = Object.getOwnPropertyNames || function (o) {
24
- var ar = [];
25
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
- return ar;
27
- };
28
- return ownKeys(o);
29
- };
30
- return function (mod) {
31
- if (mod && mod.__esModule) return mod;
32
- var result = {};
33
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
- __setModuleDefault(result, mod);
35
- return result;
36
- };
37
- })();
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.handleLogin = handleLogin;
40
- exports.createLoginCommand = createLoginCommand;
41
- const commander_1 = require("commander");
42
- const http_1 = require("http");
43
- const jwt = __importStar(require("jsonwebtoken"));
44
- const telemetry_1 = require("../core/telemetry");
45
- const user_config_1 = require("../core/user-config");
46
- const errors_1 = require("../core/errors");
47
- /**
48
- * Start OAuth callback server
49
- */
50
- function startCallbackServer() {
51
- return new Promise((resolve, reject) => {
52
- const server = (0, http_1.createServer)((req, res) => {
53
- const url = new URL(req.url || '', 'http://localhost:8765');
54
- if (url.pathname === '/callback') {
55
- const token = url.searchParams.get('token') || undefined;
56
- const username = url.searchParams.get('username') || undefined;
57
- const error = url.searchParams.get('error') || undefined;
58
- if (error) {
59
- res.writeHead(400, { 'Content-Type': 'text/html' });
60
- res.end(`
61
- <html>
62
- <body>
63
- <h1>āŒ Authentication Failed</h1>
64
- <p>Error: ${error}</p>
65
- <p>You can close this window.</p>
66
- </body>
67
- </html>
68
- `);
69
- server.close();
70
- reject(new Error(`OAuth error: ${error}`));
71
- return;
72
- }
73
- if (token) {
74
- res.writeHead(200, { 'Content-Type': 'text/html' });
75
- res.end(`
76
- <html>
77
- <body>
78
- <h1>āœ… Authentication Successful!</h1>
79
- <p>You can close this window and return to your terminal.</p>
80
- </body>
81
- </html>
82
- `);
83
- server.close();
84
- resolve({ token, username });
85
- }
86
- else {
87
- res.writeHead(400, { 'Content-Type': 'text/html' });
88
- res.end(`
89
- <html>
90
- <body>
91
- <h1>āŒ Invalid Request</h1>
92
- <p>No token received from authentication.</p>
93
- </body>
94
- </html>
95
- `);
96
- server.close();
97
- reject(new Error('No token received'));
98
- }
99
- }
100
- });
101
- server.listen(8765, () => {
102
- console.log(' Waiting for authentication...');
103
- });
104
- // Timeout after 5 minutes
105
- setTimeout(() => {
106
- server.close();
107
- reject(new Error('Authentication timeout'));
108
- }, 5 * 60 * 1000);
109
- });
110
- }
111
- /**
112
- * Login with GitHub OAuth via Nango connect link
113
- */
114
- async function loginWithOAuth(registryUrl) {
115
- console.log('\nšŸ” Opening browser for GitHub authentication...\n');
116
- // Generate a unique user ID for this CLI session
117
- const userId = `cli_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
118
- try {
119
- // Get the Nango connect session from the registry
120
- console.log(` Connecting to: ${registryUrl}`);
121
- const response = await fetch(`${registryUrl}/api/v1/auth/nango/cli/connect-session`, {
122
- method: 'POST',
123
- headers: {
124
- 'Content-Type': 'application/json',
125
- },
126
- body: JSON.stringify({
127
- userId,
128
- email: 'cli@example.com',
129
- displayName: 'CLI User',
130
- }),
131
- });
132
- if (!response.ok) {
133
- const errorText = await response.text().catch(() => 'Unable to read error response');
134
- throw new Error(`Failed to get authentication session (${response.status}): ${errorText}`);
135
- }
136
- const responseData = await response.json();
137
- const { connectSessionToken } = responseData;
138
- if (!connectSessionToken) {
139
- console.error('āŒ No session token received from server');
140
- console.error(' Response data:', JSON.stringify(responseData, null, 2));
141
- throw new Error('No session token received from server. Please check your Nango configuration.');
142
- }
143
- // Create the CLI auth URL with session token, callback, and userId
144
- const callbackUrl = 'http://localhost:8765/callback';
145
- // Determine webapp URL based on registry URL
146
- let webappUrl;
147
- if (registryUrl.includes('localhost') || registryUrl.includes('127.0.0.1')) {
148
- // Local development: registry on port 3111, webapp on port 5173
149
- webappUrl = registryUrl.replace(':3111', ':5173');
150
- }
151
- else if (registryUrl.includes('registry.prpm.dev')) {
152
- // Production: always use prpm.dev webapp
153
- webappUrl = 'https://prpm.dev';
154
- }
155
- else {
156
- // Custom registry: assume webapp is on same host without port
157
- const url = new URL(registryUrl);
158
- webappUrl = `${url.protocol}//${url.hostname}`;
159
- }
160
- const authUrl = `${webappUrl}/cli-auth?sessionToken=${encodeURIComponent(connectSessionToken)}&cliCallback=${encodeURIComponent(callbackUrl)}&userId=${encodeURIComponent(userId)}`;
161
- console.log(` Please open this link in your browser to authenticate:`);
162
- console.log(` ${authUrl}\n`);
163
- // Try to open browser
164
- const { exec } = await Promise.resolve().then(() => __importStar(require('child_process')));
165
- const platform = process.platform;
166
- const cmd = platform === 'darwin' ? 'open' : platform === 'win32' ? 'start' : 'xdg-open';
167
- exec(`${cmd} "${authUrl}"`);
168
- // Poll for authentication completion
169
- console.log(' Waiting for authentication...\n');
170
- const result = await pollForAuthentication(registryUrl, userId);
171
- if (!result.token) {
172
- throw new Error('No token received from authentication');
173
- }
174
- return { token: result.token, username: result.username || 'unknown' };
175
- }
176
- catch (error) {
177
- if (error instanceof Error) {
178
- // Check for common network errors
179
- if (error.message.includes('ECONNREFUSED')) {
180
- throw new Error(`Cannot connect to registry at ${registryUrl}. Is the registry running?`);
181
- }
182
- else if (error.message.includes('ENOTFOUND') || error.message.includes('getaddrinfo')) {
183
- throw new Error(`Cannot resolve registry hostname: ${registryUrl}. Check your internet connection.`);
184
- }
185
- }
186
- throw new Error(`Authentication failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
187
- }
188
- }
189
- /**
190
- * Poll for authentication completion
191
- */
192
- async function pollForAuthentication(registryUrl, userId) {
193
- const maxAttempts = 60; // 5 minutes with 5-second intervals
194
- let attempts = 0;
195
- while (attempts < maxAttempts) {
196
- try {
197
- const response = await fetch(`${registryUrl}/api/v1/auth/nango/cli/status/${userId}`);
198
- if (response.ok) {
199
- const { authenticated, connectionId } = await response.json();
200
- if (authenticated && connectionId) {
201
- // Authentication completed, get the JWT token
202
- const statusResponse = await fetch(`${registryUrl}/api/v1/auth/nango/status/${connectionId}`);
203
- if (statusResponse.ok) {
204
- const result = await statusResponse.json();
205
- if (result.ready && result.token) {
206
- return {
207
- token: result.token,
208
- username: result.username,
209
- };
210
- }
211
- }
212
- }
213
- }
214
- }
215
- catch (error) {
216
- // Ignore polling errors and continue
217
- }
218
- // Wait 5 seconds before next attempt
219
- await new Promise(resolve => setTimeout(resolve, 5000));
220
- attempts++;
221
- }
222
- throw new Error('Authentication timeout - please try again');
223
- }
224
- /**
225
- * Login with manual token
226
- */
227
- async function loginWithToken(token, registryUrl) {
228
- // Verify token by making a request to /api/v1/user
229
- const response = await fetch(`${registryUrl}/api/v1/user`, {
230
- headers: {
231
- 'Authorization': `Bearer ${token}`,
232
- },
233
- });
234
- if (!response.ok) {
235
- throw new Error('Invalid token');
236
- }
237
- const user = await response.json();
238
- return { token, username: user.username };
239
- }
240
- /**
241
- * Handle login command
242
- */
243
- async function handleLogin(options) {
244
- const startTime = Date.now();
245
- let success = false;
246
- let error;
247
- try {
248
- const config = await (0, user_config_1.getConfig)();
249
- const registryUrl = config.registryUrl || 'https://registry.prpm.dev';
250
- console.log('šŸ”‘ PRMP Login\n');
251
- let result;
252
- if (options.token) {
253
- // Manual token login
254
- console.log('šŸ” Logging in with provided token...\n');
255
- result = await loginWithToken(options.token, registryUrl);
256
- }
257
- else {
258
- // OAuth login
259
- result = await loginWithOAuth(registryUrl);
260
- }
261
- // Extract user_id and email from JWT token
262
- const decoded = jwt.decode(result.token);
263
- if (!decoded) {
264
- throw new Error('Failed to decode authentication token');
265
- }
266
- // Save token and user info to config
267
- await (0, user_config_1.saveConfig)({
268
- ...config,
269
- token: result.token,
270
- username: result.username,
271
- userId: decoded.user_id,
272
- email: decoded.email,
273
- });
274
- // Identify user in PostHog with user properties
275
- await telemetry_1.telemetry.identifyUser(decoded.user_id, {
276
- username: result.username,
277
- email: decoded.email,
278
- cli_version: process.env.npm_package_version,
279
- platform: process.platform,
280
- first_login: new Date().toISOString(),
281
- });
282
- console.log('āœ… Successfully logged in!\n');
283
- console.log(` Username: ${result.username}`);
284
- console.log(` Registry: ${registryUrl}\n`);
285
- console.log('šŸ’” You can now publish packages with "prpm publish"\n');
286
- success = true;
287
- }
288
- catch (err) {
289
- error = err instanceof Error ? err.message : String(err);
290
- throw new errors_1.CLIError(`\nāŒ Login failed: ${error}\n\nšŸ’” Try again or use "prpm login --token YOUR_TOKEN"\n`, 1);
291
- }
292
- finally {
293
- // Track telemetry
294
- await telemetry_1.telemetry.track({
295
- command: 'login',
296
- success,
297
- error,
298
- duration: Date.now() - startTime,
299
- data: {
300
- method: options.token ? 'token' : 'oauth',
301
- },
302
- });
303
- await telemetry_1.telemetry.shutdown();
304
- }
305
- }
306
- /**
307
- * Create the login command
308
- */
309
- function createLoginCommand() {
310
- return new commander_1.Command('login')
311
- .description('Login to the PRMP registry')
312
- .option('--token <token>', 'Login with a personal access token')
313
- .action(async (options) => {
314
- await handleLogin(options);
315
- });
316
- }
@@ -1,130 +0,0 @@
1
- "use strict";
2
- /**
3
- * Outdated command - Check for package updates
4
- */
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.handleOutdated = handleOutdated;
7
- exports.createOutdatedCommand = createOutdatedCommand;
8
- const commander_1 = require("commander");
9
- const registry_client_1 = require("@pr-pm/registry-client");
10
- const user_config_1 = require("../core/user-config");
11
- const lockfile_1 = require("../core/lockfile");
12
- const telemetry_1 = require("../core/telemetry");
13
- const errors_1 = require("../core/errors");
14
- /**
15
- * Check for outdated packages
16
- */
17
- async function handleOutdated() {
18
- const startTime = Date.now();
19
- let success = false;
20
- let error;
21
- try {
22
- console.log('šŸ” Checking for package updates...\n');
23
- const config = await (0, user_config_1.getConfig)();
24
- const client = (0, registry_client_1.getRegistryClient)(config);
25
- const installedPackages = await (0, lockfile_1.listPackages)();
26
- if (installedPackages.length === 0) {
27
- console.log('No packages installed.');
28
- success = true;
29
- return;
30
- }
31
- const outdated = [];
32
- for (const pkg of installedPackages) {
33
- try {
34
- // Get package info from registry
35
- const registryPkg = await client.getPackage(pkg.id);
36
- if (!registryPkg.latest_version || !pkg.version) {
37
- continue;
38
- }
39
- const currentVersion = pkg.version;
40
- const latestVersion = registryPkg.latest_version.version;
41
- // Check if update available
42
- if (currentVersion !== latestVersion) {
43
- const updateType = getUpdateType(currentVersion, latestVersion);
44
- outdated.push({
45
- id: pkg.id,
46
- current: currentVersion,
47
- latest: latestVersion,
48
- type: updateType,
49
- });
50
- }
51
- }
52
- catch (err) {
53
- // Skip packages that can't be found in registry
54
- continue;
55
- }
56
- }
57
- if (outdated.length === 0) {
58
- console.log('āœ… All packages are up to date!\n');
59
- success = true;
60
- return;
61
- }
62
- // Display outdated packages
63
- console.log(`šŸ“¦ ${outdated.length} package(s) have updates available:\n`);
64
- // Group by update type
65
- const major = outdated.filter(p => p.type === 'major');
66
- const minor = outdated.filter(p => p.type === 'minor');
67
- const patch = outdated.filter(p => p.type === 'patch');
68
- if (major.length > 0) {
69
- console.log('šŸ”“ Major Updates (breaking changes possible):');
70
- major.forEach(pkg => {
71
- console.log(` ${pkg.id.padEnd(30)} ${pkg.current} → ${pkg.latest}`);
72
- });
73
- console.log('');
74
- }
75
- if (minor.length > 0) {
76
- console.log('🟔 Minor Updates (new features):');
77
- minor.forEach(pkg => {
78
- console.log(` ${pkg.id.padEnd(30)} ${pkg.current} → ${pkg.latest}`);
79
- });
80
- console.log('');
81
- }
82
- if (patch.length > 0) {
83
- console.log('🟢 Patch Updates (bug fixes):');
84
- patch.forEach(pkg => {
85
- console.log(` ${pkg.id.padEnd(30)} ${pkg.current} → ${pkg.latest}`);
86
- });
87
- console.log('');
88
- }
89
- console.log('šŸ’” Run "prpm update" to update to latest minor/patch versions');
90
- console.log('šŸ’” Run "prpm upgrade" to upgrade to latest major versions\n');
91
- success = true;
92
- }
93
- catch (err) {
94
- error = err instanceof Error ? err.message : String(err);
95
- throw new errors_1.CLIError(`\nāŒ Failed to check for updates: ${error}`, 1);
96
- }
97
- finally {
98
- await telemetry_1.telemetry.track({
99
- command: 'outdated',
100
- success,
101
- error,
102
- duration: Date.now() - startTime,
103
- });
104
- await telemetry_1.telemetry.shutdown();
105
- }
106
- }
107
- /**
108
- * Determine update type based on semver
109
- */
110
- function getUpdateType(current, latest) {
111
- const currentParts = current.split('.').map(Number);
112
- const latestParts = latest.split('.').map(Number);
113
- const [currMajor = 0, currMinor = 0, currPatch = 0] = currentParts;
114
- const [latestMajor = 0, latestMinor = 0, latestPatch = 0] = latestParts;
115
- if (latestMajor > currMajor)
116
- return 'major';
117
- if (latestMinor > currMinor)
118
- return 'minor';
119
- return 'patch';
120
- }
121
- /**
122
- * Create the outdated command
123
- */
124
- function createOutdatedCommand() {
125
- return new commander_1.Command('outdated')
126
- .description('Check for package updates')
127
- .action(async () => {
128
- await handleOutdated();
129
- });
130
- }