@5minds/node-red-contrib-processcube 1.5.7-feature-ff1077-m3q69zu4 → 1.5.7-feature-5c594a-m3r00p7a

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,6 +4,19 @@ module.exports = function (RED) {
4
4
  var node = this;
5
5
  node.engine = RED.nodes.getNode(config.engine);
6
6
 
7
+ let subscription = null;
8
+
9
+ const eventEmitter = node.engine.eventEmitter;
10
+
11
+ eventEmitter.on('engine-client-dispose', () => {
12
+ node.engine.engineClient.events.removeSubscription(subscription, node.engine.identity);
13
+ });
14
+
15
+ eventEmitter.on('engine-client-changed', () => {
16
+ node.log('new engineClient received');
17
+ register();
18
+ });
19
+
7
20
  const register = async () => {
8
21
  const client = node.engine.engineClient;
9
22
 
@@ -11,10 +24,8 @@ module.exports = function (RED) {
11
24
  node.error('No engine configured.');
12
25
  return;
13
26
  }
14
-
15
- let currentIdentity = node.engine.identity;
16
27
 
17
- let subscription = null;
28
+ let currentIdentity = node.engine.identity;
18
29
 
19
30
  try {
20
31
  subscription = await client.events.onEndEventFinished(
@@ -23,24 +34,23 @@ module.exports = function (RED) {
23
34
  payload: endEventFinished,
24
35
  });
25
36
  },
26
- { identity: currentIdentity },
37
+ { identity: currentIdentity }
27
38
  );
28
39
 
29
40
  node.engine.registerOnIdentityChanged(async (identity) => {
30
41
  client.events.removeSubscription(subscription, currentIdentity);
31
-
42
+
32
43
  currentIdentity = identity;
33
44
 
34
45
  subscription = await client.events.onEndEventFinished(
35
46
  (endEventFinished) => {
36
47
  node.send({
37
- payload: endEventFinished
48
+ payload: endEventFinished,
38
49
  });
39
50
  },
40
- { identity: currentIdentity },
51
+ { identity: currentIdentity }
41
52
  );
42
53
  });
43
-
44
54
  } catch (error) {
45
55
  node.error(error);
46
56
  }
@@ -4,6 +4,19 @@ module.exports = function (RED) {
4
4
  var node = this;
5
5
  node.engine = RED.nodes.getNode(config.engine);
6
6
 
7
+ let subscription;
8
+
9
+ const eventEmitter = node.engine.eventEmitter;
10
+
11
+ eventEmitter.on('engine-client-dispose', () => {
12
+ node.engine.engineClient.notification.removeSubscription(subscription, node.engine.identity);
13
+ });
14
+
15
+ eventEmitter.on('engine-client-changed', () => {
16
+ node.log('new engineClient received');
17
+ register();
18
+ });
19
+
7
20
  const register = async () => {
8
21
  let currentIdentity = node.engine.identity;
9
22
 
@@ -14,8 +27,6 @@ module.exports = function (RED) {
14
27
  return;
15
28
  }
16
29
 
17
- let subscription;
18
-
19
30
  function externalTaskCallback() {
20
31
  return (externalTaskNotification) => {
21
32
  if (config.externaltask != '' && config.externaltask != externalTaskNotification.flowNodeId) return;
@@ -32,135 +32,156 @@ module.exports = function (RED) {
32
32
  eventEmitter = flowContext.get('emitter');
33
33
  }
34
34
 
35
- const etwCallback = async (payload, externalTask) => {
36
- const saveHandleCallback = (data, callback) => {
37
- try {
38
- callback(data);
39
- } catch (error) {
40
- node.error(`Error in callback 'saveHandleCallback': ${error.message}`);
41
- }
42
- };
35
+ const engineEventEmitter = node.engine.eventEmitter;
43
36
 
44
- return await new Promise((resolve, reject) => {
45
- const handleFinishTask = (msg) => {
46
- let result = RED.util.encodeObject(msg.payload);
37
+ engineEventEmitter.on('engine-client-dispose', () => {
38
+ node.engine.engineClient.externalTasks.removeSubscription(subscription, node.engine.identity);
39
+ });
47
40
 
48
- node.log(
49
- `handle event for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* ${externalTask.processInstanceId} with result ${result} on msg._msgid ${msg._msgid}.`
50
- );
41
+ engineEventEmitter.on('engine-client-changed', () => {
42
+ node.log('new engineClient received');
43
+ register();
44
+ });
51
45
 
52
- if (externalTask.flowNodeInstanceId) {
53
- delete started_external_tasks[externalTask.flowNodeInstanceId];
46
+ const register = async () => {
47
+ const etwCallback = async (payload, externalTask) => {
48
+ const saveHandleCallback = (data, callback) => {
49
+ try {
50
+ callback(data);
51
+ } catch (error) {
52
+ node.error(`Error in callback 'saveHandleCallback': ${error.message}`);
54
53
  }
55
-
56
- showStatus(node, Object.keys(started_external_tasks).length);
57
-
58
- //resolve(result);
59
- saveHandleCallback(result, resolve);
60
54
  };
61
55
 
62
- const handleErrorTask = (msg) => {
63
- node.log(
64
- `handle error event for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' on *msg._msgid* '${msg._msgid}'.`
65
- );
56
+ return await new Promise((resolve, reject) => {
57
+ const handleFinishTask = (msg) => {
58
+ let result = RED.util.encodeObject(msg.payload);
66
59
 
67
- if (externalTask.flowNodeInstanceId) {
68
- delete started_external_tasks[externalTask.flowNodeInstanceId];
69
- }
60
+ node.log(
61
+ `handle event for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* ${externalTask.processInstanceId} with result ${result} on msg._msgid ${msg._msgid}.`
62
+ );
70
63
 
71
- showStatus(node, Object.keys(started_external_tasks).length);
64
+ if (externalTask.flowNodeInstanceId) {
65
+ delete started_external_tasks[externalTask.flowNodeInstanceId];
66
+ }
72
67
 
73
- // TODO: with reject, the default error handling is proceed
74
- // SEE: https://github.com/5minds/ProcessCube.Engine.Client.ts/blob/develop/src/ExternalTaskWorker.ts#L180
75
- // reject(result);
76
- //resolve(msg);
77
- saveHandleCallback(msg, resolve);
78
- };
68
+ showStatus(node, Object.keys(started_external_tasks).length);
79
69
 
80
- eventEmitter.once(`handle-${externalTask.flowNodeInstanceId}`, (msg, isError = false) => {
81
- node.log(
82
- `handle event for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' with *msg._msgid* '${msg._msgid}' and *isError* '${isError}'`
83
- );
70
+ //resolve(result);
71
+ saveHandleCallback(result, resolve);
72
+ };
84
73
 
85
- if (isError) {
86
- handleErrorTask(msg);
87
- } else {
88
- handleFinishTask(msg);
89
- }
90
- });
74
+ const handleErrorTask = (msg) => {
75
+ node.log(
76
+ `handle error event for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' on *msg._msgid* '${msg._msgid}'.`
77
+ );
91
78
 
92
- started_external_tasks[externalTask.flowNodeInstanceId] = externalTask;
79
+ if (externalTask.flowNodeInstanceId) {
80
+ delete started_external_tasks[externalTask.flowNodeInstanceId];
81
+ }
93
82
 
94
- showStatus(node, Object.keys(started_external_tasks).length);
83
+ showStatus(node, Object.keys(started_external_tasks).length);
95
84
 
96
- let msg = {
97
- _msgid: RED.util.generateId(),
98
- task: RED.util.encodeObject(externalTask),
99
- payload: payload,
100
- flowNodeInstanceId: externalTask.flowNodeInstanceId,
101
- processInstanceId: externalTask.processInstanceId,
102
- };
85
+ // TODO: with reject, the default error handling is proceed
86
+ // SEE: https://github.com/5minds/ProcessCube.Engine.Client.ts/blob/develop/src/ExternalTaskWorker.ts#L180
87
+ // reject(result);
88
+ //resolve(msg);
89
+ saveHandleCallback(msg, resolve);
90
+ };
103
91
 
104
- node.log(
105
- `Received *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' with *msg._msgid* '${msg._msgid}'`
106
- );
92
+ eventEmitter.once(`handle-${externalTask.flowNodeInstanceId}`, (msg, isError = false) => {
93
+ node.log(
94
+ `handle event for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' with *msg._msgid* '${msg._msgid}' and *isError* '${isError}'`
95
+ );
107
96
 
108
- node.send(msg);
109
- });
110
- };
97
+ if (isError) {
98
+ handleErrorTask(msg);
99
+ } else {
100
+ handleFinishTask(msg);
101
+ }
102
+ });
111
103
 
112
- let options = RED.util.evaluateNodeProperty(config.workerConfig, 'json', node);
104
+ started_external_tasks[externalTask.flowNodeInstanceId] = externalTask;
113
105
 
114
- client.externalTasks
115
- .subscribeToExternalTaskTopic(config.topic, etwCallback, options)
116
- .then(async (externalTaskWorker) => {
117
- node.status({ fill: 'blue', shape: 'ring', text: 'subcribed' });
106
+ showStatus(node, Object.keys(started_external_tasks).length);
118
107
 
119
- externalTaskWorker.identity = engine.identity;
120
- engine.registerOnIdentityChanged((identity) => {
121
- externalTaskWorker.identity = identity;
122
- });
108
+ let msg = {
109
+ _msgid: RED.util.generateId(),
110
+ task: RED.util.encodeObject(externalTask),
111
+ payload: payload,
112
+ flowNodeInstanceId: externalTask.flowNodeInstanceId,
113
+ processInstanceId: externalTask.processInstanceId,
114
+ };
123
115
 
124
- // export type WorkerErrorHandler = (errorType: 'fetchAndLock' | 'extendLock' | 'processExternalTask' | 'finishExternalTask', error: Error, externalTask?: ExternalTask<any>) => void;
125
- externalTaskWorker.onWorkerError((errorType, error, externalTask) => {
126
- switch (errorType) {
127
- case 'extendLock':
128
- case 'finishExternalTask':
129
- case 'processExternalTask':
130
- node.error(
131
- `Worker error ${errorType} for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}': ${error.message}`
132
- );
133
-
134
- if (externalTask) {
135
- delete started_external_tasks[externalTask.flowNodeInstanceId];
136
- }
137
-
138
- showStatus(node, Object.keys(started_external_tasks).length);
139
- break;
140
- default:
141
- // reduce noise error logs
142
- // node.error(`Worker error ${errorType}: ${error.message}`);
143
- break;
144
- }
116
+ node.log(
117
+ `Received *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' with *msg._msgid* '${msg._msgid}'`
118
+ );
119
+
120
+ node.send(msg);
145
121
  });
122
+ };
146
123
 
147
- try {
148
- externalTaskWorker.start();
149
- } catch (error) {
150
- node.error(`Worker start 'externalTaskWorker.start' failed: ${error.message}`);
151
- }
124
+ let options = RED.util.evaluateNodeProperty(config.workerConfig, 'json', node);
125
+
126
+ client.externalTasks
127
+ .subscribeToExternalTaskTopic(config.topic, etwCallback, options)
128
+ .then(async (externalTaskWorker) => {
129
+ node.status({ fill: 'blue', shape: 'ring', text: 'subcribed' });
130
+
131
+ externalTaskWorker.identity = engine.identity;
132
+ engine.registerOnIdentityChanged((identity) => {
133
+ externalTaskWorker.identity = identity;
134
+ });
135
+
136
+ // export type WorkerErrorHandler = (errorType: 'fetchAndLock' | 'extendLock' | 'processExternalTask' | 'finishExternalTask', error: Error, externalTask?: ExternalTask<any>) => void;
137
+ externalTaskWorker.onWorkerError((errorType, error, externalTask) => {
138
+ switch (errorType) {
139
+ case 'extendLock':
140
+ case 'finishExternalTask':
141
+ case 'processExternalTask':
142
+ node.error(
143
+ `Worker error ${errorType} for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}': ${error.message}`
144
+ );
145
+
146
+ if (externalTask) {
147
+ delete started_external_tasks[externalTask.flowNodeInstanceId];
148
+ }
149
+
150
+ showStatus(node, Object.keys(started_external_tasks).length);
151
+ break;
152
+ case 'fetchAndLock':
153
+ node.status({});
154
+ node.error(`Worker error ${errorType}: ${error.message}`);
155
+ break;
156
+ default:
157
+ // reduce noise error logs
158
+ // node.error(`Worker error ${errorType}: ${error.message}`);
159
+ break;
160
+ }
161
+ });
152
162
 
153
- node.on('close', () => {
154
163
  try {
155
- externalTaskWorker.stop();
156
- } catch {
157
- node.error('Client close failed');
164
+ externalTaskWorker.start();
165
+ } catch (error) {
166
+ node.error(`Worker start 'externalTaskWorker.start' failed: ${error.message}`);
158
167
  }
168
+
169
+ node.on('close', () => {
170
+ try {
171
+ externalTaskWorker.stop();
172
+ } catch {
173
+ node.error('Client close failed');
174
+ }
175
+ });
176
+ })
177
+ .catch((error) => {
178
+ node.error(`Error in subscribeToExternalTaskTopic: ${error.message}`);
159
179
  });
160
- })
161
- .catch((error) => {
162
- node.error(`Error in subscribeToExternalTaskTopic: ${error.message}`);
163
- });
180
+ };
181
+
182
+ if (node.engine) {
183
+ register();
184
+ }
164
185
  }
165
186
 
166
187
  RED.nodes.registerType('externaltask-input', ExternalTaskInput);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@5minds/node-red-contrib-processcube",
3
- "version": "1.5.7-feature-ff1077-m3q69zu4",
3
+ "version": "1.5.7-feature-5c594a-m3r00p7a",
4
4
  "license": "MIT",
5
5
  "description": "Node-RED nodes for ProcessCube",
6
6
  "scripts": {
@@ -4,6 +4,19 @@ module.exports = function (RED) {
4
4
  var node = this;
5
5
  node.engine = RED.nodes.getNode(config.engine);
6
6
 
7
+ let subscription;
8
+
9
+ const eventEmitter = node.engine.eventEmitter;
10
+
11
+ engineEventEmitter.on('engine-client-dispose', () => {
12
+ node.engine.engineClient.notification.removeSubscription(subscription, node.engine.identity);
13
+ });
14
+
15
+ eventEmitter.on('engine-client-changed', () => {
16
+ node.log('new engineClient received');
17
+ register();
18
+ });
19
+
7
20
  const register = async () => {
8
21
  const client = node.engine.engineClient;
9
22
 
@@ -14,7 +27,6 @@ module.exports = function (RED) {
14
27
 
15
28
  let currentIdentity = node.engine.identity;
16
29
 
17
- let subscription;
18
30
  const query = RED.util.evaluateNodeProperty(config.query, config.query_type, node);
19
31
 
20
32
  async function subscribe(eventType) {
@@ -24,7 +36,8 @@ module.exports = function (RED) {
24
36
  async (processNotification) => {
25
37
  if (
26
38
  config.processmodel != '' &&
27
- config.processmodel != processNotification.processModelId) {
39
+ config.processmodel != processNotification.processModelId
40
+ ) {
28
41
  return;
29
42
  }
30
43
 
@@ -65,7 +78,8 @@ module.exports = function (RED) {
65
78
  async (processNotification) => {
66
79
  if (
67
80
  config.processmodel != '' &&
68
- config.processmodel != processNotification.processModelId) {
81
+ config.processmodel != processNotification.processModelId
82
+ ) {
69
83
  return;
70
84
  }
71
85
 
@@ -433,7 +447,6 @@ module.exports = function (RED) {
433
447
  },
434
448
  { identity: currentIdentity }
435
449
  );
436
-
437
450
  });
438
451
 
439
452
  node.on('close', () => {
@@ -1,3 +1,4 @@
1
+ const EventEmitter = require('node:events');
1
2
  const engine_client = require('@5minds/processcube_engine_client');
2
3
  const jwt = require('jwt-decode');
3
4
  const oidc = require('openid-client');
@@ -12,7 +13,8 @@ module.exports = function (RED) {
12
13
  this.credentials.clientId = RED.util.evaluateNodeProperty(n.clientId, n.clientIdType, node);
13
14
  this.credentials.clientSecret = RED.util.evaluateNodeProperty(n.clientSecret, n.clientSecretType, node);
14
15
 
15
- // known issue: kann bei falschem timing zu laufzeitfehlern führen (absprache MM)
16
+ node.eventEmitter = new EventEmitter();
17
+
16
18
  // set the engine url
17
19
  const stopRefreshing = periodicallyRefreshEngineClient(this, n, 10000);
18
20
 
@@ -41,23 +43,29 @@ module.exports = function (RED) {
41
43
  function refreshUrl() {
42
44
  const newUrl = RED.util.evaluateNodeProperty(n.url, n.urlType, node);
43
45
 
44
- if (node.url == newUrl) {
46
+ if (node.url === newUrl) {
45
47
  return;
46
48
  }
47
49
 
48
50
  node.url = newUrl;
49
51
  if (node.credentials.clientId && node.credentials.clientSecret) {
50
- if (this.engineClient) {
51
- this.engineClient.dispose();
52
+ if (node.engineClient) {
53
+ node.eventEmitter.emit('engine-client-dispose');
54
+ node.engineClient.dispose();
52
55
  }
53
56
  node.engineClient = new engine_client.EngineClient(node.url, () =>
54
57
  getFreshIdentity(node.url, node)
55
58
  );
59
+
60
+ node.eventEmitter.emit('engine-client-changed');
56
61
  } else {
57
- if (this.engineClient) {
58
- this.engineClient.dispose();
62
+ if (node.engineClient) {
63
+ node.eventEmitter.emit('engine-client-dispose');
64
+ node.engineClient.dispose();
59
65
  }
60
66
  node.engineClient = new engine_client.EngineClient(node.url);
67
+
68
+ node.eventEmitter.emit('engine-client-changed');
61
69
  }
62
70
  }
63
71
 
@@ -4,6 +4,19 @@ module.exports = function (RED) {
4
4
  var node = this;
5
5
  node.engine = RED.nodes.getNode(config.engine);
6
6
 
7
+ let subscription;
8
+
9
+ const eventEmitter = node.engine.eventEmitter;
10
+
11
+ eventEmitter.on('engine-client-dispose', () => {
12
+ node.engine.engineClient.userTasks.removeSubscription(subscription, node.engine.identity);
13
+ });
14
+
15
+ eventEmitter.on('engine-client-changed', () => {
16
+ node.log('new engineClient received');
17
+ register();
18
+ });
19
+
7
20
  const register = async () => {
8
21
  let currentIdentity = node.engine.identity;
9
22
 
@@ -14,13 +27,12 @@ module.exports = function (RED) {
14
27
  return;
15
28
  }
16
29
 
17
- let subscription;
18
30
  const query = RED.util.evaluateNodeProperty(config.query, config.query_type, node);
19
31
 
20
32
  function userTaskCallback() {
21
33
  return async (userTaskNotification) => {
22
34
  if (config.usertask != '' && config.usertask != userTaskNotification.flowNodeId) return;
23
-
35
+
24
36
  const newQuery = {
25
37
  flowNodeInstanceId: userTaskNotification.flowNodeInstanceId,
26
38
  ...query,
@@ -84,7 +96,7 @@ module.exports = function (RED) {
84
96
  currentIdentity = identity;
85
97
 
86
98
  subscription = subscribe();
87
- })
99
+ });
88
100
 
89
101
  node.on('close', async () => {
90
102
  if (node.engine && node.engine.engineClient && client) {
@@ -5,13 +5,12 @@ module.exports = function (RED) {
5
5
 
6
6
  node.engine = RED.nodes.getNode(config.engine);
7
7
 
8
- const client = node.engine.engineClient;
9
-
10
8
  let subscription = null;
11
9
  let currentIdentity = node.engine.identity;
12
10
  let subscribe = null;
13
11
 
14
12
  node.on('input', async function (msg) {
13
+ const client = node.engine.engineClient;
15
14
  subscribe = async () => {
16
15
  if (!client) {
17
16
  node.error('No engine configured.');
@@ -20,44 +19,49 @@ module.exports = function (RED) {
20
19
 
21
20
  const query = RED.util.evaluateNodeProperty(config.query, config.query_type, node, msg);
22
21
 
23
- subscription = await client.userTasks.onUserTaskWaiting(async (userTaskWaitingNotification) => {
24
-
25
- const newQuery = {
26
- 'flowNodeInstanceId': userTaskWaitingNotification.flowNodeInstanceId,
27
- ...query
28
- };
29
-
30
- try {
31
- const matchingFlowNodes = await client.userTasks.query(newQuery, { identity: currentIdentity });
32
-
33
- if (matchingFlowNodes.userTasks && matchingFlowNodes.userTasks.length == 1) {
34
- // remove subscription
35
- client.userTasks.removeSubscription(subscription, currentIdentity);
36
-
37
- const userTask = matchingFlowNodes.userTasks[0];
38
-
39
- msg.payload = { userTask: userTask };
40
- node.send(msg);
41
- } else {
42
- // nothing todo - wait for next notification
22
+ subscription = await client.userTasks.onUserTaskWaiting(
23
+ async (userTaskWaitingNotification) => {
24
+ const newQuery = {
25
+ flowNodeInstanceId: userTaskWaitingNotification.flowNodeInstanceId,
26
+ ...query,
27
+ };
28
+
29
+ try {
30
+ const matchingFlowNodes = await client.userTasks.query(newQuery, {
31
+ identity: currentIdentity,
32
+ });
33
+
34
+ if (matchingFlowNodes.userTasks && matchingFlowNodes.userTasks.length == 1) {
35
+ // remove subscription
36
+ client.userTasks.removeSubscription(subscription, currentIdentity);
37
+
38
+ const userTask = matchingFlowNodes.userTasks[0];
39
+
40
+ msg.payload = { userTask: userTask };
41
+ node.send(msg);
42
+ } else {
43
+ // nothing todo - wait for next notification
44
+ }
45
+ } catch (error) {
46
+ node.error(error);
43
47
  }
44
- } catch (error) {
45
- node.error(error);
46
- }
48
+ },
49
+ { identity: currentIdentity }
50
+ );
47
51
 
48
- }, { identity: currentIdentity });
49
-
50
- node.log({ "Handling old userTasks config.only_for_new": config.only_for_new });
52
+ node.log({ 'Handling old userTasks config.only_for_new': config.only_for_new });
51
53
 
52
54
  if (config.only_for_new === false) {
53
55
  // only check suspended user tasks
54
56
  const suspendedQuery = {
55
- 'state': 'suspended',
56
- ...query
57
+ state: 'suspended',
58
+ ...query,
57
59
  };
58
60
 
59
61
  try {
60
- const matchingFlowNodes = await client.userTasks.query(suspendedQuery, { identity: currentIdentity });
62
+ const matchingFlowNodes = await client.userTasks.query(suspendedQuery, {
63
+ identity: currentIdentity,
64
+ });
61
65
 
62
66
  if (matchingFlowNodes.userTasks && matchingFlowNodes.userTasks.length >= 1) {
63
67
  const userTask = matchingFlowNodes.userTasks[0];
@@ -80,7 +84,6 @@ module.exports = function (RED) {
80
84
  });
81
85
 
82
86
  node.engine.registerOnIdentityChanged(async (identity) => {
83
-
84
87
  if (subscription) {
85
88
  client.userTasks.removeSubscription(subscription, currentIdentity);
86
89
  currentIdentity = identity;
@@ -90,11 +93,11 @@ module.exports = function (RED) {
90
93
  }
91
94
  });
92
95
 
93
- node.on("close", async () => {
96
+ node.on('close', async () => {
94
97
  if (client != null && subscription != null) {
95
98
  client.userTasks.removeSubscription(subscription, currentIdentity);
96
99
  }
97
100
  });
98
101
  }
99
- RED.nodes.registerType("wait-for-usertask", WaitForUsertask);
100
- }
102
+ RED.nodes.registerType('wait-for-usertask', WaitForUsertask);
103
+ };