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
package/package.json CHANGED
@@ -1,22 +1,22 @@
1
1
  {
2
2
  "name": "prpm",
3
- "version": "0.1.17",
3
+ "version": "1.0.0",
4
4
  "description": "Prompt Package Manager CLI - Install and manage prompt-based files",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
7
7
  "prpm": "dist/index.js"
8
8
  },
9
9
  "scripts": {
10
- "build": "tsc",
11
- "build:watch": "tsc --watch --preserveWatchOutput",
10
+ "build": "tsup",
11
+ "build:watch": "tsup --watch",
12
12
  "dev": "tsx watch --clear-screen=false src/index.ts",
13
13
  "dev:with-build": "concurrently --kill-others --names \"BUILD,CLI\" \"tsc --watch --preserveWatchOutput\" \"nodemon --delay 1 --watch dist dist/index.js\"",
14
14
  "dev:build-only": "tsc --watch --preserveWatchOutput",
15
15
  "start": "node dist/index.js",
16
- "test": "jest",
17
- "test:watch": "jest --watch",
18
- "test:coverage": "jest --coverage",
19
- "test:ci": "jest --ci --coverage --watchAll=false",
16
+ "test": "jest --runInBand",
17
+ "test:watch": "jest --watch --runInBand",
18
+ "test:coverage": "jest --coverage --runInBand",
19
+ "test:ci": "jest --ci --coverage --watchAll=false --runInBand",
20
20
  "build:binary": "echo 'Binary builds deprecated - use npm install -g prpm or Homebrew instead'",
21
21
  "typecheck": "tsc --noEmit",
22
22
  "version:bump": "node scripts/bump-version.js",
@@ -45,8 +45,9 @@
45
45
  "license": "MIT",
46
46
  "dependencies": {
47
47
  "@octokit/rest": "^22.0.0",
48
- "@pr-pm/registry-client": "^1.3.15",
49
- "@pr-pm/types": "^0.2.16",
48
+ "@pr-pm/converters": "^0.1.0",
49
+ "@pr-pm/registry-client": "^1.4.0",
50
+ "@pr-pm/types": "^0.3.0",
50
51
  "ajv": "^8.17.1",
51
52
  "ajv-formats": "^3.0.1",
52
53
  "commander": "^11.1.0",
@@ -63,6 +64,7 @@
63
64
  "nodemon": "^3.0.2",
64
65
  "ts-jest": "^29.1.1",
65
66
  "ts-node": "^10.9.1",
67
+ "tsup": "^8.5.1",
66
68
  "tsx": "^4.20.6",
67
69
  "typescript": "^5.3.2"
68
70
  },
@@ -1,151 +0,0 @@
1
- "use strict";
2
- /**
3
- * E2E Test Helpers
4
- * Shared utilities for end-to-end CLI testing
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.createTestDir = createTestDir;
8
- exports.cleanupTestDir = cleanupTestDir;
9
- exports.createMockPackage = createMockPackage;
10
- exports.createMockCollection = createMockCollection;
11
- exports.createMockConfig = createMockConfig;
12
- exports.createMockFetch = createMockFetch;
13
- exports.delay = delay;
14
- exports.setupGlobalMocks = setupGlobalMocks;
15
- exports.mockProcessExit = mockProcessExit;
16
- const promises_1 = require("fs/promises");
17
- const path_1 = require("path");
18
- const os_1 = require("os");
19
- /**
20
- * Create a temporary test directory
21
- */
22
- async function createTestDir() {
23
- const testDir = (0, path_1.join)((0, os_1.tmpdir)(), `prpm-e2e-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
24
- await (0, promises_1.mkdir)(testDir, { recursive: true });
25
- return testDir;
26
- }
27
- /**
28
- * Clean up test directory
29
- */
30
- async function cleanupTestDir(testDir) {
31
- try {
32
- await (0, promises_1.rm)(testDir, { recursive: true, force: true });
33
- }
34
- catch {
35
- // Ignore cleanup errors
36
- }
37
- }
38
- /**
39
- * Create a mock package manifest
40
- */
41
- async function createMockPackage(testDir, name, type = 'cursor', version = '1.0.0') {
42
- const manifest = {
43
- name,
44
- version,
45
- description: `Test package ${name}`,
46
- type,
47
- author: 'test-author',
48
- tags: ['test', type],
49
- };
50
- const manifestPath = (0, path_1.join)(testDir, 'prpm.json');
51
- await (0, promises_1.writeFile)(manifestPath, JSON.stringify(manifest, null, 2));
52
- // Create a sample .cursorrules file
53
- const rulesPath = (0, path_1.join)(testDir, '.cursorrules');
54
- await (0, promises_1.writeFile)(rulesPath, '# Test cursor rules\n\nAlways write tests.\n');
55
- return manifestPath;
56
- }
57
- /**
58
- * Create a mock collection manifest
59
- */
60
- async function createMockCollection(testDir, id, packages) {
61
- const manifest = {
62
- id,
63
- name: `Test Collection ${id}`,
64
- description: 'A test collection for E2E testing',
65
- category: 'development',
66
- tags: ['test', 'automation'],
67
- packages,
68
- icon: 'šŸ“¦',
69
- };
70
- const manifestPath = (0, path_1.join)(testDir, 'collection.json');
71
- await (0, promises_1.writeFile)(manifestPath, JSON.stringify(manifest, null, 2));
72
- return manifestPath;
73
- }
74
- /**
75
- * Create a mock user config
76
- */
77
- async function createMockConfig(configPath, options) {
78
- const config = {
79
- token: options.token || 'test-token-123',
80
- registryUrl: options.registryUrl || 'http://localhost:3111',
81
- };
82
- await (0, promises_1.mkdir)((0, path_1.join)(configPath, '..'), { recursive: true });
83
- await (0, promises_1.writeFile)(configPath, JSON.stringify(config, null, 2));
84
- }
85
- /**
86
- * Mock fetch response for registry API
87
- */
88
- function createMockFetch() {
89
- const responses = new Map();
90
- const mockFetch = jest.fn(async (url, options) => {
91
- const key = `${options?.method || 'GET'} ${url}`;
92
- const response = responses.get(key) || responses.get(url);
93
- if (!response) {
94
- return {
95
- ok: false,
96
- status: 404,
97
- statusText: 'Not Found',
98
- json: async () => ({ error: 'Not found' }),
99
- };
100
- }
101
- if (typeof response === 'function') {
102
- return response(url, options);
103
- }
104
- return {
105
- ok: true,
106
- status: 200,
107
- json: async () => response,
108
- arrayBuffer: async () => Buffer.from('mock-data').buffer,
109
- };
110
- });
111
- return {
112
- fetch: mockFetch,
113
- addResponse: (key, response) => {
114
- responses.set(key, response);
115
- },
116
- clear: () => {
117
- responses.clear();
118
- mockFetch.mockClear();
119
- },
120
- };
121
- }
122
- /**
123
- * Wait for async operations
124
- */
125
- function delay(ms) {
126
- return new Promise(resolve => setTimeout(resolve, ms));
127
- }
128
- /**
129
- * Setup global mocks for E2E tests
130
- */
131
- function setupGlobalMocks() {
132
- // Mock console to reduce noise
133
- beforeAll(() => {
134
- jest.spyOn(console, 'log').mockImplementation();
135
- jest.spyOn(console, 'error').mockImplementation();
136
- jest.spyOn(console, 'warn').mockImplementation();
137
- });
138
- afterAll(() => {
139
- jest.restoreAllMocks();
140
- });
141
- }
142
- /**
143
- * Mock process.exit to throw instead of exiting
144
- * @deprecated No longer needed - commands now throw CLIError instead of calling process.exit
145
- */
146
- function mockProcessExit() {
147
- const mockExit = jest.spyOn(process, 'exit').mockImplementation((code) => {
148
- throw new Error(`Process exited with code ${code}`);
149
- });
150
- return mockExit;
151
- }
@@ -1,224 +0,0 @@
1
- "use strict";
2
- /**
3
- * Buy Credits command - Purchase one-time playground credits
4
- */
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.handleBuyCredits = handleBuyCredits;
7
- exports.createBuyCreditsCommand = createBuyCreditsCommand;
8
- const commander_1 = require("commander");
9
- const user_config_1 = require("../core/user-config");
10
- const telemetry_1 = require("../core/telemetry");
11
- const child_process_1 = require("child_process");
12
- const util_1 = require("util");
13
- const webapp_url_1 = require("../utils/webapp-url");
14
- const errors_1 = require("../core/errors");
15
- const execAsync = (0, util_1.promisify)(child_process_1.exec);
16
- /**
17
- * Make authenticated API call
18
- */
19
- async function apiCall(endpoint) {
20
- const config = await (0, user_config_1.getConfig)();
21
- const baseUrl = (config.registryUrl || 'https://registry.prpm.dev').replace(/\/$/, '');
22
- if (!config.token) {
23
- throw new Error('Authentication required. Please run `prpm login` first.');
24
- }
25
- const response = await fetch(`${baseUrl}${endpoint}`, {
26
- headers: {
27
- Authorization: `Bearer ${config.token}`,
28
- },
29
- });
30
- if (!response.ok) {
31
- const errorData = await response.json().catch(() => ({}));
32
- throw new Error(errorData.message || `API request failed: ${response.statusText}`);
33
- }
34
- return response;
35
- }
36
- /**
37
- * Get current credits balance
38
- */
39
- async function getBalance() {
40
- const response = await apiCall('/api/v1/playground/credits');
41
- return response.json();
42
- }
43
- /**
44
- * Open URL in default browser
45
- */
46
- async function openBrowser(url) {
47
- const platform = process.platform;
48
- let command;
49
- if (platform === 'darwin') {
50
- command = `open "${url}"`;
51
- }
52
- else if (platform === 'win32') {
53
- command = `start "" "${url}"`;
54
- }
55
- else {
56
- // Linux and other Unix-like systems
57
- command = `xdg-open "${url}"`;
58
- }
59
- try {
60
- await execAsync(command);
61
- }
62
- catch (error) {
63
- // If automatic opening fails, just show the URL
64
- console.log(`\nšŸ”— Please open this URL in your browser:`);
65
- console.log(` ${url}`);
66
- }
67
- }
68
- /**
69
- * Poll for credits balance increase
70
- */
71
- async function pollForPurchase(initialBalance, maxAttempts = 60, intervalMs = 2000) {
72
- console.log('\nā³ Waiting for purchase confirmation...');
73
- console.log(' (This may take a minute. Press Ctrl+C to cancel)');
74
- for (let attempt = 0; attempt < maxAttempts; attempt++) {
75
- await new Promise((resolve) => setTimeout(resolve, intervalMs));
76
- try {
77
- const status = await getBalance();
78
- if (status.balance > initialBalance) {
79
- return status.balance - initialBalance;
80
- }
81
- // Show progress indicator
82
- if (attempt % 5 === 0 && attempt > 0) {
83
- process.stdout.write('.');
84
- }
85
- }
86
- catch (error) {
87
- // Continue polling even if there's an error
88
- continue;
89
- }
90
- }
91
- return null;
92
- }
93
- /**
94
- * Handle the buy-credits command
95
- */
96
- async function handleBuyCredits(options) {
97
- const startTime = Date.now();
98
- let success = false;
99
- let error;
100
- try {
101
- const config = await (0, user_config_1.getConfig)();
102
- if (!config.token) {
103
- console.error('āŒ Authentication required');
104
- console.log('\nšŸ’” Please login first:');
105
- console.log(' prpm login');
106
- throw new errors_1.CLIError('āŒ Authentication required', 1);
107
- }
108
- // Get current balance
109
- console.log('šŸ” Checking current credits balance...');
110
- const initialStatus = await getBalance();
111
- console.log(` Current balance: ${initialStatus.balance} credits`);
112
- console.log('\nšŸ’° Available credit packages:');
113
- console.log(' Small: 100 credits - $5.00 ($0.05 per credit)');
114
- console.log(' Medium: 250 credits - $11.25 ($0.045 per credit) - 10% savings');
115
- console.log(' Large: 600 credits - $24.00 ($0.04 per credit) - 20% savings');
116
- console.log('\n✨ These credits never expire!');
117
- console.log('šŸ’” Tip: Subscribe to PRPM+ for 100 monthly credits at just $6/month');
118
- // Build URL with package parameter if specified
119
- const webappUrl = (0, webapp_url_1.getWebappUrl)(config.registryUrl || 'https://registry.prpm.dev');
120
- let purchaseUrl = `${webappUrl}/playground/credits/buy`;
121
- if (options.package) {
122
- const validPackages = ['small', 'medium', 'large'];
123
- if (!validPackages.includes(options.package)) {
124
- console.error(`\nāŒ Invalid package: ${options.package}`);
125
- console.log(' Valid options: small, medium, large');
126
- throw new errors_1.CLIError(`\nāŒ Invalid package: ${options.package}`, 1);
127
- }
128
- purchaseUrl += `?package=${options.package}`;
129
- }
130
- // Open purchase page
131
- console.log(`\n🌐 Opening purchase page in your browser...`);
132
- await openBrowser(purchaseUrl);
133
- // Poll for purchase confirmation
134
- const creditsAdded = await pollForPurchase(initialStatus.balance);
135
- if (creditsAdded !== null) {
136
- const updatedStatus = await getBalance();
137
- console.log('\n\nšŸŽ‰ Successfully purchased credits!');
138
- console.log('\nšŸ“Š Credits added:');
139
- console.log(` + ${creditsAdded} credits`);
140
- console.log(` šŸ’³ New balance: ${updatedStatus.balance} credits`);
141
- console.log('\nāœ… You can now:');
142
- console.log(' - Test packages: prpm playground <package> "<input>"');
143
- console.log(' - Check balance: prpm credits');
144
- console.log(' - View history: prpm credits --history');
145
- success = true;
146
- }
147
- else {
148
- console.log('\n\nā±ļø Purchase process timed out or was canceled.');
149
- console.log('\nšŸ’” If you completed the purchase, run this to verify:');
150
- console.log(' prpm credits');
151
- console.log('\nšŸ’” Or check your transaction history:');
152
- console.log(' prpm credits --history');
153
- }
154
- }
155
- catch (err) {
156
- error = err instanceof Error ? err.message : String(err);
157
- console.error(`\nāŒ Purchase failed: ${error}`);
158
- throw new errors_1.CLIError(`\nāŒ Purchase failed: ${error}`, 1);
159
- }
160
- finally {
161
- await telemetry_1.telemetry.track({
162
- command: 'buy-credits',
163
- success,
164
- error,
165
- duration: Date.now() - startTime,
166
- data: {
167
- package: options.package,
168
- },
169
- });
170
- await telemetry_1.telemetry.shutdown();
171
- }
172
- }
173
- /**
174
- * Create the buy-credits command
175
- */
176
- function createBuyCreditsCommand() {
177
- const command = new commander_1.Command('buy-credits');
178
- command
179
- .description('Purchase one-time playground credits (never expire)')
180
- .option('-p, --package <package>', 'Credit package to purchase (small, medium, large)')
181
- .addHelpText('after', `
182
- Credit Packages:
183
- Small: 100 credits - $5.00 ($0.05 per credit)
184
- Medium: 250 credits - $11.25 ($0.045 per credit) - 10% savings
185
- Large: 600 credits - $24.00 ($0.04 per credit) - 20% savings
186
-
187
- Credits Usage:
188
- - Testing packages in playground uses 1-5 credits per request
189
- - Token-based pricing: 1 credit = 5,000 tokens
190
- - Model multipliers apply (Opus 5x, GPT-4o 2x, etc.)
191
- - Credits never expire
192
-
193
- How it works:
194
- 1. Opens purchase page in your browser
195
- 2. Select package and complete payment with Stripe
196
- 3. Credits are added to your account immediately
197
- 4. Start testing packages right away
198
-
199
- Examples:
200
- # Browse all packages
201
- $ prpm buy-credits
202
-
203
- # Pre-select a specific package
204
- $ prpm buy-credits --package small
205
- $ prpm buy-credits --package medium
206
- $ prpm buy-credits --package large
207
-
208
- # After purchase, check balance
209
- $ prpm credits
210
-
211
- # Test packages in playground
212
- $ prpm playground @user/prompt "test input"
213
-
214
- šŸ’” Better Value:
215
- Subscribe to PRPM+ for 100 monthly credits at just $6/month
216
- Run: prpm subscribe
217
-
218
- Note: Purchased credits are one-time and never expire, unlike monthly credits.
219
- `)
220
- .action(async (options) => {
221
- await handleBuyCredits(options);
222
- });
223
- return command;
224
- }