prpm 0.2.0 → 1.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 (48) hide show
  1. package/dist/index.js +14257 -109
  2. package/package.json +11 -9
  3. package/dist/__tests__/e2e/test-helpers.js +0 -153
  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 -829
  13. package/dist/commands/list.js +0 -198
  14. package/dist/commands/login.js +0 -316
  15. package/dist/commands/outdated.js +0 -130
  16. package/dist/commands/playground.js +0 -637
  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/starred.js +0 -147
  22. package/dist/commands/subscribe.js +0 -211
  23. package/dist/commands/telemetry.js +0 -104
  24. package/dist/commands/trending.js +0 -86
  25. package/dist/commands/uninstall.js +0 -120
  26. package/dist/commands/update.js +0 -121
  27. package/dist/commands/upgrade.js +0 -121
  28. package/dist/commands/whoami.js +0 -83
  29. package/dist/core/claude-config.js +0 -91
  30. package/dist/core/cursor-config.js +0 -130
  31. package/dist/core/downloader.js +0 -64
  32. package/dist/core/errors.js +0 -29
  33. package/dist/core/filesystem.js +0 -246
  34. package/dist/core/lockfile.js +0 -292
  35. package/dist/core/marketplace-converter.js +0 -224
  36. package/dist/core/prompts.js +0 -62
  37. package/dist/core/registry-client.js +0 -305
  38. package/dist/core/schema-validator.js +0 -74
  39. package/dist/core/telemetry.js +0 -253
  40. package/dist/core/user-config.js +0 -147
  41. package/dist/types/registry.js +0 -12
  42. package/dist/types.js +0 -9
  43. package/dist/utils/license-extractor.js +0 -122
  44. package/dist/utils/multi-package.js +0 -117
  45. package/dist/utils/parallel-publisher.js +0 -144
  46. package/dist/utils/script-executor.js +0 -72
  47. package/dist/utils/snippet-extractor.js +0 -77
  48. package/dist/utils/webapp-url.js +0 -44
@@ -1,144 +0,0 @@
1
- "use strict";
2
- /**
3
- * Parallel publishing utilities with concurrency control
4
- * Optimizes multi-package publishing performance
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.publishInParallel = publishInParallel;
8
- exports.withRetry = withRetry;
9
- exports.formatDuration = formatDuration;
10
- exports.calculateStats = calculateStats;
11
- /**
12
- * Execute tasks in parallel with concurrency limit
13
- */
14
- async function publishInParallel(tasks, options = {}) {
15
- const { concurrency = 5, continueOnError = false, onProgress, onSuccess, onError, } = options;
16
- const results = new Array(tasks.length);
17
- let completed = 0;
18
- let hasError = false;
19
- let taskIndex = 0;
20
- async function executeTask(task, index) {
21
- const startTime = Date.now();
22
- try {
23
- const result = await task.execute();
24
- const duration = Date.now() - startTime;
25
- results[index] = {
26
- success: true,
27
- name: task.name,
28
- result,
29
- duration,
30
- };
31
- completed++;
32
- onProgress?.(completed, tasks.length, task.name);
33
- onSuccess?.(task.name, result);
34
- }
35
- catch (error) {
36
- const duration = Date.now() - startTime;
37
- const err = error instanceof Error ? error : new Error(String(error));
38
- results[index] = {
39
- success: false,
40
- name: task.name,
41
- error: err,
42
- duration,
43
- };
44
- completed++;
45
- hasError = true;
46
- onProgress?.(completed, tasks.length, task.name);
47
- onError?.(task.name, err);
48
- // If not continuing on error, mark hasError to skip remaining tasks
49
- if (!continueOnError) {
50
- throw err;
51
- }
52
- }
53
- }
54
- // Execute tasks with concurrency control
55
- const executing = new Set();
56
- while (taskIndex < tasks.length || executing.size > 0) {
57
- // Fill up to concurrency limit
58
- while (taskIndex < tasks.length && executing.size < concurrency) {
59
- // If in strict mode and we've encountered an error, skip remaining tasks
60
- if (!continueOnError && hasError) {
61
- results[taskIndex] = {
62
- success: false,
63
- name: tasks[taskIndex].name,
64
- error: new Error('Skipped due to previous failure'),
65
- duration: 0,
66
- };
67
- taskIndex++;
68
- continue;
69
- }
70
- const currentIndex = taskIndex;
71
- const currentTask = tasks[taskIndex];
72
- taskIndex++;
73
- const promise = executeTask(currentTask, currentIndex)
74
- .catch(() => {
75
- // Errors already handled in executeTask
76
- })
77
- .finally(() => {
78
- executing.delete(promise);
79
- });
80
- executing.add(promise);
81
- }
82
- // Wait for at least one task to complete
83
- if (executing.size > 0) {
84
- await Promise.race(executing);
85
- }
86
- }
87
- return results;
88
- }
89
- /**
90
- * Retry a task with exponential backoff
91
- */
92
- async function withRetry(fn, options = {}) {
93
- const { maxRetries = 3, initialDelay = 1000, maxDelay = 10000, backoffFactor = 2, } = options;
94
- let lastError;
95
- for (let attempt = 0; attempt < maxRetries; attempt++) {
96
- try {
97
- return await fn();
98
- }
99
- catch (error) {
100
- lastError = error instanceof Error ? error : new Error(String(error));
101
- // Don't retry on last attempt
102
- if (attempt === maxRetries - 1) {
103
- break;
104
- }
105
- // Calculate delay with exponential backoff
106
- const delay = Math.min(initialDelay * Math.pow(backoffFactor, attempt), maxDelay);
107
- await sleep(delay);
108
- }
109
- }
110
- throw lastError || new Error('Max retries exceeded');
111
- }
112
- /**
113
- * Sleep utility
114
- */
115
- function sleep(ms) {
116
- return new Promise(resolve => setTimeout(resolve, ms));
117
- }
118
- /**
119
- * Format duration in human-readable format
120
- */
121
- function formatDuration(ms) {
122
- if (ms < 1000) {
123
- return `${ms}ms`;
124
- }
125
- const seconds = (ms / 1000).toFixed(1);
126
- return `${seconds}s`;
127
- }
128
- function calculateStats(results) {
129
- const succeeded = results.filter(r => r.success && r.result !== undefined).length;
130
- const failed = results.filter(r => !r.success && r.error && r.error.message !== 'Skipped due to previous failure').length;
131
- const skipped = results.filter(r => r.error?.message === 'Skipped due to previous failure').length;
132
- const totalDuration = results.reduce((sum, r) => sum + r.duration, 0);
133
- const completedCount = succeeded + failed;
134
- const avgDuration = completedCount > 0 ? totalDuration / completedCount : 0;
135
- return {
136
- total: results.length,
137
- succeeded,
138
- failed,
139
- skipped,
140
- totalDuration,
141
- avgDuration,
142
- successRate: results.length > 0 ? succeeded / results.length : 0,
143
- };
144
- }
@@ -1,72 +0,0 @@
1
- "use strict";
2
- /**
3
- * Utility for executing package lifecycle scripts
4
- */
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.executeScript = executeScript;
7
- exports.executePrepublishOnly = executePrepublishOnly;
8
- const child_process_1 = require("child_process");
9
- const util_1 = require("util");
10
- const execAsync = (0, util_1.promisify)(child_process_1.exec);
11
- /**
12
- * Execute a package lifecycle script
13
- * @param script - The script command to execute
14
- * @param scriptName - Name of the script (for logging)
15
- * @param options - Execution options
16
- * @throws Error if script fails
17
- */
18
- async function executeScript(script, scriptName, options = {}) {
19
- const { cwd = process.cwd(), timeout = 5 * 60 * 1000, // 5 minutes default
20
- maxBuffer = 10 * 1024 * 1024, // 10MB default
21
- } = options;
22
- console.log(`🔧 Running ${scriptName} script...`);
23
- console.log(` $ ${script}\n`);
24
- try {
25
- const { stdout, stderr } = await execAsync(script, {
26
- cwd,
27
- timeout,
28
- maxBuffer,
29
- // Inherit environment variables
30
- env: process.env,
31
- });
32
- // Show output in real-time
33
- if (stdout) {
34
- process.stdout.write(stdout);
35
- }
36
- if (stderr) {
37
- process.stderr.write(stderr);
38
- }
39
- console.log(`\n✓ ${scriptName} script completed successfully\n`);
40
- return {
41
- stdout,
42
- stderr,
43
- exitCode: 0,
44
- };
45
- }
46
- catch (error) {
47
- // Show error output
48
- if (error.stdout) {
49
- process.stdout.write(error.stdout);
50
- }
51
- if (error.stderr) {
52
- process.stderr.write(error.stderr);
53
- }
54
- const errorMessage = error.code === 'ETIMEDOUT'
55
- ? `${scriptName} script timed out after ${timeout}ms`
56
- : error.code === 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER'
57
- ? `${scriptName} script output exceeded maximum buffer size`
58
- : `${scriptName} script failed with exit code ${error.code || 1}`;
59
- throw new Error(errorMessage);
60
- }
61
- }
62
- /**
63
- * Execute prepublishOnly script if defined
64
- * @param scripts - Package scripts object
65
- * @param options - Execution options
66
- */
67
- async function executePrepublishOnly(scripts, options = {}) {
68
- if (!scripts?.prepublishOnly) {
69
- return; // No script defined, nothing to do
70
- }
71
- await executeScript(scripts.prepublishOnly, 'prepublishOnly', options);
72
- }
@@ -1,77 +0,0 @@
1
- "use strict";
2
- /**
3
- * Snippet extraction utilities
4
- * Extracts preview content from package files for display in modals
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.extractSnippet = extractSnippet;
8
- exports.validateSnippet = validateSnippet;
9
- const promises_1 = require("fs/promises");
10
- const path_1 = require("path");
11
- const MAX_SNIPPET_LENGTH = 2000;
12
- /**
13
- * Extract a preview snippet from package files
14
- * Uses the same path logic as the install command to determine where files will be placed
15
- */
16
- async function extractSnippet(manifest) {
17
- const cwd = process.cwd();
18
- try {
19
- // Validate manifest has required fields
20
- if (!manifest.files || manifest.files.length === 0) {
21
- console.warn('⚠️ Cannot extract snippet: no files specified in manifest');
22
- return null;
23
- }
24
- // Prefer main file over first file if specified
25
- let fileName;
26
- if (manifest.main) {
27
- fileName = manifest.main;
28
- }
29
- else {
30
- const firstFile = manifest.files[0];
31
- fileName = typeof firstFile === 'string'
32
- ? firstFile
33
- : firstFile.path;
34
- }
35
- // Use the file path directly - it should be relative to project root
36
- // (e.g., ".claude/skills/my-skill/SKILL.md" or ".cursor/rules/my-rule.mdc")
37
- const fullPath = (0, path_1.join)(cwd, fileName);
38
- // Check if path is a directory
39
- const stats = await (0, promises_1.stat)(fullPath);
40
- if (stats.isDirectory()) {
41
- console.warn(`⚠️ Skipping snippet extraction: "${fullPath}" is a directory`);
42
- return null;
43
- }
44
- // Read the file content
45
- const content = await (0, promises_1.readFile)(fullPath, 'utf-8');
46
- // Extract first N characters, trying to break at a reasonable point
47
- if (content.length <= MAX_SNIPPET_LENGTH) {
48
- return content.trim();
49
- }
50
- // Try to break at a newline near the limit
51
- let snippet = content.substring(0, MAX_SNIPPET_LENGTH);
52
- const lastNewline = snippet.lastIndexOf('\n');
53
- if (lastNewline > MAX_SNIPPET_LENGTH * 0.8) {
54
- // If we found a newline in the last 20%, break there
55
- snippet = snippet.substring(0, lastNewline);
56
- }
57
- return snippet.trim() + '\n\n[... content truncated ...]';
58
- }
59
- catch (error) {
60
- // If we can't read the file, return null (snippet is optional)
61
- console.warn('⚠️ Could not extract snippet:', error instanceof Error ? error.message : 'Unknown error');
62
- return null;
63
- }
64
- }
65
- /**
66
- * Validate snippet and warn if issues found
67
- */
68
- function validateSnippet(snippet, packageName) {
69
- if (!snippet) {
70
- console.warn(`⚠️ Warning: No content snippet extracted for package "${packageName}"`);
71
- console.warn(' A preview snippet helps users see what the prompt contains before installing.');
72
- console.warn('');
73
- }
74
- else {
75
- console.log(` Snippet: ${snippet.length} characters extracted`);
76
- }
77
- }
@@ -1,44 +0,0 @@
1
- "use strict";
2
- /**
3
- * Utility to convert registry URL to webapp URL
4
- * Handles localhost, production, and custom registry URLs
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.getWebappUrl = getWebappUrl;
8
- /**
9
- * Convert a registry URL to its corresponding webapp URL
10
- *
11
- * @param registryUrl - The registry URL (e.g., https://registry.prpm.dev)
12
- * @returns The webapp URL (e.g., https://prpm.dev)
13
- *
14
- * @example
15
- * // Production
16
- * getWebappUrl('https://registry.prpm.dev') // => 'https://prpm.dev'
17
- *
18
- * // Local development
19
- * getWebappUrl('http://localhost:3111') // => 'http://localhost:5173'
20
- *
21
- * // Custom registry
22
- * getWebappUrl('https://registry.custom.com') // => 'https://custom.com'
23
- */
24
- function getWebappUrl(registryUrl) {
25
- const cleanUrl = registryUrl.replace(/\/$/, '').replace(/\/api\/?$/, '');
26
- if (cleanUrl.includes('localhost') || cleanUrl.includes('127.0.0.1')) {
27
- // Local development: registry on port 3111, webapp on port 5173
28
- return cleanUrl.replace(':3111', ':5173');
29
- }
30
- if (cleanUrl.includes('registry.prpm.dev')) {
31
- // Production: always use prpm.dev webapp
32
- return 'https://prpm.dev';
33
- }
34
- // Custom registry: assume webapp is on same host without 'registry.' subdomain
35
- try {
36
- const url = new URL(cleanUrl);
37
- const hostname = url.hostname.replace(/^registry\./, '');
38
- return `${url.protocol}//${hostname}`;
39
- }
40
- catch {
41
- // If URL parsing fails, return as-is
42
- return cleanUrl;
43
- }
44
- }