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,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
- }