prpm 0.1.10 ā 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/e2e/test-helpers.js +1 -0
- package/dist/commands/buy-credits.js +4 -4
- package/dist/commands/catalog.js +2 -2
- package/dist/commands/collections.js +17 -9
- package/dist/commands/config.js +18 -24
- package/dist/commands/credits.js +3 -3
- package/dist/commands/index.js +2 -4
- package/dist/commands/info.js +2 -7
- package/dist/commands/init.js +5 -3
- package/dist/commands/install.js +22 -24
- package/dist/commands/list.js +2 -3
- package/dist/commands/login.js +2 -4
- package/dist/commands/outdated.js +2 -3
- package/dist/commands/playground.js +4 -4
- package/dist/commands/popular.js +0 -1
- package/dist/commands/publish.js +27 -27
- package/dist/commands/schema.js +6 -5
- package/dist/commands/search.js +4 -4
- package/dist/commands/subscribe.js +4 -4
- package/dist/commands/telemetry.js +3 -8
- package/dist/commands/trending.js +4 -4
- package/dist/commands/uninstall.js +6 -5
- package/dist/commands/update.js +2 -3
- package/dist/commands/upgrade.js +2 -3
- package/dist/commands/whoami.js +2 -3
- package/dist/core/errors.js +29 -0
- package/dist/core/telemetry.js +36 -4
- package/dist/index.js +23 -2
- package/package.json +3 -3
|
@@ -141,6 +141,7 @@ function setupGlobalMocks() {
|
|
|
141
141
|
}
|
|
142
142
|
/**
|
|
143
143
|
* Mock process.exit to throw instead of exiting
|
|
144
|
+
* @deprecated No longer needed - commands now throw CLIError instead of calling process.exit
|
|
144
145
|
*/
|
|
145
146
|
function mockProcessExit() {
|
|
146
147
|
const mockExit = jest.spyOn(process, 'exit').mockImplementation((code) => {
|
|
@@ -11,6 +11,7 @@ const telemetry_1 = require("../core/telemetry");
|
|
|
11
11
|
const child_process_1 = require("child_process");
|
|
12
12
|
const util_1 = require("util");
|
|
13
13
|
const webapp_url_1 = require("../utils/webapp-url");
|
|
14
|
+
const errors_1 = require("../core/errors");
|
|
14
15
|
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
15
16
|
/**
|
|
16
17
|
* Make authenticated API call
|
|
@@ -102,7 +103,7 @@ async function handleBuyCredits(options) {
|
|
|
102
103
|
console.error('ā Authentication required');
|
|
103
104
|
console.log('\nš” Please login first:');
|
|
104
105
|
console.log(' prpm login');
|
|
105
|
-
|
|
106
|
+
throw new errors_1.CLIError('ā Authentication required', 1);
|
|
106
107
|
}
|
|
107
108
|
// Get current balance
|
|
108
109
|
console.log('š Checking current credits balance...');
|
|
@@ -122,7 +123,7 @@ async function handleBuyCredits(options) {
|
|
|
122
123
|
if (!validPackages.includes(options.package)) {
|
|
123
124
|
console.error(`\nā Invalid package: ${options.package}`);
|
|
124
125
|
console.log(' Valid options: small, medium, large');
|
|
125
|
-
|
|
126
|
+
throw new errors_1.CLIError(`\nā Invalid package: ${options.package}`, 1);
|
|
126
127
|
}
|
|
127
128
|
purchaseUrl += `?package=${options.package}`;
|
|
128
129
|
}
|
|
@@ -154,7 +155,7 @@ async function handleBuyCredits(options) {
|
|
|
154
155
|
catch (err) {
|
|
155
156
|
error = err instanceof Error ? err.message : String(err);
|
|
156
157
|
console.error(`\nā Purchase failed: ${error}`);
|
|
157
|
-
|
|
158
|
+
throw new errors_1.CLIError(`\nā Purchase failed: ${error}`, 1);
|
|
158
159
|
}
|
|
159
160
|
finally {
|
|
160
161
|
await telemetry_1.telemetry.track({
|
|
@@ -218,7 +219,6 @@ Note: Purchased credits are one-time and never expire, unlike monthly credits.
|
|
|
218
219
|
`)
|
|
219
220
|
.action(async (options) => {
|
|
220
221
|
await handleBuyCredits(options);
|
|
221
|
-
process.exit(0);
|
|
222
222
|
});
|
|
223
223
|
return command;
|
|
224
224
|
}
|
package/dist/commands/catalog.js
CHANGED
|
@@ -10,6 +10,7 @@ const promises_1 = require("fs/promises");
|
|
|
10
10
|
const path_1 = require("path");
|
|
11
11
|
const telemetry_1 = require("../core/telemetry");
|
|
12
12
|
const lockfile_1 = require("../core/lockfile");
|
|
13
|
+
const errors_1 = require("../core/errors");
|
|
13
14
|
/**
|
|
14
15
|
* Detect format and subtype from file path and content
|
|
15
16
|
*/
|
|
@@ -333,7 +334,7 @@ async function handleCatalog(directories, options) {
|
|
|
333
334
|
catch (err) {
|
|
334
335
|
error = err instanceof Error ? err.message : String(err);
|
|
335
336
|
console.error(`\nā Failed to catalog packages: ${error}\n`);
|
|
336
|
-
|
|
337
|
+
throw new errors_1.CLIError(`\nā Failed to catalog packages: ${error}`, 1);
|
|
337
338
|
}
|
|
338
339
|
finally {
|
|
339
340
|
await telemetry_1.telemetry.track({
|
|
@@ -360,6 +361,5 @@ function createCatalogCommand() {
|
|
|
360
361
|
.option('--dry-run', 'Show what would be cataloged without making changes')
|
|
361
362
|
.action(async (directories, options) => {
|
|
362
363
|
await handleCatalog(directories, options);
|
|
363
|
-
process.exit(0);
|
|
364
364
|
});
|
|
365
365
|
}
|
|
@@ -48,6 +48,7 @@ const user_config_1 = require("../core/user-config");
|
|
|
48
48
|
const install_1 = require("./install");
|
|
49
49
|
const telemetry_1 = require("../core/telemetry");
|
|
50
50
|
const lockfile_1 = require("../core/lockfile");
|
|
51
|
+
const errors_1 = require("../core/errors");
|
|
51
52
|
/**
|
|
52
53
|
* Search collections by query
|
|
53
54
|
*/
|
|
@@ -130,7 +131,7 @@ async function handleCollectionsSearch(query, options) {
|
|
|
130
131
|
error: errorMessage,
|
|
131
132
|
duration: Date.now() - startTime,
|
|
132
133
|
});
|
|
133
|
-
|
|
134
|
+
throw new errors_1.CLIError(`\nā Failed to search collections: ${errorMessage}`, 1);
|
|
134
135
|
}
|
|
135
136
|
finally {
|
|
136
137
|
await telemetry_1.telemetry.shutdown();
|
|
@@ -218,7 +219,7 @@ async function handleCollectionsList(options) {
|
|
|
218
219
|
error: errorMessage,
|
|
219
220
|
duration: Date.now() - startTime,
|
|
220
221
|
});
|
|
221
|
-
|
|
222
|
+
throw new errors_1.CLIError(`\nā Failed to list collections: ${errorMessage}`, 1);
|
|
222
223
|
}
|
|
223
224
|
finally {
|
|
224
225
|
await telemetry_1.telemetry.shutdown();
|
|
@@ -338,7 +339,7 @@ async function handleCollectionInfo(collectionSpec) {
|
|
|
338
339
|
error: errorMessage,
|
|
339
340
|
duration: Date.now() - startTime,
|
|
340
341
|
});
|
|
341
|
-
|
|
342
|
+
throw new errors_1.CLIError(`\nā Failed to get collection info: ${errorMessage}`, 1);
|
|
342
343
|
}
|
|
343
344
|
finally {
|
|
344
345
|
await telemetry_1.telemetry.shutdown();
|
|
@@ -355,7 +356,7 @@ async function handleCollectionPublish(manifestPath = './collection.json') {
|
|
|
355
356
|
// Check authentication
|
|
356
357
|
if (!config.token) {
|
|
357
358
|
console.error('\nā Authentication required. Run `prpm login` first.\n');
|
|
358
|
-
|
|
359
|
+
throw new errors_1.CLIError('\nā Authentication required. Run `prpm login` first.', 1);
|
|
359
360
|
}
|
|
360
361
|
console.log('š¦ Publishing collection...\n');
|
|
361
362
|
// Read collection manifest
|
|
@@ -438,7 +439,7 @@ async function handleCollectionPublish(manifestPath = './collection.json') {
|
|
|
438
439
|
error: errorMessage,
|
|
439
440
|
duration: Date.now() - startTime,
|
|
440
441
|
});
|
|
441
|
-
|
|
442
|
+
throw new errors_1.CLIError(`\nā Failed to publish collection: ${errorMessage}`, 1);
|
|
442
443
|
}
|
|
443
444
|
finally {
|
|
444
445
|
await telemetry_1.telemetry.shutdown();
|
|
@@ -501,14 +502,21 @@ async function handleCollectionInstall(collectionSpec, options) {
|
|
|
501
502
|
const progress = `${i + 1}/${packages.length}`;
|
|
502
503
|
try {
|
|
503
504
|
console.log(`\n ${progress} Installing ${pkg.packageId}@${pkg.version}...`);
|
|
504
|
-
|
|
505
|
-
|
|
505
|
+
// Only pass 'as' format if user explicitly requested it via --as flag
|
|
506
|
+
// Otherwise, let handleInstall auto-detect the format based on existing directories
|
|
507
|
+
// This ensures collections respect existing .claude or .cursor directories
|
|
508
|
+
const installOptions = {
|
|
506
509
|
fromCollection: {
|
|
507
510
|
scope,
|
|
508
511
|
name_slug,
|
|
509
512
|
version: collection.version || version || '1.0.0',
|
|
510
513
|
},
|
|
511
|
-
}
|
|
514
|
+
};
|
|
515
|
+
// Only set 'as' if user explicitly provided a format
|
|
516
|
+
if (options.format) {
|
|
517
|
+
installOptions.as = options.format;
|
|
518
|
+
}
|
|
519
|
+
await (0, install_1.handleInstall)(`${pkg.packageId}@${pkg.version}`, installOptions);
|
|
512
520
|
console.log(` ${progress} ā ${pkg.packageId}`);
|
|
513
521
|
installedPackageIds.push(pkg.packageId);
|
|
514
522
|
packagesInstalled++;
|
|
@@ -566,7 +574,7 @@ async function handleCollectionInstall(collectionSpec, options) {
|
|
|
566
574
|
failed: packagesFailed,
|
|
567
575
|
},
|
|
568
576
|
});
|
|
569
|
-
|
|
577
|
+
throw new errors_1.CLIError(`\nā Failed to install collection: ${errorMessage}`, 1);
|
|
570
578
|
}
|
|
571
579
|
finally {
|
|
572
580
|
await telemetry_1.telemetry.shutdown();
|
package/dist/commands/config.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.createConfigCommand = createConfigCommand;
|
|
7
7
|
const commander_1 = require("commander");
|
|
8
8
|
const user_config_1 = require("../core/user-config");
|
|
9
|
+
const errors_1 = require("../core/errors");
|
|
9
10
|
/**
|
|
10
11
|
* Get a config value
|
|
11
12
|
*/
|
|
@@ -14,15 +15,15 @@ async function handleConfigGet(key) {
|
|
|
14
15
|
const config = await (0, user_config_1.getConfig)();
|
|
15
16
|
const value = config[key];
|
|
16
17
|
if (value === undefined) {
|
|
17
|
-
|
|
18
|
-
console.log('\nAvailable keys: registryUrl, telemetryEnabled, token, username');
|
|
19
|
-
process.exit(1);
|
|
18
|
+
throw new errors_1.CLIError(`ā Config key "${key}" not found\n\nAvailable keys: registryUrl, telemetryEnabled, token, username`, 1);
|
|
20
19
|
}
|
|
21
20
|
console.log(value);
|
|
22
21
|
}
|
|
23
22
|
catch (error) {
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
if (error instanceof errors_1.CLIError) {
|
|
24
|
+
throw error;
|
|
25
|
+
}
|
|
26
|
+
throw new errors_1.CLIError(`ā Failed to get config: ${error instanceof Error ? error.message : String(error)}`, 1);
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
29
|
/**
|
|
@@ -34,10 +35,7 @@ async function handleConfigSet(key, value) {
|
|
|
34
35
|
// Validate key
|
|
35
36
|
const validKeys = ['registryUrl', 'telemetryEnabled'];
|
|
36
37
|
if (!validKeys.includes(key)) {
|
|
37
|
-
|
|
38
|
-
console.log('\nSettable keys: registryUrl, telemetryEnabled');
|
|
39
|
-
console.log('Note: token and username are set via "prpm login"');
|
|
40
|
-
process.exit(1);
|
|
38
|
+
throw new errors_1.CLIError(`ā Cannot set config key "${key}"\n\nSettable keys: registryUrl, telemetryEnabled\nNote: token and username are set via "prpm login"`, 1);
|
|
41
39
|
}
|
|
42
40
|
// Parse boolean values
|
|
43
41
|
let parsedValue = value;
|
|
@@ -49,8 +47,7 @@ async function handleConfigSet(key, value) {
|
|
|
49
47
|
parsedValue = false;
|
|
50
48
|
}
|
|
51
49
|
else {
|
|
52
|
-
|
|
53
|
-
process.exit(1);
|
|
50
|
+
throw new errors_1.CLIError(`ā Invalid boolean value "${value}". Use: true, false, yes, no, 1, or 0`, 1);
|
|
54
51
|
}
|
|
55
52
|
}
|
|
56
53
|
// Update config
|
|
@@ -59,8 +56,10 @@ async function handleConfigSet(key, value) {
|
|
|
59
56
|
console.log(`ā
Set ${key} = ${parsedValue}`);
|
|
60
57
|
}
|
|
61
58
|
catch (error) {
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
if (error instanceof errors_1.CLIError) {
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
throw new errors_1.CLIError(`ā Failed to set config: ${error instanceof Error ? error.message : String(error)}`, 1);
|
|
64
63
|
}
|
|
65
64
|
}
|
|
66
65
|
/**
|
|
@@ -81,8 +80,7 @@ async function handleConfigList() {
|
|
|
81
80
|
console.log(`Config file: ${configPath}`);
|
|
82
81
|
}
|
|
83
82
|
catch (error) {
|
|
84
|
-
|
|
85
|
-
process.exit(1);
|
|
83
|
+
throw new errors_1.CLIError(`ā Failed to list config: ${error instanceof Error ? error.message : String(error)}`, 1);
|
|
86
84
|
}
|
|
87
85
|
}
|
|
88
86
|
/**
|
|
@@ -94,8 +92,7 @@ async function handleConfigDelete(key) {
|
|
|
94
92
|
// Validate key
|
|
95
93
|
const deletableKeys = ['registryUrl', 'telemetryEnabled', 'token', 'username'];
|
|
96
94
|
if (!deletableKeys.includes(key)) {
|
|
97
|
-
|
|
98
|
-
process.exit(1);
|
|
95
|
+
throw new errors_1.CLIError(`ā Cannot delete config key "${key}"`, 1);
|
|
99
96
|
}
|
|
100
97
|
// Reset to defaults
|
|
101
98
|
if (key === 'registryUrl') {
|
|
@@ -114,8 +111,10 @@ async function handleConfigDelete(key) {
|
|
|
114
111
|
console.log(`ā
Reset ${key} to default value`);
|
|
115
112
|
}
|
|
116
113
|
catch (error) {
|
|
117
|
-
|
|
118
|
-
|
|
114
|
+
if (error instanceof errors_1.CLIError) {
|
|
115
|
+
throw error;
|
|
116
|
+
}
|
|
117
|
+
throw new errors_1.CLIError(`ā Failed to delete config: ${error instanceof Error ? error.message : String(error)}`, 1);
|
|
119
118
|
}
|
|
120
119
|
}
|
|
121
120
|
/**
|
|
@@ -131,7 +130,6 @@ function createConfigCommand() {
|
|
|
131
130
|
.description('List all configuration values')
|
|
132
131
|
.action(async () => {
|
|
133
132
|
await handleConfigList();
|
|
134
|
-
process.exit(0);
|
|
135
133
|
});
|
|
136
134
|
// config get <key>
|
|
137
135
|
command
|
|
@@ -139,7 +137,6 @@ function createConfigCommand() {
|
|
|
139
137
|
.description('Get a configuration value')
|
|
140
138
|
.action(async (key) => {
|
|
141
139
|
await handleConfigGet(key);
|
|
142
|
-
process.exit(0);
|
|
143
140
|
});
|
|
144
141
|
// config set <key> <value>
|
|
145
142
|
command
|
|
@@ -147,7 +144,6 @@ function createConfigCommand() {
|
|
|
147
144
|
.description('Set a configuration value')
|
|
148
145
|
.action(async (key, value) => {
|
|
149
146
|
await handleConfigSet(key, value);
|
|
150
|
-
process.exit(0);
|
|
151
147
|
});
|
|
152
148
|
// config delete <key>
|
|
153
149
|
command
|
|
@@ -156,12 +152,10 @@ function createConfigCommand() {
|
|
|
156
152
|
.description('Reset a configuration value to default')
|
|
157
153
|
.action(async (key) => {
|
|
158
154
|
await handleConfigDelete(key);
|
|
159
|
-
process.exit(0);
|
|
160
155
|
});
|
|
161
156
|
// Default action (show list if no subcommand)
|
|
162
157
|
command.action(async () => {
|
|
163
158
|
await handleConfigList();
|
|
164
|
-
process.exit(0);
|
|
165
159
|
});
|
|
166
160
|
return command;
|
|
167
161
|
}
|
package/dist/commands/credits.js
CHANGED
|
@@ -8,6 +8,7 @@ exports.createCreditsCommand = createCreditsCommand;
|
|
|
8
8
|
const commander_1 = require("commander");
|
|
9
9
|
const user_config_1 = require("../core/user-config");
|
|
10
10
|
const telemetry_1 = require("../core/telemetry");
|
|
11
|
+
const errors_1 = require("../core/errors");
|
|
11
12
|
/**
|
|
12
13
|
* Make authenticated API call
|
|
13
14
|
*/
|
|
@@ -112,7 +113,7 @@ async function handleCredits(options) {
|
|
|
112
113
|
console.error('ā Authentication required');
|
|
113
114
|
console.log('\nš” Please login first:');
|
|
114
115
|
console.log(' prpm login');
|
|
115
|
-
|
|
116
|
+
throw new errors_1.CLIError('ā Authentication required', 1);
|
|
116
117
|
}
|
|
117
118
|
if (options.history) {
|
|
118
119
|
await showHistory(options.limit || 10);
|
|
@@ -130,7 +131,7 @@ async function handleCredits(options) {
|
|
|
130
131
|
catch (err) {
|
|
131
132
|
error = err instanceof Error ? err.message : String(err);
|
|
132
133
|
console.error(`\nā Failed to fetch credits: ${error}`);
|
|
133
|
-
|
|
134
|
+
throw new errors_1.CLIError(`\nā Failed to fetch credits: ${error}`, 1);
|
|
134
135
|
}
|
|
135
136
|
finally {
|
|
136
137
|
await telemetry_1.telemetry.track({
|
|
@@ -180,7 +181,6 @@ Get more credits:
|
|
|
180
181
|
history: options.history,
|
|
181
182
|
limit: options.limit ? parseInt(options.limit, 10) : undefined,
|
|
182
183
|
});
|
|
183
|
-
process.exit(0);
|
|
184
184
|
});
|
|
185
185
|
return command;
|
|
186
186
|
}
|
package/dist/commands/index.js
CHANGED
|
@@ -13,6 +13,7 @@ const fs_1 = require("fs");
|
|
|
13
13
|
const path_1 = __importDefault(require("path"));
|
|
14
14
|
const lockfile_1 = require("../core/lockfile");
|
|
15
15
|
const filesystem_1 = require("../core/filesystem");
|
|
16
|
+
const errors_1 = require("../core/errors");
|
|
16
17
|
/**
|
|
17
18
|
* Scan directory for files and return file information
|
|
18
19
|
* Recursively scans subdirectories for Claude skills/agents
|
|
@@ -167,10 +168,7 @@ async function handleIndex(options = {}) {
|
|
|
167
168
|
}
|
|
168
169
|
catch (error) {
|
|
169
170
|
console.error(`ā Failed to index packages: ${error}`);
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
finally {
|
|
173
|
-
process.exit(0);
|
|
171
|
+
throw new errors_1.CLIError(`ā Failed to index packages: ${error}`, 1);
|
|
174
172
|
}
|
|
175
173
|
}
|
|
176
174
|
/**
|
package/dist/commands/info.js
CHANGED
|
@@ -9,6 +9,7 @@ const commander_1 = require("commander");
|
|
|
9
9
|
const registry_client_1 = require("@pr-pm/registry-client");
|
|
10
10
|
const user_config_1 = require("../core/user-config");
|
|
11
11
|
const telemetry_1 = require("../core/telemetry");
|
|
12
|
+
const errors_1 = require("../core/errors");
|
|
12
13
|
async function handleInfo(packageName) {
|
|
13
14
|
const startTime = Date.now();
|
|
14
15
|
let success = false;
|
|
@@ -50,12 +51,7 @@ async function handleInfo(packageName) {
|
|
|
50
51
|
}
|
|
51
52
|
catch (err) {
|
|
52
53
|
error = err instanceof Error ? err.message : String(err);
|
|
53
|
-
|
|
54
|
-
console.log(`\nš” Tips:`);
|
|
55
|
-
console.log(` - Check the package ID spelling`);
|
|
56
|
-
console.log(` - Search for packages: prpm search <query>`);
|
|
57
|
-
console.log(` - View trending: prpm trending`);
|
|
58
|
-
process.exit(1);
|
|
54
|
+
throw new errors_1.CLIError(`\nā Failed to fetch package info: ${error}\n\nš” Tips:\n - Check the package ID spelling\n - Search for packages: prpm search <query>\n - View trending: prpm trending`, 1);
|
|
59
55
|
}
|
|
60
56
|
finally {
|
|
61
57
|
await telemetry_1.telemetry.track({
|
|
@@ -77,7 +73,6 @@ function createInfoCommand() {
|
|
|
77
73
|
.argument('<package>', 'Package ID to get information about')
|
|
78
74
|
.action(async (packageId) => {
|
|
79
75
|
await handleInfo(packageId);
|
|
80
|
-
process.exit(0);
|
|
81
76
|
});
|
|
82
77
|
return command;
|
|
83
78
|
}
|
package/dist/commands/init.js
CHANGED
|
@@ -45,6 +45,7 @@ const fs_1 = require("fs");
|
|
|
45
45
|
const readline = __importStar(require("readline/promises"));
|
|
46
46
|
const process_1 = require("process");
|
|
47
47
|
const types_1 = require("../types");
|
|
48
|
+
const errors_1 = require("../core/errors");
|
|
48
49
|
const FORMAT_EXAMPLES = {
|
|
49
50
|
cursor: {
|
|
50
51
|
description: 'Cursor AI coding rules',
|
|
@@ -648,7 +649,9 @@ async function initPackage(options) {
|
|
|
648
649
|
// Create example files
|
|
649
650
|
if (config.files && config.format && config.name) {
|
|
650
651
|
console.log('Creating example files...\n');
|
|
651
|
-
|
|
652
|
+
// Filter out README.md since createReadme will handle it with proper content
|
|
653
|
+
const filesToCreate = config.files.filter(f => f !== 'README.md');
|
|
654
|
+
await createExampleFiles(config.format, filesToCreate, config.name);
|
|
652
655
|
// Create README
|
|
653
656
|
await createReadme(config);
|
|
654
657
|
}
|
|
@@ -671,11 +674,10 @@ function createInitCommand() {
|
|
|
671
674
|
.action(async (options) => {
|
|
672
675
|
try {
|
|
673
676
|
await initPackage(options);
|
|
674
|
-
process.exit(0);
|
|
675
677
|
}
|
|
676
678
|
catch (error) {
|
|
677
679
|
console.error('\nā Error:', error instanceof Error ? error.message : error);
|
|
678
|
-
|
|
680
|
+
throw new errors_1.CLIError('\nā Error: ' + (error instanceof Error ? error.message : error), 1);
|
|
679
681
|
}
|
|
680
682
|
});
|
|
681
683
|
return command;
|
package/dist/commands/install.js
CHANGED
|
@@ -45,6 +45,7 @@ const user_config_1 = require("../core/user-config");
|
|
|
45
45
|
const filesystem_1 = require("../core/filesystem");
|
|
46
46
|
const telemetry_1 = require("../core/telemetry");
|
|
47
47
|
const tar = __importStar(require("tar"));
|
|
48
|
+
const errors_1 = require("../core/errors");
|
|
48
49
|
const lockfile_1 = require("../core/lockfile");
|
|
49
50
|
const cursor_config_1 = require("../core/cursor-config");
|
|
50
51
|
const claude_config_1 = require("../core/claude-config");
|
|
@@ -494,11 +495,7 @@ async function handleInstall(packageSpec, options) {
|
|
|
494
495
|
}
|
|
495
496
|
catch (err) {
|
|
496
497
|
error = err instanceof Error ? err.message : String(err);
|
|
497
|
-
|
|
498
|
-
console.log(`\nš” Tips:`);
|
|
499
|
-
console.log(` - Check package name: prpm search <query>`);
|
|
500
|
-
console.log(` - Get package info: prpm info <package>`);
|
|
501
|
-
process.exit(1);
|
|
498
|
+
throw new errors_1.CLIError(`\nā Installation failed: ${error}\n\nš” Tips:\n - Check package name: prpm search <query>\n - Get package info: prpm info <package>`, 1);
|
|
502
499
|
}
|
|
503
500
|
finally {
|
|
504
501
|
await telemetry_1.telemetry.track({
|
|
@@ -611,9 +608,7 @@ async function installFromLockfile(options) {
|
|
|
611
608
|
// Read lockfile
|
|
612
609
|
const lockfile = await (0, lockfile_1.readLockfile)();
|
|
613
610
|
if (!lockfile) {
|
|
614
|
-
|
|
615
|
-
console.log('\nš” Run "prpm install <package>" first to create a lockfile, or initialize a new project with "prpm init"');
|
|
616
|
-
process.exit(1);
|
|
611
|
+
throw new errors_1.CLIError('ā No prpm.lock file found\n\nš” Run "prpm install <package>" first to create a lockfile, or initialize a new project with "prpm init"', 1);
|
|
617
612
|
}
|
|
618
613
|
const packageIds = Object.keys(lockfile.packages);
|
|
619
614
|
if (packageIds.length === 0) {
|
|
@@ -642,19 +637,31 @@ async function installFromLockfile(options) {
|
|
|
642
637
|
successCount++;
|
|
643
638
|
}
|
|
644
639
|
catch (error) {
|
|
645
|
-
|
|
646
|
-
|
|
640
|
+
// Check if this is a success exit (CLIError with exitCode 0)
|
|
641
|
+
if (error instanceof errors_1.CLIError && error.exitCode === 0) {
|
|
642
|
+
successCount++;
|
|
643
|
+
}
|
|
644
|
+
else {
|
|
645
|
+
failCount++;
|
|
646
|
+
console.error(` ā Failed to install ${packageId}:`);
|
|
647
|
+
console.error(` Type: ${error?.constructor?.name}`);
|
|
648
|
+
console.error(` Message: ${error instanceof Error ? error.message : String(error)}`);
|
|
649
|
+
if (error instanceof errors_1.CLIError) {
|
|
650
|
+
console.error(` ExitCode: ${error.exitCode}`);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
647
653
|
}
|
|
648
654
|
}
|
|
649
655
|
console.log(`\nā
Installed ${successCount}/${packageIds.length} packages`);
|
|
650
656
|
if (failCount > 0) {
|
|
651
|
-
|
|
652
|
-
process.exit(1);
|
|
657
|
+
throw new errors_1.CLIError(`ā ${failCount} package${failCount === 1 ? '' : 's'} failed to install`, 1);
|
|
653
658
|
}
|
|
654
659
|
}
|
|
655
660
|
catch (error) {
|
|
656
|
-
|
|
657
|
-
|
|
661
|
+
if (error instanceof errors_1.CLIError) {
|
|
662
|
+
throw error;
|
|
663
|
+
}
|
|
664
|
+
throw new errors_1.CLIError(`ā Failed to install from lockfile: ${error}`, 1);
|
|
658
665
|
}
|
|
659
666
|
}
|
|
660
667
|
function createInstallCommand() {
|
|
@@ -671,14 +678,7 @@ function createInstallCommand() {
|
|
|
671
678
|
// Support both --as and --format (format is alias for as)
|
|
672
679
|
const convertTo = options.format || options.as;
|
|
673
680
|
if (convertTo && !['cursor', 'claude', 'continue', 'windsurf', 'copilot', 'kiro', 'agents.md', 'canonical'].includes(convertTo)) {
|
|
674
|
-
|
|
675
|
-
console.log('\nš” Examples:');
|
|
676
|
-
console.log(' prpm install my-package --as cursor # Convert to Cursor format');
|
|
677
|
-
console.log(' prpm install my-package --format claude # Convert to Claude format');
|
|
678
|
-
console.log(' prpm install my-package --format kiro # Convert to Kiro format');
|
|
679
|
-
console.log(' prpm install my-package --format agents.md # Convert to Agents.md format');
|
|
680
|
-
console.log(' prpm install my-package # Install in native format');
|
|
681
|
-
process.exit(1);
|
|
681
|
+
throw new errors_1.CLIError('ā Format must be one of: cursor, claude, continue, windsurf, copilot, kiro, agents.md, canonical\n\nš” Examples:\n prpm install my-package --as cursor # Convert to Cursor format\n prpm install my-package --format claude # Convert to Claude format\n prpm install my-package --format kiro # Convert to Kiro format\n prpm install my-package --format agents.md # Convert to Agents.md format\n prpm install my-package # Install in native format', 1);
|
|
682
682
|
}
|
|
683
683
|
// If no package specified, install from lockfile
|
|
684
684
|
if (!packageSpec) {
|
|
@@ -687,7 +687,6 @@ function createInstallCommand() {
|
|
|
687
687
|
subtype: options.subtype,
|
|
688
688
|
frozenLockfile: options.frozenLockfile
|
|
689
689
|
});
|
|
690
|
-
process.exit(0);
|
|
691
690
|
return;
|
|
692
691
|
}
|
|
693
692
|
await handleInstall(packageSpec, {
|
|
@@ -696,7 +695,6 @@ function createInstallCommand() {
|
|
|
696
695
|
subtype: options.subtype,
|
|
697
696
|
frozenLockfile: options.frozenLockfile
|
|
698
697
|
});
|
|
699
|
-
process.exit(0);
|
|
700
698
|
});
|
|
701
699
|
return command;
|
|
702
700
|
}
|
package/dist/commands/list.js
CHANGED
|
@@ -13,6 +13,7 @@ const lockfile_1 = require("../core/lockfile");
|
|
|
13
13
|
const telemetry_1 = require("../core/telemetry");
|
|
14
14
|
const fs_1 = require("fs");
|
|
15
15
|
const path_1 = __importDefault(require("path"));
|
|
16
|
+
const errors_1 = require("../core/errors");
|
|
16
17
|
/**
|
|
17
18
|
* Get destination directory based on package type
|
|
18
19
|
*/
|
|
@@ -158,8 +159,7 @@ async function handleList() {
|
|
|
158
159
|
}
|
|
159
160
|
catch (err) {
|
|
160
161
|
error = err instanceof Error ? err.message : String(err);
|
|
161
|
-
|
|
162
|
-
process.exit(1);
|
|
162
|
+
throw new errors_1.CLIError(`ā Failed to list packages: ${error}`, 1);
|
|
163
163
|
}
|
|
164
164
|
finally {
|
|
165
165
|
// Track telemetry
|
|
@@ -184,7 +184,6 @@ function createListCommand() {
|
|
|
184
184
|
.description('List all installed prompt packages')
|
|
185
185
|
.action(async () => {
|
|
186
186
|
await handleList();
|
|
187
|
-
process.exit(0);
|
|
188
187
|
});
|
|
189
188
|
return command;
|
|
190
189
|
}
|
package/dist/commands/login.js
CHANGED
|
@@ -42,6 +42,7 @@ const commander_1 = require("commander");
|
|
|
42
42
|
const http_1 = require("http");
|
|
43
43
|
const telemetry_1 = require("../core/telemetry");
|
|
44
44
|
const user_config_1 = require("../core/user-config");
|
|
45
|
+
const errors_1 = require("../core/errors");
|
|
45
46
|
/**
|
|
46
47
|
* Start OAuth callback server
|
|
47
48
|
*/
|
|
@@ -270,9 +271,7 @@ async function handleLogin(options) {
|
|
|
270
271
|
}
|
|
271
272
|
catch (err) {
|
|
272
273
|
error = err instanceof Error ? err.message : String(err);
|
|
273
|
-
|
|
274
|
-
console.error('š” Try again or use "prpm login --token YOUR_TOKEN"\n');
|
|
275
|
-
process.exit(1);
|
|
274
|
+
throw new errors_1.CLIError(`\nā Login failed: ${error}\n\nš” Try again or use "prpm login --token YOUR_TOKEN"\n`, 1);
|
|
276
275
|
}
|
|
277
276
|
finally {
|
|
278
277
|
// Track telemetry
|
|
@@ -297,6 +296,5 @@ function createLoginCommand() {
|
|
|
297
296
|
.option('--token <token>', 'Login with a personal access token')
|
|
298
297
|
.action(async (options) => {
|
|
299
298
|
await handleLogin(options);
|
|
300
|
-
process.exit(0);
|
|
301
299
|
});
|
|
302
300
|
}
|
|
@@ -10,6 +10,7 @@ const registry_client_1 = require("@pr-pm/registry-client");
|
|
|
10
10
|
const user_config_1 = require("../core/user-config");
|
|
11
11
|
const lockfile_1 = require("../core/lockfile");
|
|
12
12
|
const telemetry_1 = require("../core/telemetry");
|
|
13
|
+
const errors_1 = require("../core/errors");
|
|
13
14
|
/**
|
|
14
15
|
* Check for outdated packages
|
|
15
16
|
*/
|
|
@@ -91,8 +92,7 @@ async function handleOutdated() {
|
|
|
91
92
|
}
|
|
92
93
|
catch (err) {
|
|
93
94
|
error = err instanceof Error ? err.message : String(err);
|
|
94
|
-
|
|
95
|
-
process.exit(1);
|
|
95
|
+
throw new errors_1.CLIError(`\nā Failed to check for updates: ${error}`, 1);
|
|
96
96
|
}
|
|
97
97
|
finally {
|
|
98
98
|
await telemetry_1.telemetry.track({
|
|
@@ -126,6 +126,5 @@ function createOutdatedCommand() {
|
|
|
126
126
|
.description('Check for package updates')
|
|
127
127
|
.action(async () => {
|
|
128
128
|
await handleOutdated();
|
|
129
|
-
process.exit(0);
|
|
130
129
|
});
|
|
131
130
|
}
|
|
@@ -42,6 +42,7 @@ const commander_1 = require("commander");
|
|
|
42
42
|
const user_config_1 = require("../core/user-config");
|
|
43
43
|
const telemetry_1 = require("../core/telemetry");
|
|
44
44
|
const readline = __importStar(require("readline"));
|
|
45
|
+
const errors_1 = require("../core/errors");
|
|
45
46
|
/**
|
|
46
47
|
* Create a readline interface for user input
|
|
47
48
|
*/
|
|
@@ -252,7 +253,7 @@ async function runSingle(packageName, input, options) {
|
|
|
252
253
|
console.log(' - Subscribe to PRPM+: prpm subscribe');
|
|
253
254
|
console.log(' - Check balance: prpm credits');
|
|
254
255
|
}
|
|
255
|
-
|
|
256
|
+
throw new errors_1.CLIError(`\nā Error: ${error instanceof Error ? error.message : String(error)}`, 1);
|
|
256
257
|
}
|
|
257
258
|
}
|
|
258
259
|
/**
|
|
@@ -269,7 +270,7 @@ async function handlePlayground(packageName, input, options) {
|
|
|
269
270
|
console.error('ā Authentication required');
|
|
270
271
|
console.log('\nš” Please login first:');
|
|
271
272
|
console.log(' prpm login');
|
|
272
|
-
|
|
273
|
+
throw new errors_1.CLIError('ā Authentication required', 1);
|
|
273
274
|
}
|
|
274
275
|
// Interactive mode or single query
|
|
275
276
|
if (options.interactive || !input) {
|
|
@@ -285,7 +286,7 @@ async function handlePlayground(packageName, input, options) {
|
|
|
285
286
|
catch (err) {
|
|
286
287
|
error = err instanceof Error ? err.message : String(err);
|
|
287
288
|
console.error(`\nā Playground execution failed: ${error}`);
|
|
288
|
-
|
|
289
|
+
throw new errors_1.CLIError(`\nā Playground execution failed: ${error}`, 1);
|
|
289
290
|
}
|
|
290
291
|
finally {
|
|
291
292
|
await telemetry_1.telemetry.track({
|
|
@@ -345,7 +346,6 @@ Note: Playground usage requires credits. Run 'prpm credits' to check balance.
|
|
|
345
346
|
`)
|
|
346
347
|
.action(async (packageName, input, options) => {
|
|
347
348
|
await handlePlayground(packageName, input, options);
|
|
348
|
-
process.exit(0);
|
|
349
349
|
});
|
|
350
350
|
return command;
|
|
351
351
|
}
|
package/dist/commands/popular.js
CHANGED
|
@@ -29,6 +29,5 @@ function createPopularCommand() {
|
|
|
29
29
|
.option('--subtype <subtype>', 'Filter by subtype (rule, agent, skill, slash-command, prompt, workflow, tool, template, collection)')
|
|
30
30
|
.action(async (options) => {
|
|
31
31
|
await handlePopular(options);
|
|
32
|
-
process.exit(0);
|
|
33
32
|
});
|
|
34
33
|
}
|
package/dist/commands/publish.js
CHANGED
|
@@ -47,6 +47,7 @@ const crypto_1 = require("crypto");
|
|
|
47
47
|
const registry_client_1 = require("@pr-pm/registry-client");
|
|
48
48
|
const user_config_1 = require("../core/user-config");
|
|
49
49
|
const telemetry_1 = require("../core/telemetry");
|
|
50
|
+
const errors_1 = require("../core/errors");
|
|
50
51
|
const marketplace_converter_1 = require("../core/marketplace-converter");
|
|
51
52
|
const schema_validator_1 = require("../core/schema-validator");
|
|
52
53
|
const license_extractor_1 = require("../utils/license-extractor");
|
|
@@ -65,6 +66,7 @@ async function findAndLoadManifests() {
|
|
|
65
66
|
let prpmJsonError = null;
|
|
66
67
|
try {
|
|
67
68
|
const content = await (0, promises_1.readFile)(prpmJsonPath, 'utf-8');
|
|
69
|
+
prpmJsonExists = true; // Mark file as found after successful read
|
|
68
70
|
const manifest = JSON.parse(content);
|
|
69
71
|
// Extract collections if present
|
|
70
72
|
const collections = [];
|
|
@@ -349,8 +351,7 @@ async function handlePublish(options) {
|
|
|
349
351
|
const config = await (0, user_config_1.getConfig)();
|
|
350
352
|
// Check if logged in
|
|
351
353
|
if (!config.token) {
|
|
352
|
-
|
|
353
|
-
process.exit(1);
|
|
354
|
+
throw new errors_1.CLIError('ā Not logged in. Run "prpm login" first.', 1);
|
|
354
355
|
}
|
|
355
356
|
console.log('š¦ Publishing package...\n');
|
|
356
357
|
// Read and validate manifests
|
|
@@ -712,41 +713,41 @@ async function handlePublish(options) {
|
|
|
712
713
|
// Success if we published any packages OR collections
|
|
713
714
|
success = publishedPackages.length > 0 || publishedCollections.length > 0;
|
|
714
715
|
if (failedPackages.length > 0 && publishedPackages.length === 0 && publishedCollections.length === 0) {
|
|
715
|
-
|
|
716
|
+
// Use the first failed package's error for telemetry
|
|
717
|
+
const firstError = failedPackages[0]?.error || 'Unknown error';
|
|
718
|
+
throw new errors_1.CLIError(firstError, 1);
|
|
716
719
|
}
|
|
717
720
|
}
|
|
718
721
|
catch (err) {
|
|
719
722
|
error = err instanceof Error ? err.message : String(err);
|
|
720
|
-
|
|
723
|
+
if (err instanceof errors_1.CLIError) {
|
|
724
|
+
throw err;
|
|
725
|
+
}
|
|
726
|
+
let errorMsg = `\nā Failed to publish package: ${error}\n`;
|
|
721
727
|
// Provide helpful hints based on error type
|
|
722
728
|
if (error.includes('Manifest validation failed')) {
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
console.log('');
|
|
734
|
-
console.log('š” View the schema: prpm schema');
|
|
735
|
-
console.log('');
|
|
729
|
+
errorMsg += '\nš” Common validation issues:\n';
|
|
730
|
+
errorMsg += ' - Missing required fields (name, version, description, format)\n';
|
|
731
|
+
errorMsg += ' - Invalid format or subtype values\n';
|
|
732
|
+
errorMsg += ' - Description too short (min 10 chars) or too long (max 500 chars)\n';
|
|
733
|
+
errorMsg += ' - Package name must be lowercase with hyphens only\n';
|
|
734
|
+
errorMsg += '\nš” For Claude skills specifically:\n';
|
|
735
|
+
errorMsg += ' - Add "subtype": "skill" to your prpm.json\n';
|
|
736
|
+
errorMsg += ' - Ensure files include a SKILL.md file\n';
|
|
737
|
+
errorMsg += ' - Package name must be max 64 characters\n';
|
|
738
|
+
errorMsg += '\nš” View the schema: prpm schema\n';
|
|
736
739
|
}
|
|
737
740
|
else if (error.includes('SKILL.md')) {
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
console.log('');
|
|
741
|
+
errorMsg += '\nš” Claude skills require:\n';
|
|
742
|
+
errorMsg += ' - A file named SKILL.md (all caps) in your package\n';
|
|
743
|
+
errorMsg += ' - "format": "claude" and "subtype": "skill" in prpm.json\n';
|
|
742
744
|
}
|
|
743
745
|
else if (error.includes('No manifest file found')) {
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
console.log('');
|
|
746
|
+
errorMsg += '\nš” Create a manifest file:\n';
|
|
747
|
+
errorMsg += ' - Run: prpm init\n';
|
|
748
|
+
errorMsg += ' - Or create prpm.json manually\n';
|
|
748
749
|
}
|
|
749
|
-
|
|
750
|
+
throw new errors_1.CLIError(errorMsg, 1);
|
|
750
751
|
}
|
|
751
752
|
finally {
|
|
752
753
|
// Track telemetry
|
|
@@ -777,6 +778,5 @@ function createPublishCommand() {
|
|
|
777
778
|
.option('--collection <id>', 'Publish only a specific collection from manifest')
|
|
778
779
|
.action(async (options) => {
|
|
779
780
|
await handlePublish(options);
|
|
780
|
-
process.exit(0);
|
|
781
781
|
});
|
|
782
782
|
}
|
package/dist/commands/schema.js
CHANGED
|
@@ -7,6 +7,7 @@ exports.handleSchema = handleSchema;
|
|
|
7
7
|
exports.createSchemaCommand = createSchemaCommand;
|
|
8
8
|
const commander_1 = require("commander");
|
|
9
9
|
const schema_validator_1 = require("../core/schema-validator");
|
|
10
|
+
const errors_1 = require("../core/errors");
|
|
10
11
|
/**
|
|
11
12
|
* Handle the schema command
|
|
12
13
|
*/
|
|
@@ -14,15 +15,16 @@ async function handleSchema() {
|
|
|
14
15
|
try {
|
|
15
16
|
const schema = (0, schema_validator_1.getManifestSchema)();
|
|
16
17
|
if (!schema) {
|
|
17
|
-
|
|
18
|
-
process.exit(1);
|
|
18
|
+
throw new errors_1.CLIError('ā Schema not available', 1);
|
|
19
19
|
}
|
|
20
20
|
// Output the schema as pretty-printed JSON
|
|
21
21
|
console.log(JSON.stringify(schema, null, 2));
|
|
22
22
|
}
|
|
23
23
|
catch (error) {
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
if (error instanceof errors_1.CLIError) {
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
throw new errors_1.CLIError(`ā Failed to export schema: ${error}`, 1);
|
|
26
28
|
}
|
|
27
29
|
}
|
|
28
30
|
/**
|
|
@@ -34,7 +36,6 @@ function createSchemaCommand() {
|
|
|
34
36
|
.description('Display the PRPM manifest JSON schema')
|
|
35
37
|
.action(async () => {
|
|
36
38
|
await handleSchema();
|
|
37
|
-
process.exit(0);
|
|
38
39
|
});
|
|
39
40
|
return command;
|
|
40
41
|
}
|
package/dist/commands/search.js
CHANGED
|
@@ -43,6 +43,7 @@ const registry_client_1 = require("@pr-pm/registry-client");
|
|
|
43
43
|
const user_config_1 = require("../core/user-config");
|
|
44
44
|
const telemetry_1 = require("../core/telemetry");
|
|
45
45
|
const readline = __importStar(require("readline"));
|
|
46
|
+
const errors_1 = require("../core/errors");
|
|
46
47
|
/**
|
|
47
48
|
* Get icon for package format and subtype
|
|
48
49
|
*/
|
|
@@ -377,7 +378,7 @@ async function handleSearch(query, options) {
|
|
|
377
378
|
console.log(`\nš” Tip: You're using a local registry. Make sure it's running or update ~/.prpmrc`);
|
|
378
379
|
console.log(` To use the production registry, remove the registryUrl from ~/.prpmrc`);
|
|
379
380
|
}
|
|
380
|
-
|
|
381
|
+
throw new errors_1.CLIError(`\nā Search failed: ${error}`, 1);
|
|
381
382
|
}
|
|
382
383
|
finally {
|
|
383
384
|
await telemetry_1.telemetry.track({
|
|
@@ -424,7 +425,7 @@ function createSearchCommand() {
|
|
|
424
425
|
const validSubtypes = ['rule', 'agent', 'skill', 'slash-command', 'prompt', 'collection', 'chatmode'];
|
|
425
426
|
if (options.format && !validFormats.includes(format)) {
|
|
426
427
|
console.error(`ā Format must be one of: ${validFormats.join(', ')}`);
|
|
427
|
-
|
|
428
|
+
throw new errors_1.CLIError(`ā Format must be one of: ${validFormats.join(', ')}`, 1);
|
|
428
429
|
}
|
|
429
430
|
if (options.subtype && !validSubtypes.includes(subtype)) {
|
|
430
431
|
console.error(`ā Subtype must be one of: ${validSubtypes.join(', ')}`);
|
|
@@ -437,10 +438,9 @@ function createSearchCommand() {
|
|
|
437
438
|
console.log(` prpm search --subtype skill # List all skills`);
|
|
438
439
|
console.log(` prpm search --format claude # List all Claude packages`);
|
|
439
440
|
console.log(` prpm search --author prpm # List packages by @prpm`);
|
|
440
|
-
|
|
441
|
+
throw new errors_1.CLIError(`ā Subtype must be one of: ${validSubtypes.join(', ')}`, 1);
|
|
441
442
|
}
|
|
442
443
|
await handleSearch(query || '', { format, subtype, author, language: options.language, framework: options.framework, limit, page, interactive: options.interactive });
|
|
443
|
-
process.exit(0);
|
|
444
444
|
});
|
|
445
445
|
return command;
|
|
446
446
|
}
|
|
@@ -11,6 +11,7 @@ const telemetry_1 = require("../core/telemetry");
|
|
|
11
11
|
const child_process_1 = require("child_process");
|
|
12
12
|
const util_1 = require("util");
|
|
13
13
|
const webapp_url_1 = require("../utils/webapp-url");
|
|
14
|
+
const errors_1 = require("../core/errors");
|
|
14
15
|
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
15
16
|
/**
|
|
16
17
|
* Make authenticated API call
|
|
@@ -102,7 +103,7 @@ async function handleSubscribe() {
|
|
|
102
103
|
console.error('ā Authentication required');
|
|
103
104
|
console.log('\nš” Please login first:');
|
|
104
105
|
console.log(' prpm login');
|
|
105
|
-
|
|
106
|
+
throw new errors_1.CLIError('ā Authentication required', 1);
|
|
106
107
|
}
|
|
107
108
|
// Get current status
|
|
108
109
|
console.log('š Checking current subscription status...');
|
|
@@ -115,7 +116,7 @@ async function handleSubscribe() {
|
|
|
115
116
|
console.log(` š Early access to new features`);
|
|
116
117
|
console.log('\nš” Manage your subscription at:');
|
|
117
118
|
console.log(' https://prpm.dev/settings/billing');
|
|
118
|
-
|
|
119
|
+
return;
|
|
119
120
|
}
|
|
120
121
|
console.log('\n⨠Subscribe to PRPM+ and get:');
|
|
121
122
|
console.log(' š° 100 monthly playground credits');
|
|
@@ -154,7 +155,7 @@ async function handleSubscribe() {
|
|
|
154
155
|
catch (err) {
|
|
155
156
|
error = err instanceof Error ? err.message : String(err);
|
|
156
157
|
console.error(`\nā Subscription failed: ${error}`);
|
|
157
|
-
|
|
158
|
+
throw new errors_1.CLIError(`\nā Subscription failed: ${error}`, 1);
|
|
158
159
|
}
|
|
159
160
|
finally {
|
|
160
161
|
await telemetry_1.telemetry.track({
|
|
@@ -205,7 +206,6 @@ Note: You can cancel anytime from https://prpm.dev/settings/billing
|
|
|
205
206
|
`)
|
|
206
207
|
.action(async () => {
|
|
207
208
|
await handleSubscribe();
|
|
208
|
-
process.exit(0);
|
|
209
209
|
});
|
|
210
210
|
return command;
|
|
211
211
|
}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.createTelemetryCommand = createTelemetryCommand;
|
|
4
4
|
const commander_1 = require("commander");
|
|
5
5
|
const telemetry_1 = require("../core/telemetry");
|
|
6
|
+
const errors_1 = require("../core/errors");
|
|
6
7
|
function createTelemetryCommand() {
|
|
7
8
|
return new commander_1.Command('telemetry')
|
|
8
9
|
.description('Manage telemetry and analytics settings')
|
|
@@ -16,7 +17,7 @@ function createStatusCommand() {
|
|
|
16
17
|
return new commander_1.Command('status')
|
|
17
18
|
.description('Show current telemetry status')
|
|
18
19
|
.action(async () => {
|
|
19
|
-
const enabled = telemetry_1.telemetry.isEnabled();
|
|
20
|
+
const enabled = await telemetry_1.telemetry.isEnabled();
|
|
20
21
|
const stats = await telemetry_1.telemetry.getStats();
|
|
21
22
|
console.log('š Telemetry Status:');
|
|
22
23
|
console.log(` Status: ${enabled ? 'ā
Enabled' : 'ā Disabled'}`);
|
|
@@ -33,7 +34,6 @@ function createStatusCommand() {
|
|
|
33
34
|
else {
|
|
34
35
|
console.log('\nš” Telemetry is disabled. Run "prpm telemetry enable" to help improve the tool.');
|
|
35
36
|
}
|
|
36
|
-
process.exit(0);
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
39
|
function createEnableCommand() {
|
|
@@ -43,7 +43,6 @@ function createEnableCommand() {
|
|
|
43
43
|
await telemetry_1.telemetry.enable();
|
|
44
44
|
console.log('ā
Telemetry enabled');
|
|
45
45
|
console.log('š Anonymous usage data will be collected to help improve the tool.');
|
|
46
|
-
process.exit(0);
|
|
47
46
|
});
|
|
48
47
|
}
|
|
49
48
|
function createDisableCommand() {
|
|
@@ -53,7 +52,6 @@ function createDisableCommand() {
|
|
|
53
52
|
await telemetry_1.telemetry.disable();
|
|
54
53
|
console.log('ā Telemetry disabled');
|
|
55
54
|
console.log('š No usage data will be collected.');
|
|
56
|
-
process.exit(0);
|
|
57
55
|
});
|
|
58
56
|
}
|
|
59
57
|
function createStatsCommand() {
|
|
@@ -66,7 +64,6 @@ function createStatsCommand() {
|
|
|
66
64
|
if (stats.lastEvent) {
|
|
67
65
|
console.log(` Last event: ${stats.lastEvent}`);
|
|
68
66
|
}
|
|
69
|
-
process.exit(0);
|
|
70
67
|
});
|
|
71
68
|
}
|
|
72
69
|
function createTestCommand() {
|
|
@@ -101,9 +98,7 @@ function createTestCommand() {
|
|
|
101
98
|
console.log('4. Events may take 1-2 minutes to appear');
|
|
102
99
|
}
|
|
103
100
|
catch (error) {
|
|
104
|
-
|
|
105
|
-
process.exit(1);
|
|
101
|
+
throw new errors_1.CLIError(`ā Failed to send test event: ${error}`, 1);
|
|
106
102
|
}
|
|
107
|
-
process.exit(0);
|
|
108
103
|
});
|
|
109
104
|
}
|
|
@@ -9,6 +9,7 @@ const commander_1 = require("commander");
|
|
|
9
9
|
const registry_client_1 = require("@pr-pm/registry-client");
|
|
10
10
|
const user_config_1 = require("../core/user-config");
|
|
11
11
|
const telemetry_1 = require("../core/telemetry");
|
|
12
|
+
const errors_1 = require("../core/errors");
|
|
12
13
|
async function handleTrending(options) {
|
|
13
14
|
const startTime = Date.now();
|
|
14
15
|
let success = false;
|
|
@@ -41,7 +42,7 @@ async function handleTrending(options) {
|
|
|
41
42
|
error = err instanceof Error ? err.message : String(err);
|
|
42
43
|
console.error(`\nā Failed to fetch trending packages: ${error}`);
|
|
43
44
|
console.log(`\nš” Tip: Check your internet connection`);
|
|
44
|
-
|
|
45
|
+
throw new errors_1.CLIError(`\nā Failed to fetch trending packages: ${error}`, 1);
|
|
45
46
|
}
|
|
46
47
|
finally {
|
|
47
48
|
await telemetry_1.telemetry.track({
|
|
@@ -73,14 +74,13 @@ function createTrendingCommand() {
|
|
|
73
74
|
const validSubtypes = ['rule', 'agent', 'skill', 'slash-command', 'prompt', 'workflow', 'tool', 'template', 'collection'];
|
|
74
75
|
if (options.format && !validFormats.includes(format)) {
|
|
75
76
|
console.error(`ā Format must be one of: ${validFormats.join(', ')}`);
|
|
76
|
-
|
|
77
|
+
throw new errors_1.CLIError(`ā Format must be one of: ${validFormats.join(', ')}`, 1);
|
|
77
78
|
}
|
|
78
79
|
if (options.subtype && !validSubtypes.includes(subtype)) {
|
|
79
80
|
console.error(`ā Subtype must be one of: ${validSubtypes.join(', ')}`);
|
|
80
|
-
|
|
81
|
+
throw new errors_1.CLIError(`ā Subtype must be one of: ${validSubtypes.join(', ')}`, 1);
|
|
81
82
|
}
|
|
82
83
|
await handleTrending({ format, subtype, limit });
|
|
83
|
-
process.exit(0);
|
|
84
84
|
});
|
|
85
85
|
return command;
|
|
86
86
|
}
|
|
@@ -9,6 +9,7 @@ const commander_1 = require("commander");
|
|
|
9
9
|
const lockfile_1 = require("../core/lockfile");
|
|
10
10
|
const filesystem_1 = require("../core/filesystem");
|
|
11
11
|
const fs_1 = require("fs");
|
|
12
|
+
const errors_1 = require("../core/errors");
|
|
12
13
|
/**
|
|
13
14
|
* Handle the uninstall command
|
|
14
15
|
*/
|
|
@@ -18,8 +19,7 @@ async function handleUninstall(name) {
|
|
|
18
19
|
// Remove from lockfile and get package info
|
|
19
20
|
const pkg = await (0, lockfile_1.removePackage)(name);
|
|
20
21
|
if (!pkg) {
|
|
21
|
-
|
|
22
|
-
process.exit(1);
|
|
22
|
+
throw new errors_1.CLIError(`ā Package "${name}" not found`, 1);
|
|
23
23
|
}
|
|
24
24
|
// Get destination directory using format and subtype
|
|
25
25
|
const format = pkg.format || 'generic';
|
|
@@ -75,11 +75,12 @@ async function handleUninstall(name) {
|
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
console.log(`ā
Successfully uninstalled ${name}`);
|
|
78
|
-
process.exit(0);
|
|
79
78
|
}
|
|
80
79
|
catch (error) {
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
if (error instanceof errors_1.CLIError) {
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
throw new errors_1.CLIError(`ā Failed to uninstall package: ${error}`, 1);
|
|
83
84
|
}
|
|
84
85
|
}
|
|
85
86
|
/**
|
package/dist/commands/update.js
CHANGED
|
@@ -11,6 +11,7 @@ const user_config_1 = require("../core/user-config");
|
|
|
11
11
|
const lockfile_1 = require("../core/lockfile");
|
|
12
12
|
const install_1 = require("./install");
|
|
13
13
|
const telemetry_1 = require("../core/telemetry");
|
|
14
|
+
const errors_1 = require("../core/errors");
|
|
14
15
|
/**
|
|
15
16
|
* Update packages to latest minor/patch versions
|
|
16
17
|
*/
|
|
@@ -76,8 +77,7 @@ async function handleUpdate(packageName, options = {}) {
|
|
|
76
77
|
}
|
|
77
78
|
catch (err) {
|
|
78
79
|
error = err instanceof Error ? err.message : String(err);
|
|
79
|
-
|
|
80
|
-
process.exit(1);
|
|
80
|
+
throw new errors_1.CLIError(`\nā Update failed: ${error}`, 1);
|
|
81
81
|
}
|
|
82
82
|
finally {
|
|
83
83
|
await telemetry_1.telemetry.track({
|
|
@@ -117,6 +117,5 @@ function createUpdateCommand() {
|
|
|
117
117
|
.option('--all', 'Update all packages')
|
|
118
118
|
.action(async (packageName, options) => {
|
|
119
119
|
await handleUpdate(packageName, options);
|
|
120
|
-
process.exit(0);
|
|
121
120
|
});
|
|
122
121
|
}
|
package/dist/commands/upgrade.js
CHANGED
|
@@ -11,6 +11,7 @@ const user_config_1 = require("../core/user-config");
|
|
|
11
11
|
const lockfile_1 = require("../core/lockfile");
|
|
12
12
|
const install_1 = require("./install");
|
|
13
13
|
const telemetry_1 = require("../core/telemetry");
|
|
14
|
+
const errors_1 = require("../core/errors");
|
|
14
15
|
/**
|
|
15
16
|
* Upgrade packages to latest versions (including major updates)
|
|
16
17
|
*/
|
|
@@ -75,8 +76,7 @@ async function handleUpgrade(packageName, options = {}) {
|
|
|
75
76
|
}
|
|
76
77
|
catch (err) {
|
|
77
78
|
error = err instanceof Error ? err.message : String(err);
|
|
78
|
-
|
|
79
|
-
process.exit(1);
|
|
79
|
+
throw new errors_1.CLIError(`\nā Upgrade failed: ${error}`, 1);
|
|
80
80
|
}
|
|
81
81
|
finally {
|
|
82
82
|
await telemetry_1.telemetry.track({
|
|
@@ -117,6 +117,5 @@ function createUpgradeCommand() {
|
|
|
117
117
|
.option('--force', 'Skip warning for major version upgrades')
|
|
118
118
|
.action(async (packageName, options) => {
|
|
119
119
|
await handleUpgrade(packageName, options);
|
|
120
|
-
process.exit(0);
|
|
121
120
|
});
|
|
122
121
|
}
|
package/dist/commands/whoami.js
CHANGED
|
@@ -9,6 +9,7 @@ const commander_1 = require("commander");
|
|
|
9
9
|
const user_config_1 = require("../core/user-config");
|
|
10
10
|
const registry_client_1 = require("@pr-pm/registry-client");
|
|
11
11
|
const telemetry_1 = require("../core/telemetry");
|
|
12
|
+
const errors_1 = require("../core/errors");
|
|
12
13
|
/**
|
|
13
14
|
* Show current logged-in user
|
|
14
15
|
*/
|
|
@@ -57,8 +58,7 @@ async function handleWhoami() {
|
|
|
57
58
|
}
|
|
58
59
|
catch (err) {
|
|
59
60
|
error = err instanceof Error ? err.message : String(err);
|
|
60
|
-
|
|
61
|
-
process.exit(1);
|
|
61
|
+
throw new errors_1.CLIError(`ā Error: ${error}`, 1);
|
|
62
62
|
}
|
|
63
63
|
finally {
|
|
64
64
|
// Track telemetry
|
|
@@ -79,6 +79,5 @@ function createWhoamiCommand() {
|
|
|
79
79
|
.description('Show current logged-in user')
|
|
80
80
|
.action(async () => {
|
|
81
81
|
await handleWhoami();
|
|
82
|
-
process.exit(0);
|
|
83
82
|
});
|
|
84
83
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CLIError = void 0;
|
|
4
|
+
exports.createError = createError;
|
|
5
|
+
exports.createSuccess = createSuccess;
|
|
6
|
+
/**
|
|
7
|
+
* Custom error class for CLI commands
|
|
8
|
+
* Allows commands to throw errors with exit codes instead of calling process.exit()
|
|
9
|
+
*/
|
|
10
|
+
class CLIError extends Error {
|
|
11
|
+
constructor(message, exitCode = 1) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.name = 'CLIError';
|
|
14
|
+
this.exitCode = exitCode;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.CLIError = CLIError;
|
|
18
|
+
/**
|
|
19
|
+
* Creates a CLIError with exit code 1 (general error)
|
|
20
|
+
*/
|
|
21
|
+
function createError(message) {
|
|
22
|
+
return new CLIError(message, 1);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Creates a CLIError with exit code 0 (success, used for early termination)
|
|
26
|
+
*/
|
|
27
|
+
function createSuccess(message) {
|
|
28
|
+
return new CLIError(message || '', 0);
|
|
29
|
+
}
|
package/dist/core/telemetry.js
CHANGED
|
@@ -8,16 +8,38 @@ const fs_1 = require("fs");
|
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
const os_1 = __importDefault(require("os"));
|
|
10
10
|
const posthog_node_1 = require("posthog-node");
|
|
11
|
+
const user_config_1 = require("./user-config");
|
|
11
12
|
class Telemetry {
|
|
12
13
|
constructor() {
|
|
13
14
|
this.events = [];
|
|
14
15
|
this.maxEvents = 100; // Keep only last 100 events locally
|
|
15
16
|
this.posthog = null;
|
|
17
|
+
this.userConfigChecked = false;
|
|
18
|
+
this.userTelemetryEnabled = true; // Default to true until checked
|
|
16
19
|
this.configPath = path_1.default.join(os_1.default.homedir(), '.prpm', 'telemetry.json');
|
|
17
20
|
this.config = this.loadConfig();
|
|
18
|
-
this.initializePostHog();
|
|
19
21
|
}
|
|
20
|
-
|
|
22
|
+
async checkUserConfig() {
|
|
23
|
+
if (this.userConfigChecked)
|
|
24
|
+
return;
|
|
25
|
+
try {
|
|
26
|
+
const userConfig = await (0, user_config_1.getConfig)();
|
|
27
|
+
this.userTelemetryEnabled = userConfig.telemetryEnabled ?? true;
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
// If we can't load user config, default to enabled
|
|
31
|
+
this.userTelemetryEnabled = true;
|
|
32
|
+
}
|
|
33
|
+
this.userConfigChecked = true;
|
|
34
|
+
}
|
|
35
|
+
async initializePostHog() {
|
|
36
|
+
// Check user config first
|
|
37
|
+
await this.checkUserConfig();
|
|
38
|
+
// Only initialize if telemetry is enabled in user config
|
|
39
|
+
if (!this.userTelemetryEnabled) {
|
|
40
|
+
this.posthog = null;
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
21
43
|
try {
|
|
22
44
|
this.posthog = new posthog_node_1.PostHog('phc_aO5lXLILeylHfb1ynszVwKbQKSzO91UGdXNhN5Q0Snl', {
|
|
23
45
|
host: 'https://app.posthog.com',
|
|
@@ -59,6 +81,11 @@ class Telemetry {
|
|
|
59
81
|
}
|
|
60
82
|
}
|
|
61
83
|
async track(event) {
|
|
84
|
+
// Check user config first
|
|
85
|
+
await this.checkUserConfig();
|
|
86
|
+
// Return early if telemetry is disabled in user config
|
|
87
|
+
if (!this.userTelemetryEnabled)
|
|
88
|
+
return;
|
|
62
89
|
if (!this.config.enabled)
|
|
63
90
|
return;
|
|
64
91
|
const fullEvent = {
|
|
@@ -92,6 +119,10 @@ class Telemetry {
|
|
|
92
119
|
}
|
|
93
120
|
}
|
|
94
121
|
async sendToAnalytics(event) {
|
|
122
|
+
// Initialize PostHog if needed (this will check user config)
|
|
123
|
+
if (!this.posthog && this.userTelemetryEnabled) {
|
|
124
|
+
await this.initializePostHog();
|
|
125
|
+
}
|
|
95
126
|
// Send to PostHog
|
|
96
127
|
await this.sendToPostHog(event);
|
|
97
128
|
}
|
|
@@ -103,8 +134,9 @@ class Telemetry {
|
|
|
103
134
|
this.config.enabled = false;
|
|
104
135
|
await this.saveConfig();
|
|
105
136
|
}
|
|
106
|
-
isEnabled() {
|
|
107
|
-
|
|
137
|
+
async isEnabled() {
|
|
138
|
+
await this.checkUserConfig();
|
|
139
|
+
return this.userTelemetryEnabled && this.config.enabled;
|
|
108
140
|
}
|
|
109
141
|
async getStats() {
|
|
110
142
|
try {
|
package/dist/index.js
CHANGED
|
@@ -32,6 +32,7 @@ const credits_1 = require("./commands/credits");
|
|
|
32
32
|
const subscribe_1 = require("./commands/subscribe");
|
|
33
33
|
const buy_credits_1 = require("./commands/buy-credits");
|
|
34
34
|
const telemetry_2 = require("./core/telemetry");
|
|
35
|
+
const errors_1 = require("./core/errors");
|
|
35
36
|
// Read version from package.json
|
|
36
37
|
function getVersion() {
|
|
37
38
|
try {
|
|
@@ -77,8 +78,28 @@ program.addCommand((0, buy_credits_1.createBuyCreditsCommand)());
|
|
|
77
78
|
// Utility commands
|
|
78
79
|
program.addCommand((0, schema_1.createSchemaCommand)());
|
|
79
80
|
program.addCommand((0, config_1.createConfigCommand)());
|
|
80
|
-
// Parse command line arguments
|
|
81
|
-
|
|
81
|
+
// Parse command line arguments with error handling
|
|
82
|
+
(async () => {
|
|
83
|
+
try {
|
|
84
|
+
await program.parseAsync();
|
|
85
|
+
// Command completed successfully - let Node.js exit naturally
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
if (error instanceof errors_1.CLIError) {
|
|
89
|
+
// Print error message if present
|
|
90
|
+
if (error.message) {
|
|
91
|
+
console.error(error.message);
|
|
92
|
+
}
|
|
93
|
+
// Exit with the error's exit code
|
|
94
|
+
process.exit(error.exitCode);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
// Unexpected error - print and exit with code 1
|
|
98
|
+
console.error('Unexpected error:', error);
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
})();
|
|
82
103
|
// Cleanup telemetry on exit
|
|
83
104
|
process.on('exit', () => {
|
|
84
105
|
telemetry_2.telemetry.shutdown().catch(() => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prpm",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"description": "Prompt Package Manager CLI - Install and manage prompt-based files",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
"license": "MIT",
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@octokit/rest": "^22.0.0",
|
|
48
|
-
"@pr-pm/registry-client": "^1.3.
|
|
49
|
-
"@pr-pm/types": "^0.2.
|
|
48
|
+
"@pr-pm/registry-client": "^1.3.9",
|
|
49
|
+
"@pr-pm/types": "^0.2.10",
|
|
50
50
|
"ajv": "^8.17.1",
|
|
51
51
|
"ajv-formats": "^3.0.1",
|
|
52
52
|
"commander": "^11.1.0",
|