prpm 1.2.1 → 2.0.1

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 (67) hide show
  1. package/README.md +90 -862
  2. package/dist/index.js +23233 -65
  3. package/dist/schemas/agents-md.schema.json +24 -0
  4. package/dist/schemas/aider.schema.json +24 -0
  5. package/dist/schemas/canonical.schema.json +435 -0
  6. package/dist/schemas/claude-agent.schema.json +62 -0
  7. package/dist/schemas/claude-hook.schema.json +70 -0
  8. package/dist/schemas/claude-plugin.schema.json +122 -0
  9. package/dist/schemas/claude-skill.schema.json +51 -0
  10. package/dist/schemas/claude-slash-command.schema.json +77 -0
  11. package/dist/schemas/claude.schema.json +52 -0
  12. package/dist/schemas/continue.schema.json +98 -0
  13. package/dist/schemas/copilot.schema.json +76 -0
  14. package/dist/schemas/cursor-command.schema.json +27 -0
  15. package/dist/schemas/cursor-hooks.schema.json +59 -0
  16. package/dist/schemas/cursor.schema.json +74 -0
  17. package/dist/schemas/droid-hook.schema.json +103 -0
  18. package/dist/schemas/droid-skill.schema.json +46 -0
  19. package/dist/schemas/droid-slash-command.schema.json +53 -0
  20. package/dist/schemas/droid.schema.json +46 -0
  21. package/dist/schemas/format-registry.schema.json +99 -0
  22. package/dist/schemas/gemini-md.schema.json +24 -0
  23. package/dist/schemas/gemini.schema.json +30 -0
  24. package/dist/schemas/kiro-agent.schema.json +146 -0
  25. package/dist/schemas/kiro-hook.schema.json +120 -0
  26. package/dist/schemas/kiro-steering.schema.json +74 -0
  27. package/dist/schemas/mcp-server.schema.json +130 -0
  28. package/dist/schemas/opencode-slash-command.schema.json +60 -0
  29. package/dist/schemas/opencode.schema.json +111 -0
  30. package/dist/schemas/prpm-manifest.schema.json +733 -0
  31. package/dist/schemas/replit.schema.json +21 -0
  32. package/dist/schemas/ruler.schema.json +22 -0
  33. package/dist/schemas/trae.schema.json +24 -0
  34. package/dist/schemas/windsurf.schema.json +22 -0
  35. package/dist/schemas/zencoder.schema.json +51 -0
  36. package/package.json +20 -14
  37. package/schemas/prpm-manifest.schema.json +465 -39
  38. package/dist/__tests__/e2e/test-helpers.js +0 -150
  39. package/dist/commands/collections.js +0 -606
  40. package/dist/commands/index.js +0 -186
  41. package/dist/commands/info.js +0 -82
  42. package/dist/commands/install.js +0 -477
  43. package/dist/commands/list.js +0 -166
  44. package/dist/commands/login.js +0 -281
  45. package/dist/commands/outdated.js +0 -128
  46. package/dist/commands/popular.js +0 -27
  47. package/dist/commands/publish.js +0 -274
  48. package/dist/commands/schema.js +0 -37
  49. package/dist/commands/search.js +0 -404
  50. package/dist/commands/telemetry.js +0 -103
  51. package/dist/commands/trending.js +0 -76
  52. package/dist/commands/uninstall.js +0 -77
  53. package/dist/commands/update.js +0 -121
  54. package/dist/commands/upgrade.js +0 -121
  55. package/dist/commands/whoami.js +0 -75
  56. package/dist/core/claude-config.js +0 -91
  57. package/dist/core/cursor-config.js +0 -130
  58. package/dist/core/downloader.js +0 -64
  59. package/dist/core/filesystem.js +0 -124
  60. package/dist/core/lockfile.js +0 -239
  61. package/dist/core/marketplace-converter.js +0 -198
  62. package/dist/core/registry-client.js +0 -265
  63. package/dist/core/schema-validator.js +0 -74
  64. package/dist/core/telemetry.js +0 -175
  65. package/dist/core/user-config.js +0 -79
  66. package/dist/types/registry.js +0 -5
  67. package/dist/types.js +0 -5
@@ -1,606 +0,0 @@
1
- "use strict";
2
- /**
3
- * Collections command - Manage package collections
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.handleCollectionsSearch = handleCollectionsSearch;
40
- exports.handleCollectionsList = handleCollectionsList;
41
- exports.handleCollectionInfo = handleCollectionInfo;
42
- exports.handleCollectionPublish = handleCollectionPublish;
43
- exports.handleCollectionInstall = handleCollectionInstall;
44
- exports.createCollectionsCommand = createCollectionsCommand;
45
- const commander_1 = require("commander");
46
- const registry_client_1 = require("@pr-pm/registry-client");
47
- const user_config_1 = require("../core/user-config");
48
- const install_1 = require("./install");
49
- const telemetry_1 = require("../core/telemetry");
50
- /**
51
- * Search collections by query
52
- */
53
- async function handleCollectionsSearch(query, options) {
54
- const startTime = Date.now();
55
- try {
56
- const config = await (0, user_config_1.getConfig)();
57
- const client = (0, registry_client_1.getRegistryClient)(config);
58
- console.log(`šŸ” Searching collections for "${query}"...\n`);
59
- // Use server-side search with full-text index
60
- const result = await client.getCollections({
61
- query,
62
- category: options.category,
63
- tag: options.tag,
64
- official: options.official,
65
- limit: options.limit || 50,
66
- });
67
- if (result.collections.length === 0) {
68
- console.log('No collections found matching your search.');
69
- console.log('\nšŸ’” Try:');
70
- console.log(' - Broadening your search terms');
71
- console.log(' - Checking spelling');
72
- console.log(' - Browsing all: prpm collections list');
73
- return;
74
- }
75
- console.log(`✨ Found ${result.collections.length} collection(s):\n`);
76
- // Group by official vs community
77
- const official = result.collections.filter(c => c.official);
78
- const community = result.collections.filter(c => !c.official);
79
- if (official.length > 0) {
80
- console.log(`šŸ“¦ Official Collections (${official.length}):\n`);
81
- official.forEach(c => {
82
- const fullName = c.name_slug.padEnd(35);
83
- const pkgCount = `(${c.package_count} packages)`.padEnd(15);
84
- console.log(` ${c.icon || 'šŸ“¦'} ${fullName} ${pkgCount} ${c.name}`);
85
- if (c.description) {
86
- console.log(` ${c.description.substring(0, 70)}${c.description.length > 70 ? '...' : ''}`);
87
- }
88
- console.log(` šŸ‘¤ by @${c.author}${c.verified ? ' āœ“' : ''}`);
89
- console.log(` ā¬‡ļø ${c.downloads.toLocaleString()} installs Ā· ⭐ ${c.stars.toLocaleString()} stars`);
90
- console.log('');
91
- });
92
- }
93
- if (community.length > 0) {
94
- console.log(`\n🌟 Community Collections (${community.length}):\n`);
95
- community.forEach(c => {
96
- const fullName = c.name_slug.padEnd(35);
97
- const pkgCount = `(${c.package_count} packages)`.padEnd(15);
98
- console.log(` ${c.icon || 'šŸ“¦'} ${fullName} ${pkgCount} ${c.name}`);
99
- if (c.description) {
100
- console.log(` ${c.description.substring(0, 70)}${c.description.length > 70 ? '...' : ''}`);
101
- }
102
- console.log(` šŸ‘¤ by @${c.author}${c.verified ? ' āœ“' : ''}`);
103
- console.log(` ā¬‡ļø ${c.downloads.toLocaleString()} installs Ā· ⭐ ${c.stars.toLocaleString()} stars`);
104
- console.log('');
105
- });
106
- }
107
- // Show results count
108
- console.log(`\nšŸ“Š Found: ${result.collections.length} matching collection${result.collections.length === 1 ? '' : 's'} (searched ${result.total} total)\n`);
109
- console.log(`šŸ’” View details: prpm collection info <collection>`);
110
- console.log(`šŸ’” Install: prpm install <collection>`);
111
- await telemetry_1.telemetry.track({
112
- command: 'collections:search',
113
- success: true,
114
- duration: Date.now() - startTime,
115
- data: {
116
- query: query.substring(0, 100),
117
- count: result.collections.length,
118
- total: result.total,
119
- filters: options,
120
- },
121
- });
122
- }
123
- catch (error) {
124
- const errorMessage = error instanceof Error ? error.message : String(error);
125
- console.error(`\nāŒ Failed to search collections: ${errorMessage}`);
126
- await telemetry_1.telemetry.track({
127
- command: 'collections:search',
128
- success: false,
129
- error: errorMessage,
130
- duration: Date.now() - startTime,
131
- });
132
- process.exit(1);
133
- }
134
- finally {
135
- await telemetry_1.telemetry.shutdown();
136
- }
137
- }
138
- /**
139
- * List available collections
140
- */
141
- async function handleCollectionsList(options) {
142
- const startTime = Date.now();
143
- try {
144
- const config = await (0, user_config_1.getConfig)();
145
- const client = (0, registry_client_1.getRegistryClient)(config);
146
- console.log('šŸ“¦ Searching collections...\n');
147
- const result = await client.getCollections({
148
- category: options.category,
149
- tag: options.tag,
150
- official: options.official,
151
- scope: options.scope,
152
- limit: 500, // Increased limit to show more collections
153
- });
154
- if (result.collections.length === 0) {
155
- console.log('No collections found matching your criteria.');
156
- return;
157
- }
158
- // Group by official vs community
159
- const official = result.collections.filter(c => c.official);
160
- const community = result.collections.filter(c => !c.official);
161
- if (official.length > 0) {
162
- console.log(`šŸ“¦ Official Collections (${official.length}):\n`);
163
- official.forEach(c => {
164
- const fullName = c.name_slug.padEnd(35);
165
- const pkgCount = `(${c.package_count} packages)`.padEnd(15);
166
- console.log(` ${c.icon || 'šŸ“¦'} ${fullName} ${pkgCount} ${c.name}`);
167
- if (c.description) {
168
- console.log(` ${c.description.substring(0, 70)}${c.description.length > 70 ? '...' : ''}`);
169
- }
170
- console.log(` šŸ‘¤ by @${c.author}${c.verified ? ' āœ“' : ''}`);
171
- console.log(` ā¬‡ļø ${c.downloads.toLocaleString()} installs Ā· ⭐ ${c.stars.toLocaleString()} stars`);
172
- console.log('');
173
- });
174
- }
175
- if (community.length > 0) {
176
- console.log(`\n🌟 Community Collections (${community.length}):\n`);
177
- community.forEach(c => {
178
- const fullName = c.name_slug.padEnd(35);
179
- const pkgCount = `(${c.package_count} packages)`.padEnd(15);
180
- console.log(` ${c.icon || 'šŸ“¦'} ${fullName} ${pkgCount} ${c.name}`);
181
- if (c.description) {
182
- console.log(` ${c.description.substring(0, 70)}${c.description.length > 70 ? '...' : ''}`);
183
- }
184
- console.log(` šŸ‘¤ by @${c.author}${c.verified ? ' āœ“' : ''}`);
185
- console.log(` ā¬‡ļø ${c.downloads.toLocaleString()} installs Ā· ⭐ ${c.stars.toLocaleString()} stars`);
186
- console.log('');
187
- });
188
- }
189
- // Show total from API (which includes all collections, not just the ones returned)
190
- const showing = result.collections.length;
191
- const total = result.total;
192
- if (showing < total) {
193
- console.log(`\nšŸ“Š Showing ${showing} of ${total} collection${total === 1 ? '' : 's'}\n`);
194
- }
195
- else {
196
- console.log(`\nšŸ“Š Total: ${total} collection${total === 1 ? '' : 's'}\n`);
197
- }
198
- console.log(`šŸ’” View details: prpm collection info <collection>`);
199
- console.log(`šŸ’” Install: prpm install <collection>`);
200
- await telemetry_1.telemetry.track({
201
- command: 'collections:list',
202
- success: true,
203
- duration: Date.now() - startTime,
204
- data: {
205
- count: result.collections.length,
206
- total: result.total,
207
- filters: options,
208
- },
209
- });
210
- }
211
- catch (error) {
212
- const errorMessage = error instanceof Error ? error.message : String(error);
213
- console.error(`\nāŒ Failed to list collections: ${errorMessage}`);
214
- await telemetry_1.telemetry.track({
215
- command: 'collections:list',
216
- success: false,
217
- error: errorMessage,
218
- duration: Date.now() - startTime,
219
- });
220
- process.exit(1);
221
- }
222
- finally {
223
- await telemetry_1.telemetry.shutdown();
224
- }
225
- }
226
- /**
227
- * Show collection details
228
- */
229
- async function handleCollectionInfo(collectionSpec) {
230
- const startTime = Date.now();
231
- try {
232
- // Parse collection spec: @scope/name_slug, scope/name_slug, or just name_slug (defaults to 'collection' scope)
233
- let scope;
234
- let name_slug;
235
- let version;
236
- const matchWithScope = collectionSpec.match(/^@?([^/]+)\/([^/@]+)(?:@(.+))?$/);
237
- if (matchWithScope) {
238
- // Has explicit scope: @scope/name or scope/name
239
- [, scope, name_slug, version] = matchWithScope;
240
- }
241
- else {
242
- // No scope, assume 'collection' scope: just name or name@version
243
- const matchNoScope = collectionSpec.match(/^([^/@]+)(?:@(.+))?$/);
244
- if (!matchNoScope) {
245
- throw new Error('Invalid collection format. Use: name, @scope/name, or scope/name (optionally with @version)');
246
- }
247
- [, name_slug, version] = matchNoScope;
248
- scope = 'collection'; // Default scope
249
- }
250
- const config = await (0, user_config_1.getConfig)();
251
- const client = (0, registry_client_1.getRegistryClient)(config);
252
- console.log(`šŸ“¦ Loading collection: ${scope === 'collection' ? name_slug : `@${scope}/${name_slug}`}...\n`);
253
- const collection = await client.getCollection(scope, name_slug, version);
254
- // Header
255
- console.log(`${collection.icon || 'šŸ“¦'} ${collection.name}`);
256
- console.log(`${'='.repeat(collection.name.length + 2)}`);
257
- console.log('');
258
- console.log(collection.description);
259
- console.log('');
260
- // Stats
261
- console.log('šŸ“Š Stats:');
262
- console.log(` Downloads: ${collection.downloads.toLocaleString()}`);
263
- console.log(` Stars: ${collection.stars.toLocaleString()}`);
264
- console.log(` Version: ${collection.version}`);
265
- console.log(` Packages: ${collection.packages.length}`);
266
- console.log(` Author: ${collection.author}${collection.verified ? ' āœ“' : ''}`);
267
- if (collection.category) {
268
- console.log(` Category: ${collection.category}`);
269
- }
270
- if (collection.tags && collection.tags.length > 0) {
271
- console.log(` Tags: ${collection.tags.join(', ')}`);
272
- }
273
- console.log('');
274
- // Packages
275
- console.log('šŸ“‹ Included Packages:');
276
- console.log('');
277
- const requiredPkgs = collection.packages.filter(p => p.required);
278
- const optionalPkgs = collection.packages.filter(p => !p.required);
279
- if (requiredPkgs.length > 0) {
280
- console.log(' Required:');
281
- requiredPkgs.forEach((pkg, i) => {
282
- console.log(` ${i + 1}. āœ“ ${pkg?.package?.name}@${pkg.version || 'latest'}`);
283
- if (pkg.package && pkg.package.description) {
284
- console.log(` ${pkg.package.description}`);
285
- }
286
- if (pkg.reason) {
287
- console.log(` šŸ’” ${pkg.reason}`);
288
- }
289
- console.log('');
290
- });
291
- }
292
- if (optionalPkgs.length > 0) {
293
- console.log(' Optional:');
294
- optionalPkgs.forEach((pkg, i) => {
295
- console.log(` ${i + 1}. ā—‹ ${pkg?.package?.name}@${pkg.version || 'latest'}`);
296
- if (pkg.package && pkg.package.description) {
297
- console.log(` ${pkg.package.description}`);
298
- }
299
- if (pkg.reason) {
300
- console.log(` šŸ’” ${pkg.reason}`);
301
- }
302
- console.log('');
303
- });
304
- }
305
- // Installation
306
- console.log('šŸ’” Install:');
307
- if (scope === 'collection') {
308
- console.log(` prpm install ${name_slug}`);
309
- if (optionalPkgs.length > 0) {
310
- console.log(` prpm install ${name_slug} --skip-optional # Skip optional packages`);
311
- }
312
- }
313
- else {
314
- console.log(` prpm install @${scope}/${name_slug}`);
315
- if (optionalPkgs.length > 0) {
316
- console.log(` prpm install @${scope}/${name_slug} --skip-optional # Skip optional packages`);
317
- }
318
- }
319
- console.log('');
320
- await telemetry_1.telemetry.track({
321
- command: 'collections:info',
322
- success: true,
323
- duration: Date.now() - startTime,
324
- data: {
325
- scope,
326
- name_slug,
327
- packageCount: collection.packages.length,
328
- },
329
- });
330
- }
331
- catch (error) {
332
- const errorMessage = error instanceof Error ? error.message : String(error);
333
- console.error(`\nāŒ Failed to get collection info: ${errorMessage}`);
334
- await telemetry_1.telemetry.track({
335
- command: 'collections:info',
336
- success: false,
337
- error: errorMessage,
338
- duration: Date.now() - startTime,
339
- });
340
- process.exit(1);
341
- }
342
- finally {
343
- await telemetry_1.telemetry.shutdown();
344
- }
345
- }
346
- /**
347
- * Publish/create a collection
348
- */
349
- async function handleCollectionPublish(manifestPath = './collection.json') {
350
- const startTime = Date.now();
351
- try {
352
- const config = await (0, user_config_1.getConfig)();
353
- const client = (0, registry_client_1.getRegistryClient)(config);
354
- // Check authentication
355
- if (!config.token) {
356
- console.error('\nāŒ Authentication required. Run `prpm login` first.\n');
357
- process.exit(1);
358
- }
359
- console.log('šŸ“¦ Publishing collection...\n');
360
- // Read collection manifest
361
- const fs = await Promise.resolve().then(() => __importStar(require('fs/promises')));
362
- const manifestContent = await fs.readFile(manifestPath, 'utf-8');
363
- const manifest = JSON.parse(manifestContent);
364
- // Validate manifest
365
- const required = ['id', 'name', 'description', 'packages'];
366
- const missing = required.filter(field => !manifest[field]);
367
- if (missing.length > 0) {
368
- throw new Error(`Missing required fields: ${missing.join(', ')}`);
369
- }
370
- // Validate id format (must be lowercase alphanumeric with hyphens)
371
- if (!/^[a-z0-9-]+$/.test(manifest.id)) {
372
- throw new Error('Collection id must be lowercase alphanumeric with hyphens only');
373
- }
374
- // Validate name length
375
- if (manifest.name.length < 3) {
376
- throw new Error('Collection name must be at least 3 characters');
377
- }
378
- // Validate description length
379
- if (manifest.description.length < 10) {
380
- throw new Error('Collection description must be at least 10 characters');
381
- }
382
- // Validate packages array
383
- if (!Array.isArray(manifest.packages) || manifest.packages.length === 0) {
384
- throw new Error('Collection must include at least one package');
385
- }
386
- // Validate each package
387
- manifest.packages.forEach((pkg, idx) => {
388
- if (!pkg.packageId) {
389
- throw new Error(`Package at index ${idx} is missing packageId`);
390
- }
391
- });
392
- console.log(`šŸ” Validating collection manifest...`);
393
- console.log(` Collection: ${manifest.name}`);
394
- console.log(` ID: ${manifest.id}`);
395
- console.log(` Packages: ${manifest.packages.length}`);
396
- console.log('');
397
- // Publish to registry
398
- console.log('šŸš€ Publishing to registry...\n');
399
- const result = await client.createCollection({
400
- id: manifest.id,
401
- name: manifest.name,
402
- description: manifest.description,
403
- category: manifest.category,
404
- tags: manifest.tags,
405
- packages: manifest.packages.map((pkg) => ({
406
- packageId: pkg.packageId,
407
- version: pkg.version,
408
- required: pkg.required !== false,
409
- reason: pkg.reason,
410
- })),
411
- icon: manifest.icon,
412
- });
413
- console.log(`āœ… Collection published successfully!`);
414
- console.log(` Scope: ${result.scope}`);
415
- console.log(` Name: ${result.name_slug}`);
416
- console.log(` Version: ${result.version || '1.0.0'}`);
417
- console.log('');
418
- console.log(`šŸ’” View: prpm collection info @${result.scope}/${result.name_slug}`);
419
- console.log(`šŸ’” Install: prpm install @${result.scope}/${result.name_slug}`);
420
- console.log('');
421
- await telemetry_1.telemetry.track({
422
- command: 'collections:publish',
423
- success: true,
424
- duration: Date.now() - startTime,
425
- data: {
426
- id: manifest.id,
427
- packageCount: manifest.packages.length,
428
- },
429
- });
430
- }
431
- catch (error) {
432
- const errorMessage = error instanceof Error ? error.message : String(error);
433
- console.error(`\nāŒ Failed to publish collection: ${errorMessage}\n`);
434
- await telemetry_1.telemetry.track({
435
- command: 'collections:publish',
436
- success: false,
437
- error: errorMessage,
438
- duration: Date.now() - startTime,
439
- });
440
- process.exit(1);
441
- }
442
- finally {
443
- await telemetry_1.telemetry.shutdown();
444
- }
445
- }
446
- /**
447
- * Install a collection
448
- */
449
- async function handleCollectionInstall(collectionSpec, options) {
450
- const startTime = Date.now();
451
- let packagesInstalled = 0;
452
- let packagesFailed = 0;
453
- try {
454
- // Parse collection spec: @scope/name_slug, scope/name_slug, or just name_slug (defaults to 'collection' scope)
455
- let scope;
456
- let name_slug;
457
- let version;
458
- const matchWithScope = collectionSpec.match(/^@?([^/]+)\/([^/@]+)(?:@(.+))?$/);
459
- if (matchWithScope) {
460
- // Has explicit scope: @scope/name or scope/name
461
- [, scope, name_slug, version] = matchWithScope;
462
- }
463
- else {
464
- // No scope, assume 'collection' scope: just name or name@version
465
- const matchNoScope = collectionSpec.match(/^([^/@]+)(?:@(.+))?$/);
466
- if (!matchNoScope) {
467
- throw new Error('Invalid collection format. Use: name, @scope/name, or scope/name (optionally with @version)');
468
- }
469
- [, name_slug, version] = matchNoScope;
470
- scope = 'collection'; // Default scope
471
- }
472
- const config = await (0, user_config_1.getConfig)();
473
- const client = (0, registry_client_1.getRegistryClient)(config);
474
- // Get collection installation plan
475
- console.log(`šŸ“¦ Installing collection: ${scope === 'collection' ? name_slug : `@${scope}/${name_slug}`}...\n`);
476
- const installResult = await client.installCollection({
477
- scope,
478
- id: name_slug,
479
- version,
480
- format: options.format,
481
- skipOptional: options.skipOptional,
482
- });
483
- const collection = installResult.collection;
484
- const packages = installResult.packagesToInstall;
485
- console.log(`šŸ“¦ ${collection.name}`);
486
- console.log(` ${packages.length} packages to install\n`);
487
- if (options.dryRun) {
488
- console.log('šŸ” Dry run - would install:\n');
489
- packages.forEach((pkg, i) => {
490
- const required = pkg.required ? 'āœ“' : 'ā—‹';
491
- console.log(` ${i + 1}/${packages.length} ${required} ${pkg.packageId}@${pkg.version} (${pkg.format})`);
492
- });
493
- console.log('');
494
- return;
495
- }
496
- // Install packages sequentially
497
- for (let i = 0; i < packages.length; i++) {
498
- const pkg = packages[i];
499
- const progress = `${i + 1}/${packages.length}`;
500
- try {
501
- console.log(`\n ${progress} Installing ${pkg.packageId}@${pkg.version}...`);
502
- await (0, install_1.handleInstall)(`${pkg.packageId}@${pkg.version}`, {
503
- as: pkg.format,
504
- });
505
- console.log(` ${progress} āœ“ ${pkg.packageId}`);
506
- packagesInstalled++;
507
- }
508
- catch (error) {
509
- const errorMessage = error instanceof Error ? error.message : String(error);
510
- console.error(` ${progress} āœ— ${pkg.packageId}: ${errorMessage}`);
511
- packagesFailed++;
512
- if (pkg.required) {
513
- throw new Error(`Failed to install required package: ${pkg.packageId}`);
514
- }
515
- }
516
- }
517
- console.log(`\nāœ… Collection installed successfully!`);
518
- console.log(` ${packagesInstalled}/${packages.length} packages installed`);
519
- if (packagesFailed > 0) {
520
- console.log(` ${packagesFailed} optional packages failed`);
521
- }
522
- console.log('');
523
- await telemetry_1.telemetry.track({
524
- command: 'collections:install',
525
- success: true,
526
- duration: Date.now() - startTime,
527
- data: {
528
- scope,
529
- name_slug,
530
- packageCount: packages.length,
531
- installed: packagesInstalled,
532
- failed: packagesFailed,
533
- format: options.format,
534
- },
535
- });
536
- }
537
- catch (error) {
538
- const errorMessage = error instanceof Error ? error.message : String(error);
539
- console.error(`\nāŒ Failed to install collection: ${errorMessage}`);
540
- await telemetry_1.telemetry.track({
541
- command: 'collections:install',
542
- success: false,
543
- error: errorMessage,
544
- duration: Date.now() - startTime,
545
- data: {
546
- installed: packagesInstalled,
547
- failed: packagesFailed,
548
- },
549
- });
550
- process.exit(1);
551
- }
552
- finally {
553
- await telemetry_1.telemetry.shutdown();
554
- }
555
- }
556
- /**
557
- * Create collections command group
558
- */
559
- function createCollectionsCommand() {
560
- const command = new commander_1.Command('collections');
561
- command
562
- .description('Manage package collections')
563
- .alias('collection')
564
- .action(async (options) => {
565
- await handleCollectionsList(options);
566
- });
567
- // Search subcommand
568
- command
569
- .command('search <query>')
570
- .description('Search for collections')
571
- .option('--category <category>', 'Filter by category')
572
- .option('--tag <tag>', 'Filter by tag')
573
- .option('--official', 'Show only official collections')
574
- .option('--limit <number>', 'Number of results to show', '50')
575
- .action(async (query, options) => {
576
- await handleCollectionsSearch(query, {
577
- category: options.category,
578
- tag: options.tag,
579
- official: options.official,
580
- limit: options.limit ? parseInt(options.limit, 10) : 50,
581
- });
582
- });
583
- // List subcommand
584
- command
585
- .command('list')
586
- .description('List available collections')
587
- .option('--category <category>', 'Filter by category')
588
- .option('--tag <tag>', 'Filter by tag')
589
- .option('--official', 'Show only official collections')
590
- .option('--scope <scope>', 'Filter by scope')
591
- .action(handleCollectionsList);
592
- // Info subcommand
593
- command
594
- .command('info <collection>')
595
- .description('Show collection details')
596
- .action(handleCollectionInfo);
597
- // Publish subcommand
598
- command
599
- .command('publish [manifest]')
600
- .description('Publish a collection from collection.json')
601
- .action(async (manifest) => {
602
- await handleCollectionPublish(manifest);
603
- });
604
- // Install handled by main install command with @scope/id syntax
605
- return command;
606
- }