diff --git a/src/utils/converter.ts b/src/utils/converter.ts index 0f59170..3fd2018 100644 --- a/src/utils/converter.ts +++ b/src/utils/converter.ts @@ -16,13 +16,27 @@ import { } from '../types'; import { createBlockExpression, getLastElement } from './common'; -function createObjectExpression(): ObjectExpression { +function createObjectExpression(props: ObjectPropExpression[] = []): ObjectExpression { return { type: SyntaxType.OBJECT_EXPR, - props: [] as ObjectPropExpression[], + props, }; } +function createObjectPropExpressionWithSpread(value: Expression): ObjectPropExpression { + return { + type: SyntaxType.OBJECT_PROP_EXPR, + value: { + type: SyntaxType.SPREAD_EXPR, + value, + }, + }; +} + +function createObjectExpressionWithSpread(value: Expression): ObjectExpression { + return createObjectExpression([createObjectPropExpressionWithSpread(value)]); +} + function findOrCreateObjectPropExpression( props: ObjectPropExpression[], key: string, @@ -222,6 +236,14 @@ function isWildcardSelector(expr: Expression): boolean { return expr.type === SyntaxType.SELECTOR && expr.prop?.value === '*'; } +function isOutputPartRegularSelector(outputPart: Expression) { + return ( + outputPart?.type === SyntaxType.SELECTOR && + outputPart.prop?.value && + outputPart.prop.value !== '*' + ); +} + function processWildCardSelector( flatMapping: FlatMappingAST, currentOutputPropAST: ObjectPropExpression, @@ -282,6 +304,15 @@ function handleNextPart( currentOutputPropAST: ObjectPropExpression, ): ObjectExpression | undefined { const nextOutputPart = flatMapping.outputExpr.parts[partNum]; + const prevOutputPart = flatMapping.outputExpr.parts[partNum - 1]; + if ( + isOutputPartRegularSelector(prevOutputPart) && + isOutputPartRegularSelector(nextOutputPart) && + currentOutputPropAST.value.type !== SyntaxType.OBJECT_EXPR + ) { + currentOutputPropAST.value = createObjectExpressionWithSpread(currentOutputPropAST.value); + return currentOutputPropAST.value as ObjectExpression; + } if (nextOutputPart.filter?.type === SyntaxType.ALL_FILTER_EXPR) { const objectExpr = processAllFilter( flatMapping, @@ -336,14 +367,6 @@ function handleNextParts( return objectExpr; } -function isOutputPartRegularSelector(outputPart: Expression) { - return ( - outputPart.type === SyntaxType.SELECTOR && - outputPart.prop?.value && - outputPart.prop.value !== '*' - ); -} - function refineLeafOutputPropAST(inputExpr: Expression): Expression { if ( inputExpr.type === SyntaxType.PATH && @@ -399,13 +422,7 @@ function processFlatMappingPart( } function handleRootOnlyOutputMapping(flatMapping: FlatMappingAST, outputAST: ObjectExpression) { - outputAST.props.push({ - type: SyntaxType.OBJECT_PROP_EXPR, - value: { - type: SyntaxType.SPREAD_EXPR, - value: flatMapping.inputExpr, - }, - } as ObjectPropExpression); + outputAST.props.push(createObjectPropExpressionWithSpread(flatMapping.inputExpr)); } function validateMappingsForIndexVar(flatMapping: FlatMappingAST, indexVar: string) { diff --git a/test/scenarios/mappings/data.ts b/test/scenarios/mappings/data.ts index 76614b8..1ea5feb 100644 --- a/test/scenarios/mappings/data.ts +++ b/test/scenarios/mappings/data.ts @@ -319,6 +319,13 @@ export const data: Scenario[] = [ }, }, ], + traits3: { + display_name: 'Rudderstack Inc.', + category: 'Analytics', + custom_properties: { + bar: 1, + }, + }, }, output: { user_id: { @@ -344,6 +351,15 @@ export const data: Scenario[] = [ }, ], }, + traits3: { + value: { + display_name: 'Rudderstack Inc.', + category: 'Analytics', + custom_properties: { + bar: 1, + }, + }, + }, properties1: { name: { value: 'John Doe', @@ -360,6 +376,18 @@ export const data: Scenario[] = [ age: 30, }, ], + properties3: { + display_name: 'Rudderstack Inc.', + category: 'Analytics', + custom_properties: { + bar: 1, + }, + name: 'Rudderstack Inc.', + custom: { + bar: 1, + foo: 1, + }, + }, }, }, { diff --git a/test/scenarios/mappings/object_mappings.json b/test/scenarios/mappings/object_mappings.json index ba13424..eccc0f8 100644 --- a/test/scenarios/mappings/object_mappings.json +++ b/test/scenarios/mappings/object_mappings.json @@ -10,5 +10,21 @@ { "input": "$.traits2[*].*.value", "output": "$.properties2[*].*" + }, + { + "input": "$.traits3", + "output": "$.properties3" + }, + { + "input": "$.traits3.display_name", + "output": "$.properties3.name" + }, + { + "input": "$.traits3.custom_properties", + "output": "$.properties3.custom" + }, + { + "input": "$.traits3.custom_properties.bar", + "output": "$.properties3.custom.foo" } ]