Skip to content

Commit

Permalink
Merge branch 'develop' into resolve-vulnerabilities
Browse files Browse the repository at this point in the history
  • Loading branch information
sandeepdsvs authored Apr 1, 2024
2 parents 7ae44ff + eb7b197 commit 0c7c67f
Show file tree
Hide file tree
Showing 60 changed files with 5,919 additions and 176 deletions.
30 changes: 30 additions & 0 deletions src/cdk/v2/destinations/bloomreach/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { getMappingConfig } from '../../../../v0/util';

export const CUSTOMER_COMMAND = 'customers';
export const CUSTOMER_EVENT_COMMAND = 'customers/events';
export const MAX_BATCH_SIZE = 50;

// ref:- https://documentation.bloomreach.com/engagement/reference/batch-commands-2
export const getBatchEndpoint = (apiBaseUrl: string, projectToken: string): string =>
`${apiBaseUrl}/track/v2/projects/${projectToken}/batch`;

const CONFIG_CATEGORIES = {
CUSTOMER_PROPERTIES_CONFIG: { name: 'BloomreachCustomerPropertiesConfig' },
};
const MAPPING_CONFIG = getMappingConfig(CONFIG_CATEGORIES, __dirname);
export const EXCLUSION_FIELDS: string[] = [
'email',
'firstName',
'firstname',
'first_name',
'lastName',
'lastname',
'last_name',
'name',
'phone',
'city',
'birthday',
'country',
];
export const CUSTOMER_PROPERTIES_CONFIG =
MAPPING_CONFIG[CONFIG_CATEGORIES.CUSTOMER_PROPERTIES_CONFIG.name];
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
[
{
"destKey": "first_name",
"sourceKeys": "firstName",
"sourceFromGenericMap": true
},
{
"destKey": "last_name",
"sourceKeys": "lastName",
"sourceFromGenericMap": true
},
{
"destKey": "email",
"sourceKeys": "emailOnly",
"sourceFromGenericMap": true
},
{
"destKey": "phone",
"sourceKeys": "phone",
"sourceFromGenericMap": true
},
{
"destKey": "city",
"sourceKeys": "city",
"sourceFromGenericMap": true
},
{
"destKey": "country",
"sourceKeys": ["traits.address.country", "context.traits.address.country"]
},
{
"destKey": "birthday",
"sourceKeys": "birthday",
"sourceFromGenericMap": true
}
]
119 changes: 119 additions & 0 deletions src/cdk/v2/destinations/bloomreach/procWorkflow.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
bindings:
- name: EventType
path: ../../../../constants
- path: ../../bindings/jsontemplate
- name: defaultRequestConfig
path: ../../../../v0/util
- name: toUnixTimestamp
path: ../../../../v0/util
- name: base64Convertor
path: ../../../../v0/util
- name: removeUndefinedAndNullValues
path: ../../../../v0/util
- name: generateExclusionList
path: ../../../../v0/util
- name: extractCustomFields
path: ../../../../v0/util
- name: constructPayload
path: ../../../../v0/util
- path: ./utils
- path: ./config

steps:
- name: messageType
template: |
$.context.messageType = .message.type.toLowerCase();
- name: validateInput
template: |
let messageType = $.context.messageType;
$.assert(messageType, "message Type is not present. Aborting");
$.assert(messageType in {{$.EventType.([.IDENTIFY,.TRACK,.PAGE,.SCREEN])}}, "message type " + messageType + " is not supported");
$.assertConfig(.destination.Config.apiBaseUrl, "API Base URL is not present. Aborting");
$.assertConfig(.destination.Config.apiKey, "API Key is not present . Aborting");
$.assertConfig(.destination.Config.apiSecret, "API Secret is not present. Aborting");
$.assertConfig(.destination.Config.projectToken, "Project Token is not present. Aborting");
$.assertConfig(.destination.Config.hardID, "Hard ID is not present. Aborting");
$.assertConfig(.destination.Config.softID, "Soft ID is not present. Aborting");
$.assert(.message.timestamp ?? .message.originalTimestamp, "Timestamp is not present. Aborting");
const userId = .message.().(
{{{{$.getGenericPaths("userIdOnly")}}}};
);
$.assert(userId ?? .message.anonymousId, "Either one of userId or anonymousId is required. Aborting");
- name: prepareIdentifyPayload
condition: $.context.messageType === {{$.EventType.IDENTIFY}}
template: |
const customerIDs = $.prepareCustomerIDs(.message, .destination);
const customerProperties = $.constructPayload(.message, $.CUSTOMER_PROPERTIES_CONFIG);
const extraCustomerProperties = $.extractCustomFields(.message, {}, ['traits', 'context.traits'], $.EXCLUSION_FIELDS);
const properties = {
...customerProperties,
...extraCustomerProperties
}
const data = .message.().({
"customer_ids": customerIDs,
"update_timestamp": $.toUnixTimestamp({{{{$.getGenericPaths("timestamp")}}}}),
properties
});
$.context.payload = $.removeUndefinedAndNullValues({name: $.CUSTOMER_COMMAND, data})
- name: prepareEventName
steps:
- name: pageEventName
condition: $.context.messageType === {{$.EventType.PAGE}}
template: |
const category = .message.category ?? .message.properties.category;
const name = .message.name || .message.properties.name;
const eventNameArray = ["Viewed"];
category ? eventNameArray.push(category);
name ? eventNameArray.push(name);
eventNameArray.push("Page");
$.context.event = eventNameArray.join(" ");
- name: screenEventName
condition: $.context.messageType === {{$.EventType.SCREEN}}
template: |
const category = .message.category ?? .message.properties.category;
const name = .message.name || .message.properties.name;
const eventNameArray = ["Viewed"];
category ? eventNameArray.push(category);
name ? eventNameArray.push(name);
eventNameArray.push("Screen");
$.context.event = eventNameArray.join(" ");
- name: trackEventName
condition: $.context.messageType === {{$.EventType.TRACK}}
template: |
$.assert(.message.event, "Event name is required. Aborting");
$.context.event = .message.event
- name: prepareTrackPageScreenPayload
condition: $.context.messageType !== {{$.EventType.IDENTIFY}}
template: |
const customerIDs = $.prepareCustomerIDs(.message, .destination);
const data = .message.().({
"customer_ids": customerIDs,
"timestamp": $.toUnixTimestamp({{{{$.getGenericPaths("timestamp")}}}}),
"properties": .properties,
"event_type": $.context.event,
});
$.context.payload = $.removeUndefinedAndNullValues({name: $.CUSTOMER_EVENT_COMMAND, data})
- name: buildResponse
description: In batchMode we return payload directly
condition: $.batchMode
template: |
$.context.payload
else:
name: buildResponseForProcessTransformation
template: |
const response = $.defaultRequestConfig();
response.body.JSON = $.context.payload;
response.endpoint = $.getBatchEndpoint(.destination.Config.apiBaseUrl, .destination.Config.projectToken);
response.method = "POST";
response.headers = {
"Content-Type": "application/json",
"Authorization": "Basic " + $.base64Convertor(.destination.Config.apiKey + ":" + .destination.Config.apiSecret)
}
response;
76 changes: 76 additions & 0 deletions src/cdk/v2/destinations/bloomreach/rtWorkflow.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
bindings:
- name: handleRtTfSingleEventError
path: ../../../../v0/util/index
- path: ./utils
exportAll: true
- name: base64Convertor
path: ../../../../v0/util
- name: toUnixTimestamp
path: ../../../../v0/util
- name: BatchUtils
path: '@rudderstack/workflow-engine'
- path: ./config

steps:
- name: validateInput
template: |
$.assert(Array.isArray(^) && ^.length > 0, "Invalid event array")
- name: transform
externalWorkflow:
path: ./procWorkflow.yaml
bindings:
- name: batchMode
value: true
loopOverInput: true

- name: successfulEvents
template: |
$.outputs.transform#idx.output.({
"batchedRequest": .,
"batched": false,
"destination": ^[idx].destination,
"metadata": ^[idx].metadata,
"statusCode": 200
})[]
- name: failedEvents
template: |
$.outputs.transform#idx.error.(
$.handleRtTfSingleEventError(^[idx], .originalError ?? ., {})
)[]
- name: batchSuccessfulEvents
description: Batches the successfulEvents
template: |
let batches = $.BatchUtils.chunkArrayBySizeAndLength(
$.outputs.successfulEvents, {maxItems: $.MAX_BATCH_SIZE}).items;
batches@batch.({
"batchedRequest": {
"body": {
"JSON": {"commands": ~r batch.batchedRequest[]},
"JSON_ARRAY": {},
"XML": {},
"FORM": {}
},
"version": "1",
"type": "REST",
"method": "POST",
"endpoint": batch[0].destination.Config.().($.getBatchEndpoint(.apiBaseUrl, .projectToken)),
"headers": batch[0].destination.Config.().({
"Content-Type": "application/json",
"Authorization": "Basic " + $.base64Convertor(.apiKey + ":" + .apiSecret)
}),
"params": {},
"files": {}
},
"metadata": ~r batch.metadata[],
"batched": true,
"statusCode": 200,
"destination": batch[0].destination
})[];
- name: finalPayload
template: |
[...$.outputs.batchSuccessfulEvents, ...$.outputs.failedEvents]
31 changes: 31 additions & 0 deletions src/cdk/v2/destinations/bloomreach/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { isObject, isEmptyObject, getIntegrationsObj } from '../../../../v0/util';
import { RudderMessage, Destination } from '../../../../types';

const getCustomerIDsFromIntegrationObject = (message: RudderMessage): any => {
const integrationObj = getIntegrationsObj(message, 'bloomreach' as any) || {};
const { hardID, softID } = integrationObj;
const customerIDs = {};

if (isObject(hardID) && !isEmptyObject(hardID)) {
Object.keys(hardID).forEach((id) => {
customerIDs[id] = hardID[id];
});
}

if (isObject(softID) && !isEmptyObject(softID)) {
Object.keys(softID).forEach((id) => {
customerIDs[id] = softID[id];
});
}

return customerIDs;
};

export const prepareCustomerIDs = (message: RudderMessage, destination: Destination): any => {
const customerIDs = {
[destination.Config.hardID]: message.userId,
[destination.Config.softID]: message.anonymousId,
...getCustomerIDsFromIntegrationObject(message),
};
return customerIDs;
};
26 changes: 26 additions & 0 deletions src/cdk/v2/destinations/linkedin_ads/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const { getMappingConfig } = require('../../../../v0/util');

// ref : https://learn.microsoft.com/en-us/linkedin/marketing/integrations/ads-reporting/conversions-api?view=li-lms-2024-02&tabs=http#adding-multiple-conversion-events-in-a-batch
const BATCH_ENDPOINT = 'https://api.linkedin.com/rest/conversionEvents';
const API_HEADER_METHOD = 'BATCH_CREATE';
const API_VERSION = '202402'; // yyyymm format
const API_PROTOCOL_VERSION = '2.0.0';

const CONFIG_CATEGORIES = {
USER_INFO: {
name: 'linkedinUserInfoConfig',
type: 'user',
},
};

const MAPPING_CONFIG = getMappingConfig(CONFIG_CATEGORIES, __dirname);

module.exports = {
MAX_BATCH_SIZE: 5000,
BATCH_ENDPOINT,
API_HEADER_METHOD,
API_VERSION,
API_PROTOCOL_VERSION,
CONFIG_CATEGORIES,
MAPPING_CONFIG,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[
{
"destKey": "firstName",
"sourceKeys": "firstName",
"required": false,
"sourceFromGenericMap": true
},
{
"destKey": "lastName",
"sourceKeys": "lastName",
"required": false,
"sourceFromGenericMap": true
},
{
"destKey": "title",
"sourceKeys": "title",
"required": false,
"sourceFromGenericMap": true
},
{
"destKey": "companyName",
"sourceKeys": "context.traits.companyName",
"required": false
},
{
"destKey": "countryCode",
"sourceKeys": "countryCode",
"sourceFromGenericMap": true,
"required": false
}
]
Loading

0 comments on commit 0c7c67f

Please sign in to comment.