paymongo-cli 1.2.0 → 1.4.2
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 -0
- package/.github/workflows/ci-cd.yml +2 -46
- package/.github/workflows/ci.yml +1 -1
- package/.github/workflows/release.yml +16 -1
- package/AGENTS.md +418 -0
- package/CHANGELOG.md +331 -185
- package/README.md +94 -13
- package/TESTING.md +222 -0
- package/coverage/base.css +224 -0
- package/coverage/block-navigation.js +87 -0
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +281 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +281 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +210 -0
- package/coverage/lcov.info +5053 -0
- package/coverage/prettify.css +1 -0
- package/coverage/prettify.js +2 -0
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +210 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/commands/config.d.ts +17 -0
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +268 -55
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/dev.d.ts +13 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +40 -56
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/env.d.ts +4 -0
- package/dist/commands/env.d.ts.map +1 -0
- package/dist/commands/env.js +106 -0
- package/dist/commands/env.js.map +1 -0
- package/dist/commands/generate.js +1184 -0
- package/dist/commands/init.d.ts +11 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +33 -33
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/login.d.ts +17 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +2 -17
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/payments.d.ts +37 -0
- package/dist/commands/payments.d.ts.map +1 -1
- package/dist/commands/payments.js +367 -32
- package/dist/commands/payments.js.map +1 -1
- package/dist/commands/team/index.d.ts.map +1 -1
- package/dist/commands/team/index.js +192 -95
- package/dist/commands/team/index.js.map +1 -1
- package/dist/commands/trigger.d.ts.map +1 -1
- package/dist/commands/trigger.js +239 -75
- package/dist/commands/trigger.js.map +1 -1
- package/dist/commands/webhooks.d.ts +19 -0
- package/dist/commands/webhooks.d.ts.map +1 -1
- package/dist/commands/webhooks.js +246 -70
- package/dist/commands/webhooks.js.map +1 -1
- package/dist/index.js +56 -32
- package/dist/index.js.map +1 -1
- package/dist/services/analytics/service.js +6 -8
- package/dist/services/api/client.d.ts +6 -8
- package/dist/services/api/client.d.ts.map +1 -1
- package/dist/services/api/client.js +20 -131
- package/dist/services/api/client.js.map +1 -1
- package/dist/services/api/rate-limiter.d.ts +64 -0
- package/dist/services/api/rate-limiter.d.ts.map +1 -0
- package/dist/services/api/rate-limiter.js +83 -0
- package/dist/services/api/rate-limiter.js.map +1 -0
- package/dist/services/api/undici-client.d.ts +39 -0
- package/dist/services/api/undici-client.d.ts.map +1 -0
- package/dist/services/api/undici-client.js +294 -0
- package/dist/services/api/undici-client.js.map +1 -0
- package/dist/services/config/manager.js +1 -16
- package/dist/services/dev/process-manager.js +0 -32
- package/dist/services/github/client.d.ts +41 -0
- package/dist/services/github/client.d.ts.map +1 -1
- package/dist/services/github/client.js +28 -0
- package/dist/services/github/client.js.map +1 -1
- package/dist/services/payments/simulator.d.ts +28 -0
- package/dist/services/payments/simulator.d.ts.map +1 -0
- package/dist/services/payments/simulator.js +115 -0
- package/dist/services/payments/simulator.js.map +1 -0
- package/dist/services/team/service.d.ts +44 -0
- package/dist/services/team/service.d.ts.map +1 -0
- package/dist/services/team/service.js +153 -0
- package/dist/services/team/service.js.map +1 -0
- package/dist/types/paymongo.d.ts +36 -3
- package/dist/types/paymongo.d.ts.map +1 -1
- package/dist/types/paymongo.js +0 -1
- package/dist/types/schemas.js +0 -8
- package/dist/utils/bulk.d.ts +62 -0
- package/dist/utils/bulk.d.ts.map +1 -0
- package/dist/utils/bulk.js +123 -0
- package/dist/utils/bulk.js.map +1 -0
- package/dist/utils/cache.js +4 -16
- package/dist/utils/constants.js +2 -13
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +22 -7
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/logger.d.ts +3 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +38 -25
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/spinner.js +0 -1
- package/dist/utils/validator.js +0 -3
- package/dist/utils/webhook-store.d.ts +22 -0
- package/dist/utils/webhook-store.d.ts.map +1 -0
- package/dist/utils/webhook-store.js +57 -0
- package/dist/utils/webhook-store.js.map +1 -0
- package/package.json +75 -76
- package/jest.config.ts +0 -30
- package/web/index.html +0 -688
package/dist/index.js
CHANGED
|
@@ -4,44 +4,69 @@ import chalk from 'chalk';
|
|
|
4
4
|
import { createRequire } from 'module';
|
|
5
5
|
const require = createRequire(import.meta.url);
|
|
6
6
|
const { version } = require('../package.json');
|
|
7
|
-
// Import commands
|
|
8
|
-
import initCommand from './commands/init.js';
|
|
9
|
-
import devCommand from './commands/dev.js';
|
|
10
|
-
import loginCommand from './commands/login.js';
|
|
11
|
-
import configCommand from './commands/config.js';
|
|
12
|
-
import webhooksCommand from './commands/webhooks.js';
|
|
13
|
-
import triggerCommand from './commands/trigger.js';
|
|
14
|
-
import guiCommand from './commands/gui.js';
|
|
15
|
-
import teamCommand from './commands/team/index.js';
|
|
16
|
-
import paymentsCommand from './commands/payments.js';
|
|
17
7
|
const program = new Command();
|
|
18
8
|
program
|
|
19
9
|
.name('paymongo')
|
|
20
10
|
.description('CLI tool for PayMongo integration development')
|
|
21
11
|
.version(version)
|
|
12
|
+
.option('--no-rate-limit', 'Disable rate limiting for this command')
|
|
22
13
|
.showHelpAfterError('(add --help for additional information)');
|
|
23
|
-
program.addCommand(
|
|
24
|
-
program.addCommand(
|
|
25
|
-
program.addCommand(
|
|
26
|
-
program.addCommand(
|
|
27
|
-
program.addCommand(
|
|
28
|
-
program.addCommand(
|
|
29
|
-
program.addCommand(
|
|
30
|
-
program.addCommand(
|
|
31
|
-
program.addCommand(
|
|
32
|
-
|
|
33
|
-
program.addHelpText('after', `
|
|
34
|
-
EXAMPLES
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
14
|
+
program.addCommand(await import('./commands/init.js').then((m) => m.default));
|
|
15
|
+
program.addCommand((await import('./commands/dev.js')).command);
|
|
16
|
+
program.addCommand((await import('./commands/login.js')).command);
|
|
17
|
+
program.addCommand(await import('./commands/config.js').then((m) => m.default));
|
|
18
|
+
program.addCommand(await import('./commands/webhooks.js').then((m) => m.default));
|
|
19
|
+
program.addCommand(await import('./commands/payments.js').then((m) => m.default));
|
|
20
|
+
program.addCommand(await import('./commands/trigger.js').then((m) => m.default));
|
|
21
|
+
program.addCommand(await import('./commands/generate.js').then((m) => m.default));
|
|
22
|
+
program.addCommand(await import('./commands/team/index.js').then((m) => m.default));
|
|
23
|
+
program.addCommand(await import('./commands/env.js').then((m) => m.default));
|
|
24
|
+
program.addHelpText('after', `
|
|
25
|
+
EXAMPLES
|
|
26
|
+
Getting Started:
|
|
27
|
+
$ paymongo init # Initialize a new PayMongo project
|
|
28
|
+
$ paymongo login # Authenticate with PayMongo API keys
|
|
29
|
+
|
|
30
|
+
Development:
|
|
31
|
+
$ paymongo dev # Start development server with webhook forwarding
|
|
32
|
+
$ paymongo dev --port 4000 # Use custom port for webhook server
|
|
33
|
+
$ paymongo dev --detach # Run server in background
|
|
34
|
+
$ paymongo dev status # Check background server status
|
|
35
|
+
|
|
36
|
+
Environment Management:
|
|
37
|
+
$ paymongo env current # Show current environment (test/live)
|
|
38
|
+
$ paymongo env switch live # Switch to live environment
|
|
39
|
+
$ paymongo env switch test --force # Switch to test without validation
|
|
40
|
+
|
|
41
|
+
Webhook Management:
|
|
42
|
+
$ paymongo webhooks list # List all webhooks
|
|
43
|
+
$ paymongo webhooks create # Create a new webhook interactively
|
|
44
|
+
$ paymongo webhooks show wh_123 # Show webhook details
|
|
45
|
+
$ paymongo webhooks delete wh_123 # Delete a webhook
|
|
46
|
+
|
|
47
|
+
Payment Operations:
|
|
48
|
+
$ paymongo payments list # List recent payments
|
|
49
|
+
$ paymongo payments show pay_123 # Show payment details
|
|
50
|
+
$ paymongo payments create-intent --amount 10000 # Create payment intent for ₱100
|
|
51
|
+
$ paymongo payments confirm pi_123 --simulate # Simulate payment confirmation
|
|
52
|
+
|
|
53
|
+
Code Generation:
|
|
54
|
+
$ paymongo generate webhook-handler # Generate webhook handler boilerplate
|
|
55
|
+
$ paymongo generate payment-intent --language ts # Generate TypeScript payment intent code
|
|
56
|
+
$ paymongo generate checkout-page --framework react # Generate React checkout component
|
|
57
|
+
|
|
58
|
+
Team Collaboration:
|
|
59
|
+
$ paymongo team create "My Team" # Create a new team
|
|
60
|
+
$ paymongo team share live # Share live API keys with team
|
|
61
|
+
$ paymongo team sync # Sync team updates
|
|
62
|
+
|
|
63
|
+
Configuration:
|
|
64
|
+
$ paymongo config # View current configuration
|
|
65
|
+
$ paymongo config set environment live # Set default environment
|
|
66
|
+
$ paymongo config reset # Reset to default settings
|
|
67
|
+
|
|
68
|
+
For more information, visit: https://github.com/leodyversemilla07/paymongo-cli
|
|
43
69
|
`);
|
|
44
|
-
// Global error handler
|
|
45
70
|
process.on('uncaughtException', (error) => {
|
|
46
71
|
console.error(chalk.red('An unexpected error occurred:'), error.message);
|
|
47
72
|
process.exit(1);
|
|
@@ -51,4 +76,3 @@ process.on('unhandledRejection', (reason, promise) => {
|
|
|
51
76
|
process.exit(1);
|
|
52
77
|
});
|
|
53
78
|
program.parse();
|
|
54
|
-
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAEvC,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAE/C,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,8 +5,10 @@ export class AnalyticsService {
|
|
|
5
5
|
events = [];
|
|
6
6
|
dataFile;
|
|
7
7
|
logger;
|
|
8
|
-
|
|
8
|
+
config;
|
|
9
|
+
constructor(config) {
|
|
9
10
|
this.logger = new Logger();
|
|
11
|
+
this.config = config;
|
|
10
12
|
this.dataFile = path.join(process.cwd(), '.paymongo', 'analytics.json');
|
|
11
13
|
this.loadEvents();
|
|
12
14
|
}
|
|
@@ -15,7 +17,6 @@ export class AnalyticsService {
|
|
|
15
17
|
if (fs.existsSync(this.dataFile)) {
|
|
16
18
|
const data = JSON.parse(fs.readFileSync(this.dataFile, 'utf-8'));
|
|
17
19
|
this.events = data.events || [];
|
|
18
|
-
// Keep only last 1000 events
|
|
19
20
|
if (this.events.length > 1000) {
|
|
20
21
|
this.events = this.events.slice(-1000);
|
|
21
22
|
}
|
|
@@ -39,13 +40,15 @@ export class AnalyticsService {
|
|
|
39
40
|
}
|
|
40
41
|
}
|
|
41
42
|
recordEvent(event) {
|
|
43
|
+
if (!this.config.analytics?.enabled) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
42
46
|
const webhookEvent = {
|
|
43
47
|
...event,
|
|
44
48
|
id: `evt_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|
45
49
|
timestamp: Date.now(),
|
|
46
50
|
};
|
|
47
51
|
this.events.push(webhookEvent);
|
|
48
|
-
// Keep only last 1000 events
|
|
49
52
|
if (this.events.length > 1000) {
|
|
50
53
|
this.events = this.events.slice(-1000);
|
|
51
54
|
}
|
|
@@ -60,20 +63,16 @@ export class AnalyticsService {
|
|
|
60
63
|
let totalResponseTime = 0;
|
|
61
64
|
let responseTimeCount = 0;
|
|
62
65
|
this.events.forEach((event) => {
|
|
63
|
-
// Count events by type
|
|
64
66
|
eventsByType[event.type] = (eventsByType[event.type] || 0) + 1;
|
|
65
|
-
// Count errors by type
|
|
66
67
|
if (!event.success && event.error) {
|
|
67
68
|
errorsByType[event.type] = (errorsByType[event.type] || 0) + 1;
|
|
68
69
|
}
|
|
69
|
-
// Calculate average response time
|
|
70
70
|
if (event.responseTime !== undefined) {
|
|
71
71
|
totalResponseTime += event.responseTime;
|
|
72
72
|
responseTimeCount++;
|
|
73
73
|
}
|
|
74
74
|
});
|
|
75
75
|
const averageResponseTime = responseTimeCount > 0 ? totalResponseTime / responseTimeCount : 0;
|
|
76
|
-
// Get recent events (last 50)
|
|
77
76
|
const recentEvents = this.events.slice(-50).reverse();
|
|
78
77
|
return {
|
|
79
78
|
totalEvents,
|
|
@@ -89,4 +88,3 @@ export class AnalyticsService {
|
|
|
89
88
|
this.saveEvents();
|
|
90
89
|
}
|
|
91
90
|
}
|
|
92
|
-
//# sourceMappingURL=service.js.map
|
|
@@ -1,15 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
timeout?: number;
|
|
5
|
-
enableCache?: boolean;
|
|
1
|
+
import { UndiciClientOptions } from './undici-client.js';
|
|
2
|
+
import { WebhookData, WebhookDataWithSecret, PaymentDataFull, PaymentIntentData, RefundData } from '../../types/paymongo.js';
|
|
3
|
+
export interface ApiClientOptions extends UndiciClientOptions {
|
|
6
4
|
}
|
|
7
5
|
export declare class ApiClient {
|
|
8
6
|
private client;
|
|
9
|
-
private config;
|
|
10
|
-
private cache;
|
|
11
7
|
constructor(options: ApiClientOptions);
|
|
12
|
-
private setupInterceptors;
|
|
13
8
|
validateApiKey(): Promise<boolean>;
|
|
14
9
|
createWebhook(url: string, events: string[]): Promise<WebhookDataWithSecret>;
|
|
15
10
|
listWebhooks(): Promise<WebhookData[]>;
|
|
@@ -23,6 +18,9 @@ export declare class ApiClient {
|
|
|
23
18
|
getPayment(id: string): Promise<PaymentDataFull>;
|
|
24
19
|
listPayments(limit?: number): Promise<PaymentDataFull[]>;
|
|
25
20
|
createPaymentIntent(amount: number, currency?: string, description?: string, paymentMethods?: string[]): Promise<PaymentIntentData>;
|
|
21
|
+
confirmPaymentIntent(id: string, paymentMethodId: string, returnUrl?: string): Promise<PaymentIntentData>;
|
|
22
|
+
capturePaymentIntent(id: string): Promise<PaymentIntentData>;
|
|
23
|
+
createRefund(paymentId: string, amount?: number, reason?: 'duplicate' | 'fraudulent' | 'requested_by_customer'): Promise<RefundData>;
|
|
26
24
|
}
|
|
27
25
|
export default ApiClient;
|
|
28
26
|
//# sourceMappingURL=client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/services/api/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/services/api/client.ts"],"names":[],"mappings":"AAAA,OAAqB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,EACL,WAAW,EACX,qBAAqB,EACrB,eAAe,EACf,iBAAiB,EACjB,UAAU,EACX,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,gBAAiB,SAAQ,mBAAmB;CAAG;AAEhE,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAe;gBAEjB,OAAO,EAAE,gBAAgB;IAI/B,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;IAKlC,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAI5E,YAAY,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAItC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAI5C,aAAa,CACjB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,CAAC,EAAE,SAAS,GAAG,UAAU,CAAA;KAAE,GAC5E,OAAO,CAAC,WAAW,CAAC;IAIjB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKxC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAIhD,YAAY,CAAC,KAAK,GAAE,MAAW,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAI5D,mBAAmB,CACvB,MAAM,EAAE,MAAM,EACd,QAAQ,GAAE,MAAc,EACxB,WAAW,CAAC,EAAE,MAAM,EACpB,cAAc,GAAE,MAAM,EAAiC,GACtD,OAAO,CAAC,iBAAiB,CAAC;IAIvB,oBAAoB,CACxB,EAAE,EAAE,MAAM,EACV,eAAe,EAAE,MAAM,EACvB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,iBAAiB,CAAC;IAIvB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAI5D,YAAY,CAChB,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,WAAW,GAAG,YAAY,GAAG,uBAAuB,GAC5D,OAAO,CAAC,UAAU,CAAC;CAGvB;AAED,eAAe,SAAS,CAAC"}
|
|
@@ -1,155 +1,44 @@
|
|
|
1
|
-
import
|
|
2
|
-
const REQUEST_TIMEOUT = 30000;
|
|
3
|
-
import { NetworkError, ApiKeyError, PayMongoError, withRetry } from '../../utils/errors.js';
|
|
4
|
-
import Cache from '../../utils/cache.js';
|
|
1
|
+
import UndiciClient from './undici-client.js';
|
|
5
2
|
export class ApiClient {
|
|
6
3
|
client;
|
|
7
|
-
config;
|
|
8
|
-
cache;
|
|
9
4
|
constructor(options) {
|
|
10
|
-
this.
|
|
11
|
-
const timeout = options.timeout || REQUEST_TIMEOUT;
|
|
12
|
-
this.client = axios.create({
|
|
13
|
-
baseURL: `https://api.paymongo.com/v1`,
|
|
14
|
-
timeout,
|
|
15
|
-
headers: {
|
|
16
|
-
'Content-Type': 'application/json',
|
|
17
|
-
'User-Agent': 'paymongo-cli/1.0.0',
|
|
18
|
-
},
|
|
19
|
-
});
|
|
20
|
-
this.cache = new Cache({ ttl: 2 * 60 * 1000 }); // 2 minute cache for API responses
|
|
21
|
-
this.setupInterceptors();
|
|
22
|
-
}
|
|
23
|
-
setupInterceptors() {
|
|
24
|
-
// Request interceptor to add authentication
|
|
25
|
-
this.client.interceptors.request.use((config) => {
|
|
26
|
-
const env = this.config.environment;
|
|
27
|
-
const secretKey = this.config.apiKeys[env]?.secret;
|
|
28
|
-
if (!secretKey) {
|
|
29
|
-
throw new Error('Secret API key not found');
|
|
30
|
-
}
|
|
31
|
-
config.auth = {
|
|
32
|
-
username: secretKey,
|
|
33
|
-
password: '', // PayMongo uses username-only auth
|
|
34
|
-
};
|
|
35
|
-
return config;
|
|
36
|
-
});
|
|
37
|
-
// Response interceptor for error handling
|
|
38
|
-
this.client.interceptors.response.use((response) => response, async (error) => {
|
|
39
|
-
if (axios.isAxiosError(error)) {
|
|
40
|
-
const status = error.response?.status;
|
|
41
|
-
if (!error.response) {
|
|
42
|
-
throw new NetworkError(`Network error - no response received: ${error.message}`, error);
|
|
43
|
-
}
|
|
44
|
-
if (status === 401) {
|
|
45
|
-
throw new ApiKeyError('Invalid API key or unauthorized', 'secret');
|
|
46
|
-
}
|
|
47
|
-
if (status === 404) {
|
|
48
|
-
throw new PayMongoError('Resource not found', 'RESOURCE_NOT_FOUND', status);
|
|
49
|
-
}
|
|
50
|
-
if (status && status >= 500) {
|
|
51
|
-
throw new PayMongoError(`Server error: ${error.message}`, `SERVER_${status}`, status);
|
|
52
|
-
}
|
|
53
|
-
throw new PayMongoError(error.message, `API_${status}`, status);
|
|
54
|
-
}
|
|
55
|
-
throw new NetworkError('Unknown network error');
|
|
56
|
-
});
|
|
5
|
+
this.client = new UndiciClient(options);
|
|
57
6
|
}
|
|
58
7
|
async validateApiKey() {
|
|
59
|
-
|
|
60
|
-
await withRetry(() => this.client.get('/webhooks'));
|
|
61
|
-
return true;
|
|
62
|
-
}
|
|
63
|
-
catch (_error) {
|
|
64
|
-
return false;
|
|
65
|
-
}
|
|
8
|
+
return this.client.validateApiKey();
|
|
66
9
|
}
|
|
67
|
-
// Webhook methods
|
|
68
10
|
async createWebhook(url, events) {
|
|
69
|
-
|
|
70
|
-
.post('/webhooks', {
|
|
71
|
-
data: {
|
|
72
|
-
attributes: {
|
|
73
|
-
url,
|
|
74
|
-
events,
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
|
-
})
|
|
78
|
-
.then((response) => response.data.data));
|
|
79
|
-
// Invalidate webhook list cache when creating new webhook
|
|
80
|
-
await this.cache.invalidate(`webhooks_${this.config.environment}`);
|
|
81
|
-
return result;
|
|
11
|
+
return this.client.createWebhook(url, events);
|
|
82
12
|
}
|
|
83
13
|
async listWebhooks() {
|
|
84
|
-
|
|
85
|
-
// Try cache first for list operations
|
|
86
|
-
const cached = await this.cache.get(cacheKey);
|
|
87
|
-
if (cached) {
|
|
88
|
-
return cached;
|
|
89
|
-
}
|
|
90
|
-
const result = await withRetry(() => this.client.get('/webhooks').then((response) => response.data.data));
|
|
91
|
-
// Cache the result
|
|
92
|
-
await this.cache.set(cacheKey, result);
|
|
93
|
-
return result;
|
|
14
|
+
return this.client.listWebhooks();
|
|
94
15
|
}
|
|
95
16
|
async getWebhook(id) {
|
|
96
|
-
|
|
97
|
-
// Try cache first
|
|
98
|
-
const cached = await this.cache.get(cacheKey);
|
|
99
|
-
if (cached) {
|
|
100
|
-
return cached;
|
|
101
|
-
}
|
|
102
|
-
const result = await withRetry(() => this.client.get(`/webhooks/${id}`).then((response) => response.data.data));
|
|
103
|
-
// Cache the result
|
|
104
|
-
await this.cache.set(cacheKey, result);
|
|
105
|
-
return result;
|
|
17
|
+
return this.client.getWebhook(id);
|
|
106
18
|
}
|
|
107
19
|
async updateWebhook(id, updates) {
|
|
108
|
-
|
|
109
|
-
await this.cache.invalidate(`webhook_${id}`);
|
|
110
|
-
await this.cache.invalidate(`webhooks_${this.config.environment}`);
|
|
111
|
-
return withRetry(() => this.client
|
|
112
|
-
.put(`/webhooks/${id}`, {
|
|
113
|
-
data: {
|
|
114
|
-
attributes: updates,
|
|
115
|
-
},
|
|
116
|
-
})
|
|
117
|
-
.then((response) => response.data.data));
|
|
20
|
+
return this.client.updateWebhook(id, updates);
|
|
118
21
|
}
|
|
119
22
|
async deleteWebhook(id) {
|
|
120
|
-
|
|
121
|
-
await this.cache.invalidate(`webhook_${id}`);
|
|
122
|
-
await this.cache.invalidate(`webhooks_${this.config.environment}`);
|
|
123
|
-
return withRetry(() => this.client.delete(`/webhooks/${id}`));
|
|
23
|
+
return this.client.deleteWebhook(id);
|
|
124
24
|
}
|
|
125
|
-
// Payment methods (for validation and testing)
|
|
126
25
|
async getPayment(id) {
|
|
127
|
-
return
|
|
26
|
+
return this.client.getPayment(id);
|
|
128
27
|
}
|
|
129
28
|
async listPayments(limit = 10) {
|
|
130
|
-
|
|
131
|
-
const validLimit = Math.max(1, Math.min(100, limit));
|
|
132
|
-
const result = await withRetry(() => this.client
|
|
133
|
-
.get('/payments', {
|
|
134
|
-
params: { limit: validLimit },
|
|
135
|
-
})
|
|
136
|
-
.then((response) => response.data.data));
|
|
137
|
-
return result;
|
|
29
|
+
return this.client.listPayments(limit);
|
|
138
30
|
}
|
|
139
31
|
async createPaymentIntent(amount, currency = 'PHP', description, paymentMethods = ['card', 'gcash', 'paymaya']) {
|
|
140
|
-
return
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
})
|
|
151
|
-
.then((response) => response.data.data));
|
|
32
|
+
return this.client.createPaymentIntent(amount, currency, description, paymentMethods);
|
|
33
|
+
}
|
|
34
|
+
async confirmPaymentIntent(id, paymentMethodId, returnUrl) {
|
|
35
|
+
return this.client.confirmPaymentIntent(id, paymentMethodId, returnUrl);
|
|
36
|
+
}
|
|
37
|
+
async capturePaymentIntent(id) {
|
|
38
|
+
return this.client.capturePaymentIntent(id);
|
|
39
|
+
}
|
|
40
|
+
async createRefund(paymentId, amount, reason) {
|
|
41
|
+
return this.client.createRefund(paymentId, amount, reason);
|
|
152
42
|
}
|
|
153
43
|
}
|
|
154
44
|
export default ApiClient;
|
|
155
|
-
//# sourceMappingURL=client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/services/api/client.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/services/api/client.ts"],"names":[],"mappings":"AAAA,OAAO,YAAqC,MAAM,oBAAoB,CAAC;AAWvE,MAAM,OAAO,SAAS;IACZ,MAAM,CAAe;IAE7B,YAAY,OAAyB;QACnC,IAAI,CAAC,MAAM,GAAG,IAAI,YAAY,CAAC,OAAO,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,cAAc;QAClB,OAAO,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;IACtC,CAAC;IAED,kBAAkB;IAClB,KAAK,CAAC,aAAa,CAAC,GAAW,EAAE,MAAgB;QAC/C,OAAO,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,OAAO,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,EAAU;QACzB,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,aAAa,CACjB,EAAU,EACV,OAA6E;QAE7E,OAAO,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,EAAU;QAC5B,OAAO,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;IACvC,CAAC;IAED,+CAA+C;IAC/C,KAAK,CAAC,UAAU,CAAC,EAAU;QACzB,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,QAAgB,EAAE;QACnC,OAAO,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,mBAAmB,CACvB,MAAc,EACd,WAAmB,KAAK,EACxB,WAAoB,EACpB,iBAA2B,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC;QAEvD,OAAO,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC;IACxF,CAAC;IAED,KAAK,CAAC,oBAAoB,CACxB,EAAU,EACV,eAAuB,EACvB,SAAkB;QAElB,OAAO,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,EAAE,EAAE,eAAe,EAAE,SAAS,CAAC,CAAC;IAC1E,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,EAAU;QACnC,OAAO,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,YAAY,CAChB,SAAiB,EACjB,MAAe,EACf,MAA6D;QAE7D,OAAO,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7D,CAAC;CACF;AAED,eAAe,SAAS,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { PayMongoConfig } from '../../types/paymongo.js';
|
|
2
|
+
export interface RateLimitPolicy {
|
|
3
|
+
/** Maximum requests per time window */
|
|
4
|
+
maxRequests: number;
|
|
5
|
+
/** Time window in milliseconds */
|
|
6
|
+
windowMs: number;
|
|
7
|
+
/** Environment-specific multiplier (live environment might be stricter) */
|
|
8
|
+
environmentMultiplier?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface RateLimitConfig {
|
|
11
|
+
/** Default policy for all endpoints */
|
|
12
|
+
default: RateLimitPolicy;
|
|
13
|
+
/** Endpoint-specific policies */
|
|
14
|
+
endpoints: Record<string, RateLimitPolicy>;
|
|
15
|
+
/** Environment-specific overrides */
|
|
16
|
+
environments: {
|
|
17
|
+
test?: Partial<RateLimitPolicy>;
|
|
18
|
+
live?: Partial<RateLimitPolicy>;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export declare class RateLimiter {
|
|
22
|
+
private config;
|
|
23
|
+
private rateLimitConfig;
|
|
24
|
+
private callHistory;
|
|
25
|
+
constructor(config: PayMongoConfig, rateLimitConfig: RateLimitConfig);
|
|
26
|
+
/**
|
|
27
|
+
* Check if a request is allowed under current rate limits
|
|
28
|
+
* @param endpoint - API endpoint being called (e.g., '/webhooks', '/payments')
|
|
29
|
+
* @returns Object indicating if request is allowed and backoff time if not
|
|
30
|
+
*/
|
|
31
|
+
checkLimit(endpoint: string): {
|
|
32
|
+
allowed: boolean;
|
|
33
|
+
backoffMs?: number;
|
|
34
|
+
remainingRequests?: number;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Record a successful API call
|
|
38
|
+
* @param endpoint - API endpoint that was called
|
|
39
|
+
*/
|
|
40
|
+
recordCall(endpoint: string): void;
|
|
41
|
+
/**
|
|
42
|
+
* Get the effective rate limit policy for an endpoint considering environment
|
|
43
|
+
*/
|
|
44
|
+
private getEffectivePolicy;
|
|
45
|
+
/**
|
|
46
|
+
* Get the key used for tracking call history
|
|
47
|
+
*/
|
|
48
|
+
private getHistoryKey;
|
|
49
|
+
/**
|
|
50
|
+
* Get current rate limit status for an endpoint
|
|
51
|
+
*/
|
|
52
|
+
getStatus(endpoint: string): {
|
|
53
|
+
policy: RateLimitPolicy;
|
|
54
|
+
currentCalls: number;
|
|
55
|
+
remainingRequests: number;
|
|
56
|
+
nextAvailableInMs?: number;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Reset all call history (useful for testing)
|
|
60
|
+
*/
|
|
61
|
+
reset(): void;
|
|
62
|
+
}
|
|
63
|
+
export default RateLimiter;
|
|
64
|
+
//# sourceMappingURL=rate-limiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../../src/services/api/rate-limiter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEzD,MAAM,WAAW,eAAe;IAC9B,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,eAAe;IAC9B,uCAAuC;IACvC,OAAO,EAAE,eAAe,CAAC;IACzB,iCAAiC;IACjC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC3C,qCAAqC;IACrC,YAAY,EAAE;QACZ,IAAI,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;QAChC,IAAI,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;KACjC,CAAC;CACH;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,WAAW,CAAoC;gBAE3C,MAAM,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe;IAKpE;;;;OAIG;IACH,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG;QAC5B,OAAO,EAAE,OAAO,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;KAC5B;IAiCD;;;OAGG;IACH,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAkBlC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAyB1B;;OAEG;IACH,OAAO,CAAC,aAAa;IAIrB;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG;QAC3B,MAAM,EAAE,eAAe,CAAC;QACxB,YAAY,EAAE,MAAM,CAAC;QACrB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;KAC5B;IAgCD;;OAEG;IACH,KAAK,IAAI,IAAI;CAGd;AAED,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
export class RateLimiter {
|
|
2
|
+
config;
|
|
3
|
+
rateLimitConfig;
|
|
4
|
+
callHistory = new Map();
|
|
5
|
+
constructor(config, rateLimitConfig) {
|
|
6
|
+
this.config = config;
|
|
7
|
+
this.rateLimitConfig = rateLimitConfig;
|
|
8
|
+
}
|
|
9
|
+
checkLimit(endpoint) {
|
|
10
|
+
const policy = this.getEffectivePolicy(endpoint);
|
|
11
|
+
const key = this.getHistoryKey(endpoint);
|
|
12
|
+
const now = Date.now();
|
|
13
|
+
const calls = this.callHistory.get(key) || [];
|
|
14
|
+
const validCalls = calls.filter((callTime) => now - callTime < policy.windowMs);
|
|
15
|
+
this.callHistory.set(key, validCalls);
|
|
16
|
+
if (validCalls.length < policy.maxRequests) {
|
|
17
|
+
return {
|
|
18
|
+
allowed: true,
|
|
19
|
+
remainingRequests: policy.maxRequests - validCalls.length - 1,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
const oldestCall = Math.min(...validCalls);
|
|
23
|
+
const backoffMs = policy.windowMs - (now - oldestCall);
|
|
24
|
+
return {
|
|
25
|
+
allowed: false,
|
|
26
|
+
backoffMs: Math.max(1000, backoffMs),
|
|
27
|
+
remainingRequests: 0,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
recordCall(endpoint) {
|
|
31
|
+
const key = this.getHistoryKey(endpoint);
|
|
32
|
+
const now = Date.now();
|
|
33
|
+
const calls = this.callHistory.get(key) || [];
|
|
34
|
+
calls.push(now);
|
|
35
|
+
const maxWindow = Math.max(this.rateLimitConfig.default.windowMs, ...Object.values(this.rateLimitConfig.endpoints).map((p) => p.windowMs));
|
|
36
|
+
const cutoffTime = now - maxWindow * 10;
|
|
37
|
+
const recentCalls = calls.filter((callTime) => callTime > cutoffTime);
|
|
38
|
+
this.callHistory.set(key, recentCalls);
|
|
39
|
+
}
|
|
40
|
+
getEffectivePolicy(endpoint) {
|
|
41
|
+
let policy = { ...this.rateLimitConfig.default };
|
|
42
|
+
if (this.rateLimitConfig.endpoints[endpoint]) {
|
|
43
|
+
policy = { ...policy, ...this.rateLimitConfig.endpoints[endpoint] };
|
|
44
|
+
}
|
|
45
|
+
const env = this.config.environment;
|
|
46
|
+
const envOverrides = this.rateLimitConfig.environments[env];
|
|
47
|
+
if (envOverrides) {
|
|
48
|
+
policy = { ...policy, ...envOverrides };
|
|
49
|
+
}
|
|
50
|
+
if (policy.environmentMultiplier !== undefined) {
|
|
51
|
+
policy.maxRequests = Math.floor(policy.maxRequests * policy.environmentMultiplier);
|
|
52
|
+
}
|
|
53
|
+
return policy;
|
|
54
|
+
}
|
|
55
|
+
getHistoryKey(endpoint) {
|
|
56
|
+
return `${this.config.environment}:${endpoint}`;
|
|
57
|
+
}
|
|
58
|
+
getStatus(endpoint) {
|
|
59
|
+
const policy = this.getEffectivePolicy(endpoint);
|
|
60
|
+
const key = this.getHistoryKey(endpoint);
|
|
61
|
+
const now = Date.now();
|
|
62
|
+
const calls = this.callHistory.get(key) || [];
|
|
63
|
+
const validCalls = calls.filter((callTime) => now - callTime < policy.windowMs);
|
|
64
|
+
let nextAvailableInMs;
|
|
65
|
+
if (validCalls.length >= policy.maxRequests) {
|
|
66
|
+
const oldestCall = Math.min(...validCalls);
|
|
67
|
+
nextAvailableInMs = policy.windowMs - (now - oldestCall);
|
|
68
|
+
}
|
|
69
|
+
const result = {
|
|
70
|
+
policy,
|
|
71
|
+
currentCalls: validCalls.length,
|
|
72
|
+
remainingRequests: Math.max(0, policy.maxRequests - validCalls.length),
|
|
73
|
+
};
|
|
74
|
+
if (nextAvailableInMs !== undefined) {
|
|
75
|
+
result.nextAvailableInMs = Math.max(1000, nextAvailableInMs);
|
|
76
|
+
}
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
reset() {
|
|
80
|
+
this.callHistory.clear();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export default RateLimiter;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../../src/services/api/rate-limiter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { RateLimitConfig } from './rate-limiter.js';
|
|
2
|
+
import { PayMongoConfig, WebhookData, WebhookDataWithSecret, PaymentDataFull, PaymentIntentData, RefundData } from '../../types/paymongo.js';
|
|
3
|
+
export interface UndiciClientOptions {
|
|
4
|
+
config: PayMongoConfig;
|
|
5
|
+
timeout?: number;
|
|
6
|
+
enableCache?: boolean;
|
|
7
|
+
enableRateLimiting?: boolean;
|
|
8
|
+
rateLimitConfig?: RateLimitConfig;
|
|
9
|
+
}
|
|
10
|
+
export declare class UndiciClient {
|
|
11
|
+
private config;
|
|
12
|
+
private baseUrl;
|
|
13
|
+
private defaultHeaders;
|
|
14
|
+
private timeout;
|
|
15
|
+
private cache;
|
|
16
|
+
private rateLimiter?;
|
|
17
|
+
constructor(options: UndiciClientOptions);
|
|
18
|
+
private getDefaultRateLimitConfig;
|
|
19
|
+
private makeRequest;
|
|
20
|
+
private handleHttpError;
|
|
21
|
+
validateApiKey(): Promise<boolean>;
|
|
22
|
+
createWebhook(url: string, events: string[]): Promise<WebhookDataWithSecret>;
|
|
23
|
+
listWebhooks(): Promise<WebhookData[]>;
|
|
24
|
+
getWebhook(id: string): Promise<WebhookData>;
|
|
25
|
+
updateWebhook(id: string, updates: {
|
|
26
|
+
url?: string;
|
|
27
|
+
events?: string[];
|
|
28
|
+
status?: 'enabled' | 'disabled';
|
|
29
|
+
}): Promise<WebhookData>;
|
|
30
|
+
deleteWebhook(id: string): Promise<void>;
|
|
31
|
+
getPayment(id: string): Promise<PaymentDataFull>;
|
|
32
|
+
listPayments(limit?: number): Promise<PaymentDataFull[]>;
|
|
33
|
+
createPaymentIntent(amount: number, currency?: string, description?: string, paymentMethods?: string[]): Promise<PaymentIntentData>;
|
|
34
|
+
confirmPaymentIntent(id: string, paymentMethodId: string, returnUrl?: string): Promise<PaymentIntentData>;
|
|
35
|
+
capturePaymentIntent(id: string): Promise<PaymentIntentData>;
|
|
36
|
+
createRefund(paymentId: string, amount?: number, reason?: 'duplicate' | 'fraudulent' | 'requested_by_customer'): Promise<RefundData>;
|
|
37
|
+
}
|
|
38
|
+
export default UndiciClient;
|
|
39
|
+
//# sourceMappingURL=undici-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"undici-client.d.ts","sourceRoot":"","sources":["../../../src/services/api/undici-client.ts"],"names":[],"mappings":"AAGA,OAAoB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EACL,cAAc,EACd,WAAW,EACX,qBAAqB,EACrB,eAAe,EACf,iBAAiB,EACjB,UAAU,EACX,MAAM,yBAAyB,CAAC;AAIjC,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,cAAc,CAAyB;IAC/C,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,WAAW,CAAC,CAAc;gBAEtB,OAAO,EAAE,mBAAmB;IAoCxC,OAAO,CAAC,yBAAyB;YA2CnB,WAAW;IAyHzB,OAAO,CAAC,eAAe;IA2BjB,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;IAUlC,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAoB5E,YAAY,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAkBtC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAkB5C,aAAa,CACjB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,CAAC,EAAE,SAAS,GAAG,UAAU,CAAA;KAAE,GAC5E,OAAO,CAAC,WAAW,CAAC;IAgBjB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWxC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAMhD,YAAY,CAAC,KAAK,GAAE,MAAW,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAY5D,mBAAmB,CACvB,MAAM,EAAE,MAAM,EACd,QAAQ,GAAE,MAAc,EACxB,WAAW,CAAC,EAAE,MAAM,EACpB,cAAc,GAAE,MAAM,EAAiC,GACtD,OAAO,CAAC,iBAAiB,CAAC;IAiBvB,oBAAoB,CACxB,EAAE,EAAE,MAAM,EACV,eAAe,EAAE,MAAM,EACvB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,iBAAiB,CAAC;IAevB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAQ5D,YAAY,CAChB,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,WAAW,GAAG,YAAY,GAAG,uBAAuB,GAC5D,OAAO,CAAC,UAAU,CAAC;CAyBvB;AAED,eAAe,YAAY,CAAC"}
|