/
map-to-point.ts
135 lines (114 loc) · 3.23 KB
/
map-to-point.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import { IPoint } from "influx"
/**
* Timestamp mappings are used to source the "time" property to be sent to influx
*/
export interface TimestampMapping {
type: "timestamp"
/**
* the name of the field to source this property from
*/
from: string
/**
* default value, in case a result is missing this field
*/
default?: string
/**
* parsing function to transform the string value of the time stamp, into a number measured in ms
* @param value
*/
transform: (value: string) => number
}
/**
* Tag mappings are used to source the tags to associate with the point to be sent to influx
*/
export interface TagMapping {
type: "tag"
/**
* the name of the field to source this property from
*/
from: string
/**
* optional name to rename this field to when adding as a tag in influxdb
*/
to?: string
/**
* default value, in case a result is missing this field
*/
default?: string
/**
* optional parsing function to transform the value
* @param value
*/
transform?: (value: string) => string | void
}
/**
* Field mappings are used to source the fields to be recorded on a point to be sent to influx
*/
export interface FieldMapping {
type: "field",
/**
* the name of the field to source this property from
*/
from: string
/**
* optional name to rename this field to when adding as a tag in influxdb
*/
to?: string
/**
* default value, in case a result is missing this field
*/
default?: string
/**
* parsing function to transform the string value of the field into the correct type
* @param value
*/
transform: (value: string) => number | string | boolean | void
}
export type Mapping = TimestampMapping | TagMapping | FieldMapping
export function mapToPointFactory(measurement: string, mappings: Mapping[]) {
let timestamp: TimestampMapping
let tags: TagMapping[] = []
let fields: FieldMapping[] = []
for (let mapping of mappings) {
if (mapping.type === "timestamp") {
if (timestamp!!) {
throw new Error("cannot specify multiple timestamp mappings!")
}
if (!mapping.transform) {
throw new Error("timestamp mapping must include a transform")
}
timestamp = mapping
} else if (mapping.type === "tag") {
tags.push(mapping)
} else if (mapping.type === "field") {
fields.push(mapping)
}
}
return function mapToPoint(result: { [key: string]: string }): IPoint | undefined {
const point = {
measurement,
timestamp: timestamp.transform(result[timestamp.from]),
tags: mapValues(tags, result),
fields: mapValues(fields, result),
}
if (Object.keys(point.fields).length < fields.length || Object.keys(point.tags).length < tags.length) {
return undefined
}
return point
}
}
export function mapValues(mappings: Mapping[], result: { [key: string]: string }): any {
return mappings.reduce((acc, it) => {
const value = result[it.from] || it.default
if (!value) {
return acc
}
const transformedValue = it.transform ? it.transform(value) : value
if (!transformedValue) {
return acc
}
let dest = ("to" in it && it.to) ? it.to : it.from
acc[dest] = transformedValue
return acc
}, {} as any)
}