feat: add socker connection between client and server

This commit is contained in:
Ahmed Bouhuolia
2024-02-24 00:18:48 +02:00
parent 1fd8a53ed1
commit 2d3544fe37
16 changed files with 357 additions and 27 deletions

View File

@@ -25,11 +25,15 @@ export class PlaidFetchTransactionsJob {
const plaidFetchTransactionsService = Container.get(
PlaidUpdateTransactions
);
const io = Container.get('socket');
try {
await plaidFetchTransactionsService.updateTransactions(
tenantId,
plaidItemId
);
// Notify the frontend to reflect the new transactions changes.
io.emit('NEW_TRANSACTIONS_DATA', { plaidItemId });
done();
} catch (error) {
console.log(error);

View File

@@ -7,6 +7,7 @@ import {
IPlaidItemCreatedEventPayload,
PlaidItemDTO,
} from '@/interfaces/Plaid';
import SystemPlaidItem from '@/system/models/SystemPlaidItem';
@Service()
export class PlaidItemService {
@@ -29,19 +30,23 @@ export class PlaidItemService {
const plaidInstance = new PlaidClientWrapper();
// exchange the public token for a private access token and store with the item.
// Exchange the public token for a private access token and store with the item.
const response = await plaidInstance.itemPublicTokenExchange({
public_token: publicToken,
});
const plaidAccessToken = response.data.access_token;
const plaidItemId = response.data.item_id;
// Store the Plaid item metadata on tenant scope.
const plaidItem = await PlaidItem.query().insertAndFetch({
tenantId,
plaidAccessToken,
plaidItemId,
plaidInstitutionId: institutionId,
});
// Stores the Plaid item id on system scope.
await SystemPlaidItem.query().insert({ tenantId, plaidItemId });
// Triggers `onPlaidItemCreated` event.
await this.eventPublisher.emitAsync(events.plaid.onItemCreated, {
tenantId,

View File

@@ -0,0 +1,32 @@
import { Request, Response, NextFunction } from 'express';
import { SystemPlaidItem, Tenant } from '@/system/models';
import tenantDependencyInjection from '@/api/middleware/TenantDependencyInjection';
export const PlaidWebhookTenantBootMiddleware = async (
req: Request,
res: Response,
next: NextFunction
) => {
const { item_id: plaidItemId } = req.body;
const plaidItem = await SystemPlaidItem.query().findOne({ plaidItemId });
const notFoundOrganization = () => {
return res.boom.unauthorized('Organization identication not found.', {
errors: [{ type: 'ORGANIZATION.ID.NOT.FOUND', code: 100 }],
});
};
// In case the given organization not found.
if (!plaidItem) {
return notFoundOrganization();
}
const tenant = await Tenant.query()
.findById(plaidItem.tenantId)
.withGraphFetched('metadata');
// When the given organization id not found on the system storage.
if (!tenant) {
return notFoundOrganization();
}
tenantDependencyInjection(req, tenant);
next();
};

View File

@@ -8,17 +8,17 @@ export class PlaidWebooks {
/**
* Listens to Plaid webhooks
* @param {number} tenantId
* @param {string} webhookType
* @param {string} plaidItemId
* @param {string} webhookCode
* @param {number} tenantId - Tenant Id.
* @param {string} webhookType - Webhook type.
* @param {string} plaidItemId - Plaid item Id.
* @param {string} webhookCode - webhook code.
*/
public async webhooks(
tenantId: number,
plaidItemId: string,
webhookType: string,
webhookCode: string
) {
): Promise<void> {
const _webhookType = webhookType.toLowerCase();
// There are five types of webhooks: AUTH, TRANSACTIONS, ITEM, INCOME, and ASSETS.
@@ -43,7 +43,7 @@ export class PlaidWebooks {
webhookType: string,
webhookCode: string,
plaidItemId: string
) {
): Promise<void> {
console.log(
`UNHANDLED ${webhookType} WEBHOOK: ${webhookCode}: Plaid item id ${plaidItemId}: unhandled webhook type received.`
);
@@ -59,7 +59,7 @@ export class PlaidWebooks {
additionalInfo: string,
webhookCode: string,
plaidItemId: string
) {
): void {
console.log(
`WEBHOOK: TRANSACTIONS: ${webhookCode}: Plaid_item_id ${plaidItemId}: ${additionalInfo}`
);