chargeback-guard 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +311 -0
  3. package/docs/api.md +278 -0
  4. package/docs/architecture.md +281 -0
  5. package/docs/configuration.md +292 -0
  6. package/docs/getting-started.md +155 -0
  7. package/examples/advancedConfig.ts +123 -0
  8. package/examples/basicUsage.ts +98 -0
  9. package/examples/stripeIntegration.ts +106 -0
  10. package/package.json +181 -0
  11. package/src/ai/fraudDetection.ts +261 -0
  12. package/src/ai/patternRecognition.ts +218 -0
  13. package/src/analytics/dashboard.ts +195 -0
  14. package/src/analytics/metrics.ts +175 -0
  15. package/src/analytics/predictions.ts +135 -0
  16. package/src/analytics/reports.ts +221 -0
  17. package/src/api/controllers.ts +339 -0
  18. package/src/api/middleware.ts +172 -0
  19. package/src/api/routes.ts +141 -0
  20. package/src/config.ts +231 -0
  21. package/src/core/chargebackGuard.ts +616 -0
  22. package/src/core/eventEmitter.ts +118 -0
  23. package/src/core/lifecycle.ts +215 -0
  24. package/src/database/schema.ts +392 -0
  25. package/src/dispute/analyzer.ts +317 -0
  26. package/src/dispute/bankIntegration.ts +274 -0
  27. package/src/dispute/detector.ts +239 -0
  28. package/src/dispute/responseEngine.ts +440 -0
  29. package/src/evidence/collector.ts +426 -0
  30. package/src/evidence/encryption.ts +168 -0
  31. package/src/evidence/storage.ts +197 -0
  32. package/src/evidence/validator.ts +184 -0
  33. package/src/index.ts +43 -0
  34. package/src/integrations/paypal.ts +258 -0
  35. package/src/integrations/stripe.ts +280 -0
  36. package/src/integrations/webhook.ts +332 -0
  37. package/src/notifications/email.ts +161 -0
  38. package/src/notifications/inApp.ts +319 -0
  39. package/src/notifications/sms.ts +58 -0
  40. package/src/security/auth.ts +153 -0
  41. package/src/security/rateLimit.ts +77 -0
  42. package/src/security/validation.ts +166 -0
  43. package/src/server.ts +122 -0
  44. package/src/types/index.ts +790 -0
  45. package/src/utils/formatters.ts +72 -0
  46. package/src/utils/helpers.ts +193 -0
  47. package/src/utils/logger.ts +88 -0
  48. package/src/utils/validators.ts +39 -0
@@ -0,0 +1,155 @@
1
+ # Getting Started with chargeback-guard
2
+
3
+ chargeback-guard is an ultra-pro chargeback protection system for e-commerce merchants. It automatically collects transaction evidence, detects payment disputes, scores fraud risk with AI, and submits structured replies to banks via Stripe / PayPal / Square / Braintree webhooks.
4
+
5
+ ---
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install chargeback-guard
11
+ ```
12
+
13
+ ### Peer Dependencies
14
+
15
+ | Dependency | Purpose |
16
+ |---|---|
17
+ | `stripe` | Stripe webhook handling & dispute submission |
18
+ | `paypal-rest-sdk` | PayPal dispute API (optional) |
19
+ | `dotenv` | Environment variable loading |
20
+
21
+ ---
22
+
23
+ ## Quick Start
24
+
25
+ ### 1. Set Environment Variables
26
+
27
+ Create a `.env` file:
28
+
29
+ ```dotenv
30
+ CHARGEBACK_API_KEY=your-api-key-here
31
+ STRIPE_SECRET_KEY=sk_live_...
32
+ STRIPE_WEBHOOK_SECRET=whsec_...
33
+ DATABASE_URL=sqlite://./data/chargeback-guard.db
34
+ NODE_ENV=production
35
+ ```
36
+
37
+ ### 2. Initialize the Guard
38
+
39
+ ```typescript
40
+ import { createChargebackGuard } from 'chargeback-guard';
41
+
42
+ const guard = await createChargebackGuard({
43
+ apiKey: process.env.STRIPE_SECRET_KEY!,
44
+ webhookSecret: process.env.STRIPE_WEBHOOK_SECRET!,
45
+ autoReply: true,
46
+ evidenceCollection: true,
47
+ });
48
+
49
+ console.log('ChargebackGuard is running ✓');
50
+ ```
51
+
52
+ ### 3. Register a Payment
53
+
54
+ Call `registerPayment()` immediately after every successful charge. This pre-collects evidence so it is ready if a dispute arrives later.
55
+
56
+ ```typescript
57
+ const result = await guard.registerPayment({
58
+ orderId: 'order_abc123',
59
+ customerId: 'cust_xyz',
60
+ amount: 9999, // cents
61
+ currency: 'USD',
62
+ provider: 'stripe',
63
+ transactionId: 'ch_3Pabcdef...',
64
+ timestamp: new Date(),
65
+ metadata: {
66
+ email: 'customer@example.com',
67
+ ipAddress: '203.0.113.42',
68
+ deviceId: 'fp_abc123',
69
+ shippingAddress: '123 Main St, Austin TX 78701',
70
+ },
71
+ });
72
+
73
+ console.log('Risk level:', result.riskLevel); // 'very_low' | 'low' | 'medium' | 'high' | 'critical'
74
+ console.log('Trust score:', result.trustScore); // 0–100
75
+ ```
76
+
77
+ ### 4. Handle Disputes via Webhook
78
+
79
+ ```typescript
80
+ import express from 'express';
81
+
82
+ const app = express();
83
+
84
+ // Raw body needed for Stripe signature verification
85
+ app.post('/webhooks/stripe', express.raw({ type: 'application/json' }), async (req, res) => {
86
+ const sig = req.headers['stripe-signature'] as string;
87
+
88
+ // Verify + parse the Stripe event yourself, then call handleDispute()
89
+ const dispute = {
90
+ id: event.data.object.id,
91
+ orderId: event.data.object.metadata.orderId,
92
+ amount: event.data.object.amount,
93
+ currency: event.data.object.currency,
94
+ reason: event.data.object.reason,
95
+ status: event.data.object.status,
96
+ provider: 'stripe' as const,
97
+ dueBy: new Date(event.data.object.evidence_details.due_by * 1000),
98
+ createdAt: new Date(),
99
+ };
100
+
101
+ const outcome = await guard.handleDispute(dispute);
102
+ console.log('Action taken:', outcome.actionTaken);
103
+ // 'auto-reply_submitted' | 'manual_review_required' | 'accepted' | 'skipped'
104
+
105
+ res.json({ received: true });
106
+ });
107
+
108
+ app.listen(3000);
109
+ ```
110
+
111
+ ### 5. Graceful Shutdown
112
+
113
+ ```typescript
114
+ process.on('SIGTERM', async () => {
115
+ await guard.shutdown();
116
+ process.exit(0);
117
+ });
118
+ ```
119
+
120
+ ---
121
+
122
+ ## Core Concepts
123
+
124
+ ### Payment Registration
125
+ Every successful transaction should be registered. chargeback-guard:
126
+ - Collects device fingerprints, geolocation, and behavioral signals
127
+ - Runs an AI fraud pre-check and assigns a trust score (0–100)
128
+ - Stores all evidence in the configured database, indexed by `orderId`
129
+
130
+ ### Dispute Detection
131
+ When a chargeback is filed, `handleDispute()`:
132
+ 1. Fetches all pre-collected evidence for the associated `orderId`
133
+ 2. Analyzes the dispute reason and selects a response strategy
134
+ 3. Optionally auto-submits a reply to the payment provider
135
+
136
+ ### Auto-Reply
137
+ When `autoReply: true`, chargeback-guard submits evidence to the bank on your behalf within minutes of dispute detection — maximizing win rates by responding before the deadline.
138
+
139
+ ### Risk Levels
140
+
141
+ | Level | Trust Score | Meaning |
142
+ |---|---|---|
143
+ | `very_low` | 80–100 | Fully trusted — registered customer, normal pattern |
144
+ | `low` | 60–79 | Minor signals — investigate if disputed |
145
+ | `medium` | 40–59 | Moderate risk — watch for chargebacks |
146
+ | `high` | 20–39 | High fraud probability — consider hold |
147
+ | `critical` | 0–19 | Very high risk — block or manual review |
148
+
149
+ ---
150
+
151
+ ## Next Steps
152
+
153
+ - [API Reference](./api.md)
154
+ - [Configuration](./configuration.md)
155
+ - [Architecture](./architecture.md)
@@ -0,0 +1,123 @@
1
+ // ============================================================
2
+ // CHARGEBACK GUARD — Advanced Configuration Example
3
+ // ============================================================
4
+
5
+ import {
6
+ ChargebackGuard,
7
+ Environment,
8
+ NotificationEvent,
9
+ NotificationChannel,
10
+ SubscriptionPlan,
11
+ } from '../src';
12
+
13
+ async function advancedSetup(): Promise<void> {
14
+ // ── Full configuration ────────────────────────────────────
15
+ const guard = new ChargebackGuard({
16
+ environment: Environment.PRODUCTION,
17
+ autoReply: true,
18
+ evidenceCollection: true,
19
+
20
+ database: {
21
+ type: 'postgresql',
22
+ url: process.env.DATABASE_URL ?? 'postgresql://localhost/chargebackguard',
23
+ poolMin: 2,
24
+ poolMax: 20,
25
+ },
26
+
27
+ redis: {
28
+ url: process.env.REDIS_URL ?? 'redis://localhost:6379',
29
+ ttl: 7200,
30
+ },
31
+
32
+ security: {
33
+ jwtSecret: process.env.JWT_SECRET ?? 'change-me',
34
+ encryptionKey: process.env.ENCRYPTION_KEY ?? 'change-this-32-char-key-produc!!',
35
+ bcryptRounds: 14,
36
+ rateLimit: {
37
+ windowMs: 900000,
38
+ maxRequests: 200,
39
+ },
40
+ },
41
+
42
+ notifications: {
43
+ channels: [
44
+ NotificationChannel.EMAIL,
45
+ NotificationChannel.SMS,
46
+ NotificationChannel.WEBHOOK,
47
+ NotificationChannel.IN_APP,
48
+ ],
49
+ email: {
50
+ host: 'smtp.sendgrid.net',
51
+ port: 587,
52
+ secure: false,
53
+ user: 'apikey',
54
+ pass: process.env.SENDGRID_API_KEY ?? '',
55
+ fromName: 'Chargeback Guard',
56
+ fromAddress: 'alerts@chargebackguard.io',
57
+ },
58
+ sms: {
59
+ accountSid: process.env.TWILIO_SID ?? '',
60
+ authToken: process.env.TWILIO_TOKEN ?? '',
61
+ phoneNumber: process.env.TWILIO_PHONE ?? '',
62
+ },
63
+ webhooks: [
64
+ {
65
+ url: 'https://your-app.com/webhooks/chargebackguard',
66
+ secret: process.env.WEBHOOK_SECRET,
67
+ events: [
68
+ NotificationEvent.DISPUTE_DETECTED,
69
+ NotificationEvent.DISPUTE_WON,
70
+ NotificationEvent.DISPUTE_LOST,
71
+ NotificationEvent.FRAUD_DETECTED,
72
+ ],
73
+ retries: 3,
74
+ },
75
+ ],
76
+ },
77
+
78
+ ai: {
79
+ fraudThreshold: 0.70,
80
+ riskScoreHigh: 0.85,
81
+ riskScoreMedium: 0.50,
82
+ },
83
+
84
+ billing: {
85
+ plan: SubscriptionPlan.ENTERPRISE,
86
+ revenueSharePercentage: 0.8,
87
+ monthlyPrice: 499,
88
+ },
89
+ });
90
+
91
+ // ── Custom event handlers ─────────────────────────────────
92
+
93
+ guard.events.onAsync(NotificationEvent.DISPUTE_DETECTED, async ({ data }) => {
94
+ // Your custom logic: update CRM, send Slack notification, etc.
95
+ console.log(`[CUSTOM] Dispute received: ${data['disputeId']}`);
96
+ });
97
+
98
+ guard.events.onAsync(NotificationEvent.DISPUTE_WON, async ({ data }) => {
99
+ const amount = (Number(data['amount']) || 0) / 100;
100
+ console.log(`[CUSTOM] $${amount.toFixed(2)} recovered for dispute ${data['disputeId']}`);
101
+ // e.g., update accounting system, notify customer success team
102
+ });
103
+
104
+ guard.events.onAsync(NotificationEvent.FRAUD_DETECTED, async ({ data }) => {
105
+ console.log(`[CUSTOM] FRAUD on order ${data['orderId']} — probability: ${data['probability']}`);
106
+ // e.g., block the customer account, flag for review
107
+ });
108
+
109
+ // ── Initialize ────────────────────────────────────────────
110
+ await guard.initialize();
111
+
112
+ // ── Check health ──────────────────────────────────────────
113
+ const health = await guard.getHealth();
114
+ console.log('Health:', JSON.stringify(health.data, null, 2));
115
+
116
+ // ── Lifetime stats ────────────────────────────────────────
117
+ const stats = await guard.getProtectionStats();
118
+ console.log('\nStats:', JSON.stringify(stats, null, 2));
119
+
120
+ await guard.shutdown();
121
+ }
122
+
123
+ advancedSetup().catch(console.error);
@@ -0,0 +1,98 @@
1
+ // ============================================================
2
+ // CHARGEBACK GUARD — Basic Usage Example
3
+ // ============================================================
4
+
5
+ import { createChargebackGuard, NotificationEvent, PaymentProvider } from '../src';
6
+
7
+ async function main(): Promise<void> {
8
+ // ── 1. Initialize ─────────────────────────────────────────
9
+ console.log('🚀 Initializing ChargebackGuard...');
10
+
11
+ const guard = await createChargebackGuard({
12
+ autoReply: true,
13
+ evidenceCollection: true,
14
+ });
15
+
16
+ // ── 2. Listen for events ──────────────────────────────────
17
+ guard.events.on(NotificationEvent.PAYMENT_REGISTERED, ({ data }) => {
18
+ console.log(`✅ Payment protected: ${data['orderId']} | Trust: ${data['trustScore']}`);
19
+ });
20
+
21
+ guard.events.on(NotificationEvent.DISPUTE_DETECTED, ({ data }) => {
22
+ console.log(`⚠️ Dispute detected: ${data['disputeId']} — auto-reply in progress`);
23
+ });
24
+
25
+ guard.events.on(NotificationEvent.DISPUTE_REPLIED, ({ data }) => {
26
+ console.log(`📤 Reply submitted for: ${data['disputeId']}`);
27
+ });
28
+
29
+ guard.events.on(NotificationEvent.DISPUTE_WON, ({ data }) => {
30
+ console.log(`🏆 WON: ${data['disputeId']} | $${((Number(data['amount']) || 0) / 100).toFixed(2)} recovered`);
31
+ });
32
+
33
+ // ── 3. Register a payment ──────────────────────────────────
34
+ const registration = await guard.registerPayment({
35
+ orderId: 'ORD-2025-12345',
36
+ amount: 29999, // cents = $299.99
37
+ currency: 'USD',
38
+ customerEmail: 'alice@example.com',
39
+ customerName: 'Alice Johnson',
40
+ customerIp: '203.0.113.42',
41
+ transactionId: 'ch_3OqExample123',
42
+ provider: PaymentProvider.STRIPE,
43
+ shippingAddress: {
44
+ line1: '123 Main Street',
45
+ city: 'Cairo',
46
+ postalCode: '11511',
47
+ country: 'EG',
48
+ },
49
+ sessionData: {
50
+ sessionId: 'sess_abc123',
51
+ duration: 340,
52
+ pageViews: [
53
+ { url: '/products/item-123', duration: 120, timestamp: new Date().toISOString() },
54
+ { url: '/cart', duration: 45, timestamp: new Date().toISOString() },
55
+ { url: '/checkout', duration: 90, timestamp: new Date().toISOString() },
56
+ ],
57
+ timeOnCheckout: 90,
58
+ },
59
+ deviceFingerprint: {
60
+ screenResolution: '1920x1080',
61
+ timezone: 'UTC+2',
62
+ language: 'en-US',
63
+ platform: 'Win32',
64
+ },
65
+ });
66
+
67
+ console.log('\n📦 Registration Result:');
68
+ console.log(JSON.stringify(registration, null, 2));
69
+
70
+ // ── 4. Simulate a dispute ──────────────────────────────────
71
+ console.log('\n🚨 Simulating incoming dispute...');
72
+
73
+ const disputeResult = await guard.handleDispute({
74
+ id: 'dp_2OqTestDispute001',
75
+ orderId: 'ORD-2025-12345',
76
+ amount: 29999,
77
+ currency: 'usd',
78
+ reason: 'product_not_received' as never,
79
+ status: 'needs_response' as never,
80
+ provider: PaymentProvider.STRIPE,
81
+ evidenceDueBy: new Date(Date.now() + 7 * 86400000).toISOString(), // 7 days
82
+ createdAt: new Date().toISOString(),
83
+ });
84
+
85
+ console.log('\n📋 Dispute Handling Result:');
86
+ console.log(JSON.stringify(disputeResult, null, 2));
87
+
88
+ // ── 5. Get stats ───────────────────────────────────────────
89
+ const stats = await guard.getProtectionStats();
90
+ console.log('\n📊 Protection Stats:');
91
+ console.log(JSON.stringify(stats, null, 2));
92
+
93
+ // ── 6. Shutdown ────────────────────────────────────────────
94
+ await guard.shutdown();
95
+ console.log('\n✅ ChargebackGuard shut down gracefully');
96
+ }
97
+
98
+ main().catch(console.error);
@@ -0,0 +1,106 @@
1
+ // ============================================================
2
+ // CHARGEBACK GUARD — Stripe Integration Example (Express App)
3
+ // ============================================================
4
+
5
+ import express from 'express';
6
+ import { createChargebackGuard, PaymentProvider, DisputeStatus } from '../src';
7
+ import { WebhookHandler } from '../src/integrations/webhook';
8
+ import { createApp } from '../src/api/routes';
9
+
10
+ async function startServer(): Promise<void> {
11
+ // ── 1. Initialize guard ───────────────────────────────────
12
+ const guard = await createChargebackGuard({
13
+ autoReply: true,
14
+ evidenceCollection: true,
15
+ });
16
+
17
+ // ── 2. Setup webhook handler ──────────────────────────────
18
+ const webhookHandler = new WebhookHandler();
19
+
20
+ // When a dispute is detected via Stripe webhook
21
+ webhookHandler.onDisputeDetected(async (dispute) => {
22
+ console.log(`🚨 Handling dispute: ${dispute.id}`);
23
+ await guard.handleDispute(dispute);
24
+ });
25
+
26
+ // When a dispute is resolved (won/lost)
27
+ webhookHandler.onDisputeResolved(async (disputeId, status, provider) => {
28
+ if (status === DisputeStatus.WON) {
29
+ console.log(`🏆 Dispute WON: ${disputeId}`);
30
+ } else if (status === DisputeStatus.LOST) {
31
+ console.log(`❌ Dispute LOST: ${disputeId}`);
32
+ }
33
+ });
34
+
35
+ // ── 3. Create Express app ─────────────────────────────────
36
+ const app = createApp(webhookHandler);
37
+
38
+ // Share guard instance with controllers
39
+ app.locals['chargebackGuard'] = guard;
40
+
41
+ // ── 4. Custom route: Register payment after Stripe charge ──
42
+ app.post('/charge-and-protect', express.json(), async (req, res) => {
43
+ try {
44
+ const {
45
+ orderId, amount, currency,
46
+ customerEmail, customerIp,
47
+ stripeChargeId,
48
+ } = req.body as {
49
+ orderId: string;
50
+ amount: number;
51
+ currency: string;
52
+ customerEmail: string;
53
+ customerIp?: string;
54
+ stripeChargeId: string;
55
+ };
56
+
57
+ // Register for protection
58
+ const result = await guard.registerPayment({
59
+ orderId,
60
+ amount,
61
+ currency,
62
+ customerEmail,
63
+ customerIp: customerIp ?? req.ip,
64
+ userAgent: req.headers['user-agent'],
65
+ transactionId: stripeChargeId,
66
+ provider: PaymentProvider.STRIPE,
67
+ });
68
+
69
+ res.json({
70
+ success: true,
71
+ message: 'Payment registered and protected',
72
+ ...result,
73
+ });
74
+ } catch (err) {
75
+ res.status(500).json({
76
+ success: false,
77
+ error: err instanceof Error ? err.message : 'Unknown error',
78
+ });
79
+ }
80
+ });
81
+
82
+ // ── 5. Start server ───────────────────────────────────────
83
+ const PORT = process.env.PORT ?? 3000;
84
+ const server = app.listen(PORT, () => {
85
+ console.log(`🛡️ ChargebackGuard API running at http://localhost:${PORT}`);
86
+ console.log(` POST /api/v1/payments — Register payment`);
87
+ console.log(` GET /api/v1/disputes — List disputes`);
88
+ console.log(` POST /api/v1/webhooks/stripe — Stripe webhook`);
89
+ console.log(` GET /api/v1/analytics/stats — Get stats`);
90
+ console.log(` GET /api/v1/health — Health check`);
91
+ });
92
+
93
+ // ── 6. Graceful shutdown ──────────────────────────────────
94
+ const shutdown = async (): Promise<void> => {
95
+ console.log('\n🛑 Shutting down...');
96
+ server.close(async () => {
97
+ await guard.shutdown();
98
+ process.exit(0);
99
+ });
100
+ };
101
+
102
+ process.on('SIGTERM', shutdown);
103
+ process.on('SIGINT', shutdown);
104
+ }
105
+
106
+ startServer().catch(console.error);
package/package.json ADDED
@@ -0,0 +1,181 @@
1
+ {
2
+ "name": "chargeback-guard",
3
+ "version": "2.0.0",
4
+ "description": "Ultra Pro chargeback protection system for e-commerce merchants. Automatically collects evidence, detects disputes, and submits AI-powered replies to banks via Stripe/PayPal webhooks.",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist",
9
+ "src",
10
+ "docs",
11
+ "examples",
12
+ "README.md",
13
+ "LICENSE"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "build:watch": "tsc --watch",
18
+ "dev": "ts-node src/index.ts",
19
+ "dev:watch": "nodemon --exec ts-node src/index.ts",
20
+ "test": "jest --coverage",
21
+ "test:unit": "jest tests/unit --coverage",
22
+ "test:integration": "jest tests/integration",
23
+ "test:e2e": "jest tests/e2e",
24
+ "test:watch": "jest --watch",
25
+ "lint": "eslint src/**/*.ts",
26
+ "lint:fix": "eslint src/**/*.ts --fix",
27
+ "format": "prettier --write 'src/**/*.ts'",
28
+ "clean": "rimraf dist",
29
+ "prepublish": "npm run clean && npm run build",
30
+ "docs:generate": "typedoc --out docs/api src/index.ts",
31
+ "migrate": "ts-node src/database/migrate.ts",
32
+ "seed": "ts-node src/database/seed.ts",
33
+ "start": "node dist/index.js",
34
+ "start:pm2": "pm2 start ecosystem.config.js"
35
+ },
36
+ "keywords": [
37
+ "chargeback",
38
+ "fraud-detection",
39
+ "stripe",
40
+ "paypal",
41
+ "payment-protection",
42
+ "dispute-management",
43
+ "e-commerce",
44
+ "machine-learning",
45
+ "fintech",
46
+ "evidence-collection"
47
+ ],
48
+ "author": {
49
+ "name": "ChargebackGuard Team",
50
+ "email": "support@chargebackguard.io",
51
+ "url": "https://chargebackguard.io"
52
+ },
53
+ "license": "MIT",
54
+ "engines": {
55
+ "node": ">=18.0.0",
56
+ "npm": ">=9.0.0"
57
+ },
58
+ "dependencies": {
59
+ "stripe": "^14.0.0",
60
+ "@paypal/paypal-server-sdk": "^0.6.0",
61
+ "express": "^4.18.2",
62
+ "express-rate-limit": "^7.1.5",
63
+ "express-validator": "^7.0.1",
64
+ "cors": "^2.8.5",
65
+ "helmet": "^7.1.0",
66
+ "compression": "^1.7.4",
67
+ "morgan": "^1.10.0",
68
+ "dotenv": "^16.3.1",
69
+ "jsonwebtoken": "^9.0.2",
70
+ "bcryptjs": "^2.4.3",
71
+ "axios": "^1.6.2",
72
+ "uuid": "^9.0.1",
73
+ "date-fns": "^3.0.0",
74
+ "lodash": "^4.17.21",
75
+ "winston": "^3.11.0",
76
+ "winston-daily-rotate-file": "^4.7.1",
77
+ "ioredis": "^5.3.2",
78
+ "knex": "^3.1.0",
79
+ "pg": "^8.11.3",
80
+ "better-sqlite3": "^9.4.3",
81
+ "nodemailer": "^6.9.7",
82
+ "twilio": "^4.19.3",
83
+ "handlebars": "^4.7.8",
84
+ "node-cron": "^3.0.3",
85
+ "bull": "^4.12.0",
86
+ "socket.io": "^4.6.2",
87
+ "multer": "^1.4.5-lts.1",
88
+ "sharp": "^0.33.1",
89
+ "pdf-lib": "^1.17.1",
90
+ "archiver": "^6.0.1",
91
+ "zod": "^3.22.4",
92
+ "pino": "^8.17.2",
93
+ "pino-http": "^9.0.0",
94
+ "ms": "^2.1.3",
95
+ "p-retry": "^6.2.0",
96
+ "p-limit": "^5.0.0",
97
+ "node-cache": "^5.1.2",
98
+ "crypto-js": "^4.2.0",
99
+ "ip": "^2.0.1",
100
+ "geoip-lite": "^1.4.10",
101
+ "ua-parser-js": "^1.0.37"
102
+ },
103
+ "devDependencies": {
104
+ "@types/node": "^20.10.6",
105
+ "@types/express": "^4.17.21",
106
+ "@types/cors": "^2.8.17",
107
+ "@types/compression": "^1.7.5",
108
+ "@types/morgan": "^1.9.9",
109
+ "@types/jsonwebtoken": "^9.0.5",
110
+ "@types/bcryptjs": "^2.4.6",
111
+ "@types/lodash": "^4.14.202",
112
+ "@types/nodemailer": "^6.4.14",
113
+ "@types/multer": "^1.4.11",
114
+ "@types/archiver": "^6.0.2",
115
+ "@types/uuid": "^9.0.7",
116
+ "@types/better-sqlite3": "^7.6.8",
117
+ "@types/pg": "^8.10.9",
118
+ "@types/ms": "^0.7.34",
119
+ "@types/geoip-lite": "^1.4.4",
120
+ "@types/ua-parser-js": "^0.7.39",
121
+ "@types/jest": "^29.5.11",
122
+ "@types/supertest": "^6.0.2",
123
+ "typescript": "^5.3.3",
124
+ "ts-node": "^10.9.2",
125
+ "nodemon": "^3.0.2",
126
+ "jest": "^29.7.0",
127
+ "ts-jest": "^29.1.1",
128
+ "supertest": "^6.3.4",
129
+ "eslint": "^8.56.0",
130
+ "@typescript-eslint/eslint-plugin": "^6.17.0",
131
+ "@typescript-eslint/parser": "^6.17.0",
132
+ "prettier": "^3.1.1",
133
+ "rimraf": "^5.0.5",
134
+ "typedoc": "^0.25.6",
135
+ "husky": "^8.0.3",
136
+ "lint-staged": "^15.2.0"
137
+ },
138
+ "jest": {
139
+ "preset": "ts-jest",
140
+ "testEnvironment": "node",
141
+ "coverageDirectory": "coverage",
142
+ "collectCoverageFrom": [
143
+ "src/**/*.ts",
144
+ "!src/**/*.d.ts",
145
+ "!src/**/index.ts"
146
+ ],
147
+ "coverageThreshold": {
148
+ "global": {
149
+ "branches": 75,
150
+ "functions": 80,
151
+ "lines": 80,
152
+ "statements": 80
153
+ }
154
+ },
155
+ "testMatch": [
156
+ "<rootDir>/tests/**/*.test.ts"
157
+ ],
158
+ "setupFilesAfterEnv": [
159
+ "<rootDir>/tests/setup.ts"
160
+ ]
161
+ },
162
+ "husky": {
163
+ "hooks": {
164
+ "pre-commit": "lint-staged"
165
+ }
166
+ },
167
+ "lint-staged": {
168
+ "src/**/*.ts": [
169
+ "eslint --fix",
170
+ "prettier --write"
171
+ ]
172
+ },
173
+ "repository": {
174
+ "type": "git",
175
+ "url": "https://github.com/brah-timo/chargeback-guard.git"
176
+ },
177
+ "bugs": {
178
+ "url": "https://github.com/brah-timo/chargeback-guard/issues"
179
+ },
180
+ "homepage": "https://chargebackguard.io"
181
+ }