paymongo-cli 1.4.4 → 1.4.7
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/.github/copilot-instructions.md +95 -95
- package/CHANGELOG.md +85 -1
- package/LICENSE +20 -20
- package/dist/.tsbuildinfo +1 -1
- package/dist/commands/config.js +30 -15
- package/dist/commands/dev/logs.js +3 -3
- package/dist/commands/dev/status.js +2 -2
- package/dist/commands/dev/stop.js +3 -3
- package/dist/commands/dev.js +9 -8
- package/dist/commands/env.js +6 -6
- package/dist/commands/generate/templates/checkout-page/index.js +520 -520
- package/dist/commands/generate/templates/payment-intent/javascript.js +68 -68
- package/dist/commands/generate/templates/payment-intent/typescript.js +92 -92
- package/dist/commands/generate/templates/webhook-handler/javascript.js +192 -147
- package/dist/commands/generate/templates/webhook-handler/typescript.js +147 -117
- package/dist/commands/generate.js +43 -37
- package/dist/commands/init.js +25 -8
- package/dist/commands/login.js +56 -19
- package/dist/commands/payments.js +9 -8
- package/dist/commands/team/index.js +11 -9
- package/dist/commands/trigger.js +58 -18
- package/dist/commands/webhooks.js +8 -7
- package/dist/index.js +9 -2
- package/dist/services/analytics/service.js +24 -19
- package/dist/services/api/client.js +16 -16
- package/dist/services/config/manager.js +6 -8
- package/dist/services/dev/process-manager.js +30 -32
- package/dist/services/dev/server.js +45 -39
- package/dist/services/team/service.js +4 -1
- package/dist/types/schemas.js +38 -9
- package/dist/utils/bulk.js +36 -4
- package/dist/utils/constants.js +11 -1
- package/dist/utils/errors.js +6 -0
- package/dist/utils/validator.js +10 -9
- package/dist/utils/webhook-store.js +18 -15
- package/eslint.config.ts +70 -70
- package/package.json +2 -2
- package/coverage/base.css +0 -224
- package/coverage/block-navigation.js +0 -87
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +0 -281
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -87
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +0 -281
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -210
- package/coverage/lcov.info +0 -5053
- package/coverage/prettify.css +0 -1
- package/coverage/prettify.js +0 -2
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +0 -210
- package/dist/commands/config.d.ts +0 -21
- package/dist/commands/config.d.ts.map +0 -1
- package/dist/commands/config.js.map +0 -1
- package/dist/commands/dev.d.ts +0 -16
- package/dist/commands/dev.d.ts.map +0 -1
- package/dist/commands/dev.js.map +0 -1
- package/dist/commands/env.d.ts +0 -4
- package/dist/commands/env.d.ts.map +0 -1
- package/dist/commands/env.js.map +0 -1
- package/dist/commands/init.d.ts +0 -15
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/login.d.ts +0 -20
- package/dist/commands/login.d.ts.map +0 -1
- package/dist/commands/login.js.map +0 -1
- package/dist/commands/payments.d.ts +0 -41
- package/dist/commands/payments.d.ts.map +0 -1
- package/dist/commands/payments.js.map +0 -1
- package/dist/commands/team/index.d.ts +0 -4
- package/dist/commands/team/index.d.ts.map +0 -1
- package/dist/commands/team/index.js.map +0 -1
- package/dist/commands/trigger.d.ts +0 -4
- package/dist/commands/trigger.d.ts.map +0 -1
- package/dist/commands/trigger.js.map +0 -1
- package/dist/commands/webhooks.d.ts +0 -23
- package/dist/commands/webhooks.d.ts.map +0 -1
- package/dist/commands/webhooks.js.map +0 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/services/analytics/service.d.ts +0 -35
- package/dist/services/analytics/service.d.ts.map +0 -1
- package/dist/services/analytics/service.js.map +0 -1
- package/dist/services/api/client.d.ts +0 -26
- package/dist/services/api/client.d.ts.map +0 -1
- package/dist/services/api/client.js.map +0 -1
- package/dist/services/api/rate-limiter.d.ts +0 -64
- package/dist/services/api/rate-limiter.d.ts.map +0 -1
- package/dist/services/api/rate-limiter.js.map +0 -1
- package/dist/services/api/undici-client.d.ts +0 -39
- package/dist/services/api/undici-client.d.ts.map +0 -1
- package/dist/services/api/undici-client.js +0 -288
- package/dist/services/api/undici-client.js.map +0 -1
- package/dist/services/config/manager.d.ts +0 -16
- package/dist/services/config/manager.d.ts.map +0 -1
- package/dist/services/config/manager.js.map +0 -1
- package/dist/services/dev/process-manager.d.ts +0 -50
- package/dist/services/dev/process-manager.d.ts.map +0 -1
- package/dist/services/dev/process-manager.js.map +0 -1
- package/dist/services/github/auth.d.ts +0 -15
- package/dist/services/github/auth.d.ts.map +0 -1
- package/dist/services/github/auth.js +0 -79
- package/dist/services/github/auth.js.map +0 -1
- package/dist/services/github/client.d.ts +0 -95
- package/dist/services/github/client.d.ts.map +0 -1
- package/dist/services/github/client.js +0 -130
- package/dist/services/github/client.js.map +0 -1
- package/dist/services/github/sync.d.ts +0 -26
- package/dist/services/github/sync.d.ts.map +0 -1
- package/dist/services/github/sync.js +0 -203
- package/dist/services/github/sync.js.map +0 -1
- package/dist/services/payments/simulator.d.ts +0 -28
- package/dist/services/payments/simulator.d.ts.map +0 -1
- package/dist/services/payments/simulator.js.map +0 -1
- package/dist/services/team/service.d.ts +0 -44
- package/dist/services/team/service.d.ts.map +0 -1
- package/dist/services/team/service.js.map +0 -1
- package/dist/services/web/server.d.ts +0 -31
- package/dist/services/web/server.d.ts.map +0 -1
- package/dist/services/web/server.js +0 -206
- package/dist/services/web/server.js.map +0 -1
- package/dist/types/paymongo.d.ts +0 -204
- package/dist/types/paymongo.d.ts.map +0 -1
- package/dist/types/paymongo.js.map +0 -1
- package/dist/types/schemas.d.ts +0 -80
- package/dist/types/schemas.d.ts.map +0 -1
- package/dist/types/schemas.js.map +0 -1
- package/dist/utils/bulk.d.ts +0 -62
- package/dist/utils/bulk.d.ts.map +0 -1
- package/dist/utils/bulk.js.map +0 -1
- package/dist/utils/cache.d.ts +0 -22
- package/dist/utils/cache.d.ts.map +0 -1
- package/dist/utils/cache.js.map +0 -1
- package/dist/utils/constants.d.ts +0 -32
- package/dist/utils/constants.d.ts.map +0 -1
- package/dist/utils/constants.js.map +0 -1
- package/dist/utils/errors.d.ts +0 -34
- package/dist/utils/errors.d.ts.map +0 -1
- package/dist/utils/errors.js.map +0 -1
- package/dist/utils/logger.d.ts +0 -20
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/spinner.d.ts +0 -17
- package/dist/utils/spinner.d.ts.map +0 -1
- package/dist/utils/spinner.js.map +0 -1
- package/dist/utils/validator.d.ts +0 -10
- package/dist/utils/validator.d.ts.map +0 -1
- package/dist/utils/validator.js.map +0 -1
- package/dist/utils/webhook-store.d.ts +0 -22
- package/dist/utils/webhook-store.d.ts.map +0 -1
- package/dist/utils/webhook-store.js.map +0 -1
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
-
import { input } from '@inquirer/prompts';
|
|
3
2
|
import chalk from 'chalk';
|
|
4
3
|
import fs from 'fs/promises';
|
|
5
4
|
import ConfigManager from '../services/config/manager.js';
|
|
@@ -8,12 +7,12 @@ import { getJavaScriptWebhookHandler, getTypeScriptWebhookHandler, getJavaScript
|
|
|
8
7
|
const command = new Command('generate');
|
|
9
8
|
command
|
|
10
9
|
.description('Generate boilerplate code for PayMongo integrations')
|
|
11
|
-
.addHelpText('after', `
|
|
12
|
-
EXAMPLES
|
|
13
|
-
$ paymongo generate webhook-handler --events payment.paid,payment.failed
|
|
14
|
-
$ paymongo generate webhook-handler --language typescript --framework express
|
|
15
|
-
$ paymongo generate payment-intent --methods card,gcash --language typescript
|
|
16
|
-
$ paymongo generate checkout-page --
|
|
10
|
+
.addHelpText('after', `
|
|
11
|
+
EXAMPLES
|
|
12
|
+
$ paymongo generate webhook-handler --events payment.paid,payment.failed
|
|
13
|
+
$ paymongo generate webhook-handler --language typescript --framework express
|
|
14
|
+
$ paymongo generate payment-intent --methods card,gcash --language typescript
|
|
15
|
+
$ paymongo generate checkout-page --language react --output Checkout.jsx
|
|
17
16
|
`)
|
|
18
17
|
.addCommand(new Command('webhook-handler')
|
|
19
18
|
.description('Generate a webhook handler for specific events')
|
|
@@ -21,17 +20,18 @@ EXAMPLES
|
|
|
21
20
|
.option('-l, --language <language>', 'Programming language (javascript, typescript)', 'javascript')
|
|
22
21
|
.option('-f, --framework <framework>', 'Framework (express, fastify, hapi)', 'express')
|
|
23
22
|
.option('-o, --output <file>', 'Output file path')
|
|
24
|
-
.addHelpText('after', `
|
|
25
|
-
SUPPORTED EVENTS:
|
|
26
|
-
payment.paid, payment.failed, payment.refunded
|
|
27
|
-
source.chargeable
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
$ paymongo generate webhook-handler
|
|
33
|
-
$ paymongo generate webhook-handler --
|
|
34
|
-
$ paymongo generate webhook-handler --
|
|
23
|
+
.addHelpText('after', `
|
|
24
|
+
SUPPORTED EVENTS:
|
|
25
|
+
payment.paid, payment.failed, payment.refunded
|
|
26
|
+
source.chargeable
|
|
27
|
+
checkout_session.payment.paid
|
|
28
|
+
qrph.expired
|
|
29
|
+
|
|
30
|
+
EXAMPLES:
|
|
31
|
+
$ paymongo generate webhook-handler
|
|
32
|
+
$ paymongo generate webhook-handler --events payment.paid,payment.failed
|
|
33
|
+
$ paymongo generate webhook-handler --language typescript --framework fastify
|
|
34
|
+
$ paymongo generate webhook-handler --output my-webhook.js
|
|
35
35
|
`)
|
|
36
36
|
.action(async (options) => {
|
|
37
37
|
await generateWebhookHandler(options);
|
|
@@ -41,14 +41,14 @@ EXAMPLES:
|
|
|
41
41
|
.option('-l, --language <language>', 'Programming language (javascript, typescript)', 'javascript')
|
|
42
42
|
.option('-m, --methods <methods>', 'Payment methods (card,gcash,paymaya,grab_pay,qrph)')
|
|
43
43
|
.option('-o, --output <file>', 'Output file path')
|
|
44
|
-
.addHelpText('after', `
|
|
45
|
-
PAYMENT METHODS:
|
|
46
|
-
card, gcash, paymaya, grab_pay, qrph
|
|
47
|
-
|
|
48
|
-
EXAMPLES:
|
|
49
|
-
$ paymongo generate payment-intent
|
|
50
|
-
$ paymongo generate payment-intent --methods card,gcash
|
|
51
|
-
$ paymongo generate payment-intent --language typescript --output create-payment.js
|
|
44
|
+
.addHelpText('after', `
|
|
45
|
+
PAYMENT METHODS:
|
|
46
|
+
card, gcash, paymaya, grab_pay, qrph
|
|
47
|
+
|
|
48
|
+
EXAMPLES:
|
|
49
|
+
$ paymongo generate payment-intent
|
|
50
|
+
$ paymongo generate payment-intent --methods card,gcash
|
|
51
|
+
$ paymongo generate payment-intent --language typescript --output create-payment.js
|
|
52
52
|
`)
|
|
53
53
|
.action(async (options) => {
|
|
54
54
|
await generatePaymentIntent(options);
|
|
@@ -57,14 +57,14 @@ EXAMPLES:
|
|
|
57
57
|
.description('Generate a basic checkout page with PayMongo integration')
|
|
58
58
|
.option('-l, --language <language>', 'Frontend language/framework (html, react, vue)', 'html')
|
|
59
59
|
.option('-o, --output <file>', 'Output file path')
|
|
60
|
-
.addHelpText('after', `
|
|
61
|
-
FRAMEWORKS:
|
|
62
|
-
html (vanilla HTML/JS), react, vue
|
|
63
|
-
|
|
64
|
-
EXAMPLES:
|
|
65
|
-
$ paymongo generate checkout-page
|
|
66
|
-
$ paymongo generate checkout-page --framework react
|
|
67
|
-
$ paymongo generate checkout-page --language vue --output Checkout.vue
|
|
60
|
+
.addHelpText('after', `
|
|
61
|
+
FRAMEWORKS:
|
|
62
|
+
html (vanilla HTML/JS), react, vue
|
|
63
|
+
|
|
64
|
+
EXAMPLES:
|
|
65
|
+
$ paymongo generate checkout-page
|
|
66
|
+
$ paymongo generate checkout-page --framework react
|
|
67
|
+
$ paymongo generate checkout-page --language vue --output Checkout.vue
|
|
68
68
|
`)
|
|
69
69
|
.action(async (options) => {
|
|
70
70
|
await generateCheckoutPage(options);
|
|
@@ -83,6 +83,7 @@ async function generateWebhookHandler(options) {
|
|
|
83
83
|
}
|
|
84
84
|
spinner.succeed('Configuration loaded');
|
|
85
85
|
let events = [];
|
|
86
|
+
const { input } = await import('@inquirer/prompts');
|
|
86
87
|
if (options.events) {
|
|
87
88
|
events = options.events.split(',').map(e => e.trim());
|
|
88
89
|
}
|
|
@@ -94,9 +95,12 @@ async function generateWebhookHandler(options) {
|
|
|
94
95
|
events = eventInput.split(',').map(e => e.trim());
|
|
95
96
|
}
|
|
96
97
|
const validEvents = [
|
|
97
|
-
'payment.paid',
|
|
98
|
-
'
|
|
99
|
-
'
|
|
98
|
+
'payment.paid',
|
|
99
|
+
'payment.failed',
|
|
100
|
+
'payment.refunded',
|
|
101
|
+
'source.chargeable',
|
|
102
|
+
'checkout_session.payment.paid',
|
|
103
|
+
'qrph.expired',
|
|
100
104
|
];
|
|
101
105
|
const invalidEvents = events.filter(e => !validEvents.includes(e));
|
|
102
106
|
if (invalidEvents.length > 0) {
|
|
@@ -146,6 +150,7 @@ async function generatePaymentIntent(options) {
|
|
|
146
150
|
else {
|
|
147
151
|
code = getJavaScriptPaymentIntent(methods);
|
|
148
152
|
}
|
|
153
|
+
const { input } = await import('@inquirer/prompts');
|
|
149
154
|
let outputFile = options.output;
|
|
150
155
|
if (!outputFile) {
|
|
151
156
|
const defaultName = `create-payment-intent.${options.language === 'typescript' ? 'ts' : 'js'}`;
|
|
@@ -170,6 +175,7 @@ async function generateCheckoutPage(options) {
|
|
|
170
175
|
const spinner = new Spinner();
|
|
171
176
|
try {
|
|
172
177
|
const { code, extension } = getCheckoutPageTemplate(options.language);
|
|
178
|
+
const { input } = await import('@inquirer/prompts');
|
|
173
179
|
let outputFile = options.output;
|
|
174
180
|
if (!outputFile) {
|
|
175
181
|
const defaultName = `checkout.${extension}`;
|
package/dist/commands/init.js
CHANGED
|
@@ -6,7 +6,7 @@ import ConfigManager from '../services/config/manager.js';
|
|
|
6
6
|
import ApiClient from '../services/api/client.js';
|
|
7
7
|
import { validateApiKey } from '../utils/validator.js';
|
|
8
8
|
import Spinner from '../utils/spinner.js';
|
|
9
|
-
import { ApiKeyError, NetworkError, PayMongoError } from '../utils/errors.js';
|
|
9
|
+
import { ApiKeyError, NetworkError, PayMongoError, CommandError } from '../utils/errors.js';
|
|
10
10
|
export async function initAction(options) {
|
|
11
11
|
const spinner = new Spinner();
|
|
12
12
|
const configManager = new ConfigManager();
|
|
@@ -156,7 +156,7 @@ export async function initAction(options) {
|
|
|
156
156
|
else {
|
|
157
157
|
console.error(chalk.red('❌ Unexpected error during validation. Please try again.'));
|
|
158
158
|
}
|
|
159
|
-
|
|
159
|
+
throw new CommandError();
|
|
160
160
|
}
|
|
161
161
|
spinner.start('Saving configuration...');
|
|
162
162
|
await configManager.save(tempConfig);
|
|
@@ -170,13 +170,30 @@ PAYMONGO_ENVIRONMENT=${answers.environment}
|
|
|
170
170
|
fs.writeFileSync(envPath, envContent);
|
|
171
171
|
spinner.succeed('.env file created');
|
|
172
172
|
const gitignorePath = path.join(process.cwd(), '.gitignore');
|
|
173
|
+
const ignoreHeader = '# PayMongo';
|
|
174
|
+
let gitignoreContent = '';
|
|
173
175
|
if (fs.existsSync(gitignorePath)) {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
176
|
+
gitignoreContent = fs.readFileSync(gitignorePath, 'utf-8');
|
|
177
|
+
}
|
|
178
|
+
const needsEnv = !gitignoreContent.includes('.env');
|
|
179
|
+
const needsPaymongo = !gitignoreContent.includes('.paymongo');
|
|
180
|
+
if (needsEnv || needsPaymongo) {
|
|
181
|
+
const lines = [];
|
|
182
|
+
if (!gitignoreContent.trim()) {
|
|
183
|
+
lines.push(ignoreHeader);
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
lines.push('', ignoreHeader);
|
|
187
|
+
}
|
|
188
|
+
if (needsEnv) {
|
|
189
|
+
lines.push('.env');
|
|
190
|
+
}
|
|
191
|
+
if (needsPaymongo) {
|
|
192
|
+
lines.push('.paymongo');
|
|
179
193
|
}
|
|
194
|
+
gitignoreContent += lines.join('\n') + '\n';
|
|
195
|
+
fs.writeFileSync(gitignorePath, gitignoreContent);
|
|
196
|
+
console.log(chalk.green('✓ Added .env and .paymongo to .gitignore'));
|
|
180
197
|
}
|
|
181
198
|
console.log('\n' + chalk.green('🎉 PayMongo project initialized!'));
|
|
182
199
|
console.log('\n' + chalk.bold('Configuration saved to .paymongo'));
|
|
@@ -222,7 +239,7 @@ PAYMONGO_ENVIRONMENT=${answers.environment}
|
|
|
222
239
|
console.log('');
|
|
223
240
|
console.log(chalk.yellow('💡 For help, visit: https://developers.paymongo.com/docs'));
|
|
224
241
|
}
|
|
225
|
-
|
|
242
|
+
throw new CommandError();
|
|
226
243
|
}
|
|
227
244
|
}
|
|
228
245
|
const command = new Command('init');
|
package/dist/commands/login.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
-
import { select, password } from '@inquirer/prompts';
|
|
3
2
|
import * as fs from 'fs';
|
|
4
3
|
import * as path from 'path';
|
|
5
4
|
import * as crypto from 'crypto';
|
|
@@ -8,7 +7,7 @@ import chalk from 'chalk';
|
|
|
8
7
|
import ConfigManager from '../services/config/manager.js';
|
|
9
8
|
import ApiClient from '../services/api/client.js';
|
|
10
9
|
import { validateApiKey } from '../utils/validator.js';
|
|
11
|
-
import { ApiKeyError, NetworkError, PayMongoError } from '../utils/errors.js';
|
|
10
|
+
import { ApiKeyError, NetworkError, PayMongoError, CommandError } from '../utils/errors.js';
|
|
12
11
|
import Spinner from '../utils/spinner.js';
|
|
13
12
|
class CredentialManager {
|
|
14
13
|
credentialsPath;
|
|
@@ -20,22 +19,38 @@ class CredentialManager {
|
|
|
20
19
|
fs.mkdirSync(configDir, { recursive: true, mode: 0o700 });
|
|
21
20
|
}
|
|
22
21
|
this.credentialsPath = path.join(configDir, 'credentials.enc');
|
|
22
|
+
this.encryptionKey = this.deriveEncryptionKey();
|
|
23
|
+
}
|
|
24
|
+
deriveEncryptionKey() {
|
|
23
25
|
const machineId = os.hostname() + os.userInfo().username;
|
|
24
|
-
this.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
.
|
|
28
|
-
|
|
26
|
+
const saltPath = path.join(path.dirname(this.credentialsPath), 'credentials.salt');
|
|
27
|
+
let salt;
|
|
28
|
+
try {
|
|
29
|
+
if (fs.existsSync(saltPath)) {
|
|
30
|
+
const saltHex = fs.readFileSync(saltPath, 'utf8').trim();
|
|
31
|
+
salt = Buffer.from(saltHex, 'hex');
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
salt = crypto.randomBytes(16);
|
|
35
|
+
fs.writeFileSync(saltPath, salt.toString('hex'), { mode: 0o600 });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
salt = crypto.randomBytes(16);
|
|
40
|
+
}
|
|
41
|
+
return crypto.scryptSync(machineId, salt, 32);
|
|
29
42
|
}
|
|
30
43
|
async saveCredentials(credentials) {
|
|
31
44
|
const data = JSON.stringify(credentials);
|
|
32
|
-
const iv = crypto.randomBytes(
|
|
33
|
-
const cipher = crypto.createCipheriv('aes-256-
|
|
34
|
-
|
|
35
|
-
|
|
45
|
+
const iv = crypto.randomBytes(12);
|
|
46
|
+
const cipher = crypto.createCipheriv('aes-256-gcm', this.encryptionKey, iv);
|
|
47
|
+
const encrypted = Buffer.concat([cipher.update(data, 'utf8'), cipher.final()]);
|
|
48
|
+
const tag = cipher.getAuthTag();
|
|
36
49
|
const payload = {
|
|
50
|
+
v: 2,
|
|
37
51
|
iv: iv.toString('hex'),
|
|
38
|
-
|
|
52
|
+
tag: tag.toString('hex'),
|
|
53
|
+
data: encrypted.toString('hex'),
|
|
39
54
|
};
|
|
40
55
|
fs.writeFileSync(this.credentialsPath, JSON.stringify(payload), { mode: 0o600 });
|
|
41
56
|
}
|
|
@@ -45,11 +60,32 @@ class CredentialManager {
|
|
|
45
60
|
return null;
|
|
46
61
|
}
|
|
47
62
|
const payload = JSON.parse(fs.readFileSync(this.credentialsPath, 'utf8'));
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
63
|
+
if (payload.v === 2 && payload.iv && payload.tag && payload.data) {
|
|
64
|
+
const iv = Buffer.from(payload.iv, 'hex');
|
|
65
|
+
const tag = Buffer.from(payload.tag, 'hex');
|
|
66
|
+
const decipher = crypto.createDecipheriv('aes-256-gcm', this.encryptionKey, iv);
|
|
67
|
+
decipher.setAuthTag(tag);
|
|
68
|
+
const decrypted = Buffer.concat([
|
|
69
|
+
decipher.update(Buffer.from(payload.data, 'hex')),
|
|
70
|
+
decipher.final(),
|
|
71
|
+
]).toString('utf8');
|
|
72
|
+
return JSON.parse(decrypted);
|
|
73
|
+
}
|
|
74
|
+
if (payload.iv && payload.data) {
|
|
75
|
+
const legacyKey = crypto
|
|
76
|
+
.createHash('sha256')
|
|
77
|
+
.update(os.hostname() + os.userInfo().username)
|
|
78
|
+
.digest('hex')
|
|
79
|
+
.substring(0, 32);
|
|
80
|
+
const iv = Buffer.from(payload.iv, 'hex');
|
|
81
|
+
const decipher = crypto.createDecipheriv('aes-256-cbc', legacyKey, iv);
|
|
82
|
+
let decrypted = decipher.update(payload.data, 'hex', 'utf8');
|
|
83
|
+
decrypted += decipher.final('utf8');
|
|
84
|
+
const credentials = JSON.parse(decrypted);
|
|
85
|
+
await this.saveCredentials(credentials);
|
|
86
|
+
return credentials;
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
53
89
|
}
|
|
54
90
|
catch (_error) {
|
|
55
91
|
return null;
|
|
@@ -95,6 +131,7 @@ command
|
|
|
95
131
|
}
|
|
96
132
|
else {
|
|
97
133
|
const storedCredentials = await credentialManager.loadCredentials();
|
|
134
|
+
const { select, password } = await import('@inquirer/prompts');
|
|
98
135
|
const environment = await select({
|
|
99
136
|
message: 'Environment:',
|
|
100
137
|
choices: [
|
|
@@ -176,7 +213,7 @@ command
|
|
|
176
213
|
else {
|
|
177
214
|
console.error(chalk.red('❌ Unexpected error during validation. Please try again.'));
|
|
178
215
|
}
|
|
179
|
-
|
|
216
|
+
throw new CommandError();
|
|
180
217
|
}
|
|
181
218
|
spinner.start('Storing credentials securely...');
|
|
182
219
|
const credentials = {
|
|
@@ -248,7 +285,7 @@ command
|
|
|
248
285
|
console.log('');
|
|
249
286
|
console.log(chalk.yellow('💡 For help, visit: https://developers.paymongo.com'));
|
|
250
287
|
}
|
|
251
|
-
|
|
288
|
+
throw new CommandError();
|
|
252
289
|
}
|
|
253
290
|
});
|
|
254
291
|
export { command, CredentialManager };
|
|
@@ -6,6 +6,7 @@ import ApiClient from '../services/api/client.js';
|
|
|
6
6
|
import { PaymentSimulator } from '../services/payments/simulator.js';
|
|
7
7
|
import { BulkOperations } from '../utils/bulk.js';
|
|
8
8
|
import Spinner from '../utils/spinner.js';
|
|
9
|
+
import { CommandError } from '../utils/errors.js';
|
|
9
10
|
export async function exportAction(options) {
|
|
10
11
|
const spinner = new Spinner();
|
|
11
12
|
const configManager = new ConfigManager();
|
|
@@ -52,7 +53,7 @@ export async function exportAction(options) {
|
|
|
52
53
|
spinner.stop();
|
|
53
54
|
const err = error;
|
|
54
55
|
console.error(chalk.red('❌ Failed to export payments:'), err.message);
|
|
55
|
-
|
|
56
|
+
throw new CommandError();
|
|
56
57
|
}
|
|
57
58
|
}
|
|
58
59
|
export async function importAction(filename, options) {
|
|
@@ -90,7 +91,7 @@ export async function importAction(filename, options) {
|
|
|
90
91
|
spinner.stop();
|
|
91
92
|
const err = error;
|
|
92
93
|
console.error(chalk.red('❌ Failed to import payments:'), err.message);
|
|
93
|
-
|
|
94
|
+
throw new CommandError();
|
|
94
95
|
}
|
|
95
96
|
}
|
|
96
97
|
export async function listAction(options) {
|
|
@@ -155,7 +156,7 @@ export async function listAction(options) {
|
|
|
155
156
|
spinner.stop();
|
|
156
157
|
const err = error;
|
|
157
158
|
console.error(chalk.red('❌ Failed to fetch payments:'), err.message);
|
|
158
|
-
|
|
159
|
+
throw new CommandError();
|
|
159
160
|
}
|
|
160
161
|
}
|
|
161
162
|
export async function showAction(id, options) {
|
|
@@ -208,7 +209,7 @@ export async function showAction(id, options) {
|
|
|
208
209
|
spinner.stop();
|
|
209
210
|
const err = error;
|
|
210
211
|
console.error(chalk.red('❌ Failed to fetch payment:'), err.message);
|
|
211
|
-
|
|
212
|
+
throw new CommandError();
|
|
212
213
|
}
|
|
213
214
|
}
|
|
214
215
|
export async function createIntentAction(options) {
|
|
@@ -252,7 +253,7 @@ export async function createIntentAction(options) {
|
|
|
252
253
|
spinner.stop();
|
|
253
254
|
const err = error;
|
|
254
255
|
console.error(chalk.red('❌ Failed to create payment intent:'), err.message);
|
|
255
|
-
|
|
256
|
+
throw new CommandError();
|
|
256
257
|
}
|
|
257
258
|
}
|
|
258
259
|
export async function confirmAction(intentId, options) {
|
|
@@ -349,7 +350,7 @@ export async function confirmAction(intentId, options) {
|
|
|
349
350
|
spinner.stop();
|
|
350
351
|
const err = error;
|
|
351
352
|
console.error(chalk.red('❌ Failed to confirm payment intent:'), err.message);
|
|
352
|
-
|
|
353
|
+
throw new CommandError();
|
|
353
354
|
}
|
|
354
355
|
}
|
|
355
356
|
export async function captureAction(intentId, options) {
|
|
@@ -389,7 +390,7 @@ export async function captureAction(intentId, options) {
|
|
|
389
390
|
spinner.stop();
|
|
390
391
|
const err = error;
|
|
391
392
|
console.error(chalk.red('❌ Failed to capture payment intent:'), err.message);
|
|
392
|
-
|
|
393
|
+
throw new CommandError();
|
|
393
394
|
}
|
|
394
395
|
}
|
|
395
396
|
export async function refundAction(paymentId, options) {
|
|
@@ -435,7 +436,7 @@ export async function refundAction(paymentId, options) {
|
|
|
435
436
|
spinner.stop();
|
|
436
437
|
const err = error;
|
|
437
438
|
console.error(chalk.red('❌ Failed to create refund:'), err.message);
|
|
438
|
-
|
|
439
|
+
throw new CommandError();
|
|
439
440
|
}
|
|
440
441
|
}
|
|
441
442
|
const command = new Command('payments');
|
|
@@ -4,7 +4,7 @@ import Spinner from '../../utils/spinner.js';
|
|
|
4
4
|
import chalk from 'chalk';
|
|
5
5
|
import { ConfigManager } from '../../services/config/manager.js';
|
|
6
6
|
import { TeamService } from '../../services/team/service.js';
|
|
7
|
-
import {
|
|
7
|
+
import { CommandError } from '../../utils/errors.js';
|
|
8
8
|
const command = new Command('team')
|
|
9
9
|
.description('Team collaboration with API key sharing')
|
|
10
10
|
.showHelpAfterError();
|
|
@@ -24,7 +24,7 @@ command
|
|
|
24
24
|
if (invalidEnvs.length > 0) {
|
|
25
25
|
console.error(chalk.red(`❌ Invalid environments: ${invalidEnvs.join(', ')}`));
|
|
26
26
|
console.log(`Valid environments: ${validEnvs.join(', ')}`);
|
|
27
|
-
|
|
27
|
+
throw new CommandError();
|
|
28
28
|
}
|
|
29
29
|
spinner.start(`Creating key bundle for ${environments.join(', ')}...`);
|
|
30
30
|
const bundle = await teamService.createKeyBundle(environments);
|
|
@@ -71,16 +71,17 @@ command
|
|
|
71
71
|
spinner.stop();
|
|
72
72
|
const err = error;
|
|
73
73
|
console.error(chalk.red('❌ Failed to create key bundle:'), err.message);
|
|
74
|
-
|
|
74
|
+
throw new CommandError();
|
|
75
75
|
}
|
|
76
76
|
});
|
|
77
77
|
command
|
|
78
78
|
.command('import-keys')
|
|
79
79
|
.description('Import shared API keys from team member')
|
|
80
80
|
.option('-f, --force', 'Overwrite existing keys without confirmation')
|
|
81
|
-
.action(async (
|
|
81
|
+
.action(async (options) => {
|
|
82
82
|
const spinner = new Spinner();
|
|
83
83
|
try {
|
|
84
|
+
const { input } = await import('@inquirer/prompts');
|
|
84
85
|
const config = new ConfigManager();
|
|
85
86
|
const teamService = new TeamService({ config });
|
|
86
87
|
const bundleJson = await input({
|
|
@@ -109,7 +110,7 @@ command
|
|
|
109
110
|
});
|
|
110
111
|
spinner.start('Importing keys...');
|
|
111
112
|
const bundle = teamService.deserializeBundle(bundleJson);
|
|
112
|
-
await teamService.importKeyBundle(bundle, memberName);
|
|
113
|
+
await teamService.importKeyBundle(bundle, memberName, { force: options.force });
|
|
113
114
|
spinner.succeed('Keys imported successfully!');
|
|
114
115
|
console.log(chalk.green('✅ API keys imported'));
|
|
115
116
|
console.log('');
|
|
@@ -127,7 +128,7 @@ command
|
|
|
127
128
|
spinner.stop();
|
|
128
129
|
const err = error;
|
|
129
130
|
console.error(chalk.red('❌ Failed to import keys:'), err.message);
|
|
130
|
-
|
|
131
|
+
throw new CommandError();
|
|
131
132
|
}
|
|
132
133
|
});
|
|
133
134
|
command
|
|
@@ -190,7 +191,7 @@ command
|
|
|
190
191
|
spinner.stop();
|
|
191
192
|
const err = error;
|
|
192
193
|
console.error(chalk.red('❌ Failed to load team members:'), err.message);
|
|
193
|
-
|
|
194
|
+
throw new CommandError();
|
|
194
195
|
}
|
|
195
196
|
});
|
|
196
197
|
command
|
|
@@ -211,7 +212,7 @@ command
|
|
|
211
212
|
spinner.stop();
|
|
212
213
|
const err = error;
|
|
213
214
|
console.error(chalk.red('❌ Failed to rename team:'), err.message);
|
|
214
|
-
|
|
215
|
+
throw new CommandError();
|
|
215
216
|
}
|
|
216
217
|
});
|
|
217
218
|
command
|
|
@@ -221,6 +222,7 @@ command
|
|
|
221
222
|
.action(async (memberName) => {
|
|
222
223
|
const spinner = new Spinner();
|
|
223
224
|
try {
|
|
225
|
+
const { confirm } = await import('@inquirer/prompts');
|
|
224
226
|
const confirmed = await confirm({
|
|
225
227
|
message: `Are you sure you want to remove "${memberName}" from the team?`,
|
|
226
228
|
default: false,
|
|
@@ -241,7 +243,7 @@ command
|
|
|
241
243
|
spinner.stop();
|
|
242
244
|
const err = error;
|
|
243
245
|
console.error(chalk.red('❌ Failed to remove team member:'), err.message);
|
|
244
|
-
|
|
246
|
+
throw new CommandError();
|
|
245
247
|
}
|
|
246
248
|
});
|
|
247
249
|
export default command;
|