node-opcua-address-space 2.166.0 → 2.168.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": "node-opcua-address-space",
3
- "version": "2.166.0",
3
+ "version": "2.168.0",
4
4
  "description": "pure nodejs OPCUA SDK - module address-space",
5
5
  "main": "./dist/src/index_current.js",
6
6
  "types": "./dist/source/index.d.ts",
@@ -10,6 +10,7 @@
10
10
  "scripts": {
11
11
  "build": "tsc -b",
12
12
  "test": "mocha",
13
+ "test:check": "tsc --noEmit -p test/tsconfig.json",
13
14
  "lint": "eslint source test src source_nodejs test_helpers",
14
15
  "format": "prettier --write source test src source_nodejs test_helpers",
15
16
  "clean": "npx rimraf -g node_modules dist *.tsbuildinfo",
@@ -17,53 +18,51 @@
17
18
  "fix:tsconfig": "node ../../code_gen/extract-modules.js tsconfig_base.json"
18
19
  },
19
20
  "dependencies": {
20
- "@types/lodash": "4.17.24",
21
21
  "@types/semver": "7.7.1",
22
22
  "chalk": "4.1.2",
23
23
  "dequeue": "^1.0.5",
24
- "lodash": "4.17.23",
25
- "node-opcua-address-space-base": "2.165.0",
24
+ "node-opcua-address-space-base": "2.168.0",
26
25
  "node-opcua-assert": "2.164.0",
27
- "node-opcua-basic-types": "2.165.0",
28
- "node-opcua-binary-stream": "2.165.0",
29
- "node-opcua-client-dynamic-extension-object": "2.166.0",
26
+ "node-opcua-basic-types": "2.168.0",
27
+ "node-opcua-binary-stream": "2.168.0",
28
+ "node-opcua-client-dynamic-extension-object": "2.168.0",
30
29
  "node-opcua-constants": "2.157.0",
31
- "node-opcua-crypto": "5.3.0",
32
- "node-opcua-data-access": "2.165.0",
33
- "node-opcua-data-model": "2.165.0",
34
- "node-opcua-data-value": "2.165.0",
35
- "node-opcua-date-time": "2.165.0",
36
- "node-opcua-debug": "2.165.0",
37
- "node-opcua-enum": "2.165.0",
38
- "node-opcua-extension-object": "2.165.0",
39
- "node-opcua-factory": "2.165.0",
40
- "node-opcua-nodeid": "2.165.0",
41
- "node-opcua-nodeset-ua": "2.165.0",
42
- "node-opcua-numeric-range": "2.165.0",
43
- "node-opcua-object-registry": "2.165.0",
44
- "node-opcua-pseudo-session": "2.166.0",
45
- "node-opcua-service-browse": "2.165.0",
46
- "node-opcua-service-call": "2.165.0",
47
- "node-opcua-service-history": "2.165.0",
48
- "node-opcua-service-translate-browse-path": "2.165.0",
49
- "node-opcua-service-write": "2.165.0",
50
- "node-opcua-status-code": "2.165.0",
51
- "node-opcua-types": "2.165.0",
52
- "node-opcua-utils": "2.165.0",
53
- "node-opcua-variant": "2.165.0",
54
- "node-opcua-xml2json": "2.165.0",
30
+ "node-opcua-crypto": "5.3.3",
31
+ "node-opcua-data-access": "2.168.0",
32
+ "node-opcua-data-model": "2.168.0",
33
+ "node-opcua-data-value": "2.168.0",
34
+ "node-opcua-date-time": "2.168.0",
35
+ "node-opcua-debug": "2.168.0",
36
+ "node-opcua-enum": "2.168.0",
37
+ "node-opcua-extension-object": "2.168.0",
38
+ "node-opcua-factory": "2.168.0",
39
+ "node-opcua-nodeid": "2.168.0",
40
+ "node-opcua-nodeset-ua": "2.168.0",
41
+ "node-opcua-numeric-range": "2.168.0",
42
+ "node-opcua-object-registry": "2.168.0",
43
+ "node-opcua-pseudo-session": "2.168.0",
44
+ "node-opcua-service-browse": "2.168.0",
45
+ "node-opcua-service-call": "2.168.0",
46
+ "node-opcua-service-history": "2.168.0",
47
+ "node-opcua-service-translate-browse-path": "2.168.0",
48
+ "node-opcua-service-write": "2.168.0",
49
+ "node-opcua-status-code": "2.168.0",
50
+ "node-opcua-types": "2.168.0",
51
+ "node-opcua-utils": "2.168.0",
52
+ "node-opcua-variant": "2.168.0",
53
+ "node-opcua-xml2json": "2.168.0",
55
54
  "semver": "^7.7.4",
56
55
  "thenify-ex": "4.4.0",
57
56
  "xml-writer": "^1.7.0"
58
57
  },
59
58
  "devDependencies": {
60
59
  "humanize": "0.0.9",
61
- "node-opcua-benchmarker": "2.165.0",
62
- "node-opcua-leak-detector": "2.165.0",
60
+ "node-opcua-benchmarker": "2.168.0",
61
+ "node-opcua-leak-detector": "2.168.0",
63
62
  "node-opcua-nodesets": "2.163.1",
64
- "node-opcua-packet-analyzer": "2.165.0",
65
- "node-opcua-schemas": "2.165.0",
66
- "node-opcua-service-filter": "2.165.0",
63
+ "node-opcua-packet-analyzer": "2.168.0",
64
+ "node-opcua-schemas": "2.168.0",
65
+ "node-opcua-service-filter": "2.168.0",
67
66
  "node-opcua-test-fixtures": "2.157.0"
68
67
  },
69
68
  "author": "Etienne Rossignon",
@@ -81,7 +80,7 @@
81
80
  "internet of things"
82
81
  ],
83
82
  "homepage": "http://node-opcua.github.io/",
84
- "gitHead": "b50d48c0ebd4761670529bf66f39a9c402a07845",
83
+ "gitHead": "653b6d6df801ca17298308089dee32e5b12102b6",
85
84
  "files": [
86
85
  "dist",
87
86
  "distHelpers",
@@ -1,25 +1,26 @@
1
1
  /**
2
2
  * @module node-opcua-address-space
3
3
  */
4
+ /** biome-ignore-all lint/style/useLiteralEnumMembers: still needed */
4
5
 
6
+ import type { BaseNode, ISessionBase, ISessionContext, UAObject, UAObjectType, UAVariable } from "node-opcua-address-space-base";
5
7
  import { assert } from "node-opcua-assert";
6
- import { Certificate, CertificateInternals, exploreCertificate } from "node-opcua-crypto/web";
7
- import { AccessRestrictionsFlag, allPermissions, AttributeIds, PermissionFlag } from "node-opcua-data-model";
8
- import { PreciseClock } from "node-opcua-date-time";
9
- import { NodeId, NodeIdLike, resolveNodeId, sameNodeId } from "node-opcua-nodeid";
8
+ import { ObjectIds } from "node-opcua-constants";
9
+ import { type Certificate, type CertificateInternals, exploreCertificate } from "node-opcua-crypto/web";
10
+ import { AccessRestrictionsFlag, AttributeIds, allPermissions, PermissionFlag } from "node-opcua-data-model";
11
+ import type { PreciseClock } from "node-opcua-date-time";
12
+ import { type NodeId, type NodeIdLike, resolveNodeId, sameNodeId } from "node-opcua-nodeid";
10
13
  import {
11
14
  AnonymousIdentityToken,
12
15
  MessageSecurityMode,
13
16
  PermissionType,
14
- RolePermissionType,
17
+ type RolePermissionType,
15
18
  UserNameIdentityToken,
16
19
  X509IdentityToken
17
20
  } from "node-opcua-types";
18
- import { ISessionContext, UAObject, UAObjectType, UAVariable, BaseNode, ISessionBase } from "node-opcua-address-space-base";
19
- import { ObjectIds } from "node-opcua-constants";
20
- import { NamespacePrivate } from "../src/namespace_private";
21
+ import type { NamespacePrivate } from "../src/namespace_private";
21
22
 
22
- export { RolePermissionType, RolePermissionTypeOptions, PermissionType } from "node-opcua-types";
23
+ export { PermissionType, RolePermissionType, RolePermissionTypeOptions } from "node-opcua-types";
23
24
 
24
25
  type AnyUserIdentityToken = UserNameIdentityToken | AnonymousIdentityToken | X509IdentityToken;
25
26
 
@@ -28,7 +29,10 @@ function getUserName(userIdentityToken: AnyUserIdentityToken): string {
28
29
  return "anonymous";
29
30
  }
30
31
  if (userIdentityToken instanceof X509IdentityToken) {
31
- const certInfo: CertificateInternals = exploreCertificate(userIdentityToken.certificateData);
32
+ const cert = Array.isArray(userIdentityToken.certificateData)
33
+ ? userIdentityToken.certificateData[0]
34
+ : userIdentityToken.certificateData;
35
+ const certInfo: CertificateInternals = exploreCertificate(cert);
32
36
  const userName = certInfo.tbsCertificate.subject.commonName || "";
33
37
  if (typeof userName !== "string") {
34
38
  throw new Error("Invalid username");
@@ -39,8 +43,7 @@ function getUserName(userIdentityToken: AnyUserIdentityToken): string {
39
43
  if (userIdentityToken.policyId === "anonymous") {
40
44
  return "anonymous";
41
45
  }
42
- assert(Object.prototype.hasOwnProperty.call(userIdentityToken, "userName"));
43
- return userIdentityToken.userName!;
46
+ return typeof userIdentityToken.userName === "string" ? userIdentityToken.userName : "";
44
47
  }
45
48
  throw new Error("Invalid user identity token");
46
49
  }
@@ -48,7 +51,6 @@ function getUserName(userIdentityToken: AnyUserIdentityToken): string {
48
51
  /**
49
52
  *
50
53
  */
51
-
52
54
  export enum WellKnownRoles {
53
55
  Anonymous = ObjectIds.WellKnownRole_Anonymous,
54
56
  AuthenticatedUser = ObjectIds.WellKnownRole_AuthenticatedUser,
@@ -128,9 +130,12 @@ function getPermissionForRole(rolePermissions: RolePermissionType[] | null, role
128
130
  return allPermissions;
129
131
  }
130
132
  const a = rolePermissions.find((r) => {
131
- return sameNodeId(resolveNodeId(r.roleId!), role);
133
+ if (!r.roleId) {
134
+ return false;
135
+ }
136
+ return sameNodeId(resolveNodeId(r.roleId), role);
132
137
  });
133
- return a !== undefined ? a.permissions! | PermissionFlag.None : PermissionFlag.None;
138
+ return a?.permissions !== undefined ? a.permissions | PermissionFlag.None : PermissionFlag.None;
134
139
  }
135
140
 
136
141
  function isDefaultContext(context: SessionContext) {
@@ -152,7 +157,7 @@ function getAccessRestrictionsOnNamespace(namespace: NamespacePrivate, context:
152
157
  const defaultAccessRestriction = namespaceObject.getChildByName("defaultAccessRestriction");
153
158
  if (defaultAccessRestriction) {
154
159
  const dataValue = defaultAccessRestriction.readAttribute(null, AttributeIds.Value);
155
- if (dataValue && dataValue.statusCode.isGood()) {
160
+ if (dataValue?.statusCode.isGood()) {
156
161
  return dataValue.value.value as AccessRestrictionsFlag;
157
162
  }
158
163
  }
@@ -179,14 +184,14 @@ function getDefaultUserRolePermissionsOnNamespace(
179
184
  const defaultUserRolePermissions = uaNamespaceObject.getChildByName("DefaultUserRolePermissions") as UAVariable;
180
185
  if (defaultUserRolePermissions) {
181
186
  const dataValue = defaultUserRolePermissions.readValue();
182
- if (dataValue && dataValue.statusCode.isGood() && dataValue.value.value && dataValue.value.value.length > 0) {
187
+ if (dataValue?.statusCode.isGood() && dataValue.value.value && dataValue.value.value.length > 0) {
183
188
  return dataValue.value.value as RolePermissionType[];
184
189
  }
185
190
  }
186
191
  const defaultRolePermissions = uaNamespaceObject.getChildByName("DefaultRolePermissions") as UAVariable;
187
192
  if (defaultRolePermissions) {
188
193
  const dataValue = defaultRolePermissions.readValue();
189
- if (dataValue && dataValue.statusCode.isGood()) {
194
+ if (dataValue?.statusCode.isGood()) {
190
195
  return dataValue.value.value as RolePermissionType[] | null;
191
196
  }
192
197
  }
@@ -198,14 +203,14 @@ export function makeRoles(roleIds: NodeIdLike[] | string | WellKnownRoles): Node
198
203
  roleIds = [roleIds];
199
204
  }
200
205
  if (typeof roleIds === "string") {
201
- roleIds = roleIds.split(";").map((r) => resolveNodeId("WellKnownRole_" + r));
206
+ roleIds = roleIds.split(";").map((r) => resolveNodeId(`WellKnownRole_${r}`));
202
207
  }
203
208
  return roleIds.map((r) => resolveNodeId(r));
204
209
  }
205
210
  export class SessionContext implements ISessionContext {
206
211
  public static defaultContext = new SessionContext({});
207
212
 
208
- public object: any;
213
+ public object: UAObject | UAObjectType | undefined;
209
214
  public currentTime?: PreciseClock;
210
215
  public continuationPoints: Buffer[] = [];
211
216
  public userIdentity?: string;
@@ -355,7 +360,9 @@ export class SessionContext implements ISessionContext {
355
360
  return true;
356
361
  }
357
362
  }
358
- if (!this.session) { return false; }
363
+ if (!this.session) {
364
+ return false;
365
+ }
359
366
  const securityMode = this.session?.channel?.securityMode;
360
367
  if (accessRestrictions & AccessRestrictionsFlag.SigningRequired) {
361
368
  if (securityMode !== MessageSecurityMode.Sign && securityMode !== MessageSecurityMode.SignAndEncrypt) {
@@ -1,23 +1,21 @@
1
1
  /**
2
2
  * @module node-opcua-address-space.AlarmsAndConditions
3
3
  */
4
- import { isEqual } from "lodash";
5
-
4
+ import { isDeepStrictEqual as isEqual } from "node:util";
5
+ import type { BaseNode, INamespace, UAEventType, UAVariable } from "node-opcua-address-space-base";
6
6
  import { assert } from "node-opcua-assert";
7
7
  import { NodeClass } from "node-opcua-data-model";
8
- import { DataValue } from "node-opcua-data-value";
8
+ import type { DataValue } from "node-opcua-data-value";
9
+ import { make_debugLog } from "node-opcua-debug";
9
10
  import { NodeId, sameNodeId } from "node-opcua-nodeid";
10
11
  import { StatusCodes } from "node-opcua-status-code";
11
- import { DataType, VariantOptions } from "node-opcua-variant";
12
- import { make_debugLog } from "node-opcua-debug";
13
- import { BaseNode, INamespace, UAEventType, UAVariable } from "node-opcua-address-space-base";
14
-
12
+ import { DataType, type VariantOptions } from "node-opcua-variant";
13
+ import type { ConditionInfo } from "../../source/interfaces/alarms_and_conditions/condition_info_i";
14
+ import type { InstantiateAlarmConditionOptions } from "../../source/interfaces/alarms_and_conditions/instantiate_alarm_condition_options";
15
+ import type { UAAlarmConditionEx } from "../../source/interfaces/alarms_and_conditions/ua_alarm_condition_ex";
16
+ import type { AddressSpacePrivate } from "../address_space_private";
17
+ import { _clear_timer_if_any, UAShelvedStateMachineExImpl } from "../state_machine/ua_shelving_state_machine_ex";
15
18
  import { _install_TwoStateVariable_machinery } from "../state_machine/ua_two_state_variable";
16
- import { UAShelvedStateMachineExImpl, _clear_timer_if_any } from "../state_machine/ua_shelving_state_machine_ex";
17
- import { AddressSpacePrivate } from "../address_space_private";
18
- import { ConditionInfo } from "../../source/interfaces/alarms_and_conditions/condition_info_i";
19
- import { UAAlarmConditionEx } from "../../source/interfaces/alarms_and_conditions/ua_alarm_condition_ex";
20
- import { InstantiateAlarmConditionOptions } from "../../source/interfaces/alarms_and_conditions/instantiate_alarm_condition_options";
21
19
 
22
20
  import { ConditionInfoImpl } from "./condition_info_impl";
23
21
  import { UAAcknowledgeableConditionImpl } from "./ua_acknowledgeable_condition_impl";
@@ -35,7 +33,7 @@ export declare interface UAAlarmConditionImpl extends UAAlarmConditionEx, UAAckn
35
33
  }
36
34
 
37
35
  export class UAAlarmConditionImpl extends UAAcknowledgeableConditionImpl implements UAAlarmConditionEx {
38
- public static MaxDuration = Math.pow(2, 31);
36
+ public static MaxDuration = 2 ** 31;
39
37
 
40
38
  public static instantiate(
41
39
  namespace: INamespace,
@@ -45,12 +43,12 @@ export class UAAlarmConditionImpl extends UAAcknowledgeableConditionImpl impleme
45
43
  ): UAAlarmConditionImpl {
46
44
  const addressSpace = namespace.addressSpace;
47
45
  // xx assert(Object.prototype.hasOwnProperty.call(options,"conditionOf")); // must provide a conditionOf
48
- assert(Object.prototype.hasOwnProperty.call(options, "inputNode")); // must provide a inputNode
46
+ assert(Object.hasOwn(options, "inputNode")); // must provide a inputNode
49
47
  const alarmConditionType = addressSpace.findEventType(alarmConditionTypeId);
50
48
 
51
49
  /* c8 ignore next */
52
50
  if (!alarmConditionType) {
53
- throw new Error(" cannot find Alarm Condition Type for " + alarmConditionTypeId);
51
+ throw new Error(` cannot find Alarm Condition Type for ${alarmConditionTypeId}`);
54
52
  }
55
53
 
56
54
  const alarmConditionTypeBase = addressSpace.findEventType("AlarmConditionType");
@@ -60,9 +58,9 @@ export class UAAlarmConditionImpl extends UAAcknowledgeableConditionImpl impleme
60
58
  }
61
59
 
62
60
  options.optionals = options.optionals || [];
63
- if (Object.prototype.hasOwnProperty.call(options, "maxTimeShelved")) {
61
+ if (Object.hasOwn(options, "maxTimeShelved")) {
64
62
  options.optionals.push("MaxTimeShelved");
65
- assert(isFinite(options.maxTimeShelved!));
63
+ assert(Number.isFinite(options.maxTimeShelved!));
66
64
  }
67
65
 
68
66
  assert(alarmConditionTypeBase === alarmConditionType || alarmConditionType.isSubtypeOf(alarmConditionTypeBase));
@@ -142,12 +140,12 @@ export class UAAlarmConditionImpl extends UAAcknowledgeableConditionImpl impleme
142
140
  *
143
141
  */
144
142
  if (alarmNode.suppressedState) {
145
- alarmNode.suppressedState.on("value_changed", (newDataValue: DataValue) => {
143
+ alarmNode.suppressedState.on("value_changed", (_newDataValue: DataValue) => {
146
144
  _update_suppressedOrShelved(alarmNode);
147
145
  });
148
146
  }
149
147
  if (alarmNode.shelvingState) {
150
- alarmNode.shelvingState.currentState.on("value_changed", (newDataValue: DataValue) => {
148
+ alarmNode.shelvingState.currentState.on("value_changed", (_newDataValue: DataValue) => {
151
149
  _update_suppressedOrShelved(alarmNode);
152
150
  });
153
151
  }
@@ -220,7 +218,7 @@ export class UAAlarmConditionImpl extends UAAcknowledgeableConditionImpl impleme
220
218
  public isSuppressedOrShelved(): boolean {
221
219
  let suppressed = false;
222
220
  if (this.suppressedState) {
223
- suppressed = this.suppressedState.id!.readValue().value.value;
221
+ suppressed = this.suppressedState.id?.readValue().value.value;
224
222
  }
225
223
  let shelved = false;
226
224
  if (this.shelvingState) {
@@ -241,8 +239,8 @@ export class UAAlarmConditionImpl extends UAAcknowledgeableConditionImpl impleme
241
239
  * note: duration must be greater than 10ms and lesser than 2**31 ms
242
240
  */
243
241
  public setMaxTimeShelved(duration: number): void {
244
- if (duration < 10 || duration >= Math.pow(2, 31)) {
245
- throw new Error(" Invalid maxTimeShelved duration: " + duration + " must be [10,2**31] ");
242
+ if (duration < 10 || duration >= 2 ** 31) {
243
+ throw new Error(` Invalid maxTimeShelved duration: ${duration} must be [10,2**31] `);
246
244
  }
247
245
  this.maxTimeShelved?.setValueFromSource({
248
246
  dataType: "Duration", // <= Duration is basic Type Double! ( milliseconds)
@@ -280,7 +278,7 @@ export class UAAlarmConditionImpl extends UAAcknowledgeableConditionImpl impleme
280
278
  return this.addressSpace.findNode(nodeId) as UAVariable | null;
281
279
  }
282
280
  /**
283
- *
281
+ *
284
282
  */
285
283
  public getInputNodeValue(): any | null {
286
284
  const node = this.getInputNodeNode();
@@ -297,7 +295,7 @@ export class UAAlarmConditionImpl extends UAAcknowledgeableConditionImpl impleme
297
295
  this._onInputDataValueChange(dataValue);
298
296
  }
299
297
 
300
- protected _onInputDataValueChange(newValue: DataValue): void {
298
+ protected _onInputDataValueChange(_newValue: DataValue): void {
301
299
  /** */
302
300
  }
303
301
 
@@ -397,9 +395,9 @@ export class UAAlarmConditionImpl extends UAAcknowledgeableConditionImpl impleme
397
395
  */
398
396
  public _calculateConditionInfo(
399
397
  stateData: string | null,
400
- isActive: boolean,
398
+ _isActive: boolean,
401
399
  value: string,
402
- oldCondition: ConditionInfo
400
+ _oldCondition: ConditionInfo
403
401
  ): ConditionInfo {
404
402
  if (!stateData) {
405
403
  return new ConditionInfoImpl({
@@ -410,7 +408,7 @@ export class UAAlarmConditionImpl extends UAAcknowledgeableConditionImpl impleme
410
408
  });
411
409
  } else {
412
410
  return new ConditionInfoImpl({
413
- message: "Condition is " + value + " and state is " + stateData,
411
+ message: `Condition is ${value} and state is ${stateData}`,
414
412
  quality: StatusCodes.Good,
415
413
  retain: true,
416
414
  severity: 150
@@ -441,7 +439,7 @@ export class UAAlarmConditionImpl extends UAAcknowledgeableConditionImpl impleme
441
439
  debugLog("oldConditionInfo", oldConditionInfo);
442
440
  debugLog("oldConditionInfo", newConditionInfo);
443
441
  throw new Error(
444
- "condition values have not change, shall we really raise an event ? alarm " + this.browseName.toString()
442
+ `condition values have not change, shall we really raise an event ? alarm ${this.browseName.toString()}`
445
443
  );
446
444
  }
447
445
  assert(!isEqual(oldConditionInfo, newConditionInfo), "condition values have not change, shall we really raise an event ?");
@@ -1,16 +1,17 @@
1
1
  /**
2
2
  * @module node-opcua-address-space.AlarmsAndConditions
3
3
  */
4
- import { Certificate, exploreCertificate, makeSHA1Thumbprint } from "node-opcua-crypto/web";
5
- import { DateTime, getMinOPCUADate, isMinDate, StatusCodes } from "node-opcua-basic-types";
6
- import { make_warningLog } from "node-opcua-debug";
7
- import { NodeId } from "node-opcua-nodeid";
8
- import { DataType, Variant, VariantOptions } from "node-opcua-variant";
9
- import { INamespace, UAObject, UAProperty, UAVariable } from "node-opcua-address-space-base";
4
+
5
+ import type { INamespace, UAObject, UAProperty, UAVariable } from "node-opcua-address-space-base";
6
+ import { type DateTime, getMinOPCUADate, isMinDate, StatusCodes } from "node-opcua-basic-types";
10
7
  import { ObjectTypeIds } from "node-opcua-constants";
8
+ import { type Certificate, exploreCertificate, makeSHA1Thumbprint } from "node-opcua-crypto/web";
11
9
  import { makeAccessLevelExFlag } from "node-opcua-data-model";
12
- import { UACertificateExpirationAlarmEx } from "../../source/interfaces/alarms_and_conditions/ua_certificate_expiration_alarm_ex";
13
- import { InstantiateOffNormalAlarmOptions } from "../../source/interfaces/alarms_and_conditions/instantiate_off_normal_alarm_options";
10
+ import { make_warningLog } from "node-opcua-debug";
11
+ import type { NodeId } from "node-opcua-nodeid";
12
+ import { DataType } from "node-opcua-variant";
13
+ import type { InstantiateOffNormalAlarmOptions } from "../../source/interfaces/alarms_and_conditions/instantiate_off_normal_alarm_options";
14
+ import type { UACertificateExpirationAlarmEx } from "../../source/interfaces/alarms_and_conditions/ua_certificate_expiration_alarm_ex";
14
15
  import { registerNodePromoter } from "../../source/loader/register_node_promoter";
15
16
  import { UASystemOffNormalAlarmImpl } from "./ua_system_off_normal_alarm_impl";
16
17
 
@@ -18,7 +19,7 @@ const warningLog = make_warningLog("AlarmsAndConditions");
18
19
 
19
20
  const ellipsis = (arg0: string, arg1 = 4) => {
20
21
  arg1 = Math.max(arg1, 4);
21
- return arg0.length <= arg1 ? arg0 : arg0.slice(0, arg1 / 2) + "..." + arg0.slice(arg0.length - arg1 / 2);
22
+ return arg0.length <= arg1 ? arg0 : `${arg0.slice(0, arg1 / 2)}...${arg0.slice(arg0.length - arg1 / 2)}`;
22
23
  };
23
24
  const d = (d: Date) => {
24
25
  return d.toISOString();
@@ -31,24 +32,22 @@ export function instantiateCertificateExpirationAlarm(
31
32
  return UACertificateExpirationAlarmImpl.instantiate(namespace, alarmType, options);
32
33
  }
33
34
 
34
- interface UACertificateExpirationAlarmImpl {
35
- expirationDate: UAProperty<Date, /*z*/ DataType.DateTime>;
36
- expirationLimit?: UAProperty<number, /*z*/ DataType.Double>;
37
- certificateType: UAProperty<NodeId, /*z*/ DataType.NodeId>;
38
- certificate: UAProperty<Buffer, /*z*/ DataType.ByteString>;
39
- }
40
-
41
35
  // This Simple DataType is a Double that defines an interval of time in milliseconds (fractions can be used to define sub-millisecond values).
42
36
  // Negative values are generally invalid but may have special meanings where the Duration is used.
43
37
  export const OneDayDuration = 1000 * 60 * 60 * 24;
44
38
  export const TwoWeeksDuration = OneDayDuration * 2 * 7;
45
39
 
46
40
  /**
47
- * This UACertificateExpirationAlarm (SystemOffNormalAlarmType) is raised by the Server when the Servers
41
+ * This UACertificateExpirationAlarm (SystemOffNormalAlarmType) is raised by the Server when the Server's
48
42
  * Certificate is within the ExpirationLimit
49
43
  * of expiration. This alarm automatically returns to normal when the certificate is updated.
50
44
  */
51
45
  class UACertificateExpirationAlarmImpl extends UASystemOffNormalAlarmImpl implements UACertificateExpirationAlarmEx {
46
+ declare expirationDate: UAProperty<Date, DataType.DateTime>;
47
+ declare expirationLimit: UAProperty<number, DataType.Double> | undefined;
48
+ declare certificateType: UAProperty<NodeId, DataType.NodeId>;
49
+ declare certificate: UAProperty<Buffer, DataType.ByteString>;
50
+
52
51
  private timer: NodeJS.Timeout | null = null;
53
52
 
54
53
  public static instantiate(
@@ -57,7 +56,6 @@ class UACertificateExpirationAlarmImpl extends UASystemOffNormalAlarmImpl implem
57
56
  options: InstantiateOffNormalAlarmOptions
58
57
  // data?: Record<string, VariantOptions>
59
58
  ): UACertificateExpirationAlarmImpl {
60
-
61
59
  const alarm = UASystemOffNormalAlarmImpl.instantiate(
62
60
  namespace,
63
61
  alarmType || "CertificateExpirationAlarmType",
@@ -78,7 +76,7 @@ class UACertificateExpirationAlarmImpl extends UASystemOffNormalAlarmImpl implem
78
76
  this.raiseNewCondition({
79
77
  message,
80
78
  quality: StatusCodes.Good,
81
- retain: isActive ? true : false,
79
+ retain: !!isActive,
82
80
  severity
83
81
  });
84
82
  }
@@ -92,7 +90,7 @@ class UACertificateExpirationAlarmImpl extends UASystemOffNormalAlarmImpl implem
92
90
  warningLog(`expiry alarm ${this.nodeId.toString()} has no enabledState property`);
93
91
  return;
94
92
  }
95
-
93
+
96
94
  const expirationDate = this.getExpirationDate();
97
95
 
98
96
  const now = new Date();
@@ -104,7 +102,7 @@ class UACertificateExpirationAlarmImpl extends UASystemOffNormalAlarmImpl implem
104
102
  const certificate = this.getCertificate();
105
103
 
106
104
  if (!expirationDate || (isMinDate(expirationDate) && !certificate)) {
107
- if (!this.currentBranch() || this.currentBranch().getActiveState()) {
105
+ if (this.currentBranch()?.getActiveState()) {
108
106
  this.updateAlarmState2(true, 255, "certificate is missing");
109
107
  }
110
108
  return;
@@ -147,11 +145,11 @@ class UACertificateExpirationAlarmImpl extends UASystemOffNormalAlarmImpl implem
147
145
  if (!this.expirationLimit) {
148
146
  return TwoWeeksDuration;
149
147
  }
150
- const dataValue = this.expirationLimit!.readValue();
151
- if ((dataValue as any).dataType === DataType.Null) {
148
+ const dataValue = this.expirationLimit.readValue();
149
+ if ((dataValue.value.dataType as DataType) === DataType.Null) {
152
150
  return TwoWeeksDuration;
153
151
  }
154
- return (this.expirationLimit?.readValue().value.value as number) || 0;
152
+ return (dataValue.value.value as number) || 0;
155
153
  }
156
154
 
157
155
  public setExpirationLimit(value: number): void {
@@ -163,7 +161,7 @@ class UACertificateExpirationAlarmImpl extends UASystemOffNormalAlarmImpl implem
163
161
  }
164
162
 
165
163
  public getCertificate(): Certificate | null {
166
- return (this.getChildByName("Certificate") as UAVariable)?.readValue().value.value as Certificate || null;
164
+ return ((this.getChildByName("Certificate") as UAVariable)?.readValue().value.value as Certificate) || null;
167
165
  }
168
166
 
169
167
  private _extractAndSetExpiryDate(certificate: Certificate | null): void {
@@ -193,20 +191,28 @@ class UACertificateExpirationAlarmImpl extends UASystemOffNormalAlarmImpl implem
193
191
  this.timer = null;
194
192
  }
195
193
  }
196
-
194
+
197
195
  private _startTimer() {
198
196
  this.timer = setTimeout(() => {
199
197
  if (!this.timer) return;
200
198
  this.update();
201
199
  this._startTimer();
202
200
  }, OneDayDuration / 48);
201
+ // don't keep the process alive just for this monitoring timer
202
+ if (this.timer && typeof this.timer.unref === "function") {
203
+ this.timer.unref();
204
+ }
203
205
  }
204
206
 
205
207
  _post_initialize() {
208
+ // ensure _branch0 is created (base UAConditionImpl)
209
+ if (!this.currentBranch()) {
210
+ this.post_initialize();
211
+ }
206
212
  if (this.expirationLimit) {
207
213
  this.expirationLimit.accessLevel = makeAccessLevelExFlag("CurrentRead | CurrentWrite");
208
214
  this.expirationLimit.userAccessLevel = makeAccessLevelExFlag("CurrentRead | CurrentWrite");
209
- this.expirationLimit.on("value_changed", (dataValue) => {
215
+ this.expirationLimit.on("value_changed", (_dataValue) => {
210
216
  // make sure we re-evaluate the certificate
211
217
  const certificate = this.getCertificate();
212
218
  this.setCertificate(certificate);