From 3c4cd0816f160d4392f5ca81781a9f8a7fdc5fff Mon Sep 17 00:00:00 2001 From: David Meiklejohn Date: Tue, 12 Nov 2024 11:59:03 +1000 Subject: [PATCH] feat: new destination for accoil analytics --- .../accoil_analytics/procWorkflow.yaml | 123 ++++ .../accoil_analytics/rtWorkflow.yaml | 33 + .../v2/destinations/accoil_analytics/utils.js | 10 + .../accoil_analytics/processor/data.ts | 577 ++++++++++++++++++ .../accoil_analytics/router/data.ts | 219 +++++++ 5 files changed, 962 insertions(+) create mode 100644 src/cdk/v2/destinations/accoil_analytics/procWorkflow.yaml create mode 100644 src/cdk/v2/destinations/accoil_analytics/rtWorkflow.yaml create mode 100644 src/cdk/v2/destinations/accoil_analytics/utils.js create mode 100644 test/integrations/destinations/accoil_analytics/processor/data.ts create mode 100644 test/integrations/destinations/accoil_analytics/router/data.ts diff --git a/src/cdk/v2/destinations/accoil_analytics/procWorkflow.yaml b/src/cdk/v2/destinations/accoil_analytics/procWorkflow.yaml new file mode 100644 index 0000000000..ed6f1c44c1 --- /dev/null +++ b/src/cdk/v2/destinations/accoil_analytics/procWorkflow.yaml @@ -0,0 +1,123 @@ +bindings: + - name: EventType + path: ../../../../constants + - path: ../../bindings/jsontemplate + exportAll: true + - name: removeUndefinedAndNullValues + path: ../../../../v0/util + - name: base64Convertor + path: ../../../../v0/util + - path: ./utils + +steps: + - name: validateInput + template: | + $.assert(.message.type, "message type is not present. Aborting message."); + $.assert(.message.type in {{$.EventType.([.TRACK, .PAGE, .SCREEN, .IDENTIFY, .GROUP])}}, + "message type " + .message.type + " is not supported"); + $.assertConfig(.destination.Config.apiKey, "apiKey must be supplied in destination config"); + +# Note our auth does not require a password in basic auth just the string "key:" + - name: prepareContext + template: | + $.context.messageType = .message.type.toLowerCase(); + $.context.payload = { + "type": $.context.messageType + }; + $.context.finalHeaders = { + "authorization": "Basic " + $.base64Convertor(.destination.Config.apiKey + ":"), + "content-type": "application/json" + }; + $.context.endpoint = $.endpointUrl(.destination.Config.apiKey); + + - name: trackPayload + condition: $.context.messageType == {{$.EventType.TRACK}} + template: | + $.context.payload.event = .message.event; + $.context.payload.userId = .message.().({{{{$.getGenericPaths("userId")}}}}) + $.context.payload.timestamp = .message.().({{{{$.getGenericPaths("timestamp")}}}}) + + - name: pagePayload + condition: $.context.messageType == {{$.EventType.PAGE}} + template: | + $.context.payload.userId = .message.().({{{{$.getGenericPaths("userId")}}}}); + $.context.payload.name = .message.name; + $.context.payload.timestamp = .message.().({{{{$.getGenericPaths("timestamp")}}}}); + + - name: screenPayload + condition: $.context.messageType == {{$.EventType.SCREEN}} + template: | + $.context.payload.userId = .message.().({{{{$.getGenericPaths("userId")}}}}); + $.context.payload.name = .message.name; + $.context.payload.timestamp = .message.().({{{{$.getGenericPaths("timestamp")}}}}); + + - name: identifyPayload + condition: $.context.messageType == {{$.EventType.IDENTIFY}} + template: | + $.context.payload.userId = .message.().({{{{$.getGenericPaths("userId")}}}}); + $.context.payload.traits = .message.traits ?? .message.context.traits; + $.context.payload.timestamp = .message.().({{{{$.getGenericPaths("timestamp")}}}}); + + - name: groupPayload + condition: $.context.messageType == {{$.EventType.GROUP}} + template: | + $.context.payload.anonymousId = .message.anonymousId; + $.context.payload.userId = .message.().({{{{$.getGenericPaths("userId")}}}}); + $.context.payload.groupId = .message.groupId; + $.context.payload.timestamp = .message.().({{{{$.getGenericPaths("timestamp")}}}}); + $.context.payload.traits = .message.traits ?? .message.context.traits; + + - name: validateTimestamp + template: | + $.assert($.context.payload.timestamp, "timestamp is required for all calls") + + - name: validateTrackPayload + condition: $.context.messageType == {{$.EventType.TRACK}} + template: | + $.assert($.context.payload.event, "event is required for track call") + $.assert($.context.payload.userId, "userId is required for track call") + + - name: validatePagePayload + condition: $.context.messageType == {{$.EventType.PAGE}} + template: | + $.assert($.context.payload.name, "name is required for page call") + $.assert($.context.payload.userId, "userId is required for page call") + + - name: validateScreenPayload + condition: $.context.messageType == {{$.EventType.SCREEN}} + template: | + $.assert($.context.payload.name, "name is required for screen call") + $.assert($.context.payload.userId, "userId is required for screen call") + + - name: validateIdentifyPayload + condition: $.context.messageType == {{$.EventType.IDENTIFY}} + template: | + $.assert($.context.payload.userId, "userId is required for identify call") + + - name: validateGroupPayload + condition: $.context.messageType == {{$.EventType.GROUP}} + template: | + $.assert($.context.payload.userId, "userId is required for group call") + $.assert($.context.payload.groupId, "groupId is required for group call") + + - name: cleanPayload + template: | + $.context.payload = $.removeUndefinedAndNullValues($.context.payload); + + - name: buildResponseForProcessTransformation + template: | + $.context.payload.({ + "body": { + "JSON": ., + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": $.context.endpoint, + "headers": $.context.finalHeaders, + "params": {}, + "files": {} + }) \ No newline at end of file diff --git a/src/cdk/v2/destinations/accoil_analytics/rtWorkflow.yaml b/src/cdk/v2/destinations/accoil_analytics/rtWorkflow.yaml new file mode 100644 index 0000000000..88cb78352f --- /dev/null +++ b/src/cdk/v2/destinations/accoil_analytics/rtWorkflow.yaml @@ -0,0 +1,33 @@ +bindings: + - name: handleRtTfSingleEventError + path: ../../../../v0/util/index + +steps: + - name: validateInput + template: | + $.assert(Array.isArray(^) && ^.length > 0, "Invalid event array") + + - name: transform + externalWorkflow: + path: ./procWorkflow.yaml + 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: finalPayload + template: | + [...$.outputs.failedEvents, ...$.outputs.successfulEvents] diff --git a/src/cdk/v2/destinations/accoil_analytics/utils.js b/src/cdk/v2/destinations/accoil_analytics/utils.js new file mode 100644 index 0000000000..7a6c63d4ce --- /dev/null +++ b/src/cdk/v2/destinations/accoil_analytics/utils.js @@ -0,0 +1,10 @@ +const stgRegex = new RegExp(/^stg_/, 'i'); + +const endpointUrl = (apiKey) => { + const staging = stgRegex.test(apiKey); + return staging ? 'https://instaging.accoil.com/segment' : 'https://in.accoil.com/segment'; +}; + +module.exports = { + endpointUrl, +}; \ No newline at end of file diff --git a/test/integrations/destinations/accoil_analytics/processor/data.ts b/test/integrations/destinations/accoil_analytics/processor/data.ts new file mode 100644 index 0000000000..dd11757b8d --- /dev/null +++ b/test/integrations/destinations/accoil_analytics/processor/data.ts @@ -0,0 +1,577 @@ +const apiKeyProd = 'api_key'; +const apiKeyStg = 'stg_api_key'; + +const endpointProd = 'https://in.accoil.com/segment'; +const endpointStg = 'https://instaging.accoil.com/segment'; + +const expectedHeadersProd = { + 'authorization': 'Basic YXBpX2tleTo=', + 'content-type': 'application/json', +}; +const expectedHeadersStg = { + 'authorization': 'Basic c3RnX2FwaV9rZXk6', + 'content-type': 'application/json', +}; + +type Destination = { + Config: { + apiKey: string; + } + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + } + } +} + +const destination = (apiKey: string): Destination => { + return { + Config: { + apiKey: apiKey, + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }; +}; + +const destinationProd = destination(apiKeyProd); + +const destinationStg = destination(apiKeyStg); + +const metadata = { + destinationId: 'destId', + workspaceId: 'wspId', +}; + +const successfulData = ( + options: { + description: string, + destination: Destination, + message: Record, + endpoint: string, + response: Record, + expectedHeaders: Record + }, + expectedStatusCode: number = 200 +) => { + return { + name: 'accoil_analytics', + description: options.description, + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: options.destination, + message: options.message, + metadata: metadata, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + FORM: {}, + JSON_ARRAY: {}, + XML: {}, + JSON: options.response, + }, + endpoint: options.endpoint, + files: {}, + params: {}, + type: 'REST', + version: '1', + method: 'POST', + userId: '', + headers: options.expectedHeaders, + }, + statusCode: expectedStatusCode, + metadata: metadata, + }, + ], + }, + }, + }; +}; + +const failureData = ( + options: { + description: string, + body: [Record], + error: string, + errorCategory: string, + errorType: string, + }, + expectedStatusCode: number = 400 +) => { + return { + name: 'accoil_analytics', + description: options.description, + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: options.body, + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: expectedStatusCode, + error: options.error, + statTags: { + errorCategory: options.errorCategory, + errorType: options.errorType, + destType: 'ACCOIL_ANALYTICS', + module: 'destination', + implementation: 'cdkV2', + destinationId: 'destId', + workspaceId: 'wspId', + feature: 'processor', + }, + metadata: metadata, + }, + ], + }, + }, + }; +}; + +const successfulProdData = ( + options: { + description: string, + message: Record, + response: Record + }, + expectedStatusCode: number = 200 +) => { + return successfulData({ + ...options, + destination: destinationProd, + endpoint: endpointProd, + expectedHeaders: expectedHeadersProd, + }, expectedStatusCode); +}; + +const successfulStgData = ( + options: { + description: string, + message: Record, + response: Record + }, + expectedStatusCode: number = 200 +) => { + return successfulData({ + ...options, + destination: destinationStg, + endpoint: endpointStg, + expectedHeaders: expectedHeadersStg, + }, expectedStatusCode); +}; + +export const data = [ + // Successful track + successfulProdData({ + description: 'Successful track event', + message: { + userId: '1234567890', + event: 'Activated', + type: 'track', + messageId: '1873f8bd-68f7-40fc-b262-56a245f22862', + properties: { + email: 'frank@example.com' + }, + timestamp: '2024-01-23T08:35:17.562Z', + }, + response: { + type: 'track', + event: 'Activated', + userId: '1234567890', + timestamp: '2024-01-23T08:35:17.562Z', + }, + }), + // Successful identify + successfulProdData({ + description: 'Successful identify event', + message: { + userId: 'bobby', + type: 'identify', + traits: { + email: 'bobby@example.com', + name: 'Little Bobby', + role: 'admin', + createdAt: '2024-01-20T08:35:17.342Z', + accountStatus: 'trial', + }, + timestamp: '2024-01-20T08:35:17.342Z', + originalTimestamp: '2024-01-23T08:35:17.342Z', + sentAt: '2024-01-23T08:35:35.234Z', + }, + response: { + userId: 'bobby', + type: 'identify', + traits: { + email: 'bobby@example.com', + name: 'Little Bobby', + role: 'admin', + createdAt: '2024-01-20T08:35:17.342Z', + accountStatus: 'trial', + }, + timestamp: '2024-01-20T08:35:17.342Z', + }, + }), + // Successful group + successfulProdData({ + description: 'Successful group event', + message: { + userId: 'bobby', + groupId: 'bobbygroup', + type: 'group', + traits: { + name: 'Little Bobby Group', + createdAt: '2024-01-20T08:35:17.342Z', + status: 'paid', + mrr: '10.1', + plan: 'basic', + }, + timestamp: '2024-01-20T08:35:17.342Z', + originalTimestamp: '2024-01-23T08:35:17.342Z', + sentAt: '2024-01-23T08:35:35.234Z', + }, + response: { + userId: 'bobby', + groupId: 'bobbygroup', + type: 'group', + traits: { + name: 'Little Bobby Group', + createdAt: '2024-01-20T08:35:17.342Z', + status: 'paid', + mrr: '10.1', + plan: 'basic', + }, + timestamp: '2024-01-20T08:35:17.342Z', + }, + }), + // Successful page + successfulProdData({ + description: 'Successful page event', + message: { + userId: 'bobby', + type: 'page', + name: 'Account Details', + traits: { + name: 'Sub page: Configuration', + }, + timestamp: '2024-01-20T08:35:17.342Z', + originalTimestamp: '2024-01-23T08:35:17.342Z', + sentAt: '2024-01-23T08:35:35.234Z', + }, + response: { + userId: 'bobby', + type: 'page', + name: 'Account Details', + timestamp: '2024-01-20T08:35:17.342Z', + }, + }), + // Successful screen + successfulProdData({ + description: 'Successful screen event', + message: { + userId: 'bobby', + type: 'screen', + name: 'Configuration', + traits: { + account: 'Bobby Account', + }, + timestamp: '2024-01-20T08:35:17.342Z', + originalTimestamp: '2024-01-23T08:35:17.342Z', + sentAt: '2024-01-23T08:35:35.234Z', + }, + response: { + userId: 'bobby', + type: 'screen', + name: 'Configuration', + timestamp: '2024-01-20T08:35:17.342Z', + }, + }), + // Verify sending to staging environment + successfulStgData({ + description: 'Successful screen event: staging', + message: { + userId: 'bobby', + type: 'screen', + name: 'Configuration', + traits: { + account: 'Bobby Account', + }, + timestamp: '2024-01-20T08:35:17.342Z', + originalTimestamp: '2024-01-23T08:35:17.342Z', + sentAt: '2024-01-23T08:35:35.234Z', + }, + response: { + userId: 'bobby', + type: 'screen', + name: 'Configuration', + timestamp: '2024-01-20T08:35:17.342Z', + }, + }), + + // Verify checking for invalid payloads (eg no apiKey, missing parts of message) + // Global validation + failureData({ + description: 'Missing required apiKey in config', + body: [ + { + destination: { + Config: {}, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + userId: '1234567890', + event: 'Activated', + type: 'track', + messageId: '1873f8bd-68f7-40fc-b262-56a245f22862', + properties: { + email: 'frank@example.com' + }, + timestamp: '2024-01-23T08:35:17.562Z', + }, + metadata: metadata, + }, + ], + error: 'apiKey must be supplied in destination config: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: apiKey must be supplied in destination config', + errorCategory: 'dataValidation', + errorType: 'configuration', + }), + failureData({ + description: 'Missing required timestamp in payload', + body: [ + { + destination: destinationProd, + message: { + userId: '1234567890', + event: 'Activated', + type: 'track', + messageId: '1873f8bd-68f7-40fc-b262-56a245f22862', + properties: { + email: 'frank@example.com' + }, + }, + metadata: metadata, + }, + ], + error: 'timestamp is required for all calls: Workflow: procWorkflow, Step: validateTimestamp, ChildStep: undefined, OriginalError: timestamp is required for all calls', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + }), + // Track validation + failureData({ + description: 'Missing required event in track payload', + body: [ + { + destination: destinationProd, + message: { + userId: '1234567890', + type: 'track', + messageId: '1873f8bd-68f7-40fc-b262-56a245f22862', + properties: { + email: 'frank@example.com' + }, + timestamp: '2024-01-23T08:35:17.562Z', + }, + metadata: metadata, + }, + ], + error: 'event is required for track call: Workflow: procWorkflow, Step: validateTrackPayload, ChildStep: undefined, OriginalError: event is required for track call', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + }), + failureData({ + description: 'Missing required userId in track payload', + body: [ + { + destination: destinationProd, + message: { + event: 'event', + type: 'track', + messageId: '1873f8bd-68f7-40fc-b262-56a245f22862', + properties: { + email: 'frank@example.com' + }, + timestamp: '2024-01-23T08:35:17.562Z', + }, + metadata: metadata, + }, + ], + error: 'userId is required for track call: Workflow: procWorkflow, Step: validateTrackPayload, ChildStep: undefined, OriginalError: userId is required for track call', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + }), + // Page validation + failureData({ + description: 'Missing required name in page payload', + body: [ + { + destination: destinationProd, + message: { + userId: 'bobby', + type: 'page', + messageId: '1873f8bd-68f7-40fc-b262-56a245f22862', + properties: { + email: 'frank@example.com' + }, + timestamp: '2024-01-23T08:35:17.562Z', + }, + metadata: metadata, + }, + ], + error: 'name is required for page call: Workflow: procWorkflow, Step: validatePagePayload, ChildStep: undefined, OriginalError: name is required for page call', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + }), + failureData({ + description: 'Missing required userId in page payload', + body: [ + { + destination: destinationProd, + message: { + name: 'Page name', + type: 'page', + messageId: '1873f8bd-68f7-40fc-b262-56a245f22862', + properties: { + email: 'frank@example.com' + }, + timestamp: '2024-01-23T08:35:17.562Z', + }, + metadata: metadata, + }, + ], + error: 'userId is required for page call: Workflow: procWorkflow, Step: validatePagePayload, ChildStep: undefined, OriginalError: userId is required for page call', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + }), + // Validate screen + failureData({ + description: 'Missing required name in screen payload', + body: [ + { + destination: destinationProd, + message: { + userId: 'bobby', + type: 'screen', + messageId: '1873f8bd-68f7-40fc-b262-56a245f22862', + properties: { + email: 'frank@example.com' + }, + timestamp: '2024-01-23T08:35:17.562Z', + }, + metadata: metadata, + }, + ], + error: 'name is required for screen call: Workflow: procWorkflow, Step: validateScreenPayload, ChildStep: undefined, OriginalError: name is required for screen call', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + }), + failureData({ + description: 'Missing required userId in screen payload', + body: [ + { + destination: destinationProd, + message: { + name: 'screen name', + type: 'screen', + messageId: '1873f8bd-68f7-40fc-b262-56a245f22862', + properties: { + email: 'frank@example.com' + }, + timestamp: '2024-01-23T08:35:17.562Z', + }, + metadata: metadata, + }, + ], + error: 'userId is required for screen call: Workflow: procWorkflow, Step: validateScreenPayload, ChildStep: undefined, OriginalError: userId is required for screen call', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + }), + // Identify validate + failureData({ + description: 'Missing required userId in identify payload', + body: [ + { + destination: destinationProd, + message: { + type: 'identify', + messageId: '1873f8bd-68f7-40fc-b262-56a245f22862', + properties: { + email: 'frank@example.com' + }, + timestamp: '2024-01-23T08:35:17.562Z', + }, + metadata: metadata, + }, + ], + error: 'userId is required for identify call: Workflow: procWorkflow, Step: validateIdentifyPayload, ChildStep: undefined, OriginalError: userId is required for identify call', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + }), + // Group validate + failureData({ + description: 'Missing required userId in group payload', + body: [ + { + destination: destinationProd, + message: { + type: 'group', + groupId: 'group1', + messageId: '1873f8bd-68f7-40fc-b262-56a245f22862', + properties: { + email: 'frank@example.com' + }, + timestamp: '2024-01-23T08:35:17.562Z', + }, + metadata: metadata, + }, + ], + error: 'userId is required for group call: Workflow: procWorkflow, Step: validateGroupPayload, ChildStep: undefined, OriginalError: userId is required for group call', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + }), + failureData({ + description: 'Missing required groupId in group payload', + body: [ + { + destination: destinationProd, + message: { + userId: 'user', + type: 'group', + messageId: '1873f8bd-68f7-40fc-b262-56a245f22862', + properties: { + email: 'frank@example.com' + }, + timestamp: '2024-01-23T08:35:17.562Z', + }, + metadata: metadata, + }, + ], + error: 'groupId is required for group call: Workflow: procWorkflow, Step: validateGroupPayload, ChildStep: undefined, OriginalError: groupId is required for group call', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + }), +]; diff --git a/test/integrations/destinations/accoil_analytics/router/data.ts b/test/integrations/destinations/accoil_analytics/router/data.ts new file mode 100644 index 0000000000..a27f520963 --- /dev/null +++ b/test/integrations/destinations/accoil_analytics/router/data.ts @@ -0,0 +1,219 @@ +// TODO Do I need this? Do we want/can we support batch requests? We only /segment +// Does it make sense to even have this defined? + +export const data = [ + { + name: 'accoil_analytics', + description: 'Router batch request', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + destination: { + Config: { + apiKey: 'api_key', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + userId: 'user-uuid', + event: 'User Signed Up', + type: 'track', + timestamp: '2024-01-23T08:35:17.562Z', + }, + metadata: { + jobId: 1, + userId: 'u1', + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + { + destination: { + Config: { + apiKey: 'api_key', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + userId: 'user-uuid', + event: 'User Deleted account', + type: 'track', + messageId: '8bc79b03-2a5c-4615-b2da-54c0aaaaaae8', + timestamp: '2024-01-23T08:35:17.562Z', + }, + metadata: { + jobId: 2, + userId: 'u1', + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + { + destination: { + Config: { + apiKey: 'STG_api_key', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + userId: 'user-uuid', + event: 'User Deleted account', + type: 'track', + messageId: '8bc79b03-2a5c-4615-b2da-54c0aaaaaae8', + timestamp: '2024-01-23T08:35:17.562Z', + }, + metadata: { + jobId: 3, + userId: 'u1', + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + destType: 'accoil_analytics', + }, + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: [ + { + batchedRequest: { + body: { + FORM: {}, + JSON_ARRAY: {}, + XML: {}, + JSON: { + userId: 'user-uuid', + type: 'track', + event: 'User Signed Up', + timestamp: '2024-01-23T08:35:17.562Z', + }, + }, + endpoint: 'https://in.accoil.com/segment', + files: {}, + params: {}, + type: 'REST', + version: '1', + method: 'POST', + headers: { + 'authorization': 'Basic YXBpX2tleTo=', + 'content-type': 'application/json', + }, + }, + batched: false, + metadata: [{ jobId: 1, userId: 'u1', workspaceId: 'wspId', destinationId: 'destId' }], + statusCode: 200, + destination: { + Config: { + apiKey: 'api_key', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + }, + { + batchedRequest: { + body: { + FORM: {}, + JSON_ARRAY: {}, + XML: {}, + JSON: { + userId: 'user-uuid', + type: 'track', + event: 'User Deleted account', + timestamp: '2024-01-23T08:35:17.562Z', + }, + }, + endpoint: 'https://in.accoil.com/segment', + files: {}, + params: {}, + type: 'REST', + version: '1', + method: 'POST', + headers: { + 'authorization': 'Basic YXBpX2tleTo=', + 'content-type': 'application/json', + }, + }, + batched: false, + metadata: [{ jobId: 2, userId: 'u1', workspaceId: 'wspId', destinationId: 'destId' }], + statusCode: 200, + destination: { + Config: { + apiKey: 'api_key', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + }, + { + batchedRequest: { + body: { + FORM: {}, + JSON_ARRAY: {}, + XML: {}, + JSON: { + userId: 'user-uuid', + type: 'track', + event: 'User Deleted account', + timestamp: '2024-01-23T08:35:17.562Z', + }, + }, + endpoint: 'https://instaging.accoil.com/segment', + files: {}, + params: {}, + type: 'REST', + version: '1', + method: 'POST', + headers: { + 'authorization': 'Basic U1RHX2FwaV9rZXk6', + 'content-type': 'application/json', + }, + }, + batched: false, + metadata: [{ jobId: 3, userId: 'u1', workspaceId: 'wspId', destinationId: 'destId' }], + statusCode: 200, + destination: { + Config: { + apiKey: 'STG_api_key', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + }, + ], + }, + }, + }, + }, +];