prpm 0.2.0 → 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.
- package/dist/index.js +14257 -109
- package/package.json +11 -9
- package/dist/__tests__/e2e/test-helpers.js +0 -153
- package/dist/commands/buy-credits.js +0 -224
- package/dist/commands/catalog.js +0 -365
- package/dist/commands/collections.js +0 -655
- package/dist/commands/config.js +0 -161
- package/dist/commands/credits.js +0 -186
- package/dist/commands/index.js +0 -184
- package/dist/commands/info.js +0 -78
- package/dist/commands/init.js +0 -684
- package/dist/commands/install.js +0 -829
- package/dist/commands/list.js +0 -198
- package/dist/commands/login.js +0 -316
- package/dist/commands/outdated.js +0 -130
- package/dist/commands/playground.js +0 -637
- package/dist/commands/popular.js +0 -33
- package/dist/commands/publish.js +0 -803
- package/dist/commands/schema.js +0 -41
- package/dist/commands/search.js +0 -446
- package/dist/commands/starred.js +0 -147
- package/dist/commands/subscribe.js +0 -211
- package/dist/commands/telemetry.js +0 -104
- package/dist/commands/trending.js +0 -86
- package/dist/commands/uninstall.js +0 -120
- package/dist/commands/update.js +0 -121
- package/dist/commands/upgrade.js +0 -121
- package/dist/commands/whoami.js +0 -83
- package/dist/core/claude-config.js +0 -91
- package/dist/core/cursor-config.js +0 -130
- package/dist/core/downloader.js +0 -64
- package/dist/core/errors.js +0 -29
- package/dist/core/filesystem.js +0 -246
- package/dist/core/lockfile.js +0 -292
- package/dist/core/marketplace-converter.js +0 -224
- package/dist/core/prompts.js +0 -62
- package/dist/core/registry-client.js +0 -305
- package/dist/core/schema-validator.js +0 -74
- package/dist/core/telemetry.js +0 -253
- package/dist/core/user-config.js +0 -147
- package/dist/types/registry.js +0 -12
- package/dist/types.js +0 -9
- package/dist/utils/license-extractor.js +0 -122
- package/dist/utils/multi-package.js +0 -117
- package/dist/utils/parallel-publisher.js +0 -144
- package/dist/utils/script-executor.js +0 -72
- package/dist/utils/snippet-extractor.js +0 -77
- package/dist/utils/webapp-url.js +0 -44
package/dist/commands/schema.js
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Schema command - Export and display JSON schema
|
|
4
|
-
*/
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.handleSchema = handleSchema;
|
|
7
|
-
exports.createSchemaCommand = createSchemaCommand;
|
|
8
|
-
const commander_1 = require("commander");
|
|
9
|
-
const schema_validator_1 = require("../core/schema-validator");
|
|
10
|
-
const errors_1 = require("../core/errors");
|
|
11
|
-
/**
|
|
12
|
-
* Handle the schema command
|
|
13
|
-
*/
|
|
14
|
-
async function handleSchema() {
|
|
15
|
-
try {
|
|
16
|
-
const schema = (0, schema_validator_1.getManifestSchema)();
|
|
17
|
-
if (!schema) {
|
|
18
|
-
throw new errors_1.CLIError('❌ Schema not available', 1);
|
|
19
|
-
}
|
|
20
|
-
// Output the schema as pretty-printed JSON
|
|
21
|
-
console.log(JSON.stringify(schema, null, 2));
|
|
22
|
-
}
|
|
23
|
-
catch (error) {
|
|
24
|
-
if (error instanceof errors_1.CLIError) {
|
|
25
|
-
throw error;
|
|
26
|
-
}
|
|
27
|
-
throw new errors_1.CLIError(`❌ Failed to export schema: ${error}`, 1);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Create the schema command
|
|
32
|
-
*/
|
|
33
|
-
function createSchemaCommand() {
|
|
34
|
-
const command = new commander_1.Command('schema');
|
|
35
|
-
command
|
|
36
|
-
.description('Display the PRPM manifest JSON schema')
|
|
37
|
-
.action(async () => {
|
|
38
|
-
await handleSchema();
|
|
39
|
-
});
|
|
40
|
-
return command;
|
|
41
|
-
}
|
package/dist/commands/search.js
DELETED
|
@@ -1,446 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Search command - Search for packages in the registry
|
|
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.handleSearch = handleSearch;
|
|
40
|
-
exports.createSearchCommand = createSearchCommand;
|
|
41
|
-
const commander_1 = require("commander");
|
|
42
|
-
const registry_client_1 = require("@pr-pm/registry-client");
|
|
43
|
-
const user_config_1 = require("../core/user-config");
|
|
44
|
-
const telemetry_1 = require("../core/telemetry");
|
|
45
|
-
const readline = __importStar(require("readline"));
|
|
46
|
-
const errors_1 = require("../core/errors");
|
|
47
|
-
/**
|
|
48
|
-
* Get icon for package format and subtype
|
|
49
|
-
*/
|
|
50
|
-
function getPackageIcon(format, subtype) {
|
|
51
|
-
// Subtype icons take precedence
|
|
52
|
-
const subtypeIcons = {
|
|
53
|
-
'skill': '🎓',
|
|
54
|
-
'agent': '🤖',
|
|
55
|
-
'slash-command': '⚡',
|
|
56
|
-
'rule': '📋',
|
|
57
|
-
'prompt': '💬',
|
|
58
|
-
'collection': '📦',
|
|
59
|
-
'chatmode': '💬',
|
|
60
|
-
'tool': '🔧',
|
|
61
|
-
'hook': '🪝',
|
|
62
|
-
};
|
|
63
|
-
// Format-specific icons for rules/defaults
|
|
64
|
-
const formatIcons = {
|
|
65
|
-
'claude': '🤖',
|
|
66
|
-
'cursor': '📋',
|
|
67
|
-
'windsurf': '🌊',
|
|
68
|
-
'continue': '➡️',
|
|
69
|
-
'copilot': '✈️',
|
|
70
|
-
'kiro': '🎯',
|
|
71
|
-
'mcp': '🔗',
|
|
72
|
-
'agents.md': '📝',
|
|
73
|
-
'generic': '📦',
|
|
74
|
-
};
|
|
75
|
-
return subtypeIcons[subtype] || formatIcons[format] || '📦';
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Get human-readable label for package format and subtype
|
|
79
|
-
*/
|
|
80
|
-
function getPackageLabel(format, subtype) {
|
|
81
|
-
const formatLabels = {
|
|
82
|
-
'claude': 'Claude',
|
|
83
|
-
'cursor': 'Cursor',
|
|
84
|
-
'windsurf': 'Windsurf',
|
|
85
|
-
'continue': 'Continue',
|
|
86
|
-
'copilot': 'GitHub Copilot',
|
|
87
|
-
'kiro': 'Kiro',
|
|
88
|
-
'mcp': 'MCP',
|
|
89
|
-
'agents.md': 'Agents.md',
|
|
90
|
-
'generic': '',
|
|
91
|
-
};
|
|
92
|
-
const subtypeLabels = {
|
|
93
|
-
'skill': 'Skill',
|
|
94
|
-
'agent': 'Agent',
|
|
95
|
-
'slash-command': 'Slash Command',
|
|
96
|
-
'rule': 'Rule',
|
|
97
|
-
'prompt': 'Prompt',
|
|
98
|
-
'collection': 'Collection',
|
|
99
|
-
'chatmode': 'Chat Mode',
|
|
100
|
-
'tool': 'Tool',
|
|
101
|
-
'hook': 'Hook',
|
|
102
|
-
};
|
|
103
|
-
const formatLabel = formatLabels[format];
|
|
104
|
-
const subtypeLabel = subtypeLabels[subtype];
|
|
105
|
-
if (format === 'generic') {
|
|
106
|
-
return subtypeLabel;
|
|
107
|
-
}
|
|
108
|
-
return `${formatLabel} ${subtypeLabel}`;
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Map subtype filters for search
|
|
112
|
-
*/
|
|
113
|
-
function buildSearchFilters(options) {
|
|
114
|
-
const searchOptions = {};
|
|
115
|
-
if (options.format) {
|
|
116
|
-
searchOptions.format = options.format;
|
|
117
|
-
}
|
|
118
|
-
if (options.subtype) {
|
|
119
|
-
searchOptions.subtype = options.subtype;
|
|
120
|
-
}
|
|
121
|
-
if (options.author) {
|
|
122
|
-
searchOptions.author = options.author;
|
|
123
|
-
}
|
|
124
|
-
return searchOptions;
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Build webapp URL for search results
|
|
128
|
-
*/
|
|
129
|
-
function buildWebappUrl(query, options, page = 1) {
|
|
130
|
-
const baseUrl = process.env.PRPM_WEBAPP_URL || 'https://prpm.dev';
|
|
131
|
-
const params = new URLSearchParams();
|
|
132
|
-
if (query)
|
|
133
|
-
params.append('q', query);
|
|
134
|
-
if (options.format)
|
|
135
|
-
params.append('format', options.format);
|
|
136
|
-
if (options.subtype)
|
|
137
|
-
params.append('subtype', options.subtype);
|
|
138
|
-
if (options.author)
|
|
139
|
-
params.append('author', options.author);
|
|
140
|
-
if (options.language)
|
|
141
|
-
params.append('language', options.language);
|
|
142
|
-
if (options.framework)
|
|
143
|
-
params.append('framework', options.framework);
|
|
144
|
-
if (page > 1)
|
|
145
|
-
params.append('page', page.toString());
|
|
146
|
-
return `${baseUrl}/search?${params.toString()}`;
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Display search results
|
|
150
|
-
*/
|
|
151
|
-
function displayResults(packages, total, page, limit) {
|
|
152
|
-
const startIdx = (page - 1) * limit + 1;
|
|
153
|
-
const endIdx = Math.min(page * limit, total);
|
|
154
|
-
console.log('\n' + '─'.repeat(80));
|
|
155
|
-
console.log(`📦 Results ${startIdx}-${endIdx} of ${total}`.padEnd(80));
|
|
156
|
-
console.log('─'.repeat(80) + '\n');
|
|
157
|
-
packages.forEach((pkg, idx) => {
|
|
158
|
-
const num = startIdx + idx;
|
|
159
|
-
const rating = pkg.rating_average ? `⭐ ${pkg.rating_average.toFixed(1)}` : '';
|
|
160
|
-
const downloads = pkg.total_downloads >= 1000
|
|
161
|
-
? `${(pkg.total_downloads / 1000).toFixed(1)}k`
|
|
162
|
-
: pkg.total_downloads;
|
|
163
|
-
const typeIcon = getPackageIcon(pkg.format, pkg.subtype);
|
|
164
|
-
const typeLabel = getPackageLabel(pkg.format, pkg.subtype);
|
|
165
|
-
// Add verified badge
|
|
166
|
-
let verifiedBadge = '';
|
|
167
|
-
if (pkg.featured || pkg.official || pkg.verified) {
|
|
168
|
-
verifiedBadge = ' | ✅ Verified';
|
|
169
|
-
}
|
|
170
|
-
console.log(`\x1b[1m${num}. ${pkg.name}\x1b[0m ${rating}`);
|
|
171
|
-
console.log(` ${pkg.description || 'No description'}`);
|
|
172
|
-
console.log(` ${typeIcon} ${typeLabel} | 📥 ${downloads} downloads | 🏷️ ${pkg.tags.slice(0, 3).join(', ')}${verifiedBadge}`);
|
|
173
|
-
console.log();
|
|
174
|
-
});
|
|
175
|
-
console.log('─'.repeat(80));
|
|
176
|
-
}
|
|
177
|
-
/**
|
|
178
|
-
* Prompt user for pagination action
|
|
179
|
-
*/
|
|
180
|
-
function promptUser() {
|
|
181
|
-
return new Promise((resolve) => {
|
|
182
|
-
const rl = readline.createInterface({
|
|
183
|
-
input: process.stdin,
|
|
184
|
-
output: process.stdout,
|
|
185
|
-
});
|
|
186
|
-
rl.question('', (answer) => {
|
|
187
|
-
rl.close();
|
|
188
|
-
resolve(answer.trim().toLowerCase());
|
|
189
|
-
});
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* Interactive pagination handler
|
|
194
|
-
*/
|
|
195
|
-
async function handlePagination(query, options, client, searchOptions, initialResult, webappBaseUrl) {
|
|
196
|
-
let currentPage = 1;
|
|
197
|
-
let result = initialResult;
|
|
198
|
-
const totalPages = Math.ceil(result.total / options.limit);
|
|
199
|
-
while (true) {
|
|
200
|
-
// Display current page
|
|
201
|
-
displayResults(result.packages, result.total, currentPage, options.limit);
|
|
202
|
-
// Show navigation options
|
|
203
|
-
console.log('\n💡 \x1b[1mOptions:\x1b[0m');
|
|
204
|
-
if (currentPage < totalPages) {
|
|
205
|
-
console.log(' \x1b[36mn\x1b[0m - Next page');
|
|
206
|
-
}
|
|
207
|
-
if (currentPage > 1) {
|
|
208
|
-
console.log(' \x1b[36mp\x1b[0m - Previous page');
|
|
209
|
-
}
|
|
210
|
-
console.log(' \x1b[36m1-' + result.packages.length + '\x1b[0m - Install package by number');
|
|
211
|
-
console.log(' \x1b[36mw\x1b[0m - View in web browser');
|
|
212
|
-
console.log(' \x1b[36mq\x1b[0m - Quit');
|
|
213
|
-
// Show webapp link
|
|
214
|
-
const webappUrl = buildWebappUrl(query, options, currentPage);
|
|
215
|
-
console.log(`\n🌐 \x1b[2mView in browser: ${webappUrl}\x1b[0m`);
|
|
216
|
-
process.stdout.write('\n👉 ');
|
|
217
|
-
const input = await promptUser();
|
|
218
|
-
if (input === 'q' || input === 'quit' || input === 'exit') {
|
|
219
|
-
console.log('\n✨ Happy coding!\n');
|
|
220
|
-
break;
|
|
221
|
-
}
|
|
222
|
-
if (input === 'n' || input === 'next') {
|
|
223
|
-
if (currentPage < totalPages) {
|
|
224
|
-
currentPage++;
|
|
225
|
-
const offset = (currentPage - 1) * options.limit;
|
|
226
|
-
result = await client.search(query || '', { ...searchOptions, offset });
|
|
227
|
-
console.clear();
|
|
228
|
-
}
|
|
229
|
-
else {
|
|
230
|
-
console.log('\n❌ Already on last page');
|
|
231
|
-
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
232
|
-
console.clear();
|
|
233
|
-
}
|
|
234
|
-
continue;
|
|
235
|
-
}
|
|
236
|
-
if (input === 'p' || input === 'prev' || input === 'previous') {
|
|
237
|
-
if (currentPage > 1) {
|
|
238
|
-
currentPage--;
|
|
239
|
-
const offset = (currentPage - 1) * options.limit;
|
|
240
|
-
result = await client.search(query || '', { ...searchOptions, offset });
|
|
241
|
-
console.clear();
|
|
242
|
-
}
|
|
243
|
-
else {
|
|
244
|
-
console.log('\n❌ Already on first page');
|
|
245
|
-
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
246
|
-
console.clear();
|
|
247
|
-
}
|
|
248
|
-
continue;
|
|
249
|
-
}
|
|
250
|
-
if (input === 'w' || input === 'web' || input === 'browser') {
|
|
251
|
-
const url = buildWebappUrl(query, options, currentPage);
|
|
252
|
-
console.log(`\n🌐 Opening: ${url}`);
|
|
253
|
-
console.log(' (Copy and paste this URL into your browser)\n');
|
|
254
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
255
|
-
console.clear();
|
|
256
|
-
continue;
|
|
257
|
-
}
|
|
258
|
-
// Check if input is a number for installation
|
|
259
|
-
const num = parseInt(input, 10);
|
|
260
|
-
if (!isNaN(num) && num >= 1 && num <= result.packages.length) {
|
|
261
|
-
const pkg = result.packages[num - 1];
|
|
262
|
-
console.log(`\n📦 To install: \x1b[36mprpm install ${pkg.name}\x1b[0m`);
|
|
263
|
-
console.log(` More info: \x1b[36mprpm info ${pkg.name}\x1b[0m\n`);
|
|
264
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
265
|
-
console.clear();
|
|
266
|
-
continue;
|
|
267
|
-
}
|
|
268
|
-
console.log('\n❌ Invalid option. Try again.');
|
|
269
|
-
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
270
|
-
console.clear();
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
async function handleSearch(query, options) {
|
|
274
|
-
const startTime = Date.now();
|
|
275
|
-
let success = false;
|
|
276
|
-
let error;
|
|
277
|
-
let result = null;
|
|
278
|
-
let registryUrl = '';
|
|
279
|
-
try {
|
|
280
|
-
// Allow empty query when filtering by format/subtype or author
|
|
281
|
-
if (query) {
|
|
282
|
-
console.log(`🔍 Searching for "${query}"...`);
|
|
283
|
-
}
|
|
284
|
-
else if (options.format || options.subtype) {
|
|
285
|
-
const filterType = options.subtype || options.format;
|
|
286
|
-
console.log(`🔍 Listing ${filterType} packages...`);
|
|
287
|
-
}
|
|
288
|
-
else if (options.author) {
|
|
289
|
-
console.log(`🔍 Listing packages by @${options.author}...`);
|
|
290
|
-
}
|
|
291
|
-
else {
|
|
292
|
-
console.log('❌ Please provide a search query or use --format/--subtype/--author to filter');
|
|
293
|
-
console.log('\n💡 Examples:');
|
|
294
|
-
console.log(' prpm search react');
|
|
295
|
-
console.log(' prpm search --subtype skill');
|
|
296
|
-
console.log(' prpm search --format claude');
|
|
297
|
-
console.log(' prpm search --author prpm');
|
|
298
|
-
console.log(' prpm search react --subtype rule');
|
|
299
|
-
return;
|
|
300
|
-
}
|
|
301
|
-
const config = await (0, user_config_1.getConfig)();
|
|
302
|
-
registryUrl = config.registryUrl || 'https://registry.prpm.dev';
|
|
303
|
-
const client = (0, registry_client_1.getRegistryClient)(config);
|
|
304
|
-
// Build search options
|
|
305
|
-
const limit = options.limit || 20;
|
|
306
|
-
const page = options.page || 1;
|
|
307
|
-
const offset = (page - 1) * limit;
|
|
308
|
-
const searchOptions = {
|
|
309
|
-
limit,
|
|
310
|
-
offset,
|
|
311
|
-
};
|
|
312
|
-
// Add format/subtype filters
|
|
313
|
-
if (options.format) {
|
|
314
|
-
searchOptions.format = options.format;
|
|
315
|
-
}
|
|
316
|
-
if (options.subtype) {
|
|
317
|
-
searchOptions.subtype = options.subtype;
|
|
318
|
-
}
|
|
319
|
-
if (options.author) {
|
|
320
|
-
searchOptions.author = options.author;
|
|
321
|
-
}
|
|
322
|
-
if (options.language) {
|
|
323
|
-
searchOptions.language = options.language;
|
|
324
|
-
}
|
|
325
|
-
if (options.framework) {
|
|
326
|
-
searchOptions.framework = options.framework;
|
|
327
|
-
}
|
|
328
|
-
result = await client.search(query || '', searchOptions);
|
|
329
|
-
if (!result || result.packages.length === 0) {
|
|
330
|
-
console.log('\n❌ No packages found');
|
|
331
|
-
console.log(`\nTry:`);
|
|
332
|
-
console.log(` - Broadening your search terms`);
|
|
333
|
-
console.log(` - Checking spelling`);
|
|
334
|
-
console.log(` - Browsing trending: prpm trending`);
|
|
335
|
-
// Suggest webapp even if no results
|
|
336
|
-
const webappUrl = buildWebappUrl(query, options);
|
|
337
|
-
console.log(`\n🌐 View in browser: ${webappUrl}`);
|
|
338
|
-
return;
|
|
339
|
-
}
|
|
340
|
-
// If interactive mode is disabled or only one page, show simple results
|
|
341
|
-
const totalPages = Math.ceil(result.total / limit);
|
|
342
|
-
const shouldPaginate = options.interactive !== false && totalPages > 1;
|
|
343
|
-
if (!shouldPaginate) {
|
|
344
|
-
displayResults(result.packages, result.total, page, limit);
|
|
345
|
-
console.log('\n💡 \x1b[1mQuick Actions:\x1b[0m');
|
|
346
|
-
console.log(' Install: \x1b[36mprpm install <package-id>\x1b[0m');
|
|
347
|
-
console.log(' More info: \x1b[36mprpm info <package-id>\x1b[0m');
|
|
348
|
-
if (totalPages > 1) {
|
|
349
|
-
console.log(`\n📄 \x1b[1mMore Results:\x1b[0m`);
|
|
350
|
-
console.log(` Page ${page} of ${totalPages}`);
|
|
351
|
-
if (page < totalPages) {
|
|
352
|
-
console.log(` Next page: \x1b[36mprpm search "${query}" --page ${page + 1}\x1b[0m`);
|
|
353
|
-
}
|
|
354
|
-
console.log(` Interactive mode: \x1b[36mprpm search "${query}" --interactive\x1b[0m`);
|
|
355
|
-
}
|
|
356
|
-
// Always show webapp link
|
|
357
|
-
const webappUrl = buildWebappUrl(query, options, page);
|
|
358
|
-
console.log(`\n🌐 \x1b[1mView in Browser:\x1b[0m`);
|
|
359
|
-
console.log(` ${webappUrl}`);
|
|
360
|
-
if (page < totalPages) {
|
|
361
|
-
const nextPageUrl = buildWebappUrl(query, options, page + 1);
|
|
362
|
-
console.log(` Next page: ${nextPageUrl}`);
|
|
363
|
-
}
|
|
364
|
-
console.log();
|
|
365
|
-
}
|
|
366
|
-
else {
|
|
367
|
-
// Interactive pagination mode
|
|
368
|
-
await handlePagination(query, { ...options, limit }, client, searchOptions, result, registryUrl);
|
|
369
|
-
}
|
|
370
|
-
success = true;
|
|
371
|
-
}
|
|
372
|
-
catch (err) {
|
|
373
|
-
error = err instanceof Error ? err.message : String(err);
|
|
374
|
-
console.error(`\n❌ Search failed: ${error}`);
|
|
375
|
-
console.log(` Registry: ${registryUrl}`);
|
|
376
|
-
// Provide helpful hint if using localhost
|
|
377
|
-
if (registryUrl.includes('localhost')) {
|
|
378
|
-
console.log(`\n💡 Tip: You're using a local registry. Make sure it's running or update ~/.prpmrc`);
|
|
379
|
-
console.log(` To use the production registry, remove the registryUrl from ~/.prpmrc`);
|
|
380
|
-
}
|
|
381
|
-
throw new errors_1.CLIError(`\n❌ Search failed: ${error}`, 1);
|
|
382
|
-
}
|
|
383
|
-
finally {
|
|
384
|
-
await telemetry_1.telemetry.track({
|
|
385
|
-
command: 'search',
|
|
386
|
-
success,
|
|
387
|
-
error,
|
|
388
|
-
duration: Date.now() - startTime,
|
|
389
|
-
data: {
|
|
390
|
-
query: query.substring(0, 100),
|
|
391
|
-
format: options.format,
|
|
392
|
-
subtype: options.subtype,
|
|
393
|
-
language: options.language,
|
|
394
|
-
framework: options.framework,
|
|
395
|
-
resultCount: success && result ? result.packages.length : 0,
|
|
396
|
-
page: options.page,
|
|
397
|
-
interactive: options.interactive,
|
|
398
|
-
},
|
|
399
|
-
});
|
|
400
|
-
// Ensure telemetry is flushed before exit
|
|
401
|
-
await telemetry_1.telemetry.shutdown();
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
function createSearchCommand() {
|
|
405
|
-
const command = new commander_1.Command('search');
|
|
406
|
-
command
|
|
407
|
-
.description('Search for packages in the registry')
|
|
408
|
-
.argument('[query]', 'Search query (optional when using --format/--subtype or --author)')
|
|
409
|
-
.option('--format <format>', 'Filter by package format (cursor, claude, continue, windsurf, copilot, kiro, agents.md, generic, mcp)')
|
|
410
|
-
.option('--subtype <subtype>', 'Filter by package subtype (rule, agent, skill, slash-command, prompt, workflow, tool, template, collection, chatmode, hook)')
|
|
411
|
-
.option('--author <username>', 'Filter by author username')
|
|
412
|
-
.option('--language <language>', 'Filter by programming language (javascript, typescript, python, etc.)')
|
|
413
|
-
.option('--framework <framework>', 'Filter by framework (react, nextjs, django, etc.)')
|
|
414
|
-
.option('--limit <number>', 'Number of results per page', '20')
|
|
415
|
-
.option('--page <number>', 'Page number (default: 1)', '1')
|
|
416
|
-
.option('--interactive', 'Enable interactive pagination (default: true for multiple pages)', true)
|
|
417
|
-
.option('--no-interactive', 'Disable interactive pagination')
|
|
418
|
-
.action(async (query, options) => {
|
|
419
|
-
const format = options.format;
|
|
420
|
-
const subtype = options.subtype;
|
|
421
|
-
const author = options.author;
|
|
422
|
-
const limit = options.limit ? parseInt(options.limit, 10) : 20;
|
|
423
|
-
const page = options.page ? parseInt(options.page, 10) : 1;
|
|
424
|
-
const validFormats = ['cursor', 'claude', 'continue', 'windsurf', 'copilot', 'kiro', 'agents.md', 'generic', 'mcp'];
|
|
425
|
-
const validSubtypes = ['rule', 'agent', 'skill', 'slash-command', 'prompt', 'collection', 'chatmode', 'tool', 'hook'];
|
|
426
|
-
if (options.format && !validFormats.includes(format)) {
|
|
427
|
-
console.error(`❌ Format must be one of: ${validFormats.join(', ')}`);
|
|
428
|
-
throw new errors_1.CLIError(`❌ Format must be one of: ${validFormats.join(', ')}`, 1);
|
|
429
|
-
}
|
|
430
|
-
if (options.subtype && !validSubtypes.includes(subtype)) {
|
|
431
|
-
console.error(`❌ Subtype must be one of: ${validSubtypes.join(', ')}`);
|
|
432
|
-
console.log(`\n💡 Examples:`);
|
|
433
|
-
console.log(` prpm search postgres --subtype skill`);
|
|
434
|
-
console.log(` prpm search debugging --subtype agent`);
|
|
435
|
-
console.log(` prpm search refactor --subtype slash-command`);
|
|
436
|
-
console.log(` prpm search react --subtype rule`);
|
|
437
|
-
console.log(` prpm search --subtype slash-command # List all slash commands`);
|
|
438
|
-
console.log(` prpm search --subtype skill # List all skills`);
|
|
439
|
-
console.log(` prpm search --format claude # List all Claude packages`);
|
|
440
|
-
console.log(` prpm search --author prpm # List packages by @prpm`);
|
|
441
|
-
throw new errors_1.CLIError(`❌ Subtype must be one of: ${validSubtypes.join(', ')}`, 1);
|
|
442
|
-
}
|
|
443
|
-
await handleSearch(query || '', { format, subtype, author, language: options.language, framework: options.framework, limit, page, interactive: options.interactive });
|
|
444
|
-
});
|
|
445
|
-
return command;
|
|
446
|
-
}
|
package/dist/commands/starred.js
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Starred command implementation - List user's starred packages and collections
|
|
4
|
-
*/
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.handleStarred = handleStarred;
|
|
7
|
-
exports.createStarredCommand = createStarredCommand;
|
|
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 telemetry_1 = require("../core/telemetry");
|
|
12
|
-
const errors_1 = require("../core/errors");
|
|
13
|
-
async function handleStarred(options) {
|
|
14
|
-
let success = false;
|
|
15
|
-
try {
|
|
16
|
-
const config = await (0, user_config_1.getConfig)();
|
|
17
|
-
const token = config.token;
|
|
18
|
-
if (!token) {
|
|
19
|
-
throw new errors_1.CLIError('You must be logged in to view starred items. Run `prpm login` first.');
|
|
20
|
-
}
|
|
21
|
-
const registryUrl = config.registryUrl || process.env.PRPM_REGISTRY_URL || 'https://registry.prpm.dev';
|
|
22
|
-
const client = (0, registry_client_1.getRegistryClient)({ registryUrl, token });
|
|
23
|
-
// Determine what to show (both by default)
|
|
24
|
-
const showPackages = options.packages || (!options.packages && !options.collections);
|
|
25
|
-
const showCollections = options.collections || (!options.packages && !options.collections);
|
|
26
|
-
const limit = options.limit || 100;
|
|
27
|
-
// Fetch starred packages
|
|
28
|
-
let packages = [];
|
|
29
|
-
if (showPackages) {
|
|
30
|
-
try {
|
|
31
|
-
const response = await fetch(`${registryUrl}/api/v1/packages/starred?limit=${limit}`, {
|
|
32
|
-
headers: {
|
|
33
|
-
Authorization: `Bearer ${token}`,
|
|
34
|
-
},
|
|
35
|
-
});
|
|
36
|
-
if (!response.ok) {
|
|
37
|
-
throw new Error(`Failed to fetch starred packages: ${response.statusText}`);
|
|
38
|
-
}
|
|
39
|
-
const data = await response.json();
|
|
40
|
-
packages = data.packages || [];
|
|
41
|
-
// Filter by format if specified
|
|
42
|
-
if (options.format) {
|
|
43
|
-
packages = packages.filter((pkg) => pkg.format === options.format);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
catch (error) {
|
|
47
|
-
console.error('Failed to fetch starred packages:', error);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
// Fetch starred collections
|
|
51
|
-
let collections = [];
|
|
52
|
-
if (showCollections) {
|
|
53
|
-
try {
|
|
54
|
-
const response = await fetch(`${registryUrl}/api/v1/collections/starred?limit=${limit}`, {
|
|
55
|
-
headers: {
|
|
56
|
-
Authorization: `Bearer ${token}`,
|
|
57
|
-
},
|
|
58
|
-
});
|
|
59
|
-
if (!response.ok) {
|
|
60
|
-
throw new Error(`Failed to fetch starred collections: ${response.statusText}`);
|
|
61
|
-
}
|
|
62
|
-
const data = await response.json();
|
|
63
|
-
collections = data.collections || [];
|
|
64
|
-
}
|
|
65
|
-
catch (error) {
|
|
66
|
-
console.error('Failed to fetch starred collections:', error);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
// Display results
|
|
70
|
-
if (packages.length === 0 && collections.length === 0) {
|
|
71
|
-
console.log('\nNo starred items found.');
|
|
72
|
-
if (options.format) {
|
|
73
|
-
console.log(`Try removing the --format filter to see all starred packages.`);
|
|
74
|
-
}
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
console.log('');
|
|
78
|
-
// Display packages
|
|
79
|
-
if (packages.length > 0) {
|
|
80
|
-
console.log(`📦 Starred Packages (${packages.length}):`);
|
|
81
|
-
console.log('');
|
|
82
|
-
for (const pkg of packages) {
|
|
83
|
-
const formatBadge = `[${pkg.format || 'generic'}]`.padEnd(12);
|
|
84
|
-
const stars = `⭐ ${pkg.stars || 0}`.padEnd(8);
|
|
85
|
-
const downloads = `⬇️ ${(pkg.total_downloads || 0).toLocaleString()}`;
|
|
86
|
-
console.log(` ${formatBadge} ${pkg.name}`);
|
|
87
|
-
console.log(` ${stars} ${downloads}`);
|
|
88
|
-
if (pkg.description) {
|
|
89
|
-
const desc = pkg.description.length > 80
|
|
90
|
-
? pkg.description.substring(0, 77) + '...'
|
|
91
|
-
: pkg.description;
|
|
92
|
-
console.log(` ${desc}`);
|
|
93
|
-
}
|
|
94
|
-
console.log('');
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
// Display collections
|
|
98
|
-
if (collections.length > 0) {
|
|
99
|
-
console.log(`📚 Starred Collections (${collections.length}):`);
|
|
100
|
-
console.log('');
|
|
101
|
-
for (const collection of collections) {
|
|
102
|
-
const stars = `⭐ ${collection.stars || 0}`.padEnd(8);
|
|
103
|
-
const packages = `📦 ${collection.package_count || 0} packages`;
|
|
104
|
-
console.log(` ${collection.scope}/${collection.name_slug}`);
|
|
105
|
-
console.log(` ${stars} ${packages}`);
|
|
106
|
-
if (collection.description) {
|
|
107
|
-
const desc = collection.description.length > 80
|
|
108
|
-
? collection.description.substring(0, 77) + '...'
|
|
109
|
-
: collection.description;
|
|
110
|
-
console.log(` ${desc}`);
|
|
111
|
-
}
|
|
112
|
-
console.log('');
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
console.log(`\nTotal: ${packages.length + collections.length} starred items`);
|
|
116
|
-
console.log('');
|
|
117
|
-
success = true;
|
|
118
|
-
}
|
|
119
|
-
catch (error) {
|
|
120
|
-
if (error instanceof errors_1.CLIError) {
|
|
121
|
-
throw error;
|
|
122
|
-
}
|
|
123
|
-
throw new errors_1.CLIError(`Failed to fetch starred items: ${error instanceof Error ? error.message : String(error)}`);
|
|
124
|
-
}
|
|
125
|
-
finally {
|
|
126
|
-
await telemetry_1.telemetry.track({
|
|
127
|
-
command: 'starred',
|
|
128
|
-
success,
|
|
129
|
-
data: {
|
|
130
|
-
showPackages: options.packages,
|
|
131
|
-
showCollections: options.collections,
|
|
132
|
-
format: options.format,
|
|
133
|
-
},
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
function createStarredCommand() {
|
|
138
|
-
const command = new commander_1.Command('starred');
|
|
139
|
-
command
|
|
140
|
-
.description('List your starred packages and collections')
|
|
141
|
-
.option('--packages', 'Show only starred packages')
|
|
142
|
-
.option('--collections', 'Show only starred collections')
|
|
143
|
-
.option('--format <format>', 'Filter packages by format (cursor, claude, continue, windsurf, etc.)')
|
|
144
|
-
.option('--limit <number>', 'Maximum number of items to fetch (default: 100)', (val) => parseInt(val, 10))
|
|
145
|
-
.action(handleStarred);
|
|
146
|
-
return command;
|
|
147
|
-
}
|