prpm 0.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.
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ /**
3
+ * Add command implementation
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.handleAdd = handleAdd;
7
+ exports.createAddCommand = createAddCommand;
8
+ const commander_1 = require("commander");
9
+ const downloader_1 = require("../core/downloader");
10
+ const filesystem_1 = require("../core/filesystem");
11
+ const config_1 = require("../core/config");
12
+ const telemetry_1 = require("../core/telemetry");
13
+ // Extract repository info from GitHub URL for popularity tracking
14
+ function extractRepoFromUrl(url) {
15
+ try {
16
+ // Handle raw GitHub URLs: https://raw.githubusercontent.com/user/repo/branch/path
17
+ const rawMatch = url.match(/raw\.githubusercontent\.com\/([^\/]+)\/([^\/]+)/);
18
+ if (rawMatch) {
19
+ return `${rawMatch[1]}/${rawMatch[2]}`;
20
+ }
21
+ // Handle regular GitHub URLs: https://github.com/user/repo
22
+ const githubMatch = url.match(/github\.com\/([^\/]+)\/([^\/]+)/);
23
+ if (githubMatch) {
24
+ return `${githubMatch[1]}/${githubMatch[2]}`;
25
+ }
26
+ return 'unknown';
27
+ }
28
+ catch {
29
+ return 'unknown';
30
+ }
31
+ }
32
+ /**
33
+ * Add a prompt package from a URL
34
+ */
35
+ async function handleAdd(url, type) {
36
+ const startTime = Date.now();
37
+ let success = false;
38
+ let error;
39
+ try {
40
+ console.log(`šŸ“„ Downloading from ${url}...`);
41
+ // Download the file
42
+ const content = await (0, downloader_1.downloadFile)(url);
43
+ // Extract filename and generate ID
44
+ const filename = (0, downloader_1.extractFilename)(url);
45
+ const id = (0, filesystem_1.generateId)(filename);
46
+ // Determine destination
47
+ const destDir = (0, filesystem_1.getDestinationDir)(type);
48
+ const destPath = `${destDir}/${filename}`;
49
+ // Save the file
50
+ console.log(`šŸ’¾ Saving to ${destPath}...`);
51
+ await (0, filesystem_1.saveFile)(destPath, content);
52
+ // Create package record
53
+ const pkg = {
54
+ id,
55
+ type,
56
+ url,
57
+ dest: destPath
58
+ };
59
+ // Update configuration
60
+ await (0, config_1.addPackage)(pkg);
61
+ console.log(`āœ… Successfully added ${id} (${type})`);
62
+ console.log(` šŸ“ Saved to: ${destPath}`);
63
+ success = true;
64
+ }
65
+ catch (err) {
66
+ error = err instanceof Error ? err.message : String(err);
67
+ console.error(`āŒ Failed to add package: ${error}`);
68
+ process.exit(1);
69
+ }
70
+ finally {
71
+ // Track telemetry
72
+ await telemetry_1.telemetry.track({
73
+ command: 'add',
74
+ success,
75
+ error,
76
+ duration: Date.now() - startTime,
77
+ data: {
78
+ type,
79
+ url: url.substring(0, 100), // Truncate long URLs
80
+ filename: (0, downloader_1.extractFilename)(url),
81
+ // Package popularity tracking
82
+ packageId: (0, filesystem_1.generateId)((0, downloader_1.extractFilename)(url)),
83
+ packageType: type,
84
+ sourceRepo: extractRepoFromUrl(url),
85
+ },
86
+ });
87
+ }
88
+ }
89
+ /**
90
+ * Create the add command
91
+ */
92
+ function createAddCommand() {
93
+ const command = new commander_1.Command('add');
94
+ command
95
+ .description('Add a prompt package from a URL')
96
+ .argument('<url>', 'Raw GitHub URL to the prompt file')
97
+ .option('--as <type>', 'Package type (cursor or claude)', 'cursor')
98
+ .action(async (url, options) => {
99
+ const type = options.as;
100
+ if (type !== 'cursor' && type !== 'claude') {
101
+ console.error('āŒ Type must be either "cursor" or "claude"');
102
+ process.exit(1);
103
+ }
104
+ await handleAdd(url, type);
105
+ });
106
+ return command;
107
+ }
@@ -0,0 +1,409 @@
1
+ "use strict";
2
+ /**
3
+ * Collections command - Manage package collections
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.handleCollectionsSearch = handleCollectionsSearch;
7
+ exports.handleCollectionsList = handleCollectionsList;
8
+ exports.handleCollectionInfo = handleCollectionInfo;
9
+ exports.handleCollectionInstall = handleCollectionInstall;
10
+ exports.createCollectionsCommand = createCollectionsCommand;
11
+ const commander_1 = require("commander");
12
+ const registry_client_1 = require("@prpm/registry-client");
13
+ const user_config_1 = require("../core/user-config");
14
+ const install_1 = require("./install");
15
+ const telemetry_1 = require("../core/telemetry");
16
+ /**
17
+ * Search collections by query
18
+ */
19
+ async function handleCollectionsSearch(query, options) {
20
+ const startTime = Date.now();
21
+ try {
22
+ const config = await (0, user_config_1.getConfig)();
23
+ const client = (0, registry_client_1.getRegistryClient)(config);
24
+ console.log(`šŸ” Searching collections for "${query}"...\n`);
25
+ // Get all collections and filter by query
26
+ const result = await client.getCollections({
27
+ category: options.category,
28
+ tag: options.tag,
29
+ official: options.official,
30
+ limit: options.limit || 50,
31
+ });
32
+ // Filter collections by search query (name, description, tags)
33
+ const queryLower = query.toLowerCase();
34
+ const filtered = result.collections.filter(c => c.name.toLowerCase().includes(queryLower) ||
35
+ c.description.toLowerCase().includes(queryLower) ||
36
+ c.tags.some(tag => tag.toLowerCase().includes(queryLower)) ||
37
+ c.id.toLowerCase().includes(queryLower));
38
+ if (filtered.length === 0) {
39
+ console.log('No collections found matching your search.');
40
+ console.log('\nšŸ’” Try:');
41
+ console.log(' - Broadening your search terms');
42
+ console.log(' - Checking spelling');
43
+ console.log(' - Browsing all: prpm collections list');
44
+ return;
45
+ }
46
+ console.log(`✨ Found ${filtered.length} collection(s):\n`);
47
+ // Group by official vs community
48
+ const official = filtered.filter(c => c.official);
49
+ const community = filtered.filter(c => !c.official);
50
+ if (official.length > 0) {
51
+ console.log('šŸ“¦ Official Collections:\n');
52
+ official.forEach(c => {
53
+ const fullName = `@${c.scope}/${c.id}`.padEnd(35);
54
+ const pkgCount = `(${c.package_count} packages)`.padEnd(15);
55
+ console.log(` ${c.icon || 'šŸ“¦'} ${fullName} ${pkgCount} ${c.name}`);
56
+ if (c.description) {
57
+ console.log(` ${c.description.substring(0, 70)}${c.description.length > 70 ? '...' : ''}`);
58
+ }
59
+ console.log(` ā¬‡ļø ${c.downloads.toLocaleString()} installs Ā· ⭐ ${c.stars.toLocaleString()} stars`);
60
+ console.log('');
61
+ });
62
+ }
63
+ if (community.length > 0) {
64
+ console.log('\n🌟 Community Collections:\n');
65
+ community.forEach(c => {
66
+ const fullName = `@${c.scope}/${c.id}`.padEnd(35);
67
+ const pkgCount = `(${c.package_count} packages)`.padEnd(15);
68
+ console.log(` ${c.icon || 'šŸ“¦'} ${fullName} ${pkgCount} ${c.name}`);
69
+ if (c.description) {
70
+ console.log(` ${c.description.substring(0, 70)}${c.description.length > 70 ? '...' : ''}`);
71
+ }
72
+ console.log(` ā¬‡ļø ${c.downloads.toLocaleString()} installs Ā· ⭐ ${c.stars.toLocaleString()} stars`);
73
+ console.log('');
74
+ });
75
+ }
76
+ console.log(`\nšŸ’” View details: prpm collection info <collection>`);
77
+ console.log(`šŸ’” Install: prpm install @collection/<name>`);
78
+ await telemetry_1.telemetry.track({
79
+ command: 'collections:search',
80
+ success: true,
81
+ duration: Date.now() - startTime,
82
+ data: {
83
+ query: query.substring(0, 100),
84
+ count: filtered.length,
85
+ filters: options,
86
+ },
87
+ });
88
+ }
89
+ catch (error) {
90
+ const errorMessage = error instanceof Error ? error.message : String(error);
91
+ console.error(`\nāŒ Failed to search collections: ${errorMessage}`);
92
+ await telemetry_1.telemetry.track({
93
+ command: 'collections:search',
94
+ success: false,
95
+ error: errorMessage,
96
+ duration: Date.now() - startTime,
97
+ });
98
+ process.exit(1);
99
+ }
100
+ }
101
+ /**
102
+ * List available collections
103
+ */
104
+ async function handleCollectionsList(options) {
105
+ const startTime = Date.now();
106
+ try {
107
+ const config = await (0, user_config_1.getConfig)();
108
+ const client = (0, registry_client_1.getRegistryClient)(config);
109
+ console.log('šŸ“¦ Searching collections...\n');
110
+ const result = await client.getCollections({
111
+ category: options.category,
112
+ tag: options.tag,
113
+ official: options.official,
114
+ scope: options.scope,
115
+ limit: 50,
116
+ });
117
+ if (result.collections.length === 0) {
118
+ console.log('No collections found matching your criteria.');
119
+ return;
120
+ }
121
+ // Group by official vs community
122
+ const official = result.collections.filter(c => c.official);
123
+ const community = result.collections.filter(c => !c.official);
124
+ if (official.length > 0) {
125
+ console.log('šŸ“¦ Official Collections:\n');
126
+ official.forEach(c => {
127
+ const fullName = `@${c.scope}/${c.id}`.padEnd(35);
128
+ const pkgCount = `(${c.package_count} packages)`.padEnd(15);
129
+ console.log(` ${c.icon || 'šŸ“¦'} ${fullName} ${pkgCount} ${c.name}`);
130
+ if (c.description) {
131
+ console.log(` ${c.description.substring(0, 70)}${c.description.length > 70 ? '...' : ''}`);
132
+ }
133
+ console.log(` ā¬‡ļø ${c.downloads.toLocaleString()} installs Ā· ⭐ ${c.stars.toLocaleString()} stars`);
134
+ console.log('');
135
+ });
136
+ }
137
+ if (community.length > 0) {
138
+ console.log('\n🌟 Community Collections:\n');
139
+ community.forEach(c => {
140
+ const fullName = `@${c.scope}/${c.id}`.padEnd(35);
141
+ const pkgCount = `(${c.package_count} packages)`.padEnd(15);
142
+ console.log(` ${c.icon || 'šŸ“¦'} ${fullName} ${pkgCount} ${c.name}`);
143
+ if (c.description) {
144
+ console.log(` ${c.description.substring(0, 70)}${c.description.length > 70 ? '...' : ''}`);
145
+ }
146
+ console.log(` ā¬‡ļø ${c.downloads.toLocaleString()} installs Ā· ⭐ ${c.stars.toLocaleString()} stars`);
147
+ console.log('');
148
+ });
149
+ }
150
+ console.log(`\nšŸ’” View details: prpm collection info <collection>`);
151
+ console.log(`šŸ’” Install: prpm install @collection/<name>`);
152
+ await telemetry_1.telemetry.track({
153
+ command: 'collections:list',
154
+ success: true,
155
+ duration: Date.now() - startTime,
156
+ data: {
157
+ count: result.collections.length,
158
+ filters: options,
159
+ },
160
+ });
161
+ }
162
+ catch (error) {
163
+ const errorMessage = error instanceof Error ? error.message : String(error);
164
+ console.error(`\nāŒ Failed to list collections: ${errorMessage}`);
165
+ await telemetry_1.telemetry.track({
166
+ command: 'collections:list',
167
+ success: false,
168
+ error: errorMessage,
169
+ duration: Date.now() - startTime,
170
+ });
171
+ process.exit(1);
172
+ }
173
+ }
174
+ /**
175
+ * Show collection details
176
+ */
177
+ async function handleCollectionInfo(collectionSpec) {
178
+ const startTime = Date.now();
179
+ try {
180
+ // Parse collection spec: @scope/id or scope/id
181
+ const match = collectionSpec.match(/^@?([^/]+)\/([^/@]+)(?:@(.+))?$/);
182
+ if (!match) {
183
+ throw new Error('Invalid collection format. Use: @scope/id or scope/id[@version]');
184
+ }
185
+ const [, scope, id, version] = match;
186
+ const config = await (0, user_config_1.getConfig)();
187
+ const client = (0, registry_client_1.getRegistryClient)(config);
188
+ console.log(`šŸ“¦ Loading collection: @${scope}/${id}...\n`);
189
+ const collection = await client.getCollection(scope, id, version);
190
+ // Header
191
+ console.log(`${collection.icon || 'šŸ“¦'} ${collection.name}`);
192
+ console.log(`${'='.repeat(collection.name.length + 2)}`);
193
+ console.log('');
194
+ console.log(collection.description);
195
+ console.log('');
196
+ // Stats
197
+ console.log('šŸ“Š Stats:');
198
+ console.log(` Downloads: ${collection.downloads.toLocaleString()}`);
199
+ console.log(` Stars: ${collection.stars.toLocaleString()}`);
200
+ console.log(` Version: ${collection.version}`);
201
+ console.log(` Packages: ${collection.packages.length}`);
202
+ console.log(` Author: ${collection.author}${collection.verified ? ' āœ“' : ''}`);
203
+ if (collection.category) {
204
+ console.log(` Category: ${collection.category}`);
205
+ }
206
+ if (collection.tags && collection.tags.length > 0) {
207
+ console.log(` Tags: ${collection.tags.join(', ')}`);
208
+ }
209
+ console.log('');
210
+ // Packages
211
+ console.log('šŸ“‹ Included Packages:');
212
+ console.log('');
213
+ const requiredPkgs = collection.packages.filter(p => p.required);
214
+ const optionalPkgs = collection.packages.filter(p => !p.required);
215
+ if (requiredPkgs.length > 0) {
216
+ console.log(' Required:');
217
+ requiredPkgs.forEach((pkg, i) => {
218
+ console.log(` ${i + 1}. āœ“ ${pkg.packageId}@${pkg.version || 'latest'}`);
219
+ if (pkg.package) {
220
+ console.log(` ${pkg.package.description || pkg.package.display_name}`);
221
+ }
222
+ if (pkg.reason) {
223
+ console.log(` šŸ’” ${pkg.reason}`);
224
+ }
225
+ console.log('');
226
+ });
227
+ }
228
+ if (optionalPkgs.length > 0) {
229
+ console.log(' Optional:');
230
+ optionalPkgs.forEach((pkg, i) => {
231
+ console.log(` ${i + 1}. ā—‹ ${pkg.packageId}@${pkg.version || 'latest'}`);
232
+ if (pkg.package) {
233
+ console.log(` ${pkg.package.description || pkg.package.display_name}`);
234
+ }
235
+ if (pkg.reason) {
236
+ console.log(` šŸ’” ${pkg.reason}`);
237
+ }
238
+ console.log('');
239
+ });
240
+ }
241
+ // Installation
242
+ console.log('šŸ’” Install:');
243
+ console.log(` prpm install @${scope}/${id}`);
244
+ if (optionalPkgs.length > 0) {
245
+ console.log(` prpm install @${scope}/${id} --skip-optional # Skip optional packages`);
246
+ }
247
+ console.log('');
248
+ await telemetry_1.telemetry.track({
249
+ command: 'collections:info',
250
+ success: true,
251
+ duration: Date.now() - startTime,
252
+ data: {
253
+ scope,
254
+ id,
255
+ packageCount: collection.packages.length,
256
+ },
257
+ });
258
+ }
259
+ catch (error) {
260
+ const errorMessage = error instanceof Error ? error.message : String(error);
261
+ console.error(`\nāŒ Failed to get collection info: ${errorMessage}`);
262
+ await telemetry_1.telemetry.track({
263
+ command: 'collections:info',
264
+ success: false,
265
+ error: errorMessage,
266
+ duration: Date.now() - startTime,
267
+ });
268
+ process.exit(1);
269
+ }
270
+ }
271
+ /**
272
+ * Install a collection
273
+ */
274
+ async function handleCollectionInstall(collectionSpec, options) {
275
+ const startTime = Date.now();
276
+ let packagesInstalled = 0;
277
+ let packagesFailed = 0;
278
+ try {
279
+ // Parse collection spec
280
+ const match = collectionSpec.match(/^@?([^/]+)\/([^/@]+)(?:@(.+))?$/);
281
+ if (!match) {
282
+ throw new Error('Invalid collection format. Use: @scope/id or scope/id[@version]');
283
+ }
284
+ const [, scope, id, version] = match;
285
+ const config = await (0, user_config_1.getConfig)();
286
+ const client = (0, registry_client_1.getRegistryClient)(config);
287
+ // Get collection installation plan
288
+ console.log(`šŸ“¦ Installing collection: @${scope}/${id}...\n`);
289
+ const installResult = await client.installCollection({
290
+ scope,
291
+ id,
292
+ version,
293
+ format: options.format,
294
+ skipOptional: options.skipOptional,
295
+ });
296
+ const collection = installResult.collection;
297
+ const packages = installResult.packagesToInstall;
298
+ console.log(`šŸ“¦ ${collection.name}`);
299
+ console.log(` ${packages.length} packages to install\n`);
300
+ if (options.dryRun) {
301
+ console.log('šŸ” Dry run - would install:\n');
302
+ packages.forEach((pkg, i) => {
303
+ const required = pkg.required ? 'āœ“' : 'ā—‹';
304
+ console.log(` ${i + 1}/${packages.length} ${required} ${pkg.packageId}@${pkg.version} (${pkg.format})`);
305
+ });
306
+ console.log('');
307
+ return;
308
+ }
309
+ // Install packages sequentially
310
+ for (let i = 0; i < packages.length; i++) {
311
+ const pkg = packages[i];
312
+ const progress = `${i + 1}/${packages.length}`;
313
+ try {
314
+ console.log(`\n ${progress} Installing ${pkg.packageId}@${pkg.version}...`);
315
+ await (0, install_1.handleInstall)(`${pkg.packageId}@${pkg.version}`, {
316
+ as: pkg.format,
317
+ });
318
+ console.log(` ${progress} āœ“ ${pkg.packageId}`);
319
+ packagesInstalled++;
320
+ }
321
+ catch (error) {
322
+ const errorMessage = error instanceof Error ? error.message : String(error);
323
+ console.error(` ${progress} āœ— ${pkg.packageId}: ${errorMessage}`);
324
+ packagesFailed++;
325
+ if (pkg.required) {
326
+ throw new Error(`Failed to install required package: ${pkg.packageId}`);
327
+ }
328
+ }
329
+ }
330
+ console.log(`\nāœ… Collection installed successfully!`);
331
+ console.log(` ${packagesInstalled}/${packages.length} packages installed`);
332
+ if (packagesFailed > 0) {
333
+ console.log(` ${packagesFailed} optional packages failed`);
334
+ }
335
+ console.log('');
336
+ await telemetry_1.telemetry.track({
337
+ command: 'collections:install',
338
+ success: true,
339
+ duration: Date.now() - startTime,
340
+ data: {
341
+ scope,
342
+ id,
343
+ packageCount: packages.length,
344
+ installed: packagesInstalled,
345
+ failed: packagesFailed,
346
+ format: options.format,
347
+ },
348
+ });
349
+ }
350
+ catch (error) {
351
+ const errorMessage = error instanceof Error ? error.message : String(error);
352
+ console.error(`\nāŒ Failed to install collection: ${errorMessage}`);
353
+ await telemetry_1.telemetry.track({
354
+ command: 'collections:install',
355
+ success: false,
356
+ error: errorMessage,
357
+ duration: Date.now() - startTime,
358
+ data: {
359
+ installed: packagesInstalled,
360
+ failed: packagesFailed,
361
+ },
362
+ });
363
+ process.exit(1);
364
+ }
365
+ }
366
+ /**
367
+ * Create collections command group
368
+ */
369
+ function createCollectionsCommand() {
370
+ const command = new commander_1.Command('collections');
371
+ command
372
+ .description('Manage package collections')
373
+ .alias('collection')
374
+ .action(async (options) => {
375
+ await handleCollectionsList(options);
376
+ });
377
+ // Search subcommand
378
+ command
379
+ .command('search <query>')
380
+ .description('Search for collections')
381
+ .option('--category <category>', 'Filter by category')
382
+ .option('--tag <tag>', 'Filter by tag')
383
+ .option('--official', 'Show only official collections')
384
+ .option('--limit <number>', 'Number of results to show', '50')
385
+ .action(async (query, options) => {
386
+ await handleCollectionsSearch(query, {
387
+ category: options.category,
388
+ tag: options.tag,
389
+ official: options.official,
390
+ limit: parseInt(options.limit, 10),
391
+ });
392
+ });
393
+ // List subcommand
394
+ command
395
+ .command('list')
396
+ .description('List available collections')
397
+ .option('--category <category>', 'Filter by category')
398
+ .option('--tag <tag>', 'Filter by tag')
399
+ .option('--official', 'Show only official collections')
400
+ .option('--scope <scope>', 'Filter by scope')
401
+ .action(handleCollectionsList);
402
+ // Info subcommand
403
+ command
404
+ .command('info <collection>')
405
+ .description('Show collection details')
406
+ .action(handleCollectionInfo);
407
+ // Install handled by main install command with @scope/id syntax
408
+ return command;
409
+ }
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ /**
3
+ * Deps command - Show dependency tree for a package
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.handleDeps = handleDeps;
7
+ exports.createDepsCommand = createDepsCommand;
8
+ const commander_1 = require("commander");
9
+ const registry_client_1 = require("@prpm/registry-client");
10
+ const user_config_1 = require("../core/user-config");
11
+ const telemetry_1 = require("../core/telemetry");
12
+ /**
13
+ * Display dependency tree
14
+ */
15
+ async function handleDeps(packageSpec) {
16
+ const startTime = Date.now();
17
+ let success = false;
18
+ let error;
19
+ try {
20
+ // Parse package spec
21
+ const [packageId, version] = packageSpec.split('@');
22
+ console.log(`šŸ“¦ Resolving dependencies for ${packageId}${version ? `@${version}` : ''}...\n`);
23
+ const config = await (0, user_config_1.getConfig)();
24
+ const client = (0, registry_client_1.getRegistryClient)(config);
25
+ // Resolve dependency tree
26
+ const result = await client.resolveDependencies(packageId, version);
27
+ if (Object.keys(result.resolved).length === 1) {
28
+ console.log('āœ… No dependencies\n');
29
+ success = true;
30
+ return;
31
+ }
32
+ // Display resolved versions
33
+ console.log('šŸ“‹ Resolved Dependencies:\n');
34
+ for (const [pkgId, pkgVersion] of Object.entries(result.resolved)) {
35
+ if (pkgId === packageId)
36
+ continue; // Skip root package
37
+ console.log(` ${pkgId}@${pkgVersion}`);
38
+ }
39
+ console.log(`\nšŸ“Š Total: ${Object.keys(result.resolved).length - 1} dependencies\n`);
40
+ // Display tree structure
41
+ console.log('🌳 Dependency Tree:\n');
42
+ printTree(result.tree, packageId, '', true);
43
+ success = true;
44
+ }
45
+ catch (err) {
46
+ error = err instanceof Error ? err.message : String(err);
47
+ console.error(`\nāŒ Failed to resolve dependencies: ${error}`);
48
+ if (error.includes('Circular dependency')) {
49
+ console.log(`\nšŸ’” Tip: This package has a circular dependency which is not allowed.`);
50
+ }
51
+ else if (error.includes('not found')) {
52
+ console.log(`\nšŸ’” Tip: Check the package name and version are correct.`);
53
+ }
54
+ process.exit(1);
55
+ }
56
+ finally {
57
+ await telemetry_1.telemetry.track({
58
+ command: 'deps',
59
+ success,
60
+ error,
61
+ duration: Date.now() - startTime,
62
+ data: {
63
+ packageId: packageSpec.split('@')[0],
64
+ },
65
+ });
66
+ }
67
+ }
68
+ /**
69
+ * Print dependency tree recursively
70
+ */
71
+ function printTree(tree, packageId, prefix = '', isLast = true) {
72
+ const node = tree[packageId];
73
+ if (!node)
74
+ return;
75
+ const deps = node.dependencies || {};
76
+ const depKeys = Object.keys(deps);
77
+ console.log(`${prefix}${isLast ? '└─' : 'ā”œā”€'} ${packageId}@${node.version}`);
78
+ depKeys.forEach((depId, index) => {
79
+ const isLastDep = index === depKeys.length - 1;
80
+ const newPrefix = prefix + (isLast ? ' ' : '│ ');
81
+ printTree(tree, depId, newPrefix, isLastDep);
82
+ });
83
+ }
84
+ /**
85
+ * Create the deps command
86
+ */
87
+ function createDepsCommand() {
88
+ return new commander_1.Command('deps')
89
+ .description('Show dependency tree for a package')
90
+ .argument('<package>', 'Package to analyze (e.g., react-rules or react-rules@1.2.0)')
91
+ .action(handleDeps);
92
+ }