@valentine-efagene/qshelter-common 2.0.83 → 2.0.84
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/dist/src/events/index.d.ts +2 -0
- package/dist/src/events/index.js +3 -0
- package/dist/src/events/payments/index.d.ts +2 -0
- package/dist/src/events/payments/index.js +2 -0
- package/dist/src/events/payments/payment-event.d.ts +70 -0
- package/dist/src/events/payments/payment-event.js +18 -0
- package/dist/src/events/payments/payment-publisher.d.ts +46 -0
- package/dist/src/events/payments/payment-publisher.js +90 -0
- package/package.json +12 -11
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export * from './notifications/notification-enums';
|
|
2
2
|
export * from './notifications/notification-event';
|
|
3
3
|
export * from './notifications/event-publisher';
|
|
4
|
+
export * from './payments/payment-event';
|
|
5
|
+
export * from './payments/payment-publisher';
|
|
4
6
|
export * from './bus/event-bus.types';
|
|
5
7
|
export * from './bus/event-bus.service';
|
package/dist/src/events/index.js
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
export * from './notifications/notification-enums';
|
|
3
3
|
export * from './notifications/notification-event';
|
|
4
4
|
export * from './notifications/event-publisher';
|
|
5
|
+
// Payment events and publisher (SNS-based)
|
|
6
|
+
export * from './payments/payment-event';
|
|
7
|
+
export * from './payments/payment-publisher';
|
|
5
8
|
// Event bus (multi-transport delivery)
|
|
6
9
|
export * from './bus/event-bus.types';
|
|
7
10
|
export * from './bus/event-bus.service';
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payment event types for the payment service queue
|
|
3
|
+
* These are internal service events, not user-facing notifications
|
|
4
|
+
*/
|
|
5
|
+
export declare enum PaymentEventType {
|
|
6
|
+
WALLET_CREDITED = "wallet.credited",
|
|
7
|
+
WALLET_DEBITED = "wallet.debited",
|
|
8
|
+
WALLET_CREATED = "wallet.created",
|
|
9
|
+
ALLOCATE_TO_INSTALLMENTS = "payment.allocate_to_installments",
|
|
10
|
+
PROCESS_INSTALLMENT_PAYMENT = "payment.process_installment",
|
|
11
|
+
REFUND_PAYMENT = "payment.refund",
|
|
12
|
+
VIRTUAL_ACCOUNT_FUNDED = "virtualaccount.funded"
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Metadata for payment events
|
|
16
|
+
*/
|
|
17
|
+
export interface PaymentEventMeta {
|
|
18
|
+
/** Service that published the event */
|
|
19
|
+
source: string;
|
|
20
|
+
/** ISO timestamp of when event was created */
|
|
21
|
+
timestamp: string;
|
|
22
|
+
/** Correlation ID for distributed tracing */
|
|
23
|
+
correlationId?: string;
|
|
24
|
+
/** User ID */
|
|
25
|
+
userId?: string;
|
|
26
|
+
/** Tenant ID */
|
|
27
|
+
tenantId?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Base payment event structure
|
|
31
|
+
*/
|
|
32
|
+
export interface PaymentEvent<T = Record<string, unknown>> {
|
|
33
|
+
type: PaymentEventType;
|
|
34
|
+
payload: T;
|
|
35
|
+
meta: PaymentEventMeta;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Payload when wallet is credited
|
|
39
|
+
*/
|
|
40
|
+
export interface WalletCreditedPayload {
|
|
41
|
+
walletId: string;
|
|
42
|
+
userId: string;
|
|
43
|
+
transactionId: string;
|
|
44
|
+
amount: number;
|
|
45
|
+
currency: string;
|
|
46
|
+
newBalance: number;
|
|
47
|
+
reference: string;
|
|
48
|
+
source: 'virtual_account' | 'manual' | 'refund';
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Payload for allocating funds to installments
|
|
52
|
+
*/
|
|
53
|
+
export interface AllocateToInstallmentsPayload {
|
|
54
|
+
userId: string;
|
|
55
|
+
walletId: string;
|
|
56
|
+
/** Optional: limit to specific contract */
|
|
57
|
+
contractId?: string;
|
|
58
|
+
/** Optional: limit to specific amount */
|
|
59
|
+
maxAmount?: number;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Payload for processing an installment payment
|
|
63
|
+
*/
|
|
64
|
+
export interface ProcessInstallmentPaymentPayload {
|
|
65
|
+
installmentId: string;
|
|
66
|
+
amount: number;
|
|
67
|
+
walletId: string;
|
|
68
|
+
userId: string;
|
|
69
|
+
reference: string;
|
|
70
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payment event types for the payment service queue
|
|
3
|
+
* These are internal service events, not user-facing notifications
|
|
4
|
+
*/
|
|
5
|
+
export var PaymentEventType;
|
|
6
|
+
(function (PaymentEventType) {
|
|
7
|
+
// Wallet events (published by payment service)
|
|
8
|
+
PaymentEventType["WALLET_CREDITED"] = "wallet.credited";
|
|
9
|
+
PaymentEventType["WALLET_DEBITED"] = "wallet.debited";
|
|
10
|
+
PaymentEventType["WALLET_CREATED"] = "wallet.created";
|
|
11
|
+
// Allocation commands (published by mortgage service or after wallet credit)
|
|
12
|
+
PaymentEventType["ALLOCATE_TO_INSTALLMENTS"] = "payment.allocate_to_installments";
|
|
13
|
+
// Payment commands (published by mortgage service)
|
|
14
|
+
PaymentEventType["PROCESS_INSTALLMENT_PAYMENT"] = "payment.process_installment";
|
|
15
|
+
PaymentEventType["REFUND_PAYMENT"] = "payment.refund";
|
|
16
|
+
// Virtual account events
|
|
17
|
+
PaymentEventType["VIRTUAL_ACCOUNT_FUNDED"] = "virtualaccount.funded";
|
|
18
|
+
})(PaymentEventType || (PaymentEventType = {}));
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { PaymentEventType, PaymentEventMeta } from './payment-event';
|
|
2
|
+
/**
|
|
3
|
+
* Configuration for the payment event publisher
|
|
4
|
+
*/
|
|
5
|
+
interface PaymentPublisherConfig {
|
|
6
|
+
region?: string;
|
|
7
|
+
endpoint?: string;
|
|
8
|
+
topicArn?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Payment Event Publisher for sending payment events to SNS
|
|
12
|
+
* Used by payment-service and mortgage-service to communicate
|
|
13
|
+
*/
|
|
14
|
+
export declare class PaymentEventPublisher {
|
|
15
|
+
private readonly snsClient;
|
|
16
|
+
private readonly topicArn;
|
|
17
|
+
private readonly serviceName;
|
|
18
|
+
constructor(serviceName: string, config?: PaymentPublisherConfig);
|
|
19
|
+
/**
|
|
20
|
+
* Publish a payment event to SNS
|
|
21
|
+
*/
|
|
22
|
+
publish<T>(type: PaymentEventType, payload: T, meta?: Partial<PaymentEventMeta>): Promise<string>;
|
|
23
|
+
/**
|
|
24
|
+
* Publish wallet credited event
|
|
25
|
+
*/
|
|
26
|
+
publishWalletCredited(payload: {
|
|
27
|
+
walletId: string;
|
|
28
|
+
userId: string;
|
|
29
|
+
transactionId: string;
|
|
30
|
+
amount: number;
|
|
31
|
+
currency: string;
|
|
32
|
+
newBalance: number;
|
|
33
|
+
reference: string;
|
|
34
|
+
source: 'virtual_account' | 'manual' | 'refund';
|
|
35
|
+
}, meta?: Partial<PaymentEventMeta>): Promise<string>;
|
|
36
|
+
/**
|
|
37
|
+
* Publish allocate to installments command
|
|
38
|
+
*/
|
|
39
|
+
publishAllocateToInstallments(payload: {
|
|
40
|
+
userId: string;
|
|
41
|
+
walletId: string;
|
|
42
|
+
contractId?: string;
|
|
43
|
+
maxAmount?: number;
|
|
44
|
+
}, meta?: Partial<PaymentEventMeta>): Promise<string>;
|
|
45
|
+
}
|
|
46
|
+
export {};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { SNSClient, PublishCommand } from '@aws-sdk/client-sns';
|
|
2
|
+
import { PaymentEventType, } from './payment-event';
|
|
3
|
+
/**
|
|
4
|
+
* Get SNS client configured for LocalStack or AWS
|
|
5
|
+
*/
|
|
6
|
+
function createSNSClient(config) {
|
|
7
|
+
const endpoint = config.endpoint || process.env.LOCALSTACK_ENDPOINT;
|
|
8
|
+
const region = config.region || process.env.AWS_REGION || 'us-east-1';
|
|
9
|
+
const clientConfig = { region };
|
|
10
|
+
// For LocalStack, set custom endpoint
|
|
11
|
+
if (endpoint) {
|
|
12
|
+
clientConfig.endpoint = endpoint;
|
|
13
|
+
}
|
|
14
|
+
return new SNSClient(clientConfig);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Payment Event Publisher for sending payment events to SNS
|
|
18
|
+
* Used by payment-service and mortgage-service to communicate
|
|
19
|
+
*/
|
|
20
|
+
export class PaymentEventPublisher {
|
|
21
|
+
snsClient;
|
|
22
|
+
topicArn;
|
|
23
|
+
serviceName;
|
|
24
|
+
constructor(serviceName, config) {
|
|
25
|
+
this.serviceName = serviceName;
|
|
26
|
+
this.snsClient = createSNSClient(config || {});
|
|
27
|
+
// Topic ARN can be passed directly or constructed from env vars
|
|
28
|
+
const stage = process.env.STAGE || process.env.NODE_ENV || 'test';
|
|
29
|
+
const region = config?.region || process.env.AWS_REGION || 'us-east-1';
|
|
30
|
+
const accountId = process.env.AWS_ACCOUNT_ID || '000000000000';
|
|
31
|
+
this.topicArn = config?.topicArn ||
|
|
32
|
+
process.env.PAYMENTS_TOPIC_ARN ||
|
|
33
|
+
`arn:aws:sns:${region}:${accountId}:qshelter-${stage}-payments`;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Publish a payment event to SNS
|
|
37
|
+
*/
|
|
38
|
+
async publish(type, payload, meta) {
|
|
39
|
+
const event = {
|
|
40
|
+
type,
|
|
41
|
+
payload,
|
|
42
|
+
meta: {
|
|
43
|
+
source: this.serviceName,
|
|
44
|
+
timestamp: new Date().toISOString(),
|
|
45
|
+
correlationId: meta?.correlationId || crypto.randomUUID(),
|
|
46
|
+
userId: meta?.userId,
|
|
47
|
+
tenantId: meta?.tenantId,
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
const command = new PublishCommand({
|
|
51
|
+
TopicArn: this.topicArn,
|
|
52
|
+
Message: JSON.stringify(event),
|
|
53
|
+
MessageAttributes: {
|
|
54
|
+
eventType: {
|
|
55
|
+
DataType: 'String',
|
|
56
|
+
StringValue: type,
|
|
57
|
+
},
|
|
58
|
+
source: {
|
|
59
|
+
DataType: 'String',
|
|
60
|
+
StringValue: this.serviceName,
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
const result = await this.snsClient.send(command);
|
|
65
|
+
console.log(`[PaymentEventPublisher] Published ${type} event to SNS`, {
|
|
66
|
+
topicArn: this.topicArn,
|
|
67
|
+
messageId: result.MessageId,
|
|
68
|
+
correlationId: event.meta.correlationId,
|
|
69
|
+
});
|
|
70
|
+
return result.MessageId || '';
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Publish wallet credited event
|
|
74
|
+
*/
|
|
75
|
+
async publishWalletCredited(payload, meta) {
|
|
76
|
+
return this.publish(PaymentEventType.WALLET_CREDITED, payload, {
|
|
77
|
+
...meta,
|
|
78
|
+
userId: payload.userId,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Publish allocate to installments command
|
|
83
|
+
*/
|
|
84
|
+
async publishAllocateToInstallments(payload, meta) {
|
|
85
|
+
return this.publish(PaymentEventType.ALLOCATE_TO_INSTALLMENTS, payload, {
|
|
86
|
+
...meta,
|
|
87
|
+
userId: payload.userId,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@valentine-efagene/qshelter-common",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.84",
|
|
4
4
|
"description": "Shared database schemas and utilities for QShelter services",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"types": "dist/src/index.d.ts",
|
|
7
7
|
"type": "module",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc",
|
|
10
|
+
"dev": "tsc --watch",
|
|
11
|
+
"generate:prisma": "prisma generate && node scripts/generate-models-index.mjs",
|
|
12
|
+
"postgenerate": "node scripts/generate-models-index.mjs",
|
|
13
|
+
"migrate:dev": "prisma migrate dev",
|
|
14
|
+
"patch": "npm version patch && npm run build && npm publish --access public",
|
|
15
|
+
"prepublishOnly": "npm run build",
|
|
16
|
+
"publish:public": "npm publish --access public"
|
|
17
|
+
},
|
|
8
18
|
"keywords": [
|
|
9
19
|
"qshelter",
|
|
10
20
|
"common",
|
|
@@ -47,14 +57,5 @@
|
|
|
47
57
|
"@types/node": "^25.0.3",
|
|
48
58
|
"typescript": "^5.7.3",
|
|
49
59
|
"zod": "^4.0.0"
|
|
50
|
-
},
|
|
51
|
-
"scripts": {
|
|
52
|
-
"build": "tsc",
|
|
53
|
-
"dev": "tsc --watch",
|
|
54
|
-
"generate:prisma": "prisma generate && node scripts/generate-models-index.mjs",
|
|
55
|
-
"postgenerate": "node scripts/generate-models-index.mjs",
|
|
56
|
-
"migrate:dev": "prisma migrate dev",
|
|
57
|
-
"patch": "npm version patch && npm run build && npm publish --access public",
|
|
58
|
-
"publish:public": "npm publish --access public"
|
|
59
60
|
}
|
|
60
|
-
}
|
|
61
|
+
}
|