@things-factory/integration-influxdb 8.0.0-beta.8 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/integration-influxdb",
3
- "version": "8.0.0-beta.8",
3
+ "version": "8.0.0",
4
4
  "main": "dist-server/index.js",
5
5
  "browser": "dist-client/index.js",
6
6
  "things-factory": true,
@@ -27,8 +27,8 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "@influxdata/influxdb-client": "^1.33.2",
30
- "@things-factory/integration-base": "^8.0.0-beta.8",
30
+ "@things-factory/integration-base": "^8.0.0",
31
31
  "ses": "^1.5.0"
32
32
  },
33
- "gitHead": "bf5206511b2d84dfb95edc3dae7f54f6cbb9bcca"
33
+ "gitHead": "07ef27d272dd9a067a9648ac7013748510556a18"
34
34
  }
@@ -0,0 +1 @@
1
+ import './influxdb'
@@ -0,0 +1,69 @@
1
+ import { InfluxDB } from '@influxdata/influxdb-client'
2
+
3
+ import { Connection, ConnectionManager, Connector } from '@things-factory/integration-base'
4
+
5
+ export class InfluxDBConnector implements Connector {
6
+ async ready(connectionConfigs) {
7
+ await Promise.all(connectionConfigs.map(this.connect.bind(this)))
8
+
9
+ ConnectionManager.logger.info('influxdb connections are ready')
10
+ }
11
+
12
+ checkConnectionInstance(domain, connectionName): boolean {
13
+ try {
14
+ const connection = ConnectionManager.getConnectionInstanceByName(domain, connectionName)
15
+
16
+ return !!(connection?.client?.connectionState !== 'online')
17
+ } catch (e) {
18
+ return false
19
+ }
20
+ }
21
+
22
+ async connect(connection) {
23
+ var {
24
+ endpoint,
25
+ params: { token }
26
+ } = connection
27
+
28
+ try {
29
+ const client = new InfluxDB({ url: endpoint, token })
30
+
31
+ ConnectionManager.addConnectionInstance(connection, client)
32
+
33
+ ConnectionManager.logger.info(`influxdb connection(${connection.name}:${connection.endpoint}) is connected`)
34
+ } catch (ex) {
35
+ ConnectionManager.logger.info(
36
+ `influxdb connection(${connection.name}:${connection.endpoint}) failed to connect`,
37
+ ex
38
+ )
39
+ throw ex
40
+ }
41
+ }
42
+
43
+ async disconnect(connection: Connection) {
44
+ var client = ConnectionManager.removeConnectionInstance(connection)
45
+ // client.close()
46
+
47
+ ConnectionManager.logger.info(`influxdb connection(${connection.name}) is disconnected`)
48
+ }
49
+
50
+ get parameterSpec() {
51
+ return [
52
+ {
53
+ type: 'string',
54
+ name: 'token',
55
+ label: 'influxdb.token'
56
+ }
57
+ ]
58
+ }
59
+
60
+ get taskPrefixes() {
61
+ return ['influxdb']
62
+ }
63
+
64
+ get help() {
65
+ return 'integration/connector/influxdb-connector'
66
+ }
67
+ }
68
+
69
+ ConnectionManager.registerConnector('influxdb-connector', new InfluxDBConnector())
@@ -0,0 +1,2 @@
1
+ import './connector'
2
+ import './task'
@@ -0,0 +1,2 @@
1
+ import './influxdb-write-point'
2
+ import './influxdb-query'
@@ -0,0 +1,104 @@
1
+ import 'ses'
2
+ import { InfluxDB, FluxTableMetaData } from '@influxdata/influxdb-client'
3
+ import { ConnectionManager, Context, TaskRegistry } from '@things-factory/integration-base'
4
+
5
+ const debug = require('debug')('things-factory:influxdb-query')
6
+
7
+ interface InfluxData {
8
+ measurement: string
9
+ tags: { [key: string]: string }
10
+ fields: { [key: string]: number | string | boolean }
11
+ timestamp: string
12
+ }
13
+
14
+ interface InfluxRaw {
15
+ _time: string
16
+ _start: string
17
+ _stop: string
18
+ _measurement: string
19
+ _field: string
20
+ _value: any
21
+ table: any
22
+ result: any
23
+ [tag: string]: string
24
+ }
25
+
26
+ function processInfluxData(raws: InfluxRaw[]): InfluxData[] {
27
+ const result: { [time: string]: InfluxData } = {}
28
+
29
+ raws.forEach(raw => {
30
+ const { _time, _field, _value, _measurement, _start, _stop, result: _result, table, ...tags } = raw
31
+
32
+ result[_time] ||= {
33
+ timestamp: _time,
34
+ measurement: _measurement,
35
+ tags,
36
+ fields: {}
37
+ }
38
+
39
+ result[_time].fields[_field] = _value
40
+ })
41
+
42
+ return Object.values(result)
43
+ }
44
+
45
+ async function influxdbQuery(step, { domain, user, data, variables, lng }: Context) {
46
+ const {
47
+ connection,
48
+ params: { organization, query }
49
+ } = step
50
+
51
+ const client = ConnectionManager.getConnectionInstanceByName(domain, connection) as InfluxDB
52
+ if (!client) {
53
+ debug(`no connection : ${connection}`)
54
+ throw new Error(`no connection : ${connection}`)
55
+ }
56
+
57
+ const compartment = new Compartment({
58
+ domain,
59
+ user,
60
+ lng,
61
+ data,
62
+ variables,
63
+ console
64
+ })
65
+
66
+ let fluxQuery
67
+ try {
68
+ fluxQuery = compartment.evaluate('`' + query + '`')
69
+ } catch (err) {
70
+ throw new Error(`Failed to evaluate query: ${err.message}`)
71
+ }
72
+
73
+ const queryApi = client.getQueryApi(organization)
74
+
75
+ const result = await queryApi.collectRows(fluxQuery)
76
+
77
+ return {
78
+ data: processInfluxData(result as InfluxRaw[])
79
+ }
80
+ }
81
+
82
+ influxdbQuery.parameterSpec = [
83
+ {
84
+ type: 'string',
85
+ name: 'organization',
86
+ label: 'influxdb.organization'
87
+ },
88
+ {
89
+ type: 'textarea',
90
+ name: 'query',
91
+ label: 'influxdb.query',
92
+ property: {
93
+ language: 'text',
94
+ showLineNumbers: true
95
+ },
96
+ styles: {
97
+ flex: '1'
98
+ }
99
+ }
100
+ ]
101
+
102
+ influxdbQuery.help = 'integration/task/influxdb-query'
103
+
104
+ TaskRegistry.registerTaskHandler('influxdb-query', influxdbQuery)
@@ -0,0 +1,89 @@
1
+ import { Point } from '@influxdata/influxdb-client'
2
+
3
+ import { access } from '@things-factory/utils'
4
+ import { ConnectionManager, TaskRegistry } from '@things-factory/integration-base'
5
+
6
+ const debug = require('debug')('things-factory:influxdb-write-point')
7
+
8
+ type InfluxDBPointScheme = {
9
+ name: string
10
+ type: string
11
+ val?: any
12
+ accessor?: string
13
+ }
14
+
15
+ async function influxdbWritePoint(step, { logger, domain, data }) {
16
+ const {
17
+ connection,
18
+ params: { organization, bucket, measurement, scheme }
19
+ } = step
20
+
21
+ const client = ConnectionManager.getConnectionInstanceByName(domain, connection)
22
+ if (!client) {
23
+ debug(`no connection : ${connection}`)
24
+ throw new Error(`no connection : ${connection}`)
25
+ }
26
+
27
+ const writeClient = client.getWriteApi(organization, bucket, 'ns')
28
+ const point = new Point(measurement)
29
+
30
+ scheme.forEach((field: InfluxDBPointScheme) => {
31
+ const { name, val, type, accessor } = field
32
+ const calculated = accessor ? access(accessor, data) || val : val
33
+
34
+ switch (type) {
35
+ case 'Tag':
36
+ point.tag(name, calculated)
37
+ break
38
+ case 'String':
39
+ point.stringField(name, calculated)
40
+ break
41
+ case 'Integer':
42
+ point.intField(name, calculated)
43
+ break
44
+ case 'Unsigned':
45
+ point.uintField(name, calculated)
46
+ break
47
+ case 'Float':
48
+ point.floatField(name, calculated)
49
+ break
50
+ case 'Boolean':
51
+ point.booleanField(name, calculated)
52
+ break
53
+ }
54
+ })
55
+
56
+ await writeClient.writePoint(point)
57
+ await writeClient.close()
58
+
59
+ return {
60
+ data: point.fields
61
+ }
62
+ }
63
+
64
+ influxdbWritePoint.parameterSpec = [
65
+ {
66
+ type: 'string',
67
+ name: 'organization',
68
+ label: 'influxdb.organization'
69
+ },
70
+ {
71
+ type: 'string',
72
+ name: 'bucket',
73
+ label: 'influxdb.bucket'
74
+ },
75
+ {
76
+ type: 'string',
77
+ name: 'measurement',
78
+ label: 'influxdb.measurement'
79
+ },
80
+ {
81
+ type: 'influxdb-point-scheme',
82
+ name: 'scheme',
83
+ label: 'influxdb.point-scheme'
84
+ }
85
+ ]
86
+
87
+ influxdbWritePoint.help = 'integration/task/influxdb-write-point'
88
+
89
+ TaskRegistry.registerTaskHandler('influxdb-write-point', influxdbWritePoint)
@@ -0,0 +1 @@
1
+ import './engine'