paymongo-cli 1.4.7 → 1.4.8

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.
@@ -1,566 +1,6 @@
1
1
  import { Command } from 'commander';
2
- import chalk from 'chalk';
3
- import * as fs from 'fs';
4
- import * as path from 'path';
5
- import ConfigManager from '../services/config/manager.js';
6
- import Spinner from '../utils/spinner.js';
7
- import { validateConfig as zodValidateConfig } from '../types/schemas.js';
8
- import { CommandError } from '../utils/errors.js';
9
- function validateImportedConfig(config) {
10
- if (typeof config !== 'object' || config === null) {
11
- throw new Error('Configuration must be an object');
12
- }
13
- const cfg = config;
14
- const requiredFields = ['version', 'projectName', 'environment', 'apiKeys', 'webhooks', 'dev'];
15
- for (const field of requiredFields) {
16
- if (!(field in cfg)) {
17
- throw new Error(`Missing required field: ${field}`);
18
- }
19
- }
20
- if (typeof cfg.version !== 'string') {
21
- throw new Error('Version must be a string');
22
- }
23
- if (typeof cfg.projectName !== 'string' || cfg.projectName.trim() === '') {
24
- throw new Error('Project name must be a non-empty string');
25
- }
26
- if (cfg.environment !== 'test' && cfg.environment !== 'live') {
27
- throw new Error('Environment must be either "test" or "live"');
28
- }
29
- if (typeof cfg.apiKeys !== 'object' || cfg.apiKeys === null) {
30
- throw new Error('API keys must be an object');
31
- }
32
- if (typeof cfg.webhooks !== 'object' || cfg.webhooks === null) {
33
- throw new Error('Webhooks must be an object');
34
- }
35
- const webhooks = cfg.webhooks;
36
- if (!Array.isArray(webhooks.events)) {
37
- throw new Error('Webhook events must be an array');
38
- }
39
- if (typeof cfg.dev !== 'object' || cfg.dev === null) {
40
- throw new Error('Dev config must be an object');
41
- }
42
- const dev = cfg.dev;
43
- if (typeof dev.port !== 'number' || dev.port < 1 || dev.port > 65535) {
44
- throw new Error('Dev port must be a valid port number (1-65535)');
45
- }
46
- }
47
- function checkConfigConflicts(existing, imported) {
48
- const conflicts = [];
49
- if (existing.apiKeys && imported.apiKeys) {
50
- if (existing.apiKeys.test?.public !== imported.apiKeys.test?.public) {
51
- conflicts.push('Test environment public API key differs');
52
- }
53
- if (existing.apiKeys.test?.secret !== imported.apiKeys.test?.secret) {
54
- conflicts.push('Test environment secret API key differs');
55
- }
56
- if (existing.apiKeys.live?.public !== imported.apiKeys.live?.public) {
57
- conflicts.push('Live environment public API key differs');
58
- }
59
- if (existing.apiKeys.live?.secret !== imported.apiKeys.live?.secret) {
60
- conflicts.push('Live environment secret API key differs');
61
- }
62
- }
63
- if (existing.webhooks?.url !== imported.webhooks?.url) {
64
- conflicts.push('Webhook URL differs');
65
- }
66
- if (existing.environment !== imported.environment) {
67
- conflicts.push('Environment setting differs');
68
- }
69
- if (existing.projectName !== imported.projectName) {
70
- conflicts.push('Project name differs');
71
- }
72
- return conflicts;
73
- }
74
- export async function showAction(options) {
75
- const spinner = new Spinner();
76
- const configManager = new ConfigManager();
77
- try {
78
- spinner.start('Loading configuration...');
79
- const config = await configManager.load();
80
- if (!config) {
81
- spinner.fail('No configuration found');
82
- console.log(chalk.yellow('No PayMongo configuration found.'));
83
- console.log(chalk.gray("Run 'paymongo init' to set up your project."));
84
- return;
85
- }
86
- spinner.succeed('Configuration loaded');
87
- if (options.json) {
88
- console.log(JSON.stringify(config, null, 2));
89
- return;
90
- }
91
- console.log('\n' + chalk.bold('Configuration (.paymongo)'));
92
- console.log('');
93
- console.log(chalk.bold('Project:'), config.projectName);
94
- console.log(chalk.bold('Environment:'), config.environment);
95
- console.log(chalk.bold('Version:'), config.version);
96
- console.log('');
97
- console.log(chalk.bold('Webhook URL:'), config.webhooks.url || 'Not set');
98
- console.log(chalk.bold('Webhook Events:'), config.webhooks.events.join(', ') || 'None');
99
- console.log('');
100
- console.log(chalk.bold('Dev Port:'), config.dev.port);
101
- console.log(chalk.bold('Auto Register Webhook:'), config.dev.autoRegisterWebhook ? 'Yes' : 'No');
102
- console.log(chalk.bold('Verify Webhook Signatures:'), config.dev.verifyWebhookSignatures ? 'Yes' : 'No');
103
- console.log('');
104
- if (config.rateLimiting) {
105
- console.log(chalk.bold('Rate Limiting:'));
106
- console.log(chalk.bold(' Enabled:'), config.rateLimiting.enabled ? chalk.green('Yes') : chalk.red('No'));
107
- if (config.rateLimiting.enabled) {
108
- console.log(` Max Requests: ${config.rateLimiting.maxRequests} per ${(config.rateLimiting.windowMs || 60000) / 1000}s`);
109
- console.log(` Live Multiplier: ${config.rateLimiting.environmentMultiplier || 0.5}x`);
110
- if (config.rateLimiting.endpoints &&
111
- Object.keys(config.rateLimiting.endpoints).length > 0) {
112
- console.log(` Endpoint Overrides: ${Object.keys(config.rateLimiting.endpoints).length} configured`);
113
- }
114
- }
115
- console.log('');
116
- }
117
- console.log(chalk.bold('API Keys:'));
118
- const env = config.environment;
119
- const apiKeys = config.apiKeys[env];
120
- if (apiKeys) {
121
- if (apiKeys.public) {
122
- const maskedPublic = apiKeys.public.replace(/(.{10}).*/, '$1***');
123
- console.log(` Public (${env}):`, maskedPublic);
124
- }
125
- if (apiKeys.secret) {
126
- const maskedSecret = apiKeys.secret.replace(/(.{10}).*/, '$1***');
127
- console.log(` Secret (${env}):`, maskedSecret);
128
- }
129
- }
130
- else {
131
- console.log(` No API keys configured for ${env} environment`);
132
- console.log(chalk.gray(" Run 'paymongo login' to set API keys"));
133
- }
134
- console.log('');
135
- console.log(chalk.gray("Use 'paymongo config set <key> <value>' to modify"));
136
- console.log(chalk.gray("Use 'paymongo config reset' to reset to defaults"));
137
- }
138
- catch (error) {
139
- spinner.stop();
140
- const err = error;
141
- if (err.message.includes('No configuration') || err.message.includes('not found')) {
142
- console.error(chalk.red('❌ No configuration found:'), err.message);
143
- console.log('');
144
- console.log(chalk.yellow('💡 Solutions:'));
145
- console.log(chalk.gray('• Run "paymongo init" to create a new configuration'));
146
- console.log(chalk.gray("• Check if you're in the correct project directory"));
147
- }
148
- else if (err.message.includes('Failed to load') || err.message.includes('parse')) {
149
- console.error(chalk.red('❌ Configuration file corrupted:'), err.message);
150
- console.log('');
151
- console.log(chalk.yellow('💡 Recovery options:'));
152
- console.log(chalk.gray('• Run "paymongo config reset" to create a fresh configuration'));
153
- console.log(chalk.gray('• Check the .paymongo file for syntax errors'));
154
- console.log(chalk.gray('• Run "paymongo init" to recreate the configuration'));
155
- }
156
- else {
157
- console.error(chalk.red('❌ Failed to load configuration:'), err.message);
158
- }
159
- throw new CommandError();
160
- }
161
- }
162
- export async function setAction(key, value) {
163
- const spinner = new Spinner();
164
- const configManager = new ConfigManager();
165
- const keyMappings = {
166
- 'project.name': 'projectName',
167
- 'webhook.url': 'webhooks.url',
168
- 'webhook.events': 'webhooks.events',
169
- 'dev.port': 'dev.port',
170
- 'dev.autoRegister': 'dev.autoRegisterWebhook',
171
- 'dev.verifySignatures': 'dev.verifyWebhookSignatures',
172
- 'rateLimit.enabled': 'rateLimiting.enabled',
173
- 'rateLimit.maxRequests': 'rateLimiting.maxRequests',
174
- 'rateLimit.windowMs': 'rateLimiting.windowMs',
175
- };
176
- const mappedKey = keyMappings[key] || key;
177
- try {
178
- spinner.start('Loading configuration...');
179
- const config = await configManager.load();
180
- if (!config) {
181
- spinner.fail('No configuration found');
182
- console.log(chalk.yellow('No PayMongo configuration found.'));
183
- console.log(chalk.gray("Run 'paymongo init' to set up your project first."));
184
- return;
185
- }
186
- spinner.succeed('Configuration loaded');
187
- spinner.start('Updating configuration...');
188
- const keys = mappedKey.split('.');
189
- let current = config;
190
- for (let i = 0; i < keys.length - 1; i++) {
191
- const k = keys[i];
192
- if (k && !current[k]) {
193
- current[k] = {};
194
- }
195
- if (k) {
196
- current = current[k];
197
- }
198
- }
199
- const finalKey = keys[keys.length - 1];
200
- if (!finalKey) {
201
- throw new Error('Invalid key path');
202
- }
203
- if (value === 'true') {
204
- current[finalKey] = true;
205
- }
206
- else if (value === 'false') {
207
- current[finalKey] = false;
208
- }
209
- else if (!isNaN(Number(value))) {
210
- current[finalKey] = Number(value);
211
- }
212
- else {
213
- current[finalKey] = value;
214
- }
215
- await configManager.save(config);
216
- spinner.succeed('Configuration updated');
217
- console.log(chalk.green(`✓ Set ${key} = ${value}`));
218
- }
219
- catch (error) {
220
- spinner.stop();
221
- const err = error;
222
- console.error(chalk.red('❌ Failed to update configuration:'), err.message);
223
- throw new CommandError();
224
- }
225
- }
226
- export async function backupAction(options) {
227
- const spinner = new Spinner();
228
- const configManager = new ConfigManager();
229
- try {
230
- spinner.start('Loading current configuration...');
231
- const config = await configManager.load();
232
- if (!config) {
233
- spinner.fail('No configuration found');
234
- console.log(chalk.yellow('No PayMongo configuration found.'));
235
- console.log(chalk.gray("Run 'paymongo init' to set up your project first."));
236
- return;
237
- }
238
- spinner.succeed('Configuration loaded');
239
- const backupDir = options.directory ? path.resolve(options.directory) : process.cwd();
240
- if (options.directory && !fs.existsSync(backupDir)) {
241
- fs.mkdirSync(backupDir, { recursive: true });
242
- }
243
- const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5);
244
- const prefix = options.name || 'paymongo-config';
245
- const filename = `${prefix}-${timestamp}.json`;
246
- const backupPath = path.join(backupDir, filename);
247
- spinner.start('Creating backup...');
248
- fs.writeFileSync(backupPath, JSON.stringify(config, null, 2), 'utf-8');
249
- spinner.succeed('Backup created');
250
- console.log(chalk.green(`✓ Configuration backup created: ${backupPath}`));
251
- console.log(chalk.gray('To restore this backup, use:'));
252
- console.log(chalk.gray(` paymongo config import ${backupPath} --force`));
253
- }
254
- catch (error) {
255
- spinner.stop();
256
- const err = error;
257
- if (err.message.includes('Failed to load') || err.message.includes('parse')) {
258
- console.error(chalk.red('❌ Failed to load configuration for backup:'), err.message);
259
- console.log('');
260
- console.log(chalk.yellow('💡 Check:'));
261
- console.log(chalk.gray('• Run "paymongo config show" to verify configuration'));
262
- console.log(chalk.gray('• Run "paymongo config reset" to recreate configuration'));
263
- }
264
- else if (err.message.includes('permission') || err.message.includes('EACCES')) {
265
- console.error(chalk.red('❌ Failed to create backup:'), err.message);
266
- console.log('');
267
- console.log(chalk.yellow('💡 Check:'));
268
- console.log(chalk.gray('• File permissions in the backup directory'));
269
- console.log(chalk.gray('• Available disk space'));
270
- console.log(chalk.gray('• Try running the command with administrator/sudo privileges'));
271
- }
272
- else {
273
- console.error(chalk.red('❌ Failed to create backup:'), err.message);
274
- }
275
- throw new CommandError();
276
- }
277
- }
278
- export async function resetAction() {
279
- const spinner = new Spinner();
280
- const configManager = new ConfigManager();
281
- try {
282
- spinner.start('Resetting configuration...');
283
- const defaultConfig = configManager.getDefaultConfig();
284
- await configManager.save(defaultConfig);
285
- spinner.succeed('Configuration reset');
286
- console.log(chalk.green('✓ Configuration reset to defaults'));
287
- console.log(chalk.gray('Note: You will need to reconfigure API keys and other settings'));
288
- }
289
- catch (error) {
290
- spinner.stop();
291
- const err = error;
292
- console.error(chalk.red('❌ Failed to reset configuration:'), err.message);
293
- throw new CommandError();
294
- }
295
- }
296
- export async function importAction(filePath, options) {
297
- const spinner = new Spinner();
298
- const configManager = new ConfigManager();
299
- try {
300
- spinner.start('Reading import file...');
301
- if (!fs.existsSync(filePath)) {
302
- spinner.fail('File not found');
303
- console.error(chalk.red(`❌ Import file not found: ${filePath}`));
304
- throw new CommandError();
305
- }
306
- const fileContent = fs.readFileSync(filePath, 'utf-8');
307
- let importedConfig;
308
- try {
309
- importedConfig = JSON.parse(fileContent);
310
- }
311
- catch (_parseError) {
312
- spinner.fail('Invalid JSON');
313
- console.error(chalk.red('❌ Invalid JSON in import file'));
314
- throw new CommandError();
315
- }
316
- spinner.succeed('File read');
317
- spinner.start('Validating configuration...');
318
- validateImportedConfig(importedConfig);
319
- const validation = zodValidateConfig(importedConfig);
320
- if (!validation.success) {
321
- spinner.fail('Invalid configuration');
322
- console.error(chalk.red('❌ Configuration validation failed:'));
323
- validation.errors?.forEach((err) => console.error(chalk.gray(` • ${err}`)));
324
- throw new CommandError();
325
- }
326
- spinner.succeed('Configuration validated');
327
- const existingConfig = await configManager.load();
328
- if (existingConfig && !options.force) {
329
- spinner.start('Checking for conflicts...');
330
- const conflicts = checkConfigConflicts(existingConfig, importedConfig);
331
- if (conflicts.length > 0) {
332
- spinner.stop();
333
- console.log(chalk.yellow('⚠️ Configuration conflicts detected:'));
334
- conflicts.forEach((conflict) => {
335
- console.log(chalk.gray(` • ${conflict}`));
336
- });
337
- console.log('');
338
- console.log(chalk.bold('Use --force to overwrite existing configuration'));
339
- throw new CommandError();
340
- }
341
- spinner.succeed('No conflicts found');
342
- }
343
- if (existingConfig) {
344
- spinner.start('Creating backup...');
345
- const backupConfig = configManager.mergeConfig(existingConfig, {});
346
- const backupPath = `.paymongo.backup.${Date.now()}.json`;
347
- fs.writeFileSync(backupPath, JSON.stringify(backupConfig, null, 2));
348
- spinner.succeed(`Backup created: ${backupPath}`);
349
- }
350
- spinner.start('Importing configuration...');
351
- if (!importedConfig.apiKeys) {
352
- importedConfig.apiKeys = {};
353
- }
354
- if (!importedConfig.webhookSecrets) {
355
- importedConfig.webhookSecrets = {};
356
- }
357
- await configManager.save(importedConfig);
358
- spinner.succeed('Configuration imported');
359
- console.log(chalk.green('✓ Configuration imported successfully'));
360
- console.log(chalk.gray(`Imported from: ${filePath}`));
361
- }
362
- catch (error) {
363
- spinner.stop();
364
- const err = error;
365
- console.error(chalk.red('❌ Failed to import configuration:'), err.message);
366
- throw new CommandError();
367
- }
368
- }
369
- export async function rateLimitEnableAction() {
370
- const spinner = new Spinner();
371
- const configManager = new ConfigManager();
372
- try {
373
- spinner.start('Loading configuration...');
374
- const config = await configManager.load();
375
- if (!config) {
376
- spinner.fail('No configuration found');
377
- console.log(chalk.yellow('No PayMongo configuration found.'));
378
- console.log(chalk.gray("Run 'paymongo init' to set up your project first."));
379
- return;
380
- }
381
- spinner.succeed('Configuration loaded');
382
- if (!config.rateLimiting) {
383
- config.rateLimiting = {
384
- enabled: true,
385
- maxRequests: 100,
386
- windowMs: 60000,
387
- environmentMultiplier: 0.5,
388
- };
389
- }
390
- else {
391
- config.rateLimiting.enabled = true;
392
- }
393
- spinner.start('Enabling rate limiting...');
394
- await configManager.save(config);
395
- spinner.succeed('Rate limiting enabled');
396
- console.log(chalk.green('✓ Rate limiting enabled'));
397
- console.log(chalk.gray('Default limits: 100 requests/minute (live: 50)'));
398
- }
399
- catch (error) {
400
- spinner.stop();
401
- const err = error;
402
- console.error(chalk.red('❌ Failed to enable rate limiting:'), err.message);
403
- throw new CommandError();
404
- }
405
- }
406
- export async function rateLimitDisableAction() {
407
- const spinner = new Spinner();
408
- const configManager = new ConfigManager();
409
- try {
410
- spinner.start('Loading configuration...');
411
- const config = await configManager.load();
412
- if (!config) {
413
- spinner.fail('No configuration found');
414
- console.log(chalk.yellow('No PayMongo configuration found.'));
415
- console.log(chalk.gray("Run 'paymongo init' to set up your project first."));
416
- return;
417
- }
418
- spinner.succeed('Configuration loaded');
419
- if (config.rateLimiting) {
420
- config.rateLimiting.enabled = false;
421
- }
422
- spinner.start('Disabling rate limiting...');
423
- await configManager.save(config);
424
- spinner.succeed('Rate limiting disabled');
425
- console.log(chalk.green('✓ Rate limiting disabled'));
426
- console.log(chalk.gray('API calls will no longer be rate limited'));
427
- }
428
- catch (error) {
429
- spinner.stop();
430
- const err = error;
431
- console.error(chalk.red('❌ Failed to disable rate limiting:'), err.message);
432
- throw new CommandError();
433
- }
434
- }
435
- export async function rateLimitSetMaxRequestsAction(requestsStr) {
436
- const spinner = new Spinner();
437
- const configManager = new ConfigManager();
438
- try {
439
- const requests = parseInt(requestsStr, 10);
440
- if (isNaN(requests) || requests < 1) {
441
- console.error(chalk.red('❌ Invalid number of requests. Must be a positive integer.'));
442
- throw new CommandError();
443
- }
444
- spinner.start('Loading configuration...');
445
- const config = await configManager.load();
446
- if (!config) {
447
- spinner.fail('No configuration found');
448
- console.log(chalk.yellow('No PayMongo configuration found.'));
449
- console.log(chalk.gray("Run 'paymongo init' to set up your project first."));
450
- return;
451
- }
452
- spinner.succeed('Configuration loaded');
453
- if (!config.rateLimiting) {
454
- config.rateLimiting = {
455
- enabled: true,
456
- maxRequests: requests,
457
- windowMs: 60000,
458
- environmentMultiplier: 0.5,
459
- };
460
- }
461
- else {
462
- config.rateLimiting.maxRequests = requests;
463
- }
464
- spinner.start('Updating rate limit...');
465
- await configManager.save(config);
466
- spinner.succeed('Rate limit updated');
467
- console.log(chalk.green(`✓ Maximum requests set to ${requests} per minute`));
468
- }
469
- catch (error) {
470
- spinner.stop();
471
- const err = error;
472
- console.error(chalk.red('❌ Failed to update rate limit:'), err.message);
473
- throw new CommandError();
474
- }
475
- }
476
- export async function rateLimitSetWindowAction(secondsStr) {
477
- const spinner = new Spinner();
478
- const configManager = new ConfigManager();
479
- try {
480
- const seconds = parseInt(secondsStr, 10);
481
- if (isNaN(seconds) || seconds < 1) {
482
- console.error(chalk.red('❌ Invalid time window. Must be a positive integer (seconds).'));
483
- throw new CommandError();
484
- }
485
- spinner.start('Loading configuration...');
486
- const config = await configManager.load();
487
- if (!config) {
488
- spinner.fail('No configuration found');
489
- console.log(chalk.yellow('No PayMongo configuration found.'));
490
- console.log(chalk.gray("Run 'paymongo init' to set up your project first."));
491
- return;
492
- }
493
- spinner.succeed('Configuration loaded');
494
- if (!config.rateLimiting) {
495
- config.rateLimiting = {
496
- enabled: true,
497
- maxRequests: 100,
498
- windowMs: seconds * 1000,
499
- environmentMultiplier: 0.5,
500
- };
501
- }
502
- else {
503
- config.rateLimiting.windowMs = seconds * 1000;
504
- }
505
- spinner.start('Updating rate limit window...');
506
- await configManager.save(config);
507
- spinner.succeed('Rate limit window updated');
508
- console.log(chalk.green(`✓ Rate limit window set to ${seconds} seconds`));
509
- }
510
- catch (error) {
511
- spinner.stop();
512
- const err = error;
513
- console.error(chalk.red('❌ Failed to update rate limit window:'), err.message);
514
- throw new CommandError();
515
- }
516
- }
517
- export async function rateLimitStatusAction() {
518
- const spinner = new Spinner();
519
- const configManager = new ConfigManager();
520
- try {
521
- spinner.start('Loading configuration...');
522
- const config = await configManager.load();
523
- if (!config) {
524
- spinner.fail('No configuration found');
525
- console.log(chalk.yellow('No PayMongo configuration found.'));
526
- console.log(chalk.gray("Run 'paymongo init' to set up your project first."));
527
- return;
528
- }
529
- spinner.succeed('Configuration loaded');
530
- console.log('\n' + chalk.bold('Rate Limiting Status'));
531
- console.log('');
532
- if (!config.rateLimiting || !config.rateLimiting.enabled) {
533
- console.log(chalk.yellow('Status: Disabled'));
534
- console.log(chalk.gray('Rate limiting is not currently active'));
535
- console.log('');
536
- console.log(chalk.gray("Run 'paymongo config rate-limit enable' to enable"));
537
- return;
538
- }
539
- console.log(chalk.green('Status: Enabled'));
540
- console.log('');
541
- console.log(chalk.bold('Global Settings:'));
542
- console.log(` Max Requests: ${config.rateLimiting.maxRequests} per ${(config.rateLimiting.windowMs || 60000) / 1000}s`);
543
- console.log(` Live Environment Multiplier: ${config.rateLimiting.environmentMultiplier || 0.5}x`);
544
- if (config.rateLimiting.endpoints && Object.keys(config.rateLimiting.endpoints).length > 0) {
545
- console.log('');
546
- console.log(chalk.bold('Endpoint Overrides:'));
547
- Object.entries(config.rateLimiting.endpoints).forEach(([endpoint, limits]) => {
548
- console.log(` ${endpoint}: ${limits.maxRequests} per ${limits.windowMs / 1000}s`);
549
- });
550
- }
551
- console.log('');
552
- console.log(chalk.gray('Commands:'));
553
- console.log(chalk.gray("• 'paymongo config rate-limit disable' - Disable rate limiting"));
554
- console.log(chalk.gray("• 'paymongo config rate-limit set-max-requests <n>' - Set max requests"));
555
- console.log(chalk.gray("• 'paymongo config rate-limit set-window <seconds>' - Set time window"));
556
- }
557
- catch (error) {
558
- spinner.stop();
559
- const err = error;
560
- console.error(chalk.red('❌ Failed to check rate limiting status:'), err.message);
561
- throw new CommandError();
562
- }
563
- }
2
+ import { backupAction, importAction, resetAction, setAction, showAction, } from './config/actions.js';
3
+ import { rateLimitDisableAction, rateLimitEnableAction, rateLimitSetMaxRequestsAction, rateLimitSetWindowAction, rateLimitStatusAction, } from './config/rate-limit.js';
564
4
  const command = new Command('config');
565
5
  command
566
6
  .description('View and modify configuration')
@@ -592,10 +32,9 @@ command
592
32
  .arguments('<requests>')
593
33
  .action(rateLimitSetMaxRequestsAction))
594
34
  .addCommand(new Command('set-window')
595
- .description('Set rate limit time window in seconds')
35
+ .description('Set time window in seconds')
596
36
  .arguments('<seconds>')
597
37
  .action(rateLimitSetWindowAction))
598
- .addCommand(new Command('status')
599
- .description('Show current rate limiting status')
600
- .action(rateLimitStatusAction)));
38
+ .addCommand(new Command('status').description('Show current rate limiting settings').action(rateLimitStatusAction)));
39
+ export { showAction, setAction, backupAction, resetAction, importAction, rateLimitEnableAction, rateLimitDisableAction, rateLimitSetMaxRequestsAction, rateLimitSetWindowAction, rateLimitStatusAction, };
601
40
  export default command;
@@ -170,6 +170,10 @@ command
170
170
  console.log(chalk.blue('ℹ️'), 'You can still test webhooks manually:');
171
171
  console.log(chalk.gray(` Webhook URL: ${webhookUrl}`));
172
172
  console.log(chalk.gray(' Copy this URL to your PayMongo dashboard'));
173
+ if (config.dev.verifyWebhookSignatures) {
174
+ console.log(chalk.gray(' Signature verification is currently enabled'));
175
+ console.log(chalk.gray(' For manual unsigned testing, run: paymongo config set dev.verifySignatures false'));
176
+ }
173
177
  console.log('');
174
178
  if (err.message.includes('API key') || err.message.includes('unauthorized')) {
175
179
  console.log(chalk.yellow('💡 To fix webhook registration:'));
@@ -125,7 +125,7 @@ export async function initAction(options) {
125
125
  dev: {
126
126
  port: answers.port,
127
127
  autoRegisterWebhook: true,
128
- verifyWebhookSignatures: false,
128
+ verifyWebhookSignatures: true,
129
129
  },
130
130
  };
131
131
  const apiClient = new ApiClient({ config: tempConfig });
@@ -183,7 +183,7 @@ command
183
183
  },
184
184
  webhooks: { url: '', events: [] },
185
185
  webhookSecrets: {},
186
- dev: { port: 3000, autoRegisterWebhook: true, verifyWebhookSignatures: false },
186
+ dev: { port: 3000, autoRegisterWebhook: true, verifyWebhookSignatures: true },
187
187
  };
188
188
  const apiClient = new ApiClient({ config: tempConfig });
189
189
  try {