diff --git a/packages/destination-actions/src/destinations/stackadapt-audiences/__tests__/__snapshots__/snapshot.test.ts.snap b/packages/destination-actions/src/destinations/stackadapt-audiences/__tests__/__snapshots__/snapshot.test.ts.snap index 3274ba8b532..25113417c86 100644 --- a/packages/destination-actions/src/destinations/stackadapt-audiences/__tests__/__snapshots__/snapshot.test.ts.snap +++ b/packages/destination-actions/src/destinations/stackadapt-audiences/__tests__/__snapshots__/snapshot.test.ts.snap @@ -18,8 +18,8 @@ Object { upsertProfileMapping( input: { advertiserId: 84GW[vK%wv2xv@UF5iy, - mappingSchemaV2: [{\\\\\\"incomingKey\\\\\\":\\\\\\"userId\\\\\\",\\\\\\"destinationKey\\\\\\":\\\\\\"external_id\\\\\\",\\\\\\"type\\\\\\":STRING,\\\\\\"isPii\\\\\\":false,\\\\\\"label\\\\\\":\\\\\\"External Profile ID\\\\\\"}], - mappableType: \\"segment_io\\", + mappingSchemaV2: [{incomingKey:\\"userId\\",destinationKey:\\"external_id\\",type:STRING,isPii:false,label:\\"External Profile ID\\"}], + mappableType: \\"segment_io\\" } ) { userErrors { @@ -29,7 +29,7 @@ Object { upsertExternalAudienceMapping( input: { advertiserId: 84GW[vK%wv2xv@UF5iy, - mappingSchema: [{\\\\\\"incomingKey\\\\\\":\\\\\\"audienceId\\\\\\",\\\\\\"destinationKey\\\\\\":\\\\\\"external_id\\\\\\",\\\\\\"type\\\\\\":STRING,\\\\\\"label\\\\\\":\\\\\\"External Audience ID\\\\\\",\\\\\\"isPii\\\\\\":false},{\\\\\\"incomingKey\\\\\\":\\\\\\"audienceName\\\\\\",\\\\\\"destinationKey\\\\\\":\\\\\\"name\\\\\\",\\\\\\"type\\\\\\":STRING,\\\\\\"label\\\\\\":\\\\\\"External Audience Name\\\\\\",\\\\\\"isPii\\\\\\":false}], + mappingSchema: [{incomingKey:\\"audienceId\\",destinationKey:\\"external_id\\",type:STRING,label:\\"External Audience ID\\",isPii:false},{incomingKey:\\"audienceName\\",destinationKey:\\"name\\",type:STRING,label:\\"External Audience Name\\",isPii:false}], mappableType: \\"segment_io\\" } ) { @@ -59,8 +59,8 @@ Object { upsertProfileMapping( input: { advertiserId: 84GW[vK%wv2xv@UF5iy, - mappingSchemaV2: [{\\\\\\"incomingKey\\\\\\":\\\\\\"userId\\\\\\",\\\\\\"destinationKey\\\\\\":\\\\\\"external_id\\\\\\",\\\\\\"type\\\\\\":STRING,\\\\\\"isPii\\\\\\":false,\\\\\\"label\\\\\\":\\\\\\"External Profile ID\\\\\\"}], - mappableType: \\"segment_io\\", + mappingSchemaV2: [{incomingKey:\\"userId\\",destinationKey:\\"external_id\\",type:STRING,isPii:false,label:\\"External Profile ID\\"}], + mappableType: \\"segment_io\\" } ) { userErrors { @@ -70,7 +70,7 @@ Object { upsertExternalAudienceMapping( input: { advertiserId: 84GW[vK%wv2xv@UF5iy, - mappingSchema: [{\\\\\\"incomingKey\\\\\\":\\\\\\"audienceId\\\\\\",\\\\\\"destinationKey\\\\\\":\\\\\\"external_id\\\\\\",\\\\\\"type\\\\\\":STRING,\\\\\\"label\\\\\\":\\\\\\"External Audience ID\\\\\\",\\\\\\"isPii\\\\\\":false},{\\\\\\"incomingKey\\\\\\":\\\\\\"audienceName\\\\\\",\\\\\\"destinationKey\\\\\\":\\\\\\"name\\\\\\",\\\\\\"type\\\\\\":STRING,\\\\\\"label\\\\\\":\\\\\\"External Audience Name\\\\\\",\\\\\\"isPii\\\\\\":false}], + mappingSchema: [{incomingKey:\\"audienceId\\",destinationKey:\\"external_id\\",type:STRING,label:\\"External Audience ID\\",isPii:false},{incomingKey:\\"audienceName\\",destinationKey:\\"name\\",type:STRING,label:\\"External Audience Name\\",isPii:false}], mappableType: \\"segment_io\\" } ) { @@ -100,8 +100,8 @@ Object { upsertProfileMapping( input: { advertiserId: PsAwlRv%, - mappingSchemaV2: [{\\\\\\"incomingKey\\\\\\":\\\\\\"userId\\\\\\",\\\\\\"destinationKey\\\\\\":\\\\\\"external_id\\\\\\",\\\\\\"label\\\\\\":\\\\\\"User Id\\\\\\",\\\\\\"type\\\\\\":STRING,\\\\\\"isPii\\\\\\":false}], - mappableType: \\"segment_io\\", + mappingSchemaV2: [{incomingKey:\\"userId\\",destinationKey:\\"external_id\\",label:\\"User Id\\",type:STRING,isPii:false}], + mappableType: \\"segment_io\\" } ) { userErrors { @@ -130,8 +130,8 @@ Object { upsertProfileMapping( input: { advertiserId: PsAwlRv%, - mappingSchemaV2: [{\\\\\\"incomingKey\\\\\\":\\\\\\"userId\\\\\\",\\\\\\"destinationKey\\\\\\":\\\\\\"external_id\\\\\\",\\\\\\"label\\\\\\":\\\\\\"User Id\\\\\\",\\\\\\"type\\\\\\":STRING,\\\\\\"isPii\\\\\\":false}], - mappableType: \\"segment_io\\", + mappingSchemaV2: [{incomingKey:\\"userId\\",destinationKey:\\"external_id\\",label:\\"User Id\\",type:STRING,isPii:false}], + mappableType: \\"segment_io\\" } ) { userErrors { diff --git a/packages/destination-actions/src/destinations/stackadapt-audiences/__tests__/functions.test.ts b/packages/destination-actions/src/destinations/stackadapt-audiences/__tests__/functions.test.ts index c136c4bc942..c5215c73d38 100644 --- a/packages/destination-actions/src/destinations/stackadapt-audiences/__tests__/functions.test.ts +++ b/packages/destination-actions/src/destinations/stackadapt-audiences/__tests__/functions.test.ts @@ -1,4 +1,4 @@ -import { stringifyJsonWithEscapedQuotes } from '../functions' +import { stringifyJsonWithEscapedQuotes, stringifyMappingSchemaForGraphQL } from '../functions' describe('stringifyJsonWithEscapedQuotes', () => { it('should escape quotes in a simple object', () => { @@ -38,35 +38,96 @@ describe('stringifyJsonWithEscapedQuotes', () => { expect(stringifyJsonWithEscapedQuotes(null)).toBe('null') }) - describe('type field transformation', () => { - it('should transform type field to uppercase without quotes', () => { - const input = { type: 'string' } - const expected = '{\\"type\\":STRING}' - expect(stringifyJsonWithEscapedQuotes(input)).toBe(expected) - }) +}) - it('should transform type field when it\'s already uppercase', () => { - const input = { type: 'STRING' } - const expected = '{\\"type\\":STRING}' - expect(stringifyJsonWithEscapedQuotes(input)).toBe(expected) - }) +describe('stringifyMappingSchemaForGraphQL', () => { + it('should transform simple mapping object for GraphQL', () => { + const input = { + incomingKey: 'userId', + destinationKey: 'external_id', + label: 'User Id', + type: 'STRING', + isPii: false + } + const expected = '{incomingKey:"userId",destinationKey:"external_id",label:"User Id",type:STRING,isPii:false}' + expect(stringifyMappingSchemaForGraphQL(input)).toBe(expected) + }) + + it('should transform type field to uppercase and unquoted', () => { + const input = { type: 'string' } + const expected = '{type:STRING}' + expect(stringifyMappingSchemaForGraphQL(input)).toBe(expected) + }) - it('should transform type field in nested objects', () => { - const input = { data: { type: 'string' } } - const expected = '{\\"data\\":{\\"type\\":STRING}}' - expect(stringifyJsonWithEscapedQuotes(input)).toBe(expected) - }) + it('should transform type field when it\'s already uppercase', () => { + const input = { type: 'STRING' } + const expected = '{type:STRING}' + expect(stringifyMappingSchemaForGraphQL(input)).toBe(expected) + }) - it('should transform type fields in an array of objects', () => { - const input = { - mappings: [ - { type: 'string', field: 'name' }, - { type: 'number', field: 'age' }, - { type: 'boolean', field: 'active' } - ] + it('should handle array of mapping objects', () => { + const input = [ + { + incomingKey: 'userId', + destinationKey: 'external_id', + type: 'STRING', + isPii: false, + label: 'External Profile ID' + }, + { + incomingKey: 'email', + destinationKey: 'email', + type: 'string', + isPii: true, + label: 'Email Address' } - const expected = '{\\"mappings\\":[{\\"type\\":STRING,\\"field\\":\\"name\\"},{\\"type\\":NUMBER,\\"field\\":\\"age\\"},{\\"type\\":BOOLEAN,\\"field\\":\\"active\\"}]}' - expect(stringifyJsonWithEscapedQuotes(input)).toBe(expected) - }) + ] + const expected = '[{incomingKey:"userId",destinationKey:"external_id",type:STRING,isPii:false,label:"External Profile ID"},{incomingKey:"email",destinationKey:"email",type:STRING,isPii:true,label:"Email Address"}]' + expect(stringifyMappingSchemaForGraphQL(input)).toBe(expected) + }) + + it('should handle different type values', () => { + const input = { + mappings: [ + { type: 'string', field: 'name' }, + { type: 'number', field: 'age' }, + { type: 'boolean', field: 'active' } + ] + } + const expected = '{mappings:[{type:STRING,field:"name"},{type:NUMBER,field:"age"},{type:BOOLEAN,field:"active"}]}' + expect(stringifyMappingSchemaForGraphQL(input)).toBe(expected) + }) + + it('should unquote all object keys for GraphQL syntax', () => { + const input = { + incomingKey: 'test', + destinationKey: 'test_field', + customProperty: 'value', + type: 'string' + } + const expected = '{incomingKey:"test",destinationKey:"test_field",customProperty:"value",type:STRING}' + expect(stringifyMappingSchemaForGraphQL(input)).toBe(expected) + }) + + it('should preserve string values with quotes', () => { + const input = { + label: 'User Name with "quotes"', + description: 'Field description', + type: 'string' + } + const expected = '{label:"User Name with \\"quotes\\"",description:"Field description",type:STRING}' + expect(stringifyMappingSchemaForGraphQL(input)).toBe(expected) + }) + + it('should handle nested objects', () => { + const input = { + field: { + incomingKey: 'nested', + type: 'string' + }, + type: 'object' + } + const expected = '{field:{incomingKey:"nested",type:STRING},type:OBJECT}' + expect(stringifyMappingSchemaForGraphQL(input)).toBe(expected) }) }) \ No newline at end of file diff --git a/packages/destination-actions/src/destinations/stackadapt-audiences/forwardAudienceEvent/__tests__/index.test.ts b/packages/destination-actions/src/destinations/stackadapt-audiences/forwardAudienceEvent/__tests__/index.test.ts index 39033af3903..b893af0dc99 100644 --- a/packages/destination-actions/src/destinations/stackadapt-audiences/forwardAudienceEvent/__tests__/index.test.ts +++ b/packages/destination-actions/src/destinations/stackadapt-audiences/forwardAudienceEvent/__tests__/index.test.ts @@ -95,8 +95,8 @@ describe('forwardAudienceEvent', () => { upsertProfileMapping( input: { advertiserId: 23, - mappingSchemaV2: [{\\\\\\"incomingKey\\\\\\":\\\\\\"userId\\\\\\",\\\\\\"destinationKey\\\\\\":\\\\\\"external_id\\\\\\",\\\\\\"type\\\\\\":STRING,\\\\\\"isPii\\\\\\":false,\\\\\\"label\\\\\\":\\\\\\"External Profile ID\\\\\\"}], - mappableType: \\"segment_io\\", + mappingSchemaV2: [{incomingKey:\\"userId\\",destinationKey:\\"external_id\\",type:STRING,isPii:false,label:\\"External Profile ID\\"}], + mappableType: \\"segment_io\\" } ) { userErrors { @@ -106,7 +106,7 @@ describe('forwardAudienceEvent', () => { upsertExternalAudienceMapping( input: { advertiserId: 23, - mappingSchema: [{\\\\\\"incomingKey\\\\\\":\\\\\\"audienceId\\\\\\",\\\\\\"destinationKey\\\\\\":\\\\\\"external_id\\\\\\",\\\\\\"type\\\\\\":STRING,\\\\\\"label\\\\\\":\\\\\\"External Audience ID\\\\\\",\\\\\\"isPii\\\\\\":false},{\\\\\\"incomingKey\\\\\\":\\\\\\"audienceName\\\\\\",\\\\\\"destinationKey\\\\\\":\\\\\\"name\\\\\\",\\\\\\"type\\\\\\":STRING,\\\\\\"label\\\\\\":\\\\\\"External Audience Name\\\\\\",\\\\\\"isPii\\\\\\":false}], + mappingSchema: [{incomingKey:\\"audienceId\\",destinationKey:\\"external_id\\",type:STRING,label:\\"External Audience ID\\",isPii:false},{incomingKey:\\"audienceName\\",destinationKey:\\"name\\",type:STRING,label:\\"External Audience Name\\",isPii:false}], mappableType: \\"segment_io\\" } ) { @@ -169,8 +169,8 @@ describe('forwardAudienceEvent', () => { upsertProfileMapping( input: { advertiserId: 23, - mappingSchemaV2: [{\\\\\\"incomingKey\\\\\\":\\\\\\"userId\\\\\\",\\\\\\"destinationKey\\\\\\":\\\\\\"external_id\\\\\\",\\\\\\"type\\\\\\":STRING,\\\\\\"isPii\\\\\\":false,\\\\\\"label\\\\\\":\\\\\\"External Profile ID\\\\\\"}], - mappableType: \\"segment_io\\", + mappingSchemaV2: [{incomingKey:\\"userId\\",destinationKey:\\"external_id\\",type:STRING,isPii:false,label:\\"External Profile ID\\"}], + mappableType: \\"segment_io\\" } ) { userErrors { @@ -180,7 +180,7 @@ describe('forwardAudienceEvent', () => { upsertExternalAudienceMapping( input: { advertiserId: 23, - mappingSchema: [{\\\\\\"incomingKey\\\\\\":\\\\\\"audienceId\\\\\\",\\\\\\"destinationKey\\\\\\":\\\\\\"external_id\\\\\\",\\\\\\"type\\\\\\":STRING,\\\\\\"label\\\\\\":\\\\\\"External Audience ID\\\\\\",\\\\\\"isPii\\\\\\":false},{\\\\\\"incomingKey\\\\\\":\\\\\\"audienceName\\\\\\",\\\\\\"destinationKey\\\\\\":\\\\\\"name\\\\\\",\\\\\\"type\\\\\\":STRING,\\\\\\"label\\\\\\":\\\\\\"External Audience Name\\\\\\",\\\\\\"isPii\\\\\\":false}], + mappingSchema: [{incomingKey:\\"audienceId\\",destinationKey:\\"external_id\\",type:STRING,label:\\"External Audience ID\\",isPii:false},{incomingKey:\\"audienceName\\",destinationKey:\\"name\\",type:STRING,label:\\"External Audience Name\\",isPii:false}], mappableType: \\"segment_io\\" } ) { @@ -228,8 +228,8 @@ describe('forwardAudienceEvent', () => { upsertProfileMapping( input: { advertiserId: 23, - mappingSchemaV2: [{\\\\\\"incomingKey\\\\\\":\\\\\\"userId\\\\\\",\\\\\\"destinationKey\\\\\\":\\\\\\"external_id\\\\\\",\\\\\\"type\\\\\\":STRING,\\\\\\"isPii\\\\\\":false,\\\\\\"label\\\\\\":\\\\\\"External Profile ID\\\\\\"}], - mappableType: \\"segment_io\\", + mappingSchemaV2: [{incomingKey:\\"userId\\",destinationKey:\\"external_id\\",type:STRING,isPii:false,label:\\"External Profile ID\\"}], + mappableType: \\"segment_io\\" } ) { userErrors { @@ -239,7 +239,7 @@ describe('forwardAudienceEvent', () => { upsertExternalAudienceMapping( input: { advertiserId: 23, - mappingSchema: [{\\\\\\"incomingKey\\\\\\":\\\\\\"audienceId\\\\\\",\\\\\\"destinationKey\\\\\\":\\\\\\"external_id\\\\\\",\\\\\\"type\\\\\\":STRING,\\\\\\"label\\\\\\":\\\\\\"External Audience ID\\\\\\",\\\\\\"isPii\\\\\\":false},{\\\\\\"incomingKey\\\\\\":\\\\\\"audienceName\\\\\\",\\\\\\"destinationKey\\\\\\":\\\\\\"name\\\\\\",\\\\\\"type\\\\\\":STRING,\\\\\\"label\\\\\\":\\\\\\"External Audience Name\\\\\\",\\\\\\"isPii\\\\\\":false}], + mappingSchema: [{incomingKey:\\"audienceId\\",destinationKey:\\"external_id\\",type:STRING,label:\\"External Audience ID\\",isPii:false},{incomingKey:\\"audienceName\\",destinationKey:\\"name\\",type:STRING,label:\\"External Audience Name\\",isPii:false}], mappableType: \\"segment_io\\" } ) { diff --git a/packages/destination-actions/src/destinations/stackadapt-audiences/forwardAudienceEvent/functions.ts b/packages/destination-actions/src/destinations/stackadapt-audiences/forwardAudienceEvent/functions.ts index 0c0652887fc..ee8021b9738 100644 --- a/packages/destination-actions/src/destinations/stackadapt-audiences/forwardAudienceEvent/functions.ts +++ b/packages/destination-actions/src/destinations/stackadapt-audiences/forwardAudienceEvent/functions.ts @@ -1,8 +1,8 @@ import { RequestClient } from '@segment/actions-core' import { Payload } from './generated-types' -import { GQL_ENDPOINT, EXTERNAL_PROVIDER, sha256hash, stringifyJsonWithEscapedQuotes } from '../functions' +import { GQL_ENDPOINT, EXTERNAL_PROVIDER, sha256hash, stringifyJsonWithEscapedQuotes, stringifyMappingSchemaForGraphQL } from '../functions' -const audienceMapping = stringifyJsonWithEscapedQuotes([ +const audienceMapping = stringifyMappingSchemaForGraphQL([ { incomingKey: 'audienceId', destinationKey: 'external_id', @@ -20,7 +20,7 @@ const audienceMapping = stringifyJsonWithEscapedQuotes([ } ]) -const profileMapping = stringifyJsonWithEscapedQuotes([ +const profileMapping = stringifyMappingSchemaForGraphQL([ { incomingKey: 'userId', destinationKey: 'external_id', @@ -62,7 +62,7 @@ export async function performForwardAudienceEvents(request: RequestClient, event input: { advertiserId: ${advertiserId}, mappingSchemaV2: ${profileMapping}, - mappableType: "${EXTERNAL_PROVIDER}", + mappableType: "${EXTERNAL_PROVIDER}" } ) { userErrors { diff --git a/packages/destination-actions/src/destinations/stackadapt-audiences/forwardProfile/__tests__/index.test.ts b/packages/destination-actions/src/destinations/stackadapt-audiences/forwardProfile/__tests__/index.test.ts index 23b9a85b4cc..d15e3403b7b 100644 --- a/packages/destination-actions/src/destinations/stackadapt-audiences/forwardProfile/__tests__/index.test.ts +++ b/packages/destination-actions/src/destinations/stackadapt-audiences/forwardProfile/__tests__/index.test.ts @@ -131,8 +131,8 @@ describe('forwardProfile', () => { upsertProfileMapping( input: { advertiserId: 23, - mappingSchemaV2: [{\\\\\\"incomingKey\\\\\\":\\\\\\"userId\\\\\\",\\\\\\"destinationKey\\\\\\":\\\\\\"external_id\\\\\\",\\\\\\"label\\\\\\":\\\\\\"User Id\\\\\\",\\\\\\"type\\\\\\":STRING,\\\\\\"isPii\\\\\\":false}], - mappableType: \\"segment_io\\", + mappingSchemaV2: [{incomingKey:\\"userId\\",destinationKey:\\"external_id\\",label:\\"User Id\\",type:STRING,isPii:false}], + mappableType: \\"segment_io\\" } ) { userErrors { @@ -194,8 +194,8 @@ describe('forwardProfile', () => { upsertProfileMapping( input: { advertiserId: 23, - mappingSchemaV2: [{\\\\\\"incomingKey\\\\\\":\\\\\\"userId\\\\\\",\\\\\\"destinationKey\\\\\\":\\\\\\"external_id\\\\\\",\\\\\\"label\\\\\\":\\\\\\"User Id\\\\\\",\\\\\\"type\\\\\\":STRING,\\\\\\"isPii\\\\\\":false}], - mappableType: \\"segment_io\\", + mappingSchemaV2: [{incomingKey:\\"userId\\",destinationKey:\\"external_id\\",label:\\"User Id\\",type:STRING,isPii:false}], + mappableType: \\"segment_io\\" } ) { userErrors { @@ -242,8 +242,8 @@ describe('forwardProfile', () => { upsertProfileMapping( input: { advertiserId: 23, - mappingSchemaV2: [{\\\\\\"incomingKey\\\\\\":\\\\\\"userId\\\\\\",\\\\\\"destinationKey\\\\\\":\\\\\\"external_id\\\\\\",\\\\\\"label\\\\\\":\\\\\\"User Id\\\\\\",\\\\\\"type\\\\\\":STRING,\\\\\\"isPii\\\\\\":false},{\\\\\\"incomingKey\\\\\\":\\\\\\"customField\\\\\\",\\\\\\"destinationKey\\\\\\":\\\\\\"customField\\\\\\",\\\\\\"label\\\\\\":\\\\\\"Custom Field\\\\\\",\\\\\\"type\\\\\\":STRING,\\\\\\"isPii\\\\\\":false},{\\\\\\"incomingKey\\\\\\":\\\\\\"numberCustomField\\\\\\",\\\\\\"destinationKey\\\\\\":\\\\\\"numberCustomField\\\\\\",\\\\\\"label\\\\\\":\\\\\\"Number Custom Field\\\\\\",\\\\\\"type\\\\\\":NUMBER,\\\\\\"isPii\\\\\\":false}], - mappableType: \\"segment_io\\", + mappingSchemaV2: [{incomingKey:\\"userId\\",destinationKey:\\"external_id\\",label:\\"User Id\\",type:STRING,isPii:false},{incomingKey:\\"customField\\",destinationKey:\\"customField\\",label:\\"Custom Field\\",type:STRING,isPii:false},{incomingKey:\\"numberCustomField\\",destinationKey:\\"numberCustomField\\",label:\\"Number Custom Field\\",type:NUMBER,isPii:false}], + mappableType: \\"segment_io\\" } ) { userErrors { @@ -290,8 +290,8 @@ describe('forwardProfile', () => { upsertProfileMapping( input: { advertiserId: 23, - mappingSchemaV2: [{\\\\\\"incomingKey\\\\\\":\\\\\\"userId\\\\\\",\\\\\\"destinationKey\\\\\\":\\\\\\"external_id\\\\\\",\\\\\\"label\\\\\\":\\\\\\"User Id\\\\\\",\\\\\\"type\\\\\\":STRING,\\\\\\"isPii\\\\\\":false}], - mappableType: \\"segment_io\\", + mappingSchemaV2: [{incomingKey:\\"userId\\",destinationKey:\\"external_id\\",label:\\"User Id\\",type:STRING,isPii:false}], + mappableType: \\"segment_io\\" } ) { userErrors { diff --git a/packages/destination-actions/src/destinations/stackadapt-audiences/forwardProfile/functions.ts b/packages/destination-actions/src/destinations/stackadapt-audiences/forwardProfile/functions.ts index 67c0ff4e1ce..f89424841b8 100644 --- a/packages/destination-actions/src/destinations/stackadapt-audiences/forwardProfile/functions.ts +++ b/packages/destination-actions/src/destinations/stackadapt-audiences/forwardProfile/functions.ts @@ -2,7 +2,7 @@ import { RequestClient } from '@segment/actions-core' import camelCase from 'lodash/camelCase' import isEmpty from 'lodash/isEmpty' import { Payload } from './generated-types' -import { GQL_ENDPOINT, EXTERNAL_PROVIDER, sha256hash, stringifyJsonWithEscapedQuotes } from '../functions' +import { GQL_ENDPOINT, EXTERNAL_PROVIDER, sha256hash, stringifyJsonWithEscapedQuotes, stringifyMappingSchemaForGraphQL } from '../functions' const standardFields = new Set([ 'email', @@ -74,7 +74,7 @@ export async function performForwardProfiles(request: RequestClient, events: Pay input: { advertiserId: ${advertiserId}, mappingSchemaV2: ${getProfileMappings(Array.from(fieldsToMap), fieldTypes)}, - mappableType: "${EXTERNAL_PROVIDER}", + mappableType: "${EXTERNAL_PROVIDER}" } ) { userErrors { @@ -119,7 +119,7 @@ function getProfileMappings(customFields: string[], fieldTypes: Record - `"type":${typeValue.toUpperCase()}`); + const jsonString = JSON.stringify(value); // Finally escape all remaining quotes return jsonString.replace(/"/g, '\\"'); } + +// transform mapping schema for direct insertion into GraphQL queries (no quote escaping) +export function stringifyMappingSchemaForGraphQL(value: unknown) { + let jsonString = JSON.stringify(value); + + // Replace "type":"VALUE" with type:VALUE (unquoted enum and field) + jsonString = jsonString.replace(/"type":"([^"]+)"/g, (_, typeValue: string) => + `type:${typeValue.toUpperCase()}`); + + // Remove quotes from all object keys to make it valid GraphQL syntax + jsonString = jsonString.replace(/"([a-zA-Z_][a-zA-Z0-9_]*)"\s*:/g, '$1:'); + + return jsonString; +}