paymongo-cli 1.4.12 → 1.4.14
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.
- package/.gitattributes +2 -0
- package/.github/copilot-instructions.md +8 -6
- package/AGENTS.md +8 -9
- package/CHANGELOG.md +21 -0
- package/README.md +3 -3
- package/biome.json +72 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/commands/config/actions.js +13 -5
- package/dist/commands/config/analytics.js +75 -0
- package/dist/commands/config/helpers.js +14 -25
- package/dist/commands/config/rate-limit.js +3 -3
- package/dist/commands/config.js +7 -1
- package/dist/commands/dev/logs.js +13 -4
- package/dist/commands/dev/status.js +1 -1
- package/dist/commands/dev/stop.js +2 -2
- package/dist/commands/dev.js +10 -258
- package/dist/commands/doctor.js +7 -8
- package/dist/commands/env.js +10 -19
- package/dist/commands/generate/templates/index.js +3 -3
- package/dist/commands/generate.js +7 -7
- package/dist/commands/init.js +22 -36
- package/dist/commands/login.js +18 -29
- package/dist/commands/payments/actions.js +15 -15
- package/dist/commands/payments/helpers.js +6 -24
- package/dist/commands/payments.js +1 -1
- package/dist/commands/shared/auth.js +23 -0
- package/dist/commands/shared/runtime.js +35 -0
- package/dist/commands/team/index.js +4 -4
- package/dist/commands/trigger/actions.js +2 -2
- package/dist/commands/trigger/helpers.js +13 -9
- package/dist/commands/trigger.js +2 -2
- package/dist/commands/webhooks/actions.js +11 -11
- package/dist/commands/webhooks/helpers.js +5 -23
- package/dist/commands/webhooks.js +1 -1
- package/dist/index.js +37 -19
- package/dist/services/analytics/service.js +3 -3
- package/dist/services/api/client.js +8 -4
- package/dist/services/api/rate-limiter.js +3 -2
- package/dist/services/config/manager.js +13 -3
- package/dist/services/dev/process-manager.js +4 -4
- package/dist/services/dev/server.js +7 -8
- package/dist/services/dev/session.js +354 -0
- package/dist/services/team/service.js +1 -1
- package/dist/types/schemas.js +3 -2
- package/dist/utils/bulk.js +11 -11
- package/dist/utils/cache.js +5 -5
- package/dist/utils/constants.js +1 -1
- package/dist/utils/webhook-store.js +3 -3
- package/package.json +11 -25
- package/vitest.config.ts +18 -0
- package/eslint.config.ts +0 -70
package/dist/commands/env.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
1
|
import chalk from 'chalk';
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import { ApiKeyError, NetworkError, PayMongoError, CommandError } from '../utils/errors.js';
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { ApiKeyError, CommandError, NetworkError, PayMongoError } from '../utils/errors.js';
|
|
4
|
+
import { createApiClient, createCommandContext, loadCommandConfig, showNoConfigMessage, } from './shared/runtime.js';
|
|
7
5
|
const command = new Command('env');
|
|
8
6
|
command
|
|
9
7
|
.description('Manage PayMongo environments')
|
|
@@ -12,22 +10,16 @@ command
|
|
|
12
10
|
.arguments('<environment>')
|
|
13
11
|
.option('-f, --force', 'Skip API key validation')
|
|
14
12
|
.action(async (environment, options) => {
|
|
15
|
-
const spinner =
|
|
16
|
-
const configManager = new ConfigManager();
|
|
13
|
+
const { spinner, configManager } = createCommandContext();
|
|
17
14
|
try {
|
|
18
15
|
if (!['test', 'live'].includes(environment)) {
|
|
19
16
|
console.error(chalk.red('❌ Invalid environment. Must be "test" or "live"'));
|
|
20
17
|
throw new CommandError();
|
|
21
18
|
}
|
|
22
|
-
spinner
|
|
23
|
-
const config = await configManager.load();
|
|
19
|
+
const config = await loadCommandConfig(spinner, configManager);
|
|
24
20
|
if (!config) {
|
|
25
|
-
spinner.fail('No configuration found');
|
|
26
|
-
console.log(chalk.yellow('No PayMongo configuration found.'));
|
|
27
|
-
console.log(chalk.gray("Run 'paymongo init' to set up your project first."));
|
|
28
21
|
return;
|
|
29
22
|
}
|
|
30
|
-
spinner.succeed('Configuration loaded');
|
|
31
23
|
const envConfig = config.apiKeys[environment];
|
|
32
24
|
if (!envConfig?.secret || !envConfig?.public) {
|
|
33
25
|
spinner.fail(`Missing API keys for ${environment} environment`);
|
|
@@ -41,7 +33,7 @@ command
|
|
|
41
33
|
if (!options.force) {
|
|
42
34
|
spinner.start('Validating API keys...');
|
|
43
35
|
const testConfig = { ...config, environment: environment };
|
|
44
|
-
const apiClient =
|
|
36
|
+
const apiClient = createApiClient(testConfig);
|
|
45
37
|
try {
|
|
46
38
|
await apiClient.validateApiKey();
|
|
47
39
|
spinner.succeed('API keys validated');
|
|
@@ -102,20 +94,19 @@ command
|
|
|
102
94
|
}
|
|
103
95
|
}))
|
|
104
96
|
.addCommand(new Command('current').description('Show current environment').action(async () => {
|
|
105
|
-
const configManager =
|
|
97
|
+
const { configManager } = createCommandContext();
|
|
106
98
|
try {
|
|
107
99
|
const config = await configManager.load();
|
|
108
100
|
if (!config) {
|
|
109
|
-
|
|
110
|
-
console.log(chalk.gray("Run 'paymongo init' to set up your project first."));
|
|
101
|
+
showNoConfigMessage();
|
|
111
102
|
return;
|
|
112
103
|
}
|
|
113
104
|
const env = config.environment;
|
|
114
105
|
const envConfig = config.apiKeys[env];
|
|
115
106
|
console.log(chalk.bold('Current Environment:'));
|
|
116
107
|
console.log(`Environment: ${chalk.cyan(env.toUpperCase())}`);
|
|
117
|
-
console.log(`Public Key: ${envConfig?.public ? chalk.gray(envConfig.public.substring(0, 10)
|
|
118
|
-
console.log(`Secret Key: ${envConfig?.secret ? chalk.gray(envConfig.secret.substring(0, 10)
|
|
108
|
+
console.log(`Public Key: ${envConfig?.public ? chalk.gray(`${envConfig.public.substring(0, 10)}...`) : chalk.red('Not set')}`);
|
|
109
|
+
console.log(`Secret Key: ${envConfig?.secret ? chalk.gray(`${envConfig.secret.substring(0, 10)}...`) : chalk.red('Not set')}`);
|
|
119
110
|
if (env === 'live') {
|
|
120
111
|
console.log('');
|
|
121
112
|
console.log(chalk.yellow('⚠️ You are using LIVE environment!'));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export { getWebhookHandlerTemplate as getTypeScriptWebhookHandler } from './webhook-handler/typescript.js';
|
|
1
|
+
export { getCheckoutPageTemplate, getHtmlTemplate, getReactTemplate, getVueTemplate, } from './checkout-page/index.js';
|
|
3
2
|
export { getPaymentIntentTemplate as getJavaScriptPaymentIntent } from './payment-intent/javascript.js';
|
|
4
3
|
export { getPaymentIntentTemplate as getTypeScriptPaymentIntent } from './payment-intent/typescript.js';
|
|
5
|
-
export {
|
|
4
|
+
export { getWebhookHandlerTemplate as getJavaScriptWebhookHandler } from './webhook-handler/javascript.js';
|
|
5
|
+
export { getWebhookHandlerTemplate as getTypeScriptWebhookHandler } from './webhook-handler/typescript.js';
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
import
|
|
3
|
+
import { Command } from 'commander';
|
|
4
4
|
import ConfigManager from '../services/config/manager.js';
|
|
5
5
|
import Spinner from '../utils/spinner.js';
|
|
6
|
-
import {
|
|
6
|
+
import { getCheckoutPageTemplate, getJavaScriptPaymentIntent, getJavaScriptWebhookHandler, getTypeScriptPaymentIntent, getTypeScriptWebhookHandler, } from './generate/templates/index.js';
|
|
7
7
|
const command = new Command('generate');
|
|
8
8
|
command
|
|
9
9
|
.description('Generate boilerplate code for PayMongo integrations')
|
|
@@ -63,7 +63,7 @@ FRAMEWORKS:
|
|
|
63
63
|
|
|
64
64
|
EXAMPLES:
|
|
65
65
|
$ paymongo generate checkout-page
|
|
66
|
-
$ paymongo generate checkout-page --
|
|
66
|
+
$ paymongo generate checkout-page --language react
|
|
67
67
|
$ paymongo generate checkout-page --language vue --output Checkout.vue
|
|
68
68
|
`)
|
|
69
69
|
.action(async (options) => {
|
|
@@ -126,7 +126,7 @@ async function generateWebhookHandler(options) {
|
|
|
126
126
|
spinner.start(`Generating webhook handler...`);
|
|
127
127
|
await fs.writeFile(outputFile, code, 'utf-8');
|
|
128
128
|
spinner.succeed(`Webhook handler generated: ${outputFile}`);
|
|
129
|
-
console.log(
|
|
129
|
+
console.log(`\n${chalk.green('✅ Webhook handler generated successfully!')}`);
|
|
130
130
|
console.log(chalk.gray(`Events handled: ${events.join(', ')}`));
|
|
131
131
|
console.log(chalk.gray(`Language: ${options.language}`));
|
|
132
132
|
console.log(chalk.gray(`Framework: ${options.framework}`));
|
|
@@ -162,7 +162,7 @@ async function generatePaymentIntent(options) {
|
|
|
162
162
|
spinner.start(`Generating payment intent code...`);
|
|
163
163
|
await fs.writeFile(outputFile, code, 'utf-8');
|
|
164
164
|
spinner.succeed(`Payment intent code generated: ${outputFile}`);
|
|
165
|
-
console.log(
|
|
165
|
+
console.log(`\n${chalk.green('✅ Payment intent code generated successfully!')}`);
|
|
166
166
|
console.log(chalk.gray(`Payment methods: ${methods.join(', ')}`));
|
|
167
167
|
console.log(chalk.gray(`Language: ${options.language}`));
|
|
168
168
|
}
|
|
@@ -187,7 +187,7 @@ async function generateCheckoutPage(options) {
|
|
|
187
187
|
spinner.start(`Generating checkout page...`);
|
|
188
188
|
await fs.writeFile(outputFile, code, 'utf-8');
|
|
189
189
|
spinner.succeed(`Checkout page generated: ${outputFile}`);
|
|
190
|
-
console.log(
|
|
190
|
+
console.log(`\n${chalk.green('✅ Checkout page generated successfully!')}`);
|
|
191
191
|
console.log(chalk.gray(`Framework: ${options.language}`));
|
|
192
192
|
}
|
|
193
193
|
catch (error) {
|
package/dist/commands/init.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
import * as
|
|
3
|
-
import * as path from 'path';
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
4
3
|
import chalk from 'chalk';
|
|
5
|
-
import
|
|
6
|
-
import
|
|
4
|
+
import { Command } from 'commander';
|
|
5
|
+
import { ApiKeyError, CommandError, NetworkError, PayMongoError } from '../utils/errors.js';
|
|
7
6
|
import { validateApiKey } from '../utils/validator.js';
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
7
|
+
import { createCredentialValidationConfig } from './shared/auth.js';
|
|
8
|
+
import { createApiClient, createCommandContext } from './shared/runtime.js';
|
|
10
9
|
export async function initAction(options) {
|
|
11
|
-
const spinner =
|
|
12
|
-
const configManager = new ConfigManager();
|
|
10
|
+
const { spinner, configManager } = createCommandContext();
|
|
13
11
|
try {
|
|
14
12
|
if (await configManager.exists()) {
|
|
15
13
|
const { confirm } = await import('@inquirer/prompts');
|
|
@@ -107,28 +105,16 @@ export async function initAction(options) {
|
|
|
107
105
|
};
|
|
108
106
|
}
|
|
109
107
|
spinner.start('Validating API keys...');
|
|
110
|
-
const tempConfig = {
|
|
111
|
-
version: '1.0',
|
|
108
|
+
const tempConfig = createCredentialValidationConfig({
|
|
112
109
|
projectName: answers.projectName,
|
|
113
110
|
environment: answers.environment,
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
url: answers.webhookUrl || `http://localhost:${answers.port}/webhook`,
|
|
122
|
-
events: answers.events,
|
|
123
|
-
},
|
|
124
|
-
webhookSecrets: {},
|
|
125
|
-
dev: {
|
|
126
|
-
port: answers.port,
|
|
127
|
-
autoRegisterWebhook: true,
|
|
128
|
-
verifyWebhookSignatures: true,
|
|
129
|
-
},
|
|
130
|
-
};
|
|
131
|
-
const apiClient = new ApiClient({ config: tempConfig });
|
|
111
|
+
publicKey: answers.publicKey,
|
|
112
|
+
secretKey: answers.secretKey,
|
|
113
|
+
webhookUrl: answers.webhookUrl || `http://localhost:${answers.port}/webhook`,
|
|
114
|
+
events: answers.events,
|
|
115
|
+
port: answers.port,
|
|
116
|
+
});
|
|
117
|
+
const apiClient = createApiClient(tempConfig);
|
|
132
118
|
try {
|
|
133
119
|
await apiClient.validateApiKey();
|
|
134
120
|
spinner.succeed('API keys validated');
|
|
@@ -191,19 +177,19 @@ PAYMONGO_ENVIRONMENT=${answers.environment}
|
|
|
191
177
|
if (needsPaymongo) {
|
|
192
178
|
lines.push('.paymongo');
|
|
193
179
|
}
|
|
194
|
-
gitignoreContent += lines.join('\n')
|
|
180
|
+
gitignoreContent += `${lines.join('\n')}\n`;
|
|
195
181
|
fs.writeFileSync(gitignorePath, gitignoreContent);
|
|
196
182
|
console.log(chalk.green('✓ Added .env and .paymongo to .gitignore'));
|
|
197
183
|
}
|
|
198
|
-
console.log(
|
|
199
|
-
console.log(
|
|
184
|
+
console.log(`\n${chalk.green('🎉 PayMongo project initialized!')}`);
|
|
185
|
+
console.log(`\n${chalk.bold('Configuration saved to .paymongo')}`);
|
|
200
186
|
console.log(chalk.bold('Environment variables saved to .env'));
|
|
201
|
-
console.log(
|
|
202
|
-
console.log(
|
|
187
|
+
console.log(`\n${chalk.bold('Next steps:')}`);
|
|
188
|
+
console.log(` 1. Run ${chalk.cyan('paymongo dev')} to start development server`);
|
|
203
189
|
console.log(' 2. Configure your webhook handler at ' +
|
|
204
190
|
chalk.cyan(`http://localhost:${answers.port}/webhook`));
|
|
205
|
-
console.log(
|
|
206
|
-
console.log(
|
|
191
|
+
console.log(` 3. Visit ${chalk.cyan('https://dashboard.paymongo.com')} to view transactions`);
|
|
192
|
+
console.log(`\n${chalk.yellow('Happy building! 🚀')}`);
|
|
207
193
|
}
|
|
208
194
|
catch (error) {
|
|
209
195
|
spinner.stop();
|
package/dist/commands/login.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
import * as fs from 'fs';
|
|
3
|
-
import * as
|
|
4
|
-
import * as
|
|
5
|
-
import * as os from 'os';
|
|
1
|
+
import * as crypto from 'node:crypto';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import * as os from 'node:os';
|
|
4
|
+
import * as path from 'node:path';
|
|
6
5
|
import chalk from 'chalk';
|
|
7
|
-
import
|
|
8
|
-
import
|
|
6
|
+
import { Command } from 'commander';
|
|
7
|
+
import { ApiKeyError, CommandError, NetworkError, PayMongoError } from '../utils/errors.js';
|
|
9
8
|
import { validateApiKey } from '../utils/validator.js';
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
9
|
+
import { createCredentialValidationConfig } from './shared/auth.js';
|
|
10
|
+
import { createApiClient, createCommandContext } from './shared/runtime.js';
|
|
12
11
|
class CredentialManager {
|
|
13
12
|
credentialsPath;
|
|
14
13
|
encryptionKey;
|
|
@@ -105,8 +104,7 @@ command
|
|
|
105
104
|
.option('-e, --env <environment>', 'Environment (test or live)', 'test')
|
|
106
105
|
.option('--logout', 'Clear stored credentials')
|
|
107
106
|
.action(async (options) => {
|
|
108
|
-
const spinner =
|
|
109
|
-
const configManager = new ConfigManager();
|
|
107
|
+
const { spinner, configManager } = createCommandContext();
|
|
110
108
|
const credentialManager = new CredentialManager();
|
|
111
109
|
try {
|
|
112
110
|
if (options.logout) {
|
|
@@ -171,21 +169,12 @@ command
|
|
|
171
169
|
};
|
|
172
170
|
}
|
|
173
171
|
spinner.start('Validating API key...');
|
|
174
|
-
const tempConfig = {
|
|
175
|
-
version: '1.0',
|
|
176
|
-
projectName: 'temp',
|
|
172
|
+
const tempConfig = createCredentialValidationConfig({
|
|
177
173
|
environment: answers.environment,
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
},
|
|
183
|
-
},
|
|
184
|
-
webhooks: { url: '', events: [] },
|
|
185
|
-
webhookSecrets: {},
|
|
186
|
-
dev: { port: 3000, autoRegisterWebhook: true, verifyWebhookSignatures: true },
|
|
187
|
-
};
|
|
188
|
-
const apiClient = new ApiClient({ config: tempConfig });
|
|
174
|
+
publicKey: answers.publicKey || '',
|
|
175
|
+
secretKey: answers.secretKey,
|
|
176
|
+
});
|
|
177
|
+
const apiClient = createApiClient(tempConfig);
|
|
189
178
|
try {
|
|
190
179
|
await apiClient.validateApiKey();
|
|
191
180
|
spinner.succeed('API key validated');
|
|
@@ -244,14 +233,14 @@ command
|
|
|
244
233
|
};
|
|
245
234
|
await configManager.save(config);
|
|
246
235
|
}
|
|
247
|
-
console.log(
|
|
248
|
-
console.log(
|
|
236
|
+
console.log(`\n${chalk.green('🔐 PayMongo Login Successful')}`);
|
|
237
|
+
console.log(`\n${chalk.bold('Current configuration:')}`);
|
|
249
238
|
console.log(` Environment: ${answers.environment}`);
|
|
250
239
|
console.log(` Secret Key: ${'*'.repeat(20)}...${answers.secretKey.slice(-4)}`);
|
|
251
240
|
if (answers.publicKey) {
|
|
252
241
|
console.log(` Public Key: ${'*'.repeat(20)}...${answers.publicKey.slice(-4)}`);
|
|
253
242
|
}
|
|
254
|
-
console.log(
|
|
243
|
+
console.log(`\n${chalk.gray("Use 'paymongo config show' to view settings")}`);
|
|
255
244
|
console.log(chalk.gray("Use 'paymongo login --logout' to clear credentials"));
|
|
256
245
|
}
|
|
257
246
|
catch (error) {
|
|
@@ -288,4 +277,4 @@ command
|
|
|
288
277
|
throw new CommandError();
|
|
289
278
|
}
|
|
290
279
|
});
|
|
291
|
-
export {
|
|
280
|
+
export { CredentialManager, command };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import Table from 'cli-table3';
|
|
2
1
|
import chalk from 'chalk';
|
|
2
|
+
import Table from 'cli-table3';
|
|
3
3
|
import { BulkOperations } from '../../utils/bulk.js';
|
|
4
4
|
import { createApiClient, createPaymentSimulator, createPaymentsContext, getStatusColor, handlePaymentsError, loadPaymentsConfig, parseBoundedInt, } from './helpers.js';
|
|
5
5
|
export async function exportAction(options) {
|
|
@@ -23,7 +23,7 @@ export async function exportAction(options) {
|
|
|
23
23
|
spinner.start(`Exporting to ${filename}...`);
|
|
24
24
|
await BulkOperations.exportPayments(payments, filename, config.environment);
|
|
25
25
|
spinner.succeed('Export completed');
|
|
26
|
-
console.log(
|
|
26
|
+
console.log(`\n${chalk.green('✅ Payments exported successfully!')}`);
|
|
27
27
|
console.log('');
|
|
28
28
|
console.log(`${chalk.bold('File:')} ${filename}`);
|
|
29
29
|
console.log(`${chalk.bold('Payments:')} ${payments.length}`);
|
|
@@ -44,18 +44,18 @@ export async function importAction(filename, options) {
|
|
|
44
44
|
console.log(JSON.stringify({ payments, metadata }, null, 2));
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
|
-
console.log(
|
|
47
|
+
console.log(`\n${chalk.green('✅ Payments imported successfully!')}`);
|
|
48
48
|
console.log('');
|
|
49
49
|
console.log(`${chalk.bold('Source:')} ${filename}`);
|
|
50
50
|
console.log(`${chalk.bold('Payments:')} ${payments.length}`);
|
|
51
51
|
console.log(`${chalk.bold('Exported from:')} ${metadata.environment} environment`);
|
|
52
52
|
console.log(`${chalk.bold('Export date:')} ${new Date(metadata.exported_at).toLocaleString()}`);
|
|
53
|
-
console.log(
|
|
53
|
+
console.log(`\n${chalk.yellow('⚠️ Important Notes:')}`);
|
|
54
54
|
console.log(chalk.gray('• Payment data imported for reference only'));
|
|
55
55
|
console.log(chalk.gray('• Actual payments cannot be recreated through the API'));
|
|
56
56
|
console.log(chalk.gray('• Use this for data analysis, migration planning, or testing'));
|
|
57
57
|
if (payments.length > 0) {
|
|
58
|
-
console.log(
|
|
58
|
+
console.log(`\n${chalk.bold('Sample Payment IDs:')}`);
|
|
59
59
|
payments.slice(0, 5).forEach((payment, index) => {
|
|
60
60
|
const amount = (payment.attributes.amount / 100).toFixed(2);
|
|
61
61
|
console.log(` ${index + 1}. ${payment.id} - ₱${amount} ${payment.attributes.currency}`);
|
|
@@ -111,10 +111,10 @@ export async function listAction(options) {
|
|
|
111
111
|
chalk.yellow(amount),
|
|
112
112
|
getStatusColor(status)(status),
|
|
113
113
|
chalk.gray(created),
|
|
114
|
-
chalk.white(description.length > 25 ? description.substring(0, 22)
|
|
114
|
+
chalk.white(description.length > 25 ? `${description.substring(0, 22)}...` : description),
|
|
115
115
|
]);
|
|
116
116
|
});
|
|
117
|
-
console.log(
|
|
117
|
+
console.log(`\n${chalk.bold('Recent Payments')}`);
|
|
118
118
|
console.log(chalk.gray('─'.repeat(95)));
|
|
119
119
|
console.log(table.toString());
|
|
120
120
|
console.log(chalk.gray(`Total: ${payments.length} payments`));
|
|
@@ -142,7 +142,7 @@ export async function showAction(id, options) {
|
|
|
142
142
|
const amount = (attrs.amount / 100).toFixed(2);
|
|
143
143
|
const fees = attrs.fees ? (attrs.fees / 100).toFixed(2) : '0.00';
|
|
144
144
|
const netAmount = attrs.net_amount ? (attrs.net_amount / 100).toFixed(2) : '0.00';
|
|
145
|
-
console.log(
|
|
145
|
+
console.log(`\n${chalk.bold('Payment Details')}`);
|
|
146
146
|
console.log(chalk.gray('─'.repeat(50)));
|
|
147
147
|
console.log(`${chalk.bold('ID:')} ${payment.id}`);
|
|
148
148
|
console.log(`${chalk.bold('Amount:')} ₱${amount} ${attrs.currency}`);
|
|
@@ -183,7 +183,7 @@ export async function createIntentAction(options) {
|
|
|
183
183
|
return;
|
|
184
184
|
}
|
|
185
185
|
const attrs = paymentIntent.attributes;
|
|
186
|
-
console.log(
|
|
186
|
+
console.log(`\n${chalk.bold('Payment Intent Created')}`);
|
|
187
187
|
console.log(chalk.gray('─'.repeat(50)));
|
|
188
188
|
console.log(`${chalk.bold('ID:')} ${paymentIntent.id}`);
|
|
189
189
|
console.log(`${chalk.bold('Amount:')} ₱${(attrs.amount / 100).toFixed(2)} ${attrs.currency}`);
|
|
@@ -222,10 +222,10 @@ export async function attachAction(intentId, options) {
|
|
|
222
222
|
throw new Error(`Invalid simulation outcome. Must be one of: ${validOutcomes.join(', ')}`);
|
|
223
223
|
}
|
|
224
224
|
const delayMs = options.delay ? parseInt(options.delay, 10) : undefined;
|
|
225
|
-
if (options.delay && (delayMs === undefined || isNaN(delayMs) || delayMs <= 0)) {
|
|
225
|
+
if (options.delay && (delayMs === undefined || Number.isNaN(delayMs) || delayMs <= 0)) {
|
|
226
226
|
throw new Error('Simulation delay must be a positive number in milliseconds');
|
|
227
227
|
}
|
|
228
|
-
console.log(
|
|
228
|
+
console.log(`\n${chalk.bold('🧪 Payment Simulation Mode')}`);
|
|
229
229
|
console.log(chalk.gray('─'.repeat(50)));
|
|
230
230
|
console.log(`${chalk.bold('Method:')} ${options.method.toUpperCase()}`);
|
|
231
231
|
console.log(`${chalk.bold('Outcome:')} ${options.outcome}`);
|
|
@@ -243,7 +243,7 @@ export async function attachAction(intentId, options) {
|
|
|
243
243
|
return;
|
|
244
244
|
}
|
|
245
245
|
const attrs = result.paymentIntent.attributes;
|
|
246
|
-
console.log(
|
|
246
|
+
console.log(`\n${chalk.bold('Payment Intent Confirmed (Simulated)')}`);
|
|
247
247
|
console.log(chalk.gray('─'.repeat(50)));
|
|
248
248
|
console.log(`${chalk.bold('ID:')} ${result.paymentIntent.id}`);
|
|
249
249
|
console.log(`${chalk.bold('Amount:')} ₱${(attrs.amount / 100).toFixed(2)} ${attrs.currency}`);
|
|
@@ -264,7 +264,7 @@ export async function attachAction(intentId, options) {
|
|
|
264
264
|
return;
|
|
265
265
|
}
|
|
266
266
|
const attrs = result.attributes;
|
|
267
|
-
console.log(
|
|
267
|
+
console.log(`\n${chalk.bold('Payment Method Attached')}`);
|
|
268
268
|
console.log(chalk.gray('─'.repeat(50)));
|
|
269
269
|
console.log(`${chalk.bold('ID:')} ${result.id}`);
|
|
270
270
|
console.log(`${chalk.bold('Amount:')} ₱${(attrs.amount / 100).toFixed(2)} ${attrs.currency}`);
|
|
@@ -295,7 +295,7 @@ export async function captureAction(intentId, options) {
|
|
|
295
295
|
return;
|
|
296
296
|
}
|
|
297
297
|
const attrs = result.attributes;
|
|
298
|
-
console.log(
|
|
298
|
+
console.log(`\n${chalk.bold('Payment Intent Captured')}`);
|
|
299
299
|
console.log(chalk.gray('─'.repeat(50)));
|
|
300
300
|
console.log(`${chalk.bold('ID:')} ${result.id}`);
|
|
301
301
|
console.log(`${chalk.bold('Amount:')} ₱${(attrs.amount / 100).toFixed(2)} ${attrs.currency}`);
|
|
@@ -331,7 +331,7 @@ export async function refundAction(paymentId, options) {
|
|
|
331
331
|
return;
|
|
332
332
|
}
|
|
333
333
|
const attrs = refund.attributes;
|
|
334
|
-
console.log(
|
|
334
|
+
console.log(`\n${chalk.bold('Refund Created')}`);
|
|
335
335
|
console.log(chalk.gray('─'.repeat(50)));
|
|
336
336
|
console.log(`${chalk.bold('ID:')} ${refund.id}`);
|
|
337
337
|
console.log(`${chalk.bold('Payment ID:')} ${attrs.payment_id}`);
|
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import ApiClient from '../../services/api/client.js';
|
|
3
|
-
import ConfigManager from '../../services/config/manager.js';
|
|
4
|
-
import Spinner from '../../utils/spinner.js';
|
|
5
2
|
import { PaymentSimulator } from '../../services/payments/simulator.js';
|
|
6
|
-
import {
|
|
3
|
+
import { createCommandContext, createApiClient as createSharedApiClient, failCommand, loadCommandConfig, } from '../shared/runtime.js';
|
|
7
4
|
export function createPaymentsContext() {
|
|
8
|
-
return
|
|
9
|
-
spinner: new Spinner(),
|
|
10
|
-
configManager: new ConfigManager(),
|
|
11
|
-
};
|
|
5
|
+
return createCommandContext();
|
|
12
6
|
}
|
|
13
7
|
export function getStatusColor(status) {
|
|
14
8
|
switch (status) {
|
|
@@ -30,32 +24,20 @@ export function getStatusColor(status) {
|
|
|
30
24
|
}
|
|
31
25
|
}
|
|
32
26
|
export async function loadPaymentsConfig(spinner, configManager) {
|
|
33
|
-
spinner
|
|
34
|
-
const config = await configManager.load();
|
|
35
|
-
if (!config) {
|
|
36
|
-
spinner.fail('No configuration found');
|
|
37
|
-
console.log(chalk.yellow('No PayMongo configuration found.'));
|
|
38
|
-
console.log(chalk.gray("Run 'paymongo init' to set up your project first."));
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
spinner.succeed('Configuration loaded');
|
|
42
|
-
return config;
|
|
27
|
+
return loadCommandConfig(spinner, configManager);
|
|
43
28
|
}
|
|
44
29
|
export function createApiClient(config) {
|
|
45
|
-
return
|
|
30
|
+
return createSharedApiClient(config);
|
|
46
31
|
}
|
|
47
32
|
export function createPaymentSimulator() {
|
|
48
33
|
return new PaymentSimulator();
|
|
49
34
|
}
|
|
50
35
|
export function handlePaymentsError(prefix, spinner, error) {
|
|
51
|
-
spinner
|
|
52
|
-
const err = error;
|
|
53
|
-
console.error(chalk.red(prefix), err.message);
|
|
54
|
-
throw new CommandError();
|
|
36
|
+
return failCommand(prefix, error, spinner);
|
|
55
37
|
}
|
|
56
38
|
export function parseBoundedInt(value, fallback, errorMessage, validate) {
|
|
57
39
|
const parsed = parseInt(value || fallback, 10);
|
|
58
|
-
if (isNaN(parsed) || !validate(parsed)) {
|
|
40
|
+
if (Number.isNaN(parsed) || !validate(parsed)) {
|
|
59
41
|
throw new Error(errorMessage);
|
|
60
42
|
}
|
|
61
43
|
return parsed;
|
|
@@ -54,5 +54,5 @@ command
|
|
|
54
54
|
.option('-r, --reason <reason>', 'Refund reason: duplicate, fraudulent, requested_by_customer')
|
|
55
55
|
.option('-j, --json', 'Output as JSON')
|
|
56
56
|
.action(refundAction));
|
|
57
|
-
export {
|
|
57
|
+
export { attachAction, captureAction, confirmAction, createIntentAction, exportAction, importAction, listAction, refundAction, showAction, };
|
|
58
58
|
export default command;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export function createCredentialValidationConfig({ projectName = 'temp', environment, publicKey = '', secretKey, webhookUrl = '', events = [], port = 3000, }) {
|
|
2
|
+
return {
|
|
3
|
+
version: '1.0',
|
|
4
|
+
projectName,
|
|
5
|
+
environment,
|
|
6
|
+
apiKeys: {
|
|
7
|
+
[environment]: {
|
|
8
|
+
public: publicKey,
|
|
9
|
+
secret: secretKey,
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
webhooks: {
|
|
13
|
+
url: webhookUrl,
|
|
14
|
+
events,
|
|
15
|
+
},
|
|
16
|
+
webhookSecrets: {},
|
|
17
|
+
dev: {
|
|
18
|
+
port,
|
|
19
|
+
autoRegisterWebhook: true,
|
|
20
|
+
verifyWebhookSignatures: true,
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import ApiClient from '../../services/api/client.js';
|
|
3
|
+
import ConfigManager from '../../services/config/manager.js';
|
|
4
|
+
import { CommandError } from '../../utils/errors.js';
|
|
5
|
+
import Spinner from '../../utils/spinner.js';
|
|
6
|
+
export function createCommandContext() {
|
|
7
|
+
return {
|
|
8
|
+
spinner: new Spinner(),
|
|
9
|
+
configManager: new ConfigManager(),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export function showNoConfigMessage(message = "Run 'paymongo init' to set up your project first.") {
|
|
13
|
+
console.log(chalk.yellow('No PayMongo configuration found.'));
|
|
14
|
+
console.log(chalk.gray(message));
|
|
15
|
+
}
|
|
16
|
+
export async function loadCommandConfig(spinner, configManager, loadingText = 'Loading configuration...', missingMessage) {
|
|
17
|
+
spinner.start(loadingText);
|
|
18
|
+
const config = await configManager.load();
|
|
19
|
+
if (!config) {
|
|
20
|
+
spinner.fail('No configuration found');
|
|
21
|
+
showNoConfigMessage(missingMessage);
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
spinner.succeed('Configuration loaded');
|
|
25
|
+
return config;
|
|
26
|
+
}
|
|
27
|
+
export function createApiClient(config) {
|
|
28
|
+
return new ApiClient({ config });
|
|
29
|
+
}
|
|
30
|
+
export function failCommand(prefix, error, spinner) {
|
|
31
|
+
spinner?.stop();
|
|
32
|
+
const err = error;
|
|
33
|
+
console.error(chalk.red(prefix), err.message);
|
|
34
|
+
throw new CommandError();
|
|
35
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
1
2
|
import Table from 'cli-table3';
|
|
2
3
|
import { Command } from 'commander';
|
|
3
|
-
import Spinner from '../../utils/spinner.js';
|
|
4
|
-
import chalk from 'chalk';
|
|
5
4
|
import { ConfigManager } from '../../services/config/manager.js';
|
|
6
5
|
import { TeamService } from '../../services/team/service.js';
|
|
7
6
|
import { CommandError } from '../../utils/errors.js';
|
|
7
|
+
import Spinner from '../../utils/spinner.js';
|
|
8
8
|
const command = new Command('team')
|
|
9
9
|
.description('Team collaboration with API key sharing')
|
|
10
10
|
.showHelpAfterError();
|
|
@@ -44,7 +44,7 @@ command
|
|
|
44
44
|
console.log(chalk.gray(`Environments: ${bundle.environments.join(', ')}`));
|
|
45
45
|
if (options.copy) {
|
|
46
46
|
try {
|
|
47
|
-
const { execSync } = await import('child_process');
|
|
47
|
+
const { execSync } = await import('node:child_process');
|
|
48
48
|
const bundleJson = teamService.serializeBundle(bundle);
|
|
49
49
|
try {
|
|
50
50
|
execSync(`echo '${bundleJson.replace(/'/g, "'\\''")}' | clip`, { stdio: 'pipe' });
|
|
@@ -121,7 +121,7 @@ command
|
|
|
121
121
|
console.log(`Imported at: ${new Date().toLocaleString()}`);
|
|
122
122
|
console.log('');
|
|
123
123
|
console.log(chalk.yellow('ℹ️ Next steps:'));
|
|
124
|
-
console.log('• Run "paymongo config
|
|
124
|
+
console.log('• Run "paymongo config show" to see the imported keys');
|
|
125
125
|
console.log('• Test with "paymongo payments list" to verify access');
|
|
126
126
|
}
|
|
127
127
|
catch (error) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import Table from 'cli-table3';
|
|
2
1
|
import chalk from 'chalk';
|
|
2
|
+
import Table from 'cli-table3';
|
|
3
3
|
import { CommandError } from '../../utils/errors.js';
|
|
4
4
|
import { AVAILABLE_TRIGGER_EVENTS, createTriggerContext, failTriggerCommand, generateWebhookPayload, printJsonResponse, sendWebhookRequest, } from './helpers.js';
|
|
5
5
|
export async function sendWebhookEvent(options) {
|
|
@@ -235,7 +235,7 @@ export async function replayWebhookEvent(eventId, options) {
|
|
|
235
235
|
console.log(chalk.bold.blue(`\n📋 Recent "${options.event}" Events`));
|
|
236
236
|
console.log(chalk.gray('─'.repeat(60)));
|
|
237
237
|
matchingEvents.slice(0, 5).forEach((event, index) => {
|
|
238
|
-
console.log(`${chalk.cyan((index + 1).toString()
|
|
238
|
+
console.log(`${chalk.cyan(`${(index + 1).toString()}.`)} ${chalk.yellow(event.id)} - ${chalk.gray(new Date(event.timestamp * 1000).toLocaleString())}`);
|
|
239
239
|
});
|
|
240
240
|
console.log(chalk.gray('\n💡 Use "paymongo trigger replay <eventId>" to replay a specific event'));
|
|
241
241
|
return;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import crypto from 'crypto';
|
|
2
|
-
import ConfigManager from '../../services/config/manager.js';
|
|
3
|
-
import Spinner from '../../utils/spinner.js';
|
|
4
|
-
import Logger from '../../utils/logger.js';
|
|
5
|
-
import WebhookEventStore from '../../utils/webhook-store.js';
|
|
1
|
+
import crypto from 'node:crypto';
|
|
6
2
|
import { CLI_VERSION } from '../../utils/constants.js';
|
|
7
3
|
import { CommandError } from '../../utils/errors.js';
|
|
4
|
+
import Logger from '../../utils/logger.js';
|
|
5
|
+
import WebhookEventStore from '../../utils/webhook-store.js';
|
|
6
|
+
import { createCommandContext } from '../shared/runtime.js';
|
|
8
7
|
export function createTriggerContext() {
|
|
8
|
+
const { spinner, configManager } = createCommandContext();
|
|
9
9
|
return {
|
|
10
|
-
spinner
|
|
11
|
-
configManager
|
|
10
|
+
spinner,
|
|
11
|
+
configManager,
|
|
12
12
|
logger: new Logger(),
|
|
13
13
|
store: new WebhookEventStore(),
|
|
14
14
|
};
|
|
@@ -46,7 +46,11 @@ export function buildSignatureHeader(config, webhookUrl, body, livemode) {
|
|
|
46
46
|
.createHmac('sha256', secret)
|
|
47
47
|
.update(`${timestamp}.${body}`)
|
|
48
48
|
.digest('hex');
|
|
49
|
-
const parts = [
|
|
49
|
+
const parts = [
|
|
50
|
+
`t=${timestamp}`,
|
|
51
|
+
livemode ? 'te=' : `te=${signature}`,
|
|
52
|
+
livemode ? `li=${signature}` : 'li=',
|
|
53
|
+
];
|
|
50
54
|
return parts.join(',');
|
|
51
55
|
}
|
|
52
56
|
export async function sendWebhookRequest(config, webhookUrl, payload) {
|
|
@@ -219,7 +223,7 @@ export function generateWebhookPayload(eventType) {
|
|
|
219
223
|
}
|
|
220
224
|
export async function printJsonResponse(response) {
|
|
221
225
|
const contentType = response.headers['content-type'];
|
|
222
|
-
if (contentType
|
|
226
|
+
if (contentType?.includes('application/json')) {
|
|
223
227
|
return response.body.json();
|
|
224
228
|
}
|
|
225
229
|
return null;
|