@things-factory/integration-influxdb 8.0.0-beta.1 → 8.0.0-beta.2

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.1",
3
+ "version": "8.0.0-beta.2",
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.1",
30
+ "@things-factory/integration-base": "^8.0.0-beta.2",
31
31
  "ses": "^1.5.0"
32
32
  },
33
- "gitHead": "36c494e587640c1490318ef7b95adab02606e0c2"
33
+ "gitHead": "f03431a09435511b2595515658f9cb8f78ba4ebb"
34
34
  }
@@ -1,9 +0,0 @@
1
- import { OxPropertyEditor } from '@operato/property-editor'
2
-
3
- import './editors/property-editor'
4
-
5
- export default function bootstrap() {
6
- OxPropertyEditor.register({
7
- 'influxdb-point-scheme': 'property-editor-influxdb-point-scheme'
8
- })
9
- }
@@ -1,20 +0,0 @@
1
- /*
2
- * Copyright © HatioLab Inc. All rights reserved.
3
- */
4
- import './things-editor-influxdb-point-scheme'
5
-
6
- import { html } from 'lit'
7
-
8
- import { OxPropertyEditor } from '@operato/property-editor'
9
-
10
- export class PropertyEditorInfluxDBScheme extends OxPropertyEditor {
11
- static get styles() {
12
- return [...OxPropertyEditor.styles]
13
- }
14
-
15
- editorTemplate(value, spec) {
16
- return html` <things-editor-influxdb-point-scheme id="editor" .value=${value}></things-editor-influxdb-point-scheme> `
17
- }
18
- }
19
-
20
- customElements.define('property-editor-influxdb-point-scheme', PropertyEditorInfluxDBScheme)
@@ -1,308 +0,0 @@
1
- /**
2
- * @license Copyright © HatioLab Inc. All rights reserved.
3
- */
4
-
5
- import '@material/web/icon/icon.js'
6
- import '@operato/i18n/ox-i18n.js'
7
-
8
- import { css, html } from 'lit'
9
- import { customElement, property, queryAll } from 'lit/decorators.js'
10
-
11
- import { OxFormField } from '@operato/input'
12
-
13
- type InfluxDBPointScheme = {
14
- name: string
15
- type: string
16
- val?: any
17
- accessor?: string
18
- }
19
-
20
- /**
21
- input component for influxdb point scheme
22
-
23
- Example:
24
-
25
- <things-editor-influxdb-point-scheme
26
- value=${map}
27
- </things-editor-influxdb-point-scheme>
28
- */
29
- @customElement('things-editor-influxdb-point-scheme')
30
- export class ThingsEditorInfluxPointScheme extends OxFormField {
31
- static styles = [
32
- css`
33
- :host {
34
- display: flex;
35
- flex-direction: column;
36
- overflow: hidden;
37
- gap: var(--spacing-medium);
38
- }
39
-
40
- div {
41
- display: flex;
42
- flex-flow: row nowrap;
43
- gap: var(--spacing-medium);
44
- }
45
-
46
- button {
47
- border: var(--button-border);
48
- border-radius: var(--border-radius);
49
- background-color: var(--button-background-color);
50
- padding: var(--spacing-small) var(--spacing-medium);
51
- line-height: 0.8;
52
- color: var(--button-color);
53
- cursor: pointer;
54
- }
55
-
56
- button + button {
57
- margin-left: -5px;
58
- }
59
-
60
- button md-icon {
61
- font-size: var(--fontsize-default);
62
- }
63
-
64
- button:focus,
65
- button:hover,
66
- button:active {
67
- border: var(--button-activ-border);
68
- background-color: var(--button-background-focus-color);
69
- color: var(--md-sys-color-on-primary);
70
- }
71
-
72
- input {
73
- flex: 1;
74
- border: 0;
75
- border-bottom: var(--border-dim-color);
76
- padding: var(--input-padding);
77
- font: var(--input-font);
78
- color: var(--primary-text-color);
79
- min-width: 50px;
80
- }
81
-
82
- input:focus {
83
- outline: none;
84
- border-bottom: 1px solid var(--md-sys-color-primary);
85
- }
86
-
87
- button.hidden {
88
- opacity: 0;
89
- cursor: default;
90
- }
91
-
92
- select,
93
- ox-select,
94
- input:not([type='checkbox']) {
95
- border: 1px solid rgba(0, 0, 0, 0.2);
96
- border-radius: 4px;
97
- }
98
- `
99
- ]
100
-
101
- @property({ type: Array }) value: InfluxDBPointScheme[] = []
102
-
103
- private _changingNow: boolean = false
104
-
105
- @queryAll('[data-record]') records!: NodeListOf<HTMLElement>
106
-
107
- firstUpdated() {
108
- this.renderRoot.addEventListener('change', this._onChange.bind(this))
109
- }
110
-
111
- render() {
112
- const parameters = this.value || []
113
-
114
- return html`
115
- ${parameters.map(
116
- item => html`
117
- <div data-record>
118
- <input type="text" data-name placeholder="name" .value=${item.name} />
119
- <select data-type placeholder="type" .value=${item.type}>
120
- <option value="" ?selected=${item.type == ''}>&nbsp;</option>
121
- <option value="Tag" ?selected=${item.type == 'Tag'}>Tag</option>
122
- <option value="String" ?selected=${item.type == 'String'}>String</option>
123
- <option value="Integer" ?selected=${item.type == 'Integer'}>Integer</option>
124
- <option value="Unsigned" ?selected=${item.type == 'Unsigned'}>Unsigned</option>
125
- <option value="Float" ?selected=${item.type == 'Float'}>Float</option>
126
- <option value="Boolean" ?selected=${item.type == 'Boolean'}>Boolean</option>
127
- </select>
128
-
129
- <input type="text" data-accessor placeholder="accessor" .value=${item.accessor || ''} list="step-list" />
130
- <input type="text" data-val placeholder="val" .value=${item.val || ''} />
131
-
132
- <button class="record-action" @click=${(e: MouseEvent) => this._delete(e)} tabindex="-1">
133
- <md-icon>remove</md-icon>
134
- </button>
135
- <button class="record-action" @click=${(e: MouseEvent) => this._up(e)} tabindex="-1">
136
- <md-icon>arrow_upward</md-icon>
137
- </button>
138
- <button class="record-action" @click=${(e: MouseEvent) => this._down(e)} tabindex="-1">
139
- <md-icon>arrow_downward</md-icon>
140
- </button>
141
- </div>
142
- `
143
- )}
144
-
145
- <div data-record-new>
146
- <input type="text" data-name placeholder="name" value="" />
147
- <select data-type placeholder="type" value="">
148
- <option value="" selected>&nbsp;</option>
149
- <option value="Tag">Tag</option>
150
- <option value="String">String</option>
151
- <option value="Integer">Integer</option>
152
- <option value="Unsigned">Unsigned</option>
153
- <option value="Float">Float</option>
154
- <option value="Boolean">Boolean</option>
155
- </select>
156
- <input type="text" data-accessor placeholder="accessor" value="" list="step-list" />
157
- <input type="text" data-val placeholder="val" value="" />
158
-
159
- <button class="record-action" @click=${(e: MouseEvent) => this._add()} tabindex="-1">
160
- <md-icon>add</md-icon>
161
- </button>
162
- <button class="hidden"><md-icon>arrow_upward</md-icon></button>
163
- <button class="hidden"><md-icon>arrow_downward</md-icon></button>
164
- </div>
165
- `
166
- }
167
-
168
- _onChange(e: Event) {
169
- if (this._changingNow) {
170
- return
171
- }
172
-
173
- this._changingNow = true
174
-
175
- const input = e.target as HTMLInputElement
176
-
177
- const record = (e.target as Element).closest('[data-record],[data-record-new]') as HTMLElement
178
-
179
- if (record.hasAttribute('data-record')) {
180
- this._build()
181
- } else if (record.hasAttribute('data-record-new') && input.hasAttribute('data-type')) {
182
- this._add()
183
- }
184
-
185
- this._changingNow = false
186
- }
187
-
188
- _adjust({ name, type, val, accessor }: InfluxDBPointScheme): InfluxDBPointScheme {
189
- const entry = {
190
- name: name && String(name).trim(),
191
- type,
192
- accessor: accessor && String(accessor).trim(),
193
- val
194
- } as InfluxDBPointScheme
195
-
196
- return entry
197
- }
198
-
199
- _build(includeNewRecord?: boolean) {
200
- if (includeNewRecord) {
201
- var records = this.renderRoot.querySelectorAll('[data-record],[data-record-new]') as NodeListOf<HTMLElement>
202
- } else {
203
- var records = this.renderRoot.querySelectorAll('[data-record]') as NodeListOf<HTMLElement>
204
- }
205
-
206
- var newmap: InfluxDBPointScheme[] = []
207
-
208
- for (var i = 0; i < records.length; i++) {
209
- var record = records[i]
210
-
211
- const name = (record.querySelector('[data-name]') as HTMLInputElement).value
212
- const type = (record.querySelector('[data-type]') as HTMLInputElement).value
213
- const val = (record.querySelector('[data-val]') as HTMLInputElement).value
214
- const accessor = (record.querySelector('[data-accessor]') as HTMLInputElement).value
215
-
216
- const inputs = record.querySelectorAll(
217
- '[data-type]:not([style*="display: none"])'
218
- ) as NodeListOf<HTMLInputElement>
219
-
220
- if (!inputs || inputs.length == 0) {
221
- continue
222
- }
223
-
224
- if (name) {
225
- newmap.push(this._adjust({ name, type, val, accessor }))
226
- }
227
- }
228
-
229
- this.value = newmap
230
- this._updateValue()
231
- }
232
-
233
- _updateValue() {
234
- this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))
235
- }
236
-
237
- _add() {
238
- this._build(true)
239
-
240
- const inputs = this.renderRoot.querySelectorAll(
241
- '[data-record-new] input:not([style*="display: none"])'
242
- ) as NodeListOf<HTMLInputElement & { value: any }>
243
-
244
- for (var i = 0; i < inputs.length; i++) {
245
- let input = inputs[i]
246
-
247
- input.value = ''
248
- }
249
-
250
- inputs[0].focus()
251
- }
252
-
253
- _delete(e: MouseEvent) {
254
- const record = (e.target as Element).closest('[data-record]') as HTMLElement
255
-
256
- ;(record!.querySelector('[data-name]') as HTMLInputElement)!.value = ''
257
-
258
- this._build()
259
- }
260
-
261
- _up(e: MouseEvent) {
262
- const record = (e.target as Element).closest('[data-record]') as HTMLElement
263
- const array = Array.from(this.records)
264
- const index = array.indexOf(record) - 1
265
-
266
- if (index < 0) {
267
- return
268
- }
269
-
270
- const deleted = array.splice(index, 1)
271
- array.splice(index + 1, 0, ...deleted)
272
-
273
- this.value = array.map(record => {
274
- const name = (record.querySelector('[data-name]') as HTMLInputElement).value
275
- const type = (record.querySelector('[data-type]') as HTMLInputElement).value
276
- const val = (record.querySelector('[data-val]') as HTMLInputElement).value
277
- const accessor = (record.querySelector('[data-accessor]') as HTMLInputElement).value
278
-
279
- return this._adjust({ name, type, val, accessor })
280
- })
281
-
282
- this._updateValue()
283
- }
284
-
285
- _down(e: MouseEvent) {
286
- const record = (e.target as Element).closest('[data-record]') as HTMLElement
287
- const array = Array.from(this.records)
288
- const index = array.indexOf(record)
289
-
290
- if (index > array.length) {
291
- return
292
- }
293
-
294
- array.splice(index, 1)
295
- array.splice(index + 1, 0, record)
296
-
297
- this.value = array.map(record => {
298
- const name = (record.querySelector('[data-name]') as HTMLInputElement).value
299
- const type = (record.querySelector('[data-type]') as HTMLInputElement).value
300
- const val = (record.querySelector('[data-val]') as HTMLInputElement).value
301
- const accessor = (record.querySelector('[data-accessor]') as HTMLInputElement).value
302
-
303
- return this._adjust({ name, type, val, accessor })
304
- })
305
-
306
- this._updateValue()
307
- }
308
- }
package/client/index.ts DELETED
File without changes
@@ -1 +0,0 @@
1
- import './influxdb'
@@ -1,69 +0,0 @@
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())
@@ -1,2 +0,0 @@
1
- import './connector'
2
- import './task'
@@ -1,2 +0,0 @@
1
- import './influxdb-write-point'
2
- import './influxdb-query'
@@ -1,104 +0,0 @@
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)
@@ -1,89 +0,0 @@
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)
package/server/index.ts DELETED
@@ -1 +0,0 @@
1
- import './engine'