Skip to content

Commit

Permalink
Merge branch 'develop' into fix.pinterestTag_typecasting
Browse files Browse the repository at this point in the history
  • Loading branch information
ItsSudip authored Nov 15, 2024
2 parents cfa5c04 + 3d7db73 commit aeb291b
Show file tree
Hide file tree
Showing 27 changed files with 626 additions and 2,645 deletions.
10 changes: 3 additions & 7 deletions src/util/fetchDestinationHandlers.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
import * as V0MarketoBulkUploadFileUpload from '../v0/destinations/marketo_bulk_upload/fileUpload';
import * as V0MarketoBulkUploadPollStatus from '../v0/destinations/marketo_bulk_upload/poll';
import * as V0MarketoBulkUploadJobStatus from '../v0/destinations/marketo_bulk_upload/fetchJobStatus';

const fileUploadHandlers = {
v0: {
marketo_bulk_upload: V0MarketoBulkUploadFileUpload,
marketo_bulk_upload: undefined,
},
};

const pollStatusHandlers = {
v0: {
marketo_bulk_upload: V0MarketoBulkUploadPollStatus,
marketo_bulk_upload: undefined,
},
};

const jobStatusHandlers = {
v0: {
marketo_bulk_upload: V0MarketoBulkUploadJobStatus,
marketo_bulk_upload: undefined,
},
};

Expand Down
31 changes: 26 additions & 5 deletions src/v0/destinations/gainsight_px/config.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,27 @@
const { getMappingConfig } = require('../../util');

const BASE_ENDPOINT = 'https://api.aptrinsic.com/v1';
const ENDPOINTS = {
USERS_ENDPOINT: `${BASE_ENDPOINT}/users`,
CUSTOM_EVENTS_ENDPOINT: `${BASE_ENDPOINT}/events/custom`,
ACCOUNTS_ENDPOINT: `${BASE_ENDPOINT}/accounts`,
const BASE_EU_ENDPOINT = 'https://api-eu.aptrinsic.com/v1';
const BASE_US2_ENDPOINT = 'https://api-us2.aptrinsic.com/v1';

const getBaseEndpoint = (Config) => {
const { dataCenter } = Config;
switch (dataCenter) {
case 'EU':
return BASE_EU_ENDPOINT;
case 'US2':
return BASE_US2_ENDPOINT;
default:
return BASE_ENDPOINT;
}
};

const getUsersEndpoint = (Config) => `${getBaseEndpoint(Config)}/users`;

const getCustomEventsEndpoint = (Config) => `${getBaseEndpoint(Config)}/events/custom`;

const getAccountsEndpoint = (Config) => `${getBaseEndpoint(Config)}/accounts`;

const CONFIG_CATEGORIES = {
IDENTIFY: { type: 'identify', name: 'GainsightPX_Identify' },
TRACK: { type: 'track', name: 'GainsightPX_Track' },
Expand Down Expand Up @@ -79,10 +94,16 @@ const ACCOUNT_EXCLUSION_FIELDS = [
];

module.exports = {
ENDPOINTS,
USER_EXCLUSION_FIELDS,
ACCOUNT_EXCLUSION_FIELDS,
identifyMapping: MAPPING_CONFIG[CONFIG_CATEGORIES.IDENTIFY.name],
trackMapping: MAPPING_CONFIG[CONFIG_CATEGORIES.TRACK.name],
groupMapping: MAPPING_CONFIG[CONFIG_CATEGORIES.GROUP.name],
getUsersEndpoint,
getCustomEventsEndpoint,
getAccountsEndpoint,
BASE_ENDPOINT,
BASE_EU_ENDPOINT,
BASE_US2_ENDPOINT,
getBaseEndpoint,
};
27 changes: 27 additions & 0 deletions src/v0/destinations/gainsight_px/config.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const { BASE_ENDPOINT, BASE_EU_ENDPOINT, BASE_US2_ENDPOINT, getBaseEndpoint } = require('./config');

describe('getBaseEndpoint method test', () => {
it('Should return BASE_ENDPOINT when destination.Config.dataCenter is not "EU" or "US2"', () => {
const Config = {
dataCenter: 'US',
};
const result = getBaseEndpoint(Config);
expect(result).toBe(BASE_ENDPOINT);
});

it('Should return BASE_EU_ENDPOINT when destination.Config.dataCenter is "EU"', () => {
const Config = {
dataCenter: 'EU',
};
const result = getBaseEndpoint(Config);
expect(result).toBe(BASE_EU_ENDPOINT);
});

it('Should return BASE_US2_ENDPOINT when destination.Config.dataCenter is "US2"', () => {
const Config = {
dataCenter: 'US2',
};
const result = getBaseEndpoint(Config);
expect(result).toBe(BASE_US2_ENDPOINT);
});
});
13 changes: 7 additions & 6 deletions src/v0/destinations/gainsight_px/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,13 @@ const {
formatEventProps,
} = require('./util');
const {
ENDPOINTS,
USER_EXCLUSION_FIELDS,
ACCOUNT_EXCLUSION_FIELDS,
trackMapping,
groupMapping,
identifyMapping,
getUsersEndpoint,
getCustomEventsEndpoint,
} = require('./config');
const { JSON_MIME_TYPE } = require('../../util/constant');

Expand Down Expand Up @@ -92,15 +93,15 @@ const identifyResponseBuilder = async (message, { Config }, metadata) => {
if (isUserPresent) {
// update user
response.method = defaultPutRequestConfig.requestMethod;
response.endpoint = `${ENDPOINTS.USERS_ENDPOINT}/${userId}`;
response.endpoint = `${getUsersEndpoint(Config)}/${userId}`;
response.body.JSON = removeUndefinedAndNullValues(payload);
return response;
}

// create new user
payload.identifyId = userId;
response.method = defaultPostRequestConfig.requestMethod;
response.endpoint = ENDPOINTS.USERS_ENDPOINT;
response.endpoint = getUsersEndpoint(Config);
response.body.JSON = removeUndefinedAndNullValues(payload);
return response;
};
Expand Down Expand Up @@ -162,7 +163,7 @@ const newGroupResponseBuilder = async (message, { Config }, metadata) => {
'X-APTRINSIC-API-KEY': Config.apiKey,
'Content-Type': JSON_MIME_TYPE,
};
response.endpoint = `${ENDPOINTS.USERS_ENDPOINT}/${userId}`;
response.endpoint = `${getUsersEndpoint(Config)}/${userId}`;
response.body.JSON = {
accountId: groupId,
};
Expand Down Expand Up @@ -230,7 +231,7 @@ const groupResponseBuilder = async (message, { Config }, metadata) => {
'X-APTRINSIC-API-KEY': Config.apiKey,
'Content-Type': JSON_MIME_TYPE,
};
response.endpoint = `${ENDPOINTS.USERS_ENDPOINT}/${userId}`;
response.endpoint = `${getUsersEndpoint(Config)}/${userId}`;
response.body.JSON = {
accountId: groupId,
};
Expand Down Expand Up @@ -271,7 +272,7 @@ const trackResponseBuilder = (message, { Config }) => {
'X-APTRINSIC-API-KEY': Config.apiKey,
'Content-Type': JSON_MIME_TYPE,
};
response.endpoint = ENDPOINTS.CUSTOM_EVENTS_ENDPOINT;
response.endpoint = getCustomEventsEndpoint(Config);
return response;
};

Expand Down
10 changes: 5 additions & 5 deletions src/v0/destinations/gainsight_px/util.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const { NetworkError } = require('@rudderstack/integrations-lib');
const { ENDPOINTS } = require('./config');
const tags = require('../../util/tags');
const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils');
const { JSON_MIME_TYPE } = require('../../util/constant');
const { handleHttpRequest } = require('../../../adapters/network');
const { getUsersEndpoint, getAccountsEndpoint } = require('./config');

const handleErrorResponse = (error, customErrMessage, expectedErrStatus, defaultStatus = 400) => {
let destResp;
Expand Down Expand Up @@ -38,10 +38,10 @@ const handleErrorResponse = (error, customErrMessage, expectedErrStatus, default
* @returns
*/
const objectExists = async (id, Config, objectType, metadata) => {
let url = `${ENDPOINTS.USERS_ENDPOINT}/${id}`;
let url = `${getUsersEndpoint(Config)}/${id}`;

if (objectType === 'account') {
url = `${ENDPOINTS.ACCOUNTS_ENDPOINT}/${id}`;
url = `${getAccountsEndpoint(Config)}/${id}`;
}
const { httpResponse: res } = await handleHttpRequest(
'get',
Expand Down Expand Up @@ -70,7 +70,7 @@ const objectExists = async (id, Config, objectType, metadata) => {
const createAccount = async (payload, Config, metadata) => {
const { httpResponse: res } = await handleHttpRequest(
'post',
ENDPOINTS.ACCOUNTS_ENDPOINT,
getAccountsEndpoint(Config),
payload,
{
headers: {
Expand All @@ -96,7 +96,7 @@ const createAccount = async (payload, Config, metadata) => {
const updateAccount = async (accountId, payload, Config, metadata) => {
const { httpResponse: res } = await handleHttpRequest(
'put',
`${ENDPOINTS.ACCOUNTS_ENDPOINT}/${accountId}`,
`${getAccountsEndpoint(Config)}/${accountId}`,
payload,
{
headers: {
Expand Down
7 changes: 7 additions & 0 deletions src/v0/destinations/intercom_v2/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ const ApiVersions = {
v2: '2.10',
};

const RecordAction = {
INSERT: 'insert',
UPDATE: 'update',
DELETE: 'delete',
};

const ConfigCategory = {
IDENTIFY: {
name: 'IntercomIdentifyConfig',
Expand All @@ -25,4 +31,5 @@ module.exports = {
ConfigCategory,
MappingConfig,
ApiVersions,
RecordAction,
};
51 changes: 47 additions & 4 deletions src/v0/destinations/intercom_v2/transform.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { InstrumentationError } = require('@rudderstack/integrations-lib');
const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib');
const {
handleRtTfSingleEventError,
getSuccessRespEvents,
Expand All @@ -17,13 +17,14 @@ const {
addOrUpdateTagsToCompany,
getStatusCode,
getBaseEndpoint,
getRecordAction,
} = require('./utils');
const {
getName,
filterCustomAttributes,
addMetadataToPayload,
} = require('../../../cdk/v2/destinations/intercom/utils');
const { MappingConfig, ConfigCategory } = require('./config');
const { MappingConfig, ConfigCategory, RecordAction } = require('./config');

const transformIdentifyPayload = (event) => {
const { message, destination } = event;
Expand All @@ -38,7 +39,7 @@ const transformIdentifyPayload = (event) => {
}
payload.name = getName(message);
payload.custom_attributes = message.traits || message.context.traits || {};
payload.custom_attributes = filterCustomAttributes(payload, 'user', destination);
payload.custom_attributes = filterCustomAttributes(payload, 'user', destination, message);
return payload;
};

Expand Down Expand Up @@ -66,7 +67,7 @@ const transformGroupPayload = (event) => {
const category = ConfigCategory.GROUP;
const payload = constructPayload(message, MappingConfig[category.name]);
payload.custom_attributes = message.traits || message.context.traits || {};
payload.custom_attributes = filterCustomAttributes(payload, 'company', destination);
payload.custom_attributes = filterCustomAttributes(payload, 'company', destination, message);
return payload;
};

Expand Down Expand Up @@ -131,6 +132,45 @@ const constructGroupResponse = async (event) => {
return getResponse(method, endpoint, headers, finalPayload);
};

const constructRecordResponse = async (event) => {
const { message, destination, metadata } = event;
const { identifiers, fields } = message;

let method = 'POST';
let endpoint = `${getBaseEndpoint(destination)}/contacts`;
let payload = {};

const action = getRecordAction(message);
const contactId = await searchContact(event);

if ((action === RecordAction.UPDATE || action === RecordAction.DELETE) && !contactId) {
throw new ConfigurationError('Contact is not present. Aborting.');
}

switch (action) {
case RecordAction.INSERT:
payload = { ...identifiers, ...fields };
if (contactId) {
endpoint += `/${contactId}`;
payload = { ...fields };
method = 'PUT';
}
break;
case RecordAction.UPDATE:
endpoint += `/${contactId}`;
payload = { ...fields };
method = 'PUT';
break;
case RecordAction.DELETE:
endpoint += `/${contactId}`;
method = 'DELETE';
break;
default:
throw new InstrumentationError(`action ${action} is not supported.`);
}
return getResponse(method, endpoint, getHeaders(metadata), payload);
};

const processEvent = async (event) => {
const { message } = event;
const messageType = getEventType(message);
Expand All @@ -145,6 +185,9 @@ const processEvent = async (event) => {
case EventType.GROUP:
response = await constructGroupResponse(event);
break;
case EventType.RECORD:
response = constructRecordResponse(event);
break;
default:
throw new InstrumentationError(`message type ${messageType} is not supported.`);
}
Expand Down
25 changes: 21 additions & 4 deletions src/v0/destinations/intercom_v2/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ const { getAccessToken } = require('../../util');
const { ApiVersions, destType } = require('./config');
const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils');

const getRecordAction = (message) => message?.action?.toLowerCase();

/**
* method to handle error during api call
* ref docs: https://developers.intercom.com/docs/references/rest-api/errors/http-responses/
Expand Down Expand Up @@ -99,11 +101,25 @@ const getResponse = (method, endpoint, headers, payload) => {

const searchContact = async (event) => {
const { message, destination, metadata } = event;
const lookupField = getLookUpField(message);
let lookupFieldValue = getFieldValueFromMessage(message, lookupField);
if (!lookupFieldValue) {
lookupFieldValue = message?.context?.traits?.[lookupField];

const extractLookupFieldAndValue = () => {
const messageType = getEventType(message);
if (messageType === EventType.RECORD) {
const { identifiers } = message;
return Object.entries(identifiers || {})[0] || [null, null];
}
const lookupField = getLookUpField(message);
const lookupFieldValue =
getFieldValueFromMessage(message, lookupField) || message?.context?.traits?.[lookupField];
return [lookupField, lookupFieldValue];
};

const [lookupField, lookupFieldValue] = extractLookupFieldAndValue();

if (!lookupField || !lookupFieldValue) {
throw new InstrumentationError('Missing lookup field or lookup field value for searchContact');
}

const data = JSON.stringify({
query: {
operator: 'AND',
Expand Down Expand Up @@ -329,4 +345,5 @@ module.exports = {
attachContactToCompany,
addOrUpdateTagsToCompany,
getBaseEndpoint,
getRecordAction,
};
Loading

0 comments on commit aeb291b

Please sign in to comment.