Skip to content

Commit e1e6ea2

Browse files
committed
fix conflicts
1 parent 9bd27c7 commit e1e6ea2

File tree

5 files changed

+155
-303
lines changed

5 files changed

+155
-303
lines changed

packages/destination-actions/src/destinations/amazon-amc/function.ts

Lines changed: 19 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
1-
import {
2-
InvalidAuthenticationError,
3-
JSONLikeObject,
4-
MultiStatusResponse,
5-
PayloadValidationError,
6-
RequestClient
7-
} from '@segment/actions-core'
1+
import { InvalidAuthenticationError } from '@segment/actions-core'
2+
import { JSONLikeObject, MultiStatusResponse, PayloadValidationError, RequestClient } from '@segment/actions-core'
83
import { AudienceSettings, Settings } from './generated-types'
94
import type { Payload } from './syncAudiencesToDSP/generated-types'
10-
import { AudienceRecord, HashedPIIObject, RecordsResponseType } from './types'
5+
import { AudienceRecord, HashedPIIObject } from './types'
6+
import { CONSTANTS, RecordsResponseType, REGEX_EXTERNALUSERID } from './utils'
117
import { processHashing } from '../../lib/hashing-utils'
12-
import { CONSTANTS, REGEX_EXTERNALUSERID, ALPHA_NUMERIC, EMAIL_ALLOWED, NON_DIGIT, SYNC_TO } from './constants'
138
import { AMAZON_AMC_API_VERSION } from './versioning-info'
149

1510
export async function processPayload(
@@ -53,20 +48,7 @@ export async function processPayload(
5348
*/
5449
export function createPayloadToUploadRecords(payloads: Payload[], audienceSettings: AudienceSettings) {
5550
const records: AudienceRecord[] = []
56-
const [audienceId, connectionId = ''] = payloads[0].audienceId.split(':')
57-
58-
const { syncTo, advertiserId, amcInstanceId, amcAccountId, amcAccountMarketplaceId } = audienceSettings || {}
59-
60-
if ((!syncTo || syncTo === SYNC_TO.DSP) && !advertiserId) {
61-
throw new PayloadValidationError('Advertiser Id value is required when syncing an audience to DSP')
62-
}
63-
64-
if (syncTo === SYNC_TO.AMC && (!amcInstanceId || !amcAccountId || !amcAccountMarketplaceId)) {
65-
throw new PayloadValidationError(
66-
'AMC Instance Id, AMC Account Id and AMC Account Marketplace Id value are required when syncing audience to AMC'
67-
)
68-
}
69-
51+
const { audienceId } = payloads[0]
7052
payloads.forEach((payload: Payload) => {
7153
// Check if the externalUserId matches the pattern
7254
if (!REGEX_EXTERNALUSERID.test(payload.externalUserId)) {
@@ -89,9 +71,8 @@ export function createPayloadToUploadRecords(payloads: Payload[], audienceSettin
8971
}
9072

9173
return {
92-
records,
93-
audienceId,
94-
...(connectionId ? { targetResource: { connectionId } } : {})
74+
records: records,
75+
audienceId: audienceId
9576
}
9677
}
9778

@@ -113,27 +94,6 @@ function validateAndPreparePayload(
11394
return
11495
}
11596

116-
const { syncTo, advertiserId, amcInstanceId, amcAccountId, amcAccountMarketplaceId } = audienceSettings || {}
117-
118-
if ((!syncTo || syncTo === SYNC_TO.DSP) && !advertiserId) {
119-
multiStatusResponse.setErrorResponseAtIndex(originalBatchIndex, {
120-
status: 400,
121-
errortype: 'PAYLOAD_VALIDATION_FAILED',
122-
errormessage: 'Advertiser Id value is required when syncing an audience to DSP'
123-
})
124-
return
125-
}
126-
127-
if (syncTo === SYNC_TO.AMC && (!amcInstanceId || !amcAccountId || !amcAccountMarketplaceId)) {
128-
multiStatusResponse.setErrorResponseAtIndex(originalBatchIndex, {
129-
status: 400,
130-
errortype: 'PAYLOAD_VALIDATION_FAILED',
131-
errormessage:
132-
'AMC Instance Id, AMC Account Id and AMC Account Marketplace Id value are required when syncing audience to AMC'
133-
})
134-
return
135-
}
136-
13797
const hashedPII = hashedPayload(payload)
13898
const payloadRecord: AudienceRecord = {
13999
externalUserId: payload.externalUserId,
@@ -178,13 +138,10 @@ export async function processBatchPayload(
178138
return multiStatusResponse
179139
}
180140

181-
const [audienceId, connectionId = ''] = payloads[0].audienceId.split(':')
182-
183-
const payloadString = JSON.stringify({
184-
audienceId: audienceId,
185-
records: filteredPayloads,
186-
...(connectionId ? { targetResource: { connectionId } } : {})
187-
}).replace(/"audienceId":"(\d+)"/, '"audienceId":$1')
141+
const payloadString = JSON.stringify({ audienceId: payloads[0].audienceId, records: filteredPayloads }).replace(
142+
/"audienceId":"(\d+)"/,
143+
'"audienceId":$1'
144+
)
188145

189146
const response = await request<RecordsResponseType>(`${settings.region}/amc/audiences/records`, {
190147
method: 'POST',
@@ -244,17 +201,22 @@ function normalize(value: string, allowedChars: RegExp, trim = true): string {
244201
return normalized
245202
}
246203

204+
// Define allowed character patterns
205+
const alphanumeric = /[^a-z0-9]/g
206+
const emailAllowed = /[^a-z0-9.@-]/g
207+
const nonDigits = /[^\d]/g
208+
247209
// Combine city,state,firstName,lastName normalization
248210
function normalizeStandard(value: string): string {
249-
return normalize(value, ALPHA_NUMERIC)
211+
return normalize(value, alphanumeric)
250212
}
251213

252214
function normalizePhone(phone: string): string {
253-
return normalize(phone, NON_DIGIT)
215+
return normalize(phone, nonDigits)
254216
}
255217

256218
function normalizeEmail(email: string): string {
257-
return normalize(email, EMAIL_ALLOWED)
219+
return normalize(email, emailAllowed)
258220
}
259221

260222
/**

packages/destination-actions/src/destinations/amazon-amc/generated-types.ts

Lines changed: 2 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/destination-actions/src/destinations/amazon-amc/index.ts

Lines changed: 41 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
import {
22
AudienceDestinationDefinition,
33
InvalidAuthenticationError,
4-
PayloadValidationError,
4+
IntegrationError,
55
defaultValues
66
} from '@segment/actions-core'
7+
import type { RefreshTokenResponse, AmazonTestAuthenticationError } from './types'
8+
import type { Settings, AudienceSettings } from './generated-types'
79
import {
8-
RefreshTokenResponse,
9-
AmazonTestAuthenticationError,
1010
AudiencePayload,
11-
DSPTargetResource,
12-
AMCTargetResource
13-
} from './types'
14-
import type { Settings, AudienceSettings } from './generated-types'
15-
import { extractNumberAndSubstituteWithStringValue, getAuthToken } from './utils'
16-
import { SYNC_TO, REGEX_AUDIENCEID, REGEX_ADVERTISERID, TTL_MAX_VALUE } from './constants'
11+
extractNumberAndSubstituteWithStringValue,
12+
getAuthToken,
13+
REGEX_ADVERTISERID,
14+
REGEX_AUDIENCEID,
15+
TTL_MAX_VALUE
16+
} from './utils'
17+
import { AMAZON_AMC_AUTH_API_VERSION } from './versioning-info'
1718
import syncAudiencesToDSP from './syncAudiencesToDSP'
1819

1920
const destination: AudienceDestinationDefinition<Settings, AudienceSettings> = {
@@ -76,17 +77,6 @@ const destination: AudienceDestinationDefinition<Settings, AudienceSettings> = {
7677
},
7778

7879
audienceFields: {
79-
syncTo: {
80-
type: 'string',
81-
label: 'Sync To',
82-
required: false,
83-
description: 'Chose whether to sync audience to DSP or AMC. Defaults to DSP.',
84-
choices: [
85-
{ label: 'DSP', value: SYNC_TO.DSP },
86-
{ label: 'AMC', value: SYNC_TO.AMC }
87-
],
88-
default: SYNC_TO.DSP
89-
},
9080
description: {
9181
type: 'string',
9282
label: 'Description',
@@ -141,23 +131,9 @@ const destination: AudienceDestinationDefinition<Settings, AudienceSettings> = {
141131
//As per the discussion, for now taking `advertiserId` in `audienceFields` as user can create multiple audiences within a single instance of destination.
142132
advertiserId: {
143133
label: 'Advertiser ID',
144-
description: 'Advertiser ID when when syncing an Audience to Amazon Ads DSP',
145-
type: 'string'
146-
},
147-
amcInstanceId: {
148-
label: 'AMC Instance ID',
149-
description: 'AMC Instance ID used when syncing an audience to Amazon Marketing Cloud (AMC)',
150-
type: 'string'
151-
},
152-
amcAccountId: {
153-
label: 'AMC Account ID',
154-
description: 'AMC Account ID used when syncing an audience to Amazon Marketing Cloud (AMC)',
155-
type: 'string'
156-
},
157-
amcAccountMarketplaceId: {
158-
label: 'AMC Account Marketplace ID',
159-
description: 'AMC Account Marketplace ID used when syncing an audience to Amazon Marketing Cloud (AMC)',
160-
type: 'string'
134+
description: 'Advertiser Id',
135+
type: 'string',
136+
required: true
161137
}
162138
},
163139

@@ -169,115 +145,64 @@ const destination: AudienceDestinationDefinition<Settings, AudienceSettings> = {
169145
async createAudience(request, createAudienceInput) {
170146
const { audienceName, audienceSettings, settings } = createAudienceInput
171147
const endpoint = settings.region
148+
const description = audienceSettings?.description
149+
const advertiser_id = audienceSettings?.advertiserId
150+
const external_audience_id = audienceSettings?.externalAudienceId
151+
const country_code = audienceSettings?.countryCode
152+
const ttl = audienceSettings?.ttl
153+
const currency = audienceSettings?.currency
154+
const cpm_cents = audienceSettings?.cpmCents
172155

173-
const {
174-
syncTo = SYNC_TO.DSP,
175-
description,
176-
advertiserId,
177-
externalAudienceId,
178-
countryCode,
179-
ttl,
180-
currency,
181-
cpmCents,
182-
amcInstanceId,
183-
amcAccountId,
184-
amcAccountMarketplaceId
185-
} = audienceSettings || {}
186-
187-
if (syncTo === SYNC_TO.DSP && !advertiserId) {
188-
throw new PayloadValidationError('Advertiser Id value is required when syncing an audience to DSP')
189-
}
190-
191-
if (syncTo === SYNC_TO.AMC && (!amcInstanceId || !amcAccountId || !amcAccountMarketplaceId)) {
192-
throw new PayloadValidationError(
193-
'AMC Instance Id, AMC Account Id and AMC Account Marketplace Id value are required when syncing audience to AMC'
194-
)
156+
if (!advertiser_id) {
157+
throw new IntegrationError('Missing advertiserId Value', 'MISSING_REQUIRED_FIELD', 400)
195158
}
196159

197160
if (!description) {
198-
throw new PayloadValidationError('Missing description Value')
161+
throw new IntegrationError('Missing description Value', 'MISSING_REQUIRED_FIELD', 400)
199162
}
200163

201-
if (!externalAudienceId) {
202-
throw new PayloadValidationError('Missing externalAudienceId Value')
164+
if (!external_audience_id) {
165+
throw new IntegrationError('Missing externalAudienceId Value', 'MISSING_REQUIRED_FIELD', 400)
203166
}
204167

205168
if (!audienceName) {
206-
throw new PayloadValidationError('Missing audienceName Value')
169+
throw new IntegrationError('Missing audienceName Value', 'MISSING_REQUIRED_FIELD', 400)
207170
}
208-
209-
if (!countryCode) {
210-
throw new PayloadValidationError('Missing countryCode Value')
171+
if (!country_code) {
172+
throw new IntegrationError('Missing countryCode Value', 'MISSING_REQUIRED_FIELD', 400)
211173
}
212-
213174
if (ttl && ttl > TTL_MAX_VALUE) {
214-
throw new PayloadValidationError(`TTL must have value less than or equal to ${TTL_MAX_VALUE}`)
215-
}
216-
217-
let connectionId: string | undefined = undefined
218-
if (syncTo === SYNC_TO.AMC) {
219-
const payloadStringConnsAPI = JSON.stringify({ amcInstanceId, amcAccountId, amcAccountMarketplaceId })
220-
const response = await request(`${endpoint}/amc/audiences/connections`, {
221-
method: 'POST',
222-
body: payloadStringConnsAPI,
223-
headers: {
224-
'Content-Type': 'application/vnd.amcaudiencesconnections.v1+json'
225-
}
226-
})
227-
228-
connectionId = JSON.parse(await response.text())?.connectionId
229-
if (!connectionId) {
230-
throw new PayloadValidationError(
231-
'Unable to fetch connectionId with given AMC amcInstanceId amcAccountId and amcAccountMarketplaceId details'
232-
)
233-
}
175+
throw new IntegrationError(`TTL must have value less than or equal to ${TTL_MAX_VALUE}`, 'INVALID_INPUT', 400)
234176
}
235177

236178
const payload: AudiencePayload = {
237179
name: audienceName,
238-
description,
239-
targetResource: (() => {
240-
if (syncTo === SYNC_TO.AMC) {
241-
const targetResource: AMCTargetResource = {
242-
amcInstanceId: amcInstanceId as string,
243-
amcAccountId: amcAccountId as string,
244-
amcAccountMarketplaceId: amcAccountMarketplaceId as string,
245-
connectionId: connectionId as string
246-
}
247-
return targetResource
248-
}
249-
if (syncTo === SYNC_TO.DSP) {
250-
const targetResource: DSPTargetResource = {
251-
advertiserId: advertiserId as string
252-
}
253-
return targetResource
254-
}
255-
throw new PayloadValidationError('Invalid syncTo value')
256-
})(),
180+
description: description,
181+
targetResource: {
182+
advertiserId: advertiser_id
183+
},
257184
metadata: {
258-
externalAudienceId
185+
externalAudienceId: external_audience_id
259186
},
260-
countryCode
187+
countryCode: country_code
261188
}
262189

263190
if (ttl) {
264191
payload.metadata.ttl = ttl
265192
}
266193

267-
if (cpmCents && currency) {
194+
if (cpm_cents && currency) {
268195
payload.metadata.audienceFees = []
269196
payload.metadata?.audienceFees.push({
270197
currency,
271-
cpmCents
198+
cpmCents: cpm_cents
272199
})
273200
}
274201

275202
let payloadString = JSON.stringify(payload)
276203
// Regular expression to find a advertiserId numeric string and replace the quoted advertiserId string with an unquoted number
277204
// AdvertiserId is very big number string and can not be assigned or converted to number directly as it changes the value due to integer overflow.
278-
if (syncTo === SYNC_TO.DSP) {
279-
payloadString = payloadString.replace(REGEX_ADVERTISERID, '"advertiserId":$1')
280-
}
205+
payloadString = payloadString.replace(REGEX_ADVERTISERID, '"advertiserId":$1')
281206

282207
const response = await request(`${endpoint}/amc/audiences/metadata`, {
283208
method: 'POST',
@@ -292,17 +217,17 @@ const destination: AudienceDestinationDefinition<Settings, AudienceSettings> = {
292217
// Regular expression to find a audienceId number and replace the audienceId with quoted string
293218
const resp = extractNumberAndSubstituteWithStringValue(res, REGEX_AUDIENCEID, '"audienceId":"$1"')
294219
return {
295-
externalId: syncTo === SYNC_TO.DSP ? resp.audienceId : resp.audienceId + ':' + connectionId
220+
externalId: resp.audienceId
296221
}
297222
},
298223

299224
async getAudience(request, getAudienceInput) {
300225
// getAudienceInput.externalId represents audience ID that was created in createAudience
301-
const audience_id = getAudienceInput.externalId.split(':')[0]
226+
const audience_id = getAudienceInput.externalId
302227
const { settings } = getAudienceInput
303228
const endpoint = settings.region
304229
if (!audience_id) {
305-
throw new PayloadValidationError('Missing audienceId value')
230+
throw new IntegrationError('Missing audienceId value', 'MISSING_REQUIRED_FIELD', 400)
306231
}
307232
const response = await request(`${endpoint}/amc/audiences/metadata/${audience_id}`, {
308233
method: 'GET',

0 commit comments

Comments
 (0)