prpm 0.1.17 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/index.js +14257 -107
  2. package/package.json +11 -9
  3. package/dist/__tests__/e2e/test-helpers.js +0 -151
  4. package/dist/commands/buy-credits.js +0 -224
  5. package/dist/commands/catalog.js +0 -365
  6. package/dist/commands/collections.js +0 -655
  7. package/dist/commands/config.js +0 -161
  8. package/dist/commands/credits.js +0 -186
  9. package/dist/commands/index.js +0 -184
  10. package/dist/commands/info.js +0 -78
  11. package/dist/commands/init.js +0 -684
  12. package/dist/commands/install.js +0 -789
  13. package/dist/commands/list.js +0 -189
  14. package/dist/commands/login.js +0 -316
  15. package/dist/commands/outdated.js +0 -130
  16. package/dist/commands/playground.js +0 -570
  17. package/dist/commands/popular.js +0 -33
  18. package/dist/commands/publish.js +0 -803
  19. package/dist/commands/schema.js +0 -41
  20. package/dist/commands/search.js +0 -446
  21. package/dist/commands/subscribe.js +0 -211
  22. package/dist/commands/telemetry.js +0 -104
  23. package/dist/commands/trending.js +0 -86
  24. package/dist/commands/uninstall.js +0 -120
  25. package/dist/commands/update.js +0 -121
  26. package/dist/commands/upgrade.js +0 -121
  27. package/dist/commands/whoami.js +0 -83
  28. package/dist/core/claude-config.js +0 -91
  29. package/dist/core/cursor-config.js +0 -130
  30. package/dist/core/downloader.js +0 -64
  31. package/dist/core/errors.js +0 -29
  32. package/dist/core/filesystem.js +0 -242
  33. package/dist/core/lockfile.js +0 -292
  34. package/dist/core/marketplace-converter.js +0 -224
  35. package/dist/core/registry-client.js +0 -305
  36. package/dist/core/schema-validator.js +0 -74
  37. package/dist/core/telemetry.js +0 -253
  38. package/dist/core/user-config.js +0 -147
  39. package/dist/types/registry.js +0 -12
  40. package/dist/types.js +0 -36
  41. package/dist/utils/license-extractor.js +0 -122
  42. package/dist/utils/multi-package.js +0 -117
  43. package/dist/utils/parallel-publisher.js +0 -144
  44. package/dist/utils/script-executor.js +0 -72
  45. package/dist/utils/snippet-extractor.js +0 -77
  46. package/dist/utils/webapp-url.js +0 -44
@@ -1,684 +0,0 @@
1
- "use strict";
2
- /**
3
- * Init command implementation
4
- * Scaffolds a new PRPM package with interactive prompts
5
- */
6
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
- if (k2 === undefined) k2 = k;
8
- var desc = Object.getOwnPropertyDescriptor(m, k);
9
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
- desc = { enumerable: true, get: function() { return m[k]; } };
11
- }
12
- Object.defineProperty(o, k2, desc);
13
- }) : (function(o, m, k, k2) {
14
- if (k2 === undefined) k2 = k;
15
- o[k2] = m[k];
16
- }));
17
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
- Object.defineProperty(o, "default", { enumerable: true, value: v });
19
- }) : function(o, v) {
20
- o["default"] = v;
21
- });
22
- var __importStar = (this && this.__importStar) || (function () {
23
- var ownKeys = function(o) {
24
- ownKeys = Object.getOwnPropertyNames || function (o) {
25
- var ar = [];
26
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
- return ar;
28
- };
29
- return ownKeys(o);
30
- };
31
- return function (mod) {
32
- if (mod && mod.__esModule) return mod;
33
- var result = {};
34
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
- __setModuleDefault(result, mod);
36
- return result;
37
- };
38
- })();
39
- Object.defineProperty(exports, "__esModule", { value: true });
40
- exports.createInitCommand = createInitCommand;
41
- const commander_1 = require("commander");
42
- const promises_1 = require("fs/promises");
43
- const path_1 = require("path");
44
- const fs_1 = require("fs");
45
- const readline = __importStar(require("readline/promises"));
46
- const process_1 = require("process");
47
- const types_1 = require("../types");
48
- const errors_1 = require("../core/errors");
49
- const FORMAT_EXAMPLES = {
50
- cursor: {
51
- description: 'Cursor AI coding rules',
52
- files: ['.cursorrules', 'README.md'],
53
- },
54
- claude: {
55
- description: 'Claude AI skills and agents',
56
- files: ['.claude/skills/example-skill/SKILL.md', 'README.md'],
57
- },
58
- continue: {
59
- description: 'Continue AI coding rules',
60
- files: ['.continuerules', 'README.md'],
61
- },
62
- windsurf: {
63
- description: 'Windsurf AI coding rules',
64
- files: ['.windsurf/rules', 'README.md'],
65
- },
66
- copilot: {
67
- description: 'GitHub Copilot (repository-wide, path-specific, and chat modes)',
68
- files: ['.github/copilot-instructions.md', '.github/instructions/typescript.instructions.md', '.github/chatmodes/code-reviewer.chatmode.md', 'README.md'],
69
- },
70
- kiro: {
71
- description: 'Kiro steering files and hooks',
72
- files: ['.kiro/steering/example.md', '.kiro/hooks/example-hook.kiro.hook', 'README.md'],
73
- },
74
- 'agents.md': {
75
- description: 'OpenAI agents.md project instructions',
76
- files: ['agents.md', 'README.md'],
77
- },
78
- generic: {
79
- description: 'Generic AI prompts',
80
- files: ['prompts/example.md', 'README.md'],
81
- },
82
- mcp: {
83
- description: 'Model Context Protocol',
84
- files: ['mcp.json', 'README.md'],
85
- },
86
- };
87
- const EXAMPLE_TEMPLATES = {
88
- cursor: {
89
- '.cursorrules': `# Cursor Rules
90
-
91
- Add your Cursor AI coding rules here.
92
-
93
- ## Code Style
94
-
95
- - Use TypeScript
96
- - Follow functional programming patterns
97
- - Write comprehensive tests
98
-
99
- ## Best Practices
100
-
101
- - Keep functions small and focused
102
- - Use meaningful variable names
103
- - Document complex logic
104
- `,
105
- },
106
- claude: {
107
- '.claude/skills/example-skill/SKILL.md': `---
108
- name: example-skill
109
- description: Example Claude skill - replace with your actual skill
110
- tags: example, template
111
- ---
112
-
113
- # Example Skill
114
-
115
- This is an example Claude skill. Replace this content with your actual skill definition.
116
-
117
- ## What this skill does
118
-
119
- Describe what this skill helps the AI accomplish.
120
-
121
- ## When to use this skill
122
-
123
- Explain when this skill should be invoked.
124
-
125
- ## Instructions
126
-
127
- Provide detailed instructions for the AI to follow when using this skill.
128
- `,
129
- },
130
- windsurf: {
131
- '.windsurf/rules': `# Windsurf Rules
132
-
133
- Add your Windsurf AI coding rules here.
134
-
135
- ## Code Conventions
136
-
137
- - Use TypeScript for type safety
138
- - Follow React best practices
139
- - Write unit tests for all components
140
-
141
- ## Architecture
142
-
143
- - Component-based architecture
144
- - Separate business logic from UI
145
- - Use hooks for state management
146
- `,
147
- },
148
- copilot: {
149
- '.github/copilot-instructions.md': `# GitHub Copilot Repository-Wide Instructions
150
-
151
- These instructions apply to all files in this repository.
152
-
153
- ## Code Standards
154
-
155
- - Use TypeScript strict mode
156
- - Follow ESLint rules
157
- - Write JSDoc comments for public APIs
158
-
159
- ## Patterns to Follow
160
-
161
- - Use async/await for asynchronous operations
162
- - Implement error handling with try/catch
163
- - Export named functions instead of default exports
164
- - Write unit tests for all new features
165
- `,
166
- '.github/instructions/typescript.instructions.md': `---
167
- applyTo:
168
- - "**/*.ts"
169
- - "**/*.tsx"
170
- ---
171
-
172
- # TypeScript-Specific Instructions
173
-
174
- These instructions apply only to TypeScript files.
175
-
176
- ## Type Safety
177
-
178
- - Use strict null checks
179
- - Avoid 'any' type - use 'unknown' or specific types
180
- - Define interfaces for all object shapes
181
- - Use type guards for runtime type checking
182
-
183
- ## Patterns
184
-
185
- - Prefer const over let
186
- - Use template literals for string concatenation
187
- - Destructure objects and arrays when appropriate
188
- `,
189
- '.github/chatmodes/code-reviewer.chatmode.md': `---
190
- name: Code Reviewer
191
- description: Expert code reviewer focusing on best practices, security, and maintainability
192
- ---
193
-
194
- # Example Chat Mode
195
-
196
- This is an example chat mode. Replace with your actual chat mode persona and instructions.
197
-
198
- ## Role
199
-
200
- You are a [describe the role/persona].
201
-
202
- ## Capabilities
203
-
204
- - Capability 1
205
- - Capability 2
206
- - Capability 3
207
-
208
- ## Guidelines
209
-
210
- When responding:
211
- 1. Guideline 1
212
- 2. Guideline 2
213
- 3. Guideline 3
214
-
215
- ## Example Interactions
216
-
217
- Provide examples of how this chat mode should respond.
218
- `,
219
- },
220
- kiro: {
221
- '.kiro/steering/example.md': `---
222
- inclusion: manual
223
- ---
224
-
225
- # Example Kiro Steering File
226
-
227
- Add your Kiro steering instructions here.
228
-
229
- ## Context
230
-
231
- Describe the context where this steering file applies.
232
-
233
- ## Guidelines
234
-
235
- - Guideline 1
236
- - Guideline 2
237
- - Guideline 3
238
-
239
- ## Examples
240
-
241
- Provide examples of correct patterns.
242
- `,
243
- '.kiro/hooks/example-hook.kiro.hook': `{
244
- "enabled": false,
245
- "name": "Example Hook",
246
- "description": "Example Kiro hook - disabled by default. Replace with your actual hook logic.",
247
- "version": "1",
248
- "when": {
249
- "type": "fileEdited",
250
- "patterns": [
251
- "**/*.ts",
252
- "**/*.tsx"
253
- ]
254
- },
255
- "then": {
256
- "type": "askAgent",
257
- "prompt": "A file has been modified. Please review it for best practices:\\n1. Check for code quality issues\\n2. Verify error handling\\n3. Suggest improvements\\n4. Ensure tests are updated"
258
- }
259
- }`,
260
- },
261
- 'agents.md': {
262
- 'agents.md': `# Project Coding Guidelines
263
-
264
- Project-specific instructions for AI coding agents (OpenAI Codex, etc.).
265
-
266
- ## TypeScript Conventions
267
-
268
- - Use strict mode for type safety
269
- - Prefer interfaces over types for object shapes
270
- - Use const assertions where appropriate
271
-
272
- ## Testing Requirements
273
-
274
- - Write tests for all public APIs
275
- - Maintain >80% code coverage
276
- - Use descriptive test names
277
-
278
- ## Code Examples
279
-
280
- ### Preferred: Async/Await
281
-
282
- \`\`\`typescript
283
- async function fetchData() {
284
- const response = await fetch('/api/data');
285
- return response.json();
286
- }
287
- \`\`\`
288
-
289
- ### Avoid: Callback Hell
290
-
291
- \`\`\`typescript
292
- getData(function(data) {
293
- processData(data, function(result) {
294
- // Deeply nested callbacks
295
- });
296
- });
297
- \`\`\`
298
- `,
299
- },
300
- generic: {
301
- 'prompts/example.md': `# Example Prompt
302
-
303
- This is an example generic AI prompt. Replace with your actual prompt content.
304
-
305
- ## Purpose
306
-
307
- Describe what this prompt is meant to accomplish.
308
-
309
- ## Instructions
310
-
311
- Provide clear instructions for the AI.
312
-
313
- ## Examples
314
-
315
- Include examples if helpful.
316
- `,
317
- },
318
- };
319
- /**
320
- * Prompt user for input with a default value
321
- */
322
- async function prompt(rl, question, defaultValue) {
323
- const promptText = defaultValue
324
- ? `${question} (${defaultValue}): `
325
- : `${question}: `;
326
- const answer = await rl.question(promptText);
327
- return answer.trim() || defaultValue || '';
328
- }
329
- /**
330
- * Prompt user to select from a list
331
- */
332
- async function select(rl, question, options, defaultValue) {
333
- console.log(`\n${question}`);
334
- options.forEach((opt, idx) => {
335
- const isDefault = opt === defaultValue;
336
- console.log(` ${idx + 1}. ${opt}${isDefault ? ' (default)' : ''}`);
337
- });
338
- const answer = await rl.question('\nSelect (1-' + options.length + '): ');
339
- const selection = parseInt(answer.trim(), 10);
340
- if (!answer.trim() && defaultValue) {
341
- return defaultValue;
342
- }
343
- if (selection >= 1 && selection <= options.length) {
344
- return options[selection - 1];
345
- }
346
- console.log('Invalid selection, using default.');
347
- return defaultValue || options[0];
348
- }
349
- /**
350
- * Extract metadata from file content (YAML frontmatter or comments)
351
- */
352
- async function extractMetadataFromFile(filePath) {
353
- try {
354
- const content = await (0, promises_1.readFile)(filePath, 'utf-8');
355
- const metadata = {};
356
- // Try to extract YAML frontmatter (---\nkey: value\n---)
357
- const frontmatterMatch = content.match(/^---\s*\n([\s\S]*?)\n---/);
358
- if (frontmatterMatch) {
359
- const frontmatter = frontmatterMatch[1];
360
- // Extract description
361
- const descMatch = frontmatter.match(/description:\s*(.+)/i);
362
- if (descMatch) {
363
- metadata.description = descMatch[1].trim().replace(/^["']|["']$/g, '');
364
- }
365
- // Extract name
366
- const nameMatch = frontmatter.match(/name:\s*(.+)/i);
367
- if (nameMatch) {
368
- metadata.name = nameMatch[1].trim().replace(/^["']|["']$/g, '');
369
- }
370
- // Extract tags
371
- const tagsMatch = frontmatter.match(/tags:\s*(.+)/i);
372
- if (tagsMatch) {
373
- const tagsStr = tagsMatch[1].trim();
374
- // Handle both array format [tag1, tag2] and comma-separated
375
- if (tagsStr.startsWith('[')) {
376
- metadata.tags = tagsStr
377
- .replace(/[\[\]]/g, '')
378
- .split(',')
379
- .map(t => t.trim().replace(/^["']|["']$/g, ''))
380
- .filter(Boolean);
381
- }
382
- else {
383
- metadata.tags = tagsStr
384
- .split(',')
385
- .map(t => t.trim().replace(/^["']|["']$/g, ''))
386
- .filter(Boolean);
387
- }
388
- }
389
- }
390
- // If no frontmatter, try to extract from first heading or comments
391
- if (!metadata.description) {
392
- // Try markdown heading
393
- const headingMatch = content.match(/^#\s+(.+)/m);
394
- if (headingMatch) {
395
- metadata.description = headingMatch[1].trim();
396
- }
397
- else {
398
- // Try HTML/JSDoc style comment
399
- const commentMatch = content.match(/\/\*\*\s*\n\s*\*\s*(.+)/);
400
- if (commentMatch) {
401
- metadata.description = commentMatch[1].trim();
402
- }
403
- }
404
- }
405
- return metadata;
406
- }
407
- catch (error) {
408
- // File might not exist yet, that's okay
409
- return {};
410
- }
411
- }
412
- /**
413
- * Get package name from current directory or git config
414
- */
415
- function getDefaultPackageName() {
416
- const cwd = process.cwd();
417
- const dirName = cwd.split('/').pop() || 'my-package';
418
- // Normalize to package name format
419
- return dirName.toLowerCase().replace(/[^a-z0-9-]/g, '-');
420
- }
421
- /**
422
- * Get author from git config
423
- */
424
- function getDefaultAuthor() {
425
- try {
426
- const { execSync } = require('child_process');
427
- const name = execSync('git config user.name', { encoding: 'utf-8' }).trim();
428
- const email = execSync('git config user.email', { encoding: 'utf-8' }).trim();
429
- if (name && email) {
430
- return `${name} <${email}>`;
431
- }
432
- if (name) {
433
- return name;
434
- }
435
- }
436
- catch {
437
- // Git not configured
438
- }
439
- return '';
440
- }
441
- /**
442
- * Create example files based on format
443
- */
444
- async function createExampleFiles(format, files, packageName) {
445
- const templates = EXAMPLE_TEMPLATES[format] || {};
446
- for (const file of files) {
447
- const filePath = (0, path_1.join)(process.cwd(), file);
448
- const dirPath = (0, path_1.join)(filePath, '..');
449
- // Create directory if it doesn't exist
450
- if (!(0, fs_1.existsSync)(dirPath)) {
451
- await (0, promises_1.mkdir)(dirPath, { recursive: true });
452
- }
453
- // Skip if file already exists
454
- if ((0, fs_1.existsSync)(filePath)) {
455
- console.log(` Skipping ${file} (already exists)`);
456
- continue;
457
- }
458
- // Use template or create empty file
459
- let content = templates[file] || `# ${file}\n\nAdd your content here.\n`;
460
- // Replace 'example-skill' placeholder with actual package name in template content
461
- content = content.replace(/example-skill/g, packageName);
462
- await (0, promises_1.writeFile)(filePath, content, 'utf-8');
463
- console.log(` Created ${file}`);
464
- }
465
- }
466
- /**
467
- * Create README.md
468
- */
469
- async function createReadme(config) {
470
- const readmePath = (0, path_1.join)(process.cwd(), 'README.md');
471
- if ((0, fs_1.existsSync)(readmePath)) {
472
- console.log(' Skipping README.md (already exists)');
473
- return;
474
- }
475
- const content = `# ${config.name}
476
-
477
- ${config.description}
478
-
479
- ## Installation
480
-
481
- \`\`\`bash
482
- prpm install ${config.name}
483
- \`\`\`
484
-
485
- ## Format
486
-
487
- ${config.format}${config.subtype ? ` (${config.subtype})` : ''}
488
-
489
- ## Files
490
-
491
- ${config.files.map(f => `- ${f}`).join('\n')}
492
-
493
- ## Author
494
-
495
- ${config.author}
496
-
497
- ## License
498
-
499
- ${config.license}
500
- `;
501
- await (0, promises_1.writeFile)(readmePath, content, 'utf-8');
502
- console.log(' Created README.md');
503
- }
504
- /**
505
- * Initialize a new PRPM package
506
- */
507
- async function initPackage(options) {
508
- const manifestPath = (0, path_1.join)(process.cwd(), 'prpm.json');
509
- // Check if prpm.json already exists
510
- if ((0, fs_1.existsSync)(manifestPath) && !options.force) {
511
- throw new Error('prpm.json already exists. Use --force to overwrite, or run this command in a different directory.');
512
- }
513
- const config = {};
514
- // Use defaults if --yes flag
515
- if (options.yes) {
516
- config.name = getDefaultPackageName();
517
- config.version = '1.0.0';
518
- config.description = 'A PRPM package';
519
- config.format = 'cursor';
520
- config.subtype = 'rule';
521
- config.author = getDefaultAuthor() || 'Your Name';
522
- config.license = 'MIT';
523
- config.tags = [];
524
- // Replace 'example-skill' with actual package name in file paths
525
- config.files = FORMAT_EXAMPLES.cursor.files.map(f => f.replace(/example-skill/g, config.name || 'example-skill'));
526
- }
527
- else {
528
- // Interactive prompts
529
- const rl = readline.createInterface({ input: process_1.stdin, output: process_1.stdout });
530
- try {
531
- console.log('\nšŸš€ Welcome to PRPM package initialization!\n');
532
- console.log('This utility will walk you through creating a prpm.json file.\n');
533
- // Package name
534
- const defaultName = getDefaultPackageName();
535
- config.name = await prompt(rl, 'Package name', defaultName);
536
- // Version
537
- config.version = await prompt(rl, 'Version', '1.0.0');
538
- // Description
539
- config.description = await prompt(rl, 'Description', 'A PRPM package for AI coding assistants');
540
- // Format
541
- config.format = await select(rl, 'Select package format:', types_1.FORMATS, 'cursor');
542
- // Subtype
543
- config.subtype = await select(rl, 'Select package subtype:', types_1.SUBTYPES, 'rule');
544
- // Author
545
- const defaultAuthor = getDefaultAuthor();
546
- config.author = await prompt(rl, 'Author', defaultAuthor || 'Your Name');
547
- // License
548
- config.license = await prompt(rl, 'License', 'MIT');
549
- // Repository
550
- const includeRepo = await prompt(rl, 'Add repository URL? (y/N)', 'n');
551
- if (includeRepo.toLowerCase() === 'y') {
552
- config.repository = await prompt(rl, 'Repository URL', '');
553
- }
554
- // Tags
555
- const tagsInput = await prompt(rl, 'Tags (comma-separated)', config.format);
556
- config.tags = tagsInput
557
- .split(',')
558
- .map(t => t.trim())
559
- .filter(Boolean);
560
- // Files - use examples based on format
561
- const formatExamples = FORMAT_EXAMPLES[config.format];
562
- // Replace 'example-skill' with actual package name in file paths
563
- const exampleFiles = formatExamples.files.map(f => f.replace(/example-skill/g, config.name || 'example-skill'));
564
- console.log(`\nExample files for ${config.format}:`);
565
- exampleFiles.forEach((f, idx) => console.log(` ${idx + 1}. ${f}`));
566
- const useExamples = await prompt(rl, '\nUse example file structure? (Y/n)', 'y');
567
- if (useExamples.toLowerCase() !== 'n') {
568
- config.files = exampleFiles;
569
- }
570
- else {
571
- const filesInput = await prompt(rl, 'Files (comma-separated)', exampleFiles.join(', '));
572
- config.files = filesInput
573
- .split(',')
574
- .map(f => f.trim())
575
- .filter(Boolean);
576
- }
577
- // Try to extract metadata from the first file if it exists
578
- if (config.files.length > 0) {
579
- const firstFile = config.files[0];
580
- console.log(`\nšŸ” Checking ${firstFile} for metadata...`);
581
- const extractedMetadata = await extractMetadataFromFile(firstFile);
582
- if (extractedMetadata.description) {
583
- console.log(` Found description: "${extractedMetadata.description}"`);
584
- const useExtracted = await prompt(rl, ' Use this description? (Y/n)', 'y');
585
- if (useExtracted.toLowerCase() !== 'n') {
586
- config.description = extractedMetadata.description;
587
- }
588
- }
589
- if (extractedMetadata.tags && extractedMetadata.tags.length > 0) {
590
- console.log(` Found tags: ${extractedMetadata.tags.join(', ')}`);
591
- const useExtractedTags = await prompt(rl, ' Use these tags? (Y/n)', 'y');
592
- if (useExtractedTags.toLowerCase() !== 'n') {
593
- config.tags = extractedMetadata.tags;
594
- }
595
- }
596
- if (extractedMetadata.name && !config.name.includes(extractedMetadata.name)) {
597
- console.log(` Found name: "${extractedMetadata.name}"`);
598
- const useExtractedName = await prompt(rl, ' Include in package name? (y/N)', 'n');
599
- if (useExtractedName.toLowerCase() === 'y') {
600
- config.name = `${config.name}-${extractedMetadata.name.toLowerCase().replace(/\s+/g, '-')}`;
601
- }
602
- }
603
- }
604
- // Ask if user wants to add more files
605
- let addingMoreFiles = true;
606
- while (addingMoreFiles) {
607
- const addMore = await prompt(rl, '\nAdd more files to the package? (y/N)', 'n');
608
- if (addMore.toLowerCase() === 'y') {
609
- const additionalFiles = await prompt(rl, 'Additional files (comma-separated)', '');
610
- const newFiles = additionalFiles
611
- .split(',')
612
- .map(f => f.trim())
613
- .filter(Boolean);
614
- if (newFiles.length > 0) {
615
- config.files = [...config.files, ...newFiles];
616
- console.log(`\nCurrent files (${config.files.length}):`);
617
- config.files.forEach((f, idx) => console.log(` ${idx + 1}. ${f}`));
618
- }
619
- }
620
- else {
621
- addingMoreFiles = false;
622
- }
623
- }
624
- }
625
- finally {
626
- rl.close();
627
- }
628
- }
629
- // Create manifest
630
- const manifest = {
631
- name: config.name,
632
- version: config.version,
633
- description: config.description,
634
- format: config.format,
635
- subtype: config.subtype || 'rule', // Default to 'rule' if not specified
636
- };
637
- manifest.author = config.author;
638
- manifest.license = config.license;
639
- if (config.repository) {
640
- manifest.repository = config.repository;
641
- }
642
- if (config.tags && config.tags.length > 0) {
643
- manifest.tags = config.tags;
644
- }
645
- manifest.files = config.files;
646
- // Write prpm.json
647
- await (0, promises_1.writeFile)(manifestPath, JSON.stringify(manifest, null, 2) + '\n', 'utf-8');
648
- console.log('\nāœ… Created prpm.json\n');
649
- // Create example files
650
- if (config.files && config.format && config.name) {
651
- console.log('Creating example files...\n');
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);
655
- // Create README
656
- await createReadme(config);
657
- }
658
- console.log('\n✨ Package initialized successfully!\n');
659
- console.log('Next steps:');
660
- console.log(' 1. Edit the generated files with your content');
661
- console.log(' 2. Review and update prpm.json as needed');
662
- console.log(' 3. Run `prpm publish` to publish your package\n');
663
- }
664
- /**
665
- * Create init command
666
- */
667
- function createInitCommand() {
668
- const command = new commander_1.Command('init');
669
- command
670
- .description('Initialize a new PRPM package with interactive prompts')
671
- .option('-y, --yes', 'Skip prompts and use defaults')
672
- .option('--private', 'Create a private package')
673
- .option('-f, --force', 'Overwrite existing prpm.json')
674
- .action(async (options) => {
675
- try {
676
- await initPackage(options);
677
- }
678
- catch (error) {
679
- console.error('\nāŒ Error:', error instanceof Error ? error.message : error);
680
- throw new errors_1.CLIError('\nāŒ Error: ' + (error instanceof Error ? error.message : error), 1);
681
- }
682
- });
683
- return command;
684
- }