Skip to content

Commit

Permalink
feat: refine root mappings (#90)
Browse files Browse the repository at this point in the history
  • Loading branch information
koladilip authored Jun 13, 2024
1 parent 5a56f64 commit f84aac6
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 49 deletions.
55 changes: 55 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,61 @@ JsonTemplateEngine.create(`let a = {{$.a.b.c}};`, {
We can use compile time expressions to generate a template and then recompile it as expression. Refer these examples [simple compilation](test/scenarios/compile_time_expressions/template.jt) and [complex compilation](test/scenarios/compile_time_expressions/two_level_path_processing.jt) for more details.
### Mappings
If you are familiar with [JSON Paths](https://goessner.net/articles/JsonPath/index.html#), you can easily begin working with JSON templates by leveraging your existing knowledge through the mappings feature.
**Example:**
* Let's say we want to tranform the following data.
* Input:
```json
{
"a": {
"foo": 1,
"bar": 2
},
"b": [
{
"firstName": "foo",
"lastName": "bar"
},
{
"firstName": "fizz",
"lastName": "buzz"
}
]
}
```
* Output:
```json
{
"foo": 1,
"bar": 2,
"items":[
{
"name": "foo bar"
},
{
"name": "fizz buzz"
}
]
}
```
* Mappings:
```json
[
{
"description": "Copies properties of a to root level in the output",
"input": "$.a",
"output": "$",
},
{
"description": "Combines first and last name in the output",
"input": "$.b[*].(@.firstName + ' ' + @.lastName)",
"output": "$.items[*].name"
}
]
```
For more examples, refer [Mappings](test/scenarios/mappings/)
### Comments
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ export interface ThrowExpression extends Expression {
}

export type FlatMappingPaths = {
description?: string;
input: string;
output: string;
};
Expand Down
20 changes: 11 additions & 9 deletions src/utils/converter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,16 @@ function processFlatMappingPart(
}

function processFlatMapping(flatMapping, currentOutputPropsAST) {
if (flatMapping.outputExpr.parts.length === 0) {
currentOutputPropsAST.push({
type: SyntaxType.OBJECT_PROP_EXPR,
value: {
type: SyntaxType.SPREAD_EXPR,
value: flatMapping.inputExpr,
},
} as ObjectPropExpression);
return;
}
for (let i = 0; i < flatMapping.outputExpr.parts.length; i++) {
currentOutputPropsAST = processFlatMappingPart(flatMapping, i, currentOutputPropsAST);
}
Expand All @@ -216,15 +226,7 @@ export function convertToObjectMapping(
flatMappingASTs: FlatMappingAST[],
): ObjectExpression | PathExpression {
const outputAST: ObjectExpression = createObjectExpression();

for (let i = 0; i < flatMappingASTs.length; i++) {
const flatMapping = flatMappingASTs[i];
if (flatMapping.outputExpr.parts.length === 0) {
if (outputAST.props.length === 0 && i === flatMappingASTs.length - 1) {
return flatMapping.inputExpr;
}
throw new Error(`Invalid output mapping: ${flatMapping.output}`);
}
for (const flatMapping of flatMappingASTs) {
processFlatMapping(flatMapping, outputAST.props);
}

Expand Down
31 changes: 17 additions & 14 deletions test/scenarios/mappings/data.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { PathType } from '../../../src';
import type { Scenario } from '../../types';

const input = {
userId: 'u1',
discount: 10,
coupon: 'DISCOUNT',
events: ['purchase', 'custom'],
details: {
name: 'Purchase',
timestamp: 1630000000,
},
context: {
traits: {
email: '[email protected]',
Expand Down Expand Up @@ -153,16 +156,6 @@ export const data: Scenario[] = [
mappingsPath: 'invalid_object_mappings.json',
error: 'Invalid object mapping',
},
{
description: 'Root mapping is used after other mappings',
mappingsPath: 'invalid_root_mapping1.json',
error: 'Invalid output mapping',
},
{
description: 'Root mapping is used before other mappings',
mappingsPath: 'invalid_root_mapping2.json',
error: 'Invalid output mapping',
},
{
mappingsPath: 'mappings_with_root_fields.json',
input,
Expand Down Expand Up @@ -271,9 +264,19 @@ export const data: Scenario[] = [
},
},
{
mappingsPath: 'only_root_mapping.json',
input: { a: 1 },
output: { a: 1 },
mappingsPath: 'root_mappings.json',
input,
output: {
traits: {
email: '[email protected]',
first_name: 'John',
last_name: 'Doe',
phone: '1234567890',
},
event_names: ['purchase', 'custom'],
name: 'Purchase',
timestamp: 1630000000,
},
},
{
mappingsPath: 'transformations.json',
Expand Down
10 changes: 0 additions & 10 deletions test/scenarios/mappings/invalid_root_mapping1.json

This file was deleted.

10 changes: 0 additions & 10 deletions test/scenarios/mappings/invalid_root_mapping2.json

This file was deleted.

6 changes: 0 additions & 6 deletions test/scenarios/mappings/only_root_mapping.json

This file was deleted.

14 changes: 14 additions & 0 deletions test/scenarios/mappings/root_mappings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[
{
"input": "$.context",
"output": "$"
},
{
"input": "$.events",
"output": "$.event_names"
},
{
"input": "$.details",
"output": "$"
}
]

0 comments on commit f84aac6

Please sign in to comment.