Skip to content

Commit

Permalink
📝 Updated md files for contributions
Browse files Browse the repository at this point in the history
  • Loading branch information
naelob committed Dec 27, 2023
1 parent ec50d9d commit 45fc51a
Show file tree
Hide file tree
Showing 11 changed files with 160 additions and 80 deletions.
92 changes: 68 additions & 24 deletions INTEGRATIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ First choose wisely which vertical the 3rd party belongs to among these:

For the sake of the guide, now on we'll consider adding a 3rd party belonging to the `crm` vertical.

## 1. Add a new service for your 3rd Party
## 1. Add a new connection service for your 3rd Party

Create a new folder with the name of your 3rd party. Let's call it *my3rdParty*.

Expand Down Expand Up @@ -69,52 +69,63 @@ export class My3rdPartyConnectionService implements ICrmConnectionService {

Now that you have the structure, check other 3rd parties implementations under `/@core/connections/crm/services` to build your functions.

## 2. Add a new connection to handle oAuth granting access
## 2. Enable your connection service to handle oAuth granting access

`cd @core/connections/crm/services/crm-connection.service.ts`
`cd @core/connections/crm/services/registry.service.ts`

Add your new 3rd party service to the `serviceMapping` object.
Add your new 3rd party service to the `registry` service.

```ts
private serviceMapping: { [key: string]: ICrmConnectionService } = {
"hubspot": this.hubspotConnectionService,
"zoho": this.zohoConnectionService,
"zendesk": this.zendeskConnectionService,
"freshsales": this.freshsalesConnectionService,
"pipedrive": this.pipedriveConnectionService,
// INSERT BELOW YOUR 3rd PARTY HERE
"my_3rd_party": this.my3rdPartyConnectionService
};
```
//ADD YOUR IMPORT
import { My3rdPartyConnectionService } from './my3rdParty/my3rdParty.service';

Don't forget to add your service you've defined at step 1 inside the constructor.
@Injectable()
export class ServiceConnectionRegistry {
private serviceMap: Map<string, ICrmConnectionService>;

```ts
constructor(private my3rdPartyConnectionService: My3rdPartyConnectionService)
constructor(
freshsales: FreshsalesConnectionService,
hubspot: HubspotConnectionService,
zoho: ZohoConnectionService,
zendesk: ZendeskConnectionService,
pipedrive: PipedriveConnectionService,
) {
this.serviceMap = new Map<string, ICrmConnectionService>();
this.serviceMap.set('freshsales', freshsales);
this.serviceMap.set('hubspot', hubspot);
this.serviceMap.set('zoho', zoho);
this.serviceMap.set('zendesk', zendesk);
this.serviceMap.set('pipedrive', pipedrive);
//ADD YOUR SERVICE
this.serviceMap.set('my3rdParty', my3rdParty);
}
}
```

Finally, don't forget to add your newly created service inside CrmConnectionModule under `/@core/connections/crm/crm-connection.module.ts`
Don't forget to ddd your service to the `CrmConnectionModule` module !

```ts
@Module({
imports: [WebhookModule],
providers: [
CrmConnectionsService,
PrismaService,
FreshsalesConnectionService,
HubspotConnectionService,
PipedriveConnectionService,
ZendeskConnectionService,
ZohoConnectionService,
ServiceConnectionRegistry,
LoggerService,
WebhookService,
EnvironmentService,
EncryptionService,
//INSERT BELOW YOUR SERVICE
FreshsalesConnectionService,
HubspotConnectionService,
ZohoConnectionService,
ZendeskConnectionService,
PipedriveConnectionService,
//INSERT YOUR SERVICE HERE
My3rdPartyConnectionService
],
exports: [CrmConnectionsService],
})
export class CrmConnectionModule {}
```

# You want to map a common object to your new 3rd Party ? 👩‍🎤
Expand Down Expand Up @@ -303,6 +314,39 @@ export class ServiceRegistry {
}
```

Finally, add it under the `ContactModule` module !

```ts
@Module({
imports: [
BullModule.registerQueue({
name: 'webhookDelivery',
}),
],
controllers: [ContactController],
providers: [
ContactService,
PrismaService,
FreshSalesService,
ZendeskService,
ZohoService,
PipedriveService,
HubspotService,
LoggerService,
FieldMappingService,
SyncContactsService,
WebhookService,
EncryptionService,
ServiceRegistry,
//INSERT YOUR SERVICE HERE
My3rdPartyService
],
exports: [SyncContactsService],
})
export class ContactModule {}

```

### Congrats Hero ! 🦸‍♀️

### You now have built a new integration with Panora
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Controller, Get, Query, Res } from '@nestjs/common';
import { Response } from 'express';
import { CrmConnectionsService } from './crm/services/crm-connection.service';
import { CrmConnectionsService } from './crm/services/crm.connection.service';
import { LoggerService } from '@@core/logger/logger.service';
import { NotFoundError, handleServiceError } from '@@core/utils/errors';
import { PrismaService } from '@@core/prisma/prisma.service';
Expand Down
2 changes: 1 addition & 1 deletion packages/api/src/@core/connections/connections.module.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Module } from '@nestjs/common';
import { CrmConnectionModule } from './crm/crm-connection.module';
import { CrmConnectionModule } from './crm/crm.connection.module';
import { ConnectionsController } from './connections.controller';
import { LoggerService } from '@@core/logger/logger.service';
import { PrismaService } from '@@core/prisma/prisma.service';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
import { Module } from '@nestjs/common';
import { CrmConnectionsService } from './services/crm-connection.service';
import { CrmConnectionsService } from './services/crm.connection.service';
import { PrismaService } from '@@core/prisma/prisma.service';
import { FreshsalesConnectionService } from './services/freshsales/freshsales.service';
import { HubspotConnectionService } from './services/hubspot/hubspot.service';
import { PipedriveConnectionService } from './services/pipedrive/pipedrive.service';
import { ZendeskConnectionService } from './services/zendesk/zendesk.service';
import { ZohoConnectionService } from './services/zoho/zoho.service';
import { LoggerService } from '@@core/logger/logger.service';
import { WebhookService } from '@@core/webhook/webhook.service';
import { WebhookModule } from '@@core/webhook/webhook.module';
import { EnvironmentService } from '@@core/environment/environment.service';
import { EncryptionService } from '@@core/encryption/encryption.service';
import { ServiceConnectionRegistry } from './services/registry.service';
import { FreshsalesConnectionService } from './services/freshsales/freshsales.service';
import { HubspotConnectionService } from './services/hubspot/hubspot.service';
import { ZohoConnectionService } from './services/zoho/zoho.service';
import { ZendeskConnectionService } from './services/zendesk/zendesk.service';
import { PipedriveConnectionService } from './services/pipedrive/pipedrive.service';

@Module({
imports: [WebhookModule],
providers: [
CrmConnectionsService,
PrismaService,
FreshsalesConnectionService,
HubspotConnectionService,
PipedriveConnectionService,
ZendeskConnectionService,
ZohoConnectionService,
ServiceConnectionRegistry,
LoggerService,
WebhookService,
EnvironmentService,
EncryptionService,
FreshsalesConnectionService,
HubspotConnectionService,
ZohoConnectionService,
ZendeskConnectionService,
PipedriveConnectionService,
],
exports: [CrmConnectionsService],
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,40 +1,24 @@
import { Injectable } from '@nestjs/common';
import { ZohoConnectionService } from './zoho/zoho.service';
import { NotFoundError, handleServiceError } from '@@core/utils/errors';
import { HubspotConnectionService } from './hubspot/hubspot.service';
import { PipedriveConnectionService } from './pipedrive/pipedrive.service';
import { ZendeskConnectionService } from './zendesk/zendesk.service';
import { FreshsalesConnectionService } from './freshsales/freshsales.service';
import { LoggerService } from '@@core/logger/logger.service';
import { WebhookService } from '@@core/webhook/webhook.service';
import { connections as Connection } from '@prisma/client';
import { PrismaService } from '@@core/prisma/prisma.service';
import { v4 as uuidv4 } from 'uuid';
import { CallbackParams, ICrmConnectionService, RefreshParams } from '../types';
import { CallbackParams, RefreshParams } from '../types';
import { ServiceConnectionRegistry } from './registry.service';

@Injectable()
export class CrmConnectionsService {
constructor(
private zohoConnectionService: ZohoConnectionService,
private hubspotConnectionService: HubspotConnectionService,
private pipedriveConnectionService: PipedriveConnectionService,
private zendeskConnectionService: ZendeskConnectionService,
private freshsalesConnectionService: FreshsalesConnectionService,
private serviceRegistry: ServiceConnectionRegistry,
private webhook: WebhookService,
private logger: LoggerService,
private prisma: PrismaService,
) {
this.logger.setContext(CrmConnectionsService.name);
}

private serviceMapping: { [key: string]: ICrmConnectionService } = {
hubspot: this.hubspotConnectionService,
zoho: this.zohoConnectionService,
zendesk: this.zendeskConnectionService,
//'freshsales': this.freshsalesConnectionService,
pipedrive: this.pipedriveConnectionService,
};

//STEP 1:[FRONTEND STEP]
//create a frontend SDK snippet in which an authorization embedded link is set up so when users click
// on it to grant access => they grant US the access and then when confirmed
Expand Down Expand Up @@ -75,7 +59,8 @@ export class CrmConnectionsService {
}

const serviceName = providerName.toLowerCase();
const service = this.serviceMapping[serviceName];
const service = this.serviceRegistry.getService(serviceName);

if (!service) {
throw new NotFoundError(`Unknown provider, found ${providerName}`);
}
Expand Down Expand Up @@ -114,7 +99,7 @@ export class CrmConnectionsService {
) {
try {
const serviceName = providerName.toLowerCase();
const service = this.serviceMapping[serviceName];
const service = this.serviceRegistry.getService(serviceName);
if (!service) {
throw new NotFoundError(`Unknown provider, found ${providerName}`);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { Injectable } from '@nestjs/common';
import { PrismaService } from '@@core/prisma/prisma.service';
import axios from 'axios';
import { CallbackParams, HubspotOAuthResponse, ICrmConnectionService, RefreshParams } from '../../types';
import {
CallbackParams,
HubspotOAuthResponse,
ICrmConnectionService,
RefreshParams,
} from '../../types';
import { LoggerService } from '@@core/logger/logger.service';
import { Action, handleServiceError } from '@@core/utils/errors';
import { v4 as uuidv4 } from 'uuid';
Expand All @@ -19,9 +24,7 @@ export class HubspotConnectionService implements ICrmConnectionService {
this.logger.setContext(HubspotConnectionService.name);
}

async handleCallback(
opts: CallbackParams
) {
async handleCallback(opts: CallbackParams) {
try {
const { linkedUserId, projectId, code } = opts;
this.logger.log(
Expand Down Expand Up @@ -104,7 +107,7 @@ export class HubspotConnectionService implements ICrmConnectionService {

async handleTokenRefresh(opts: RefreshParams) {
try {
const {connectionId, refreshToken} = opts;
const { connectionId, refreshToken } = opts;
const REDIRECT_URI = `${this.env.getOAuthRredirectBaseUrl()}/connections/oauth/callback`; //tocheck
const formData = new URLSearchParams({
grant_type: 'refresh_token',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { Injectable } from '@nestjs/common';
import { PrismaService } from '@@core/prisma/prisma.service';
import axios from 'axios';
import { CallbackParams, ICrmConnectionService, PipeDriveOAuthResponse, RefreshParams } from '../../types';
import {
CallbackParams,
ICrmConnectionService,
PipeDriveOAuthResponse,
RefreshParams,
} from '../../types';
import { Action, handleServiceError } from '@@core/utils/errors';
import { LoggerService } from '@@core/logger/logger.service';
import { v4 as uuidv4 } from 'uuid';
Expand All @@ -19,9 +24,7 @@ export class PipedriveConnectionService implements ICrmConnectionService {
this.logger.setContext(PipedriveConnectionService.name);
}

async handleCallback(
opts: CallbackParams
) {
async handleCallback(opts: CallbackParams) {
try {
const { linkedUserId, projectId, code } = opts;
const isNotUnique = await this.prisma.connections.findFirst({
Expand Down Expand Up @@ -102,7 +105,7 @@ export class PipedriveConnectionService implements ICrmConnectionService {

async handleTokenRefresh(opts: RefreshParams) {
try {
const {connectionId, refreshToken} = opts;
const { connectionId, refreshToken } = opts;
const REDIRECT_URI = `${this.env.getOAuthRredirectBaseUrl()}/connections/oauth/callback`;

const formData = new URLSearchParams({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Injectable } from '@nestjs/common';
import { ICrmConnectionService } from '../types';
import { ZohoConnectionService } from './zoho/zoho.service';
import { ZendeskConnectionService } from './zendesk/zendesk.service';
import { PipedriveConnectionService } from './pipedrive/pipedrive.service';
import { HubspotConnectionService } from './hubspot/hubspot.service';
import { FreshsalesConnectionService } from './freshsales/freshsales.service';

@Injectable()
export class ServiceConnectionRegistry {
private serviceMap: Map<string, ICrmConnectionService>;

constructor(
freshsales: FreshsalesConnectionService,
hubspot: HubspotConnectionService,
zoho: ZohoConnectionService,
zendesk: ZendeskConnectionService,
pipedrive: PipedriveConnectionService,
) {
this.serviceMap = new Map<string, ICrmConnectionService>();
this.serviceMap.set('freshsales', freshsales);
this.serviceMap.set('hubspot', hubspot);
this.serviceMap.set('zoho', zoho);
this.serviceMap.set('zendesk', zendesk);
this.serviceMap.set('pipedrive', pipedrive);
}

getService(integrationId: string): ICrmConnectionService {
const service = this.serviceMap.get(integrationId);
if (!service) {
throw new Error(
`Connection Service not found for integration ID: ${integrationId}`,
);
}
return service;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { Injectable } from '@nestjs/common';
import axios from 'axios';
import { PrismaService } from '@@core/prisma/prisma.service';
import { CallbackParams, ICrmConnectionService, RefreshParams, ZendeskOAuthResponse } from '../../types';
import {
CallbackParams,
ICrmConnectionService,
RefreshParams,
ZendeskOAuthResponse,
} from '../../types';
import { Action, handleServiceError } from '@@core/utils/errors';
import { LoggerService } from '@@core/logger/logger.service';
import { v4 as uuidv4 } from 'uuid';
Expand All @@ -18,9 +23,7 @@ export class ZendeskConnectionService implements ICrmConnectionService {
) {
this.logger.setContext(ZendeskConnectionService.name);
}
async handleCallback(
opts: CallbackParams
) {
async handleCallback(opts: CallbackParams) {
try {
const { linkedUserId, projectId, code } = opts;
const isNotUnique = await this.prisma.connections.findFirst({
Expand Down Expand Up @@ -105,7 +108,7 @@ export class ZendeskConnectionService implements ICrmConnectionService {
}
async handleTokenRefresh(opts: RefreshParams) {
try {
const {connectionId, refreshToken} = opts;
const { connectionId, refreshToken } = opts;
const formData = new URLSearchParams({
grant_type: 'refresh_token',
refresh_token: this.cryptoService.decrypt(refreshToken),
Expand Down
Loading

0 comments on commit 45fc51a

Please sign in to comment.