Skip to content

Commit 1fef0e2

Browse files
authored
add types for @JSON directive (segmentio#1867)
* add types for @JSON directive * add explicit test for json
1 parent 329c0a8 commit 1fef0e2

File tree

2 files changed

+43
-3
lines changed

2 files changed

+43
-3
lines changed

packages/core/src/mapping-kit/__tests__/value-keys.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,19 @@ describe('getFieldValueKeys', () => {
8484

8585
expect(keys).toEqual(['properties.products', 'productId'])
8686
})
87+
88+
it('should return correct keys for @json', () => {
89+
const value = {
90+
'@json': {
91+
mode: 'encode',
92+
value: {
93+
'@template': '{{properties.products}}'
94+
}
95+
}
96+
}
97+
98+
const keys = getFieldValueKeys(value)
99+
100+
expect(keys).toEqual(['properties.products'])
101+
})
87102
})

packages/core/src/mapping-kit/value-keys.ts

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export function isDirective(value: FieldValue): value is Directive {
1616
value !== null &&
1717
typeof value === 'object' &&
1818
Object.keys(value).some((key) =>
19-
['@if', '@path', '@template', '@literal', '@arrayPath', '@case', '@replace'].includes(key)
19+
['@if', '@path', '@template', '@literal', '@arrayPath', '@case', '@replace', '@json'].includes(key)
2020
)
2121
)
2222
}
@@ -36,7 +36,7 @@ export function isTemplateDirective(value: FieldValue): value is TemplateDirecti
3636
return isDirective(value) && '@template' in value
3737
}
3838

39-
export function getFieldValue(value: FieldValue): any {
39+
export function getFieldValue(value: FieldValue): unknown {
4040
if (isTemplateDirective(value)) {
4141
return value['@template']
4242
}
@@ -123,6 +123,24 @@ export function isReplaceDirective(value: FieldValue): value is ReplaceDirective
123123
'pattern' in value['@replace']
124124
)
125125
}
126+
127+
export interface JSONDirective extends DirectiveMetadata {
128+
'@json': {
129+
value: FieldValue
130+
mode: PrimitiveValue
131+
}
132+
}
133+
134+
export function isJSONDirective(value: FieldValue): value is JSONDirective {
135+
return (
136+
isDirective(value) &&
137+
'@json' in value &&
138+
value['@json'] !== null &&
139+
typeof value['@json'] === 'object' &&
140+
'value' in value['@json']
141+
)
142+
}
143+
126144
type DirectiveKeysToType<T> = {
127145
['@arrayPath']: (input: ArrayPathDirective) => T
128146
['@case']: (input: CaseDirective) => T
@@ -131,6 +149,7 @@ type DirectiveKeysToType<T> = {
131149
['@path']: (input: PathDirective) => T
132150
['@replace']: (input: ReplaceDirective) => T
133151
['@template']: (input: TemplateDirective) => T
152+
['@json']: (input: JSONDirective) => T
134153
}
135154

136155
function directiveType<T>(directive: Directive, checker: DirectiveKeysToType<T>): T | null {
@@ -155,6 +174,9 @@ function directiveType<T>(directive: Directive, checker: DirectiveKeysToType<T>)
155174
if (isTemplateDirective(directive)) {
156175
return checker['@template'](directive)
157176
}
177+
if (isJSONDirective(directive)) {
178+
return checker['@json'](directive)
179+
}
158180
return null
159181
}
160182

@@ -166,6 +188,8 @@ export type Directive =
166188
| PathDirective
167189
| ReplaceDirective
168190
| TemplateDirective
191+
| JSONDirective
192+
169193
export type PrimitiveValue = boolean | number | string | null
170194
export type FieldValue = Directive | PrimitiveValue | { [key: string]: FieldValue } | FieldValue[] | undefined
171195

@@ -188,7 +212,8 @@ export function getFieldValueKeys(value: FieldValue): string[] {
188212
'@literal': (_: LiteralDirective) => [''],
189213
'@path': (input: PathDirective) => [input['@path']],
190214
'@replace': (input: ReplaceDirective) => getRawKeys(input['@replace'].value),
191-
'@template': (input: TemplateDirective) => getTemplateKeys(input['@template'])
215+
'@template': (input: TemplateDirective) => getTemplateKeys(input['@template']),
216+
'@json': (input: JSONDirective) => getRawKeys(input['@json'].value)
192217
})?.filter((k) => k) ?? []
193218
)
194219
} else if (isObject(value)) {

0 commit comments

Comments
 (0)