prpm 0.2.0 → 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 (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
package/package.json CHANGED
@@ -1,22 +1,22 @@
1
1
  {
2
2
  "name": "prpm",
3
- "version": "0.2.0",
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.16",
49
- "@pr-pm/types": "^0.2.17",
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,153 +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
- format: type,
47
- subtype: 'rule',
48
- author: 'test-author',
49
- tags: ['test', type],
50
- files: ['prpm.json', '.cursorrules'],
51
- };
52
- const manifestPath = (0, path_1.join)(testDir, 'prpm.json');
53
- await (0, promises_1.writeFile)(manifestPath, JSON.stringify(manifest, null, 2));
54
- // Create a sample .cursorrules file
55
- const rulesPath = (0, path_1.join)(testDir, '.cursorrules');
56
- await (0, promises_1.writeFile)(rulesPath, '# Test cursor rules\n\nAlways write tests.\n');
57
- return manifestPath;
58
- }
59
- /**
60
- * Create a mock collection manifest
61
- */
62
- async function createMockCollection(testDir, id, packages) {
63
- const manifest = {
64
- id,
65
- name: `Test Collection ${id}`,
66
- description: 'A test collection for E2E testing',
67
- category: 'development',
68
- tags: ['test', 'automation'],
69
- packages,
70
- icon: 'šŸ“¦',
71
- };
72
- const manifestPath = (0, path_1.join)(testDir, 'collection.json');
73
- await (0, promises_1.writeFile)(manifestPath, JSON.stringify(manifest, null, 2));
74
- return manifestPath;
75
- }
76
- /**
77
- * Create a mock user config
78
- */
79
- async function createMockConfig(configPath, options) {
80
- const config = {
81
- token: options.token || 'test-token-123',
82
- registryUrl: options.registryUrl || 'http://localhost:3111',
83
- };
84
- await (0, promises_1.mkdir)((0, path_1.join)(configPath, '..'), { recursive: true });
85
- await (0, promises_1.writeFile)(configPath, JSON.stringify(config, null, 2));
86
- }
87
- /**
88
- * Mock fetch response for registry API
89
- */
90
- function createMockFetch() {
91
- const responses = new Map();
92
- const mockFetch = jest.fn(async (url, options) => {
93
- const key = `${options?.method || 'GET'} ${url}`;
94
- const response = responses.get(key) || responses.get(url);
95
- if (!response) {
96
- return {
97
- ok: false,
98
- status: 404,
99
- statusText: 'Not Found',
100
- json: async () => ({ error: 'Not found' }),
101
- };
102
- }
103
- if (typeof response === 'function') {
104
- return response(url, options);
105
- }
106
- return {
107
- ok: true,
108
- status: 200,
109
- json: async () => response,
110
- arrayBuffer: async () => Buffer.from('mock-data').buffer,
111
- };
112
- });
113
- return {
114
- fetch: mockFetch,
115
- addResponse: (key, response) => {
116
- responses.set(key, response);
117
- },
118
- clear: () => {
119
- responses.clear();
120
- mockFetch.mockClear();
121
- },
122
- };
123
- }
124
- /**
125
- * Wait for async operations
126
- */
127
- function delay(ms) {
128
- return new Promise(resolve => setTimeout(resolve, ms));
129
- }
130
- /**
131
- * Setup global mocks for E2E tests
132
- */
133
- function setupGlobalMocks() {
134
- // Mock console to reduce noise
135
- beforeAll(() => {
136
- jest.spyOn(console, 'log').mockImplementation();
137
- jest.spyOn(console, 'error').mockImplementation();
138
- jest.spyOn(console, 'warn').mockImplementation();
139
- });
140
- afterAll(() => {
141
- jest.restoreAllMocks();
142
- });
143
- }
144
- /**
145
- * Mock process.exit to throw instead of exiting
146
- * @deprecated No longer needed - commands now throw CLIError instead of calling process.exit
147
- */
148
- function mockProcessExit() {
149
- const mockExit = jest.spyOn(process, 'exit').mockImplementation((code) => {
150
- throw new Error(`Process exited with code ${code}`);
151
- });
152
- return mockExit;
153
- }
@@ -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
- }