node-opcua-service-filter 2.183.0 → 2.184.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.
Files changed (52) hide show
  1. package/dist/check_event_clause.d.ts +1 -0
  2. package/dist/check_event_clause.d.ts.map +1 -0
  3. package/dist/check_event_clause.js +23 -19
  4. package/dist/check_event_clause.js.map +1 -1
  5. package/dist/check_where_clause.d.ts +1 -0
  6. package/dist/check_where_clause.d.ts.map +1 -0
  7. package/dist/check_where_clause.js +112 -116
  8. package/dist/check_where_clause.js.map +1 -1
  9. package/dist/extract_event_field.d.ts +2 -1
  10. package/dist/extract_event_field.d.ts.map +1 -0
  11. package/dist/extract_event_field.js +14 -42
  12. package/dist/extract_event_field.js.map +1 -1
  13. package/dist/filter_context.d.ts +1 -0
  14. package/dist/filter_context.d.ts.map +1 -0
  15. package/dist/filter_context.js +1 -2
  16. package/dist/imports.d.ts +1 -0
  17. package/dist/imports.d.ts.map +1 -0
  18. package/dist/imports.js +1 -15
  19. package/dist/imports.js.map +1 -1
  20. package/dist/index.d.ts +1 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +10 -26
  23. package/dist/index.js.map +1 -1
  24. package/dist/make_content_filter.d.ts +1 -0
  25. package/dist/make_content_filter.d.ts.map +1 -0
  26. package/dist/make_content_filter.js +47 -62
  27. package/dist/make_content_filter.js.map +1 -1
  28. package/dist/on_address_space/extract_event_fields.d.ts +1 -0
  29. package/dist/on_address_space/extract_event_fields.d.ts.map +1 -0
  30. package/dist/on_address_space/extract_event_fields.js +5 -8
  31. package/dist/on_address_space/extract_event_fields.js.map +1 -1
  32. package/dist/on_address_space/filter_context_on_address_space.d.ts +1 -0
  33. package/dist/on_address_space/filter_context_on_address_space.d.ts.map +1 -0
  34. package/dist/on_address_space/filter_context_on_address_space.js +21 -25
  35. package/dist/on_address_space/filter_context_on_address_space.js.map +1 -1
  36. package/dist/on_address_space/index.d.ts +1 -0
  37. package/dist/on_address_space/index.d.ts.map +1 -0
  38. package/dist/on_address_space/index.js +2 -18
  39. package/dist/on_address_space/index.js.map +1 -1
  40. package/dist/resolve_operand.d.ts +14 -0
  41. package/dist/resolve_operand.d.ts.map +1 -0
  42. package/dist/resolve_operand.js +66 -21
  43. package/dist/resolve_operand.js.map +1 -1
  44. package/dist/tools_event_filter.d.ts +1 -0
  45. package/dist/tools_event_filter.d.ts.map +1 -0
  46. package/dist/tools_event_filter.js +17 -22
  47. package/dist/tools_event_filter.js.map +1 -1
  48. package/package.json +18 -17
  49. package/source/check_event_clause.ts +11 -2
  50. package/source/check_where_clause.ts +2 -2
  51. package/source/extract_event_field.ts +7 -33
  52. package/source/resolve_operand.ts +53 -2
@@ -1,19 +1,3 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./extract_event_fields.js"), exports);
18
- __exportStar(require("./filter_context_on_address_space.js"), exports);
1
+ export * from "./extract_event_fields.js";
2
+ export * from "./filter_context_on_address_space.js";
19
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../source/on_address_space/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4DAA0C;AAC1C,uEAAqD"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../source/on_address_space/index.ts"],"names":[],"mappings":"AAAA,cAAc,2BAA2B,CAAC;AAC1C,cAAc,sCAAsC,CAAC"}
@@ -1,4 +1,18 @@
1
1
  import { AttributeOperand, SimpleAttributeOperand } from "node-opcua-types";
2
2
  import { Variant } from "node-opcua-variant";
3
3
  import type { FilterContext } from "./filter_context.js";
4
+ /**
5
+ * OPC 10000-4 7.4.4.5: a SimpleAttributeOperand with an empty browsePath denotes the instance of
6
+ * typeDefinitionId itself, not "nothing to do". A ConditionId operand (typeDefinitionId
7
+ * ConditionType or a subtype, attributeId NodeId, empty browsePath) resolves to the event's own
8
+ * condition instance NodeId - this is what every Alarms and Conditions client sends, in both the
9
+ * select clause (delivery, via extractEventField) and the where clause (evaluation, via
10
+ * resolveOperand below). FEAT-58 taught the select-clause validation this; both consumers share
11
+ * this one resolution so they never drift apart again.
12
+ *
13
+ * Returns undefined when the operand does not match this shape, so the caller falls back to its
14
+ * normal browsePath resolution.
15
+ */
16
+ export declare function resolveConditionIdOperand(context: FilterContext, operand: SimpleAttributeOperand): Variant | undefined;
4
17
  export declare function resolveOperand(context: FilterContext, operand: SimpleAttributeOperand | AttributeOperand): Variant;
18
+ //# sourceMappingURL=resolve_operand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve_operand.d.ts","sourceRoot":"","sources":["../source/resolve_operand.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC5E,OAAO,EAAY,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAOzD;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,sBAAsB,GAAG,OAAO,GAAG,SAAS,CA+BtH;AAYD,wBAAgB,cAAc,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,sBAAsB,GAAG,gBAAgB,GAAG,OAAO,CAiClH"}
@@ -1,15 +1,56 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.resolveOperand = resolveOperand;
4
- const node_opcua_data_model_1 = require("node-opcua-data-model");
5
- const node_opcua_debug_1 = require("node-opcua-debug");
6
- const node_opcua_service_translate_browse_path_1 = require("node-opcua-service-translate-browse-path");
7
- const node_opcua_status_code_1 = require("node-opcua-status-code");
8
- const node_opcua_types_1 = require("node-opcua-types");
9
- const node_opcua_variant_1 = require("node-opcua-variant");
10
- const warningLog = (0, node_opcua_debug_1.make_warningLog)("FILTER");
11
- const debugLog = (0, node_opcua_debug_1.make_debugLog)("FILTER");
12
- const doDebug = (0, node_opcua_debug_1.checkDebugFlag)("FILTER");
1
+ import { AttributeIds, NodeClass } from "node-opcua-data-model";
2
+ import { checkDebugFlag, make_debugLog, make_warningLog } from "node-opcua-debug";
3
+ import { resolveNodeId, sameNodeId } from "node-opcua-nodeid";
4
+ import { constructBrowsePathFromQualifiedName } from "node-opcua-service-translate-browse-path";
5
+ import { StatusCodes } from "node-opcua-status-code";
6
+ import { AttributeOperand, SimpleAttributeOperand } from "node-opcua-types";
7
+ import { DataType, Variant } from "node-opcua-variant";
8
+ const warningLog = make_warningLog("FILTER");
9
+ const debugLog = make_debugLog("FILTER");
10
+ const doDebug = checkDebugFlag("FILTER");
11
+ const conditionTypeNodeId = resolveNodeId("ConditionType");
12
+ /**
13
+ * OPC 10000-4 7.4.4.5: a SimpleAttributeOperand with an empty browsePath denotes the instance of
14
+ * typeDefinitionId itself, not "nothing to do". A ConditionId operand (typeDefinitionId
15
+ * ConditionType or a subtype, attributeId NodeId, empty browsePath) resolves to the event's own
16
+ * condition instance NodeId - this is what every Alarms and Conditions client sends, in both the
17
+ * select clause (delivery, via extractEventField) and the where clause (evaluation, via
18
+ * resolveOperand below). FEAT-58 taught the select-clause validation this; both consumers share
19
+ * this one resolution so they never drift apart again.
20
+ *
21
+ * Returns undefined when the operand does not match this shape, so the caller falls back to its
22
+ * normal browsePath resolution.
23
+ */
24
+ export function resolveConditionIdOperand(context, operand) {
25
+ if (operand.browsePath && operand.browsePath.length > 0) {
26
+ return undefined;
27
+ }
28
+ if (operand.attributeId !== AttributeIds.NodeId) {
29
+ return undefined;
30
+ }
31
+ // "ns=0;i=2782" => ConditionType
32
+ // "ns=0;i=2041" => BaseEventType
33
+ if (!sameNodeId(operand.typeDefinitionId, conditionTypeNodeId)) {
34
+ // not a ConditionType
35
+ // but could be on of its derived type. for instance ns=0;i=2881 => AcknowledgeableConditionType
36
+ if (!context.isSubtypeOf(operand.typeDefinitionId, conditionTypeNodeId)) {
37
+ warningLog(" ", operand.typeDefinitionId.toString());
38
+ warningLog(`this case is not handled yet : selectClause.typeDefinitionId = ${operand.typeDefinitionId.toString()}`);
39
+ warningLog(operand.toString());
40
+ return new Variant({ dataType: DataType.NodeId, value: context.eventSource });
41
+ }
42
+ }
43
+ const eventSourceTypeDefinition = context.getTypeDefinition(context.eventSource);
44
+ if (!eventSourceTypeDefinition) {
45
+ // eventSource is a EventType class
46
+ return new Variant();
47
+ }
48
+ if (!context.isSubtypeOf(eventSourceTypeDefinition, conditionTypeNodeId)) {
49
+ return new Variant();
50
+ }
51
+ // Yeh : our EventType is a Condition Type !
52
+ return new Variant({ dataType: DataType.NodeId, value: context.eventSource });
53
+ }
13
54
  // export function readOperand(context: FilterContext, operand: SimpleAttributeOperand): Variant {
14
55
  // // navigate to the innerNode specified by the browsePath [ QualifiedName]
15
56
  // const browsePath = constructBrowsePathFromQualifiedName({ nodeId: context.eventSource }, operand.browsePath);
@@ -19,29 +60,33 @@ const doDebug = (0, node_opcua_debug_1.checkDebugFlag)("FILTER");
19
60
  // }
20
61
  // return context.readNodeValue(targetNode);
21
62
  // }
22
- function resolveOperand(context, operand) {
23
- if (operand instanceof node_opcua_types_1.SimpleAttributeOperand) {
24
- const browsePath = (0, node_opcua_service_translate_browse_path_1.constructBrowsePathFromQualifiedName)({ nodeId: context.eventSource }, operand.browsePath);
63
+ export function resolveOperand(context, operand) {
64
+ if (operand instanceof SimpleAttributeOperand) {
65
+ const conditionIdValue = resolveConditionIdOperand(context, operand);
66
+ if (conditionIdValue) {
67
+ return conditionIdValue;
68
+ }
69
+ const browsePath = constructBrowsePathFromQualifiedName({ nodeId: context.eventSource }, operand.browsePath);
25
70
  const target = context.browsePath(browsePath);
26
71
  if (!target) {
27
- return new node_opcua_variant_1.Variant({ dataType: node_opcua_variant_1.DataType.Null });
72
+ return new Variant({ dataType: DataType.Null });
28
73
  // return new Variant({ dataType: DataType.StatusCode, value: StatusCodes.BadNodeIdUnknown });
29
74
  }
30
75
  const nodeClass = context.getNodeClass(target);
31
- if (nodeClass !== node_opcua_data_model_1.NodeClass.Variable) {
76
+ if (nodeClass !== NodeClass.Variable) {
32
77
  doDebug &&
33
- debugLog("resolveOperand: cannot find variable here but got nodeClass", node_opcua_data_model_1.NodeClass[nodeClass], browsePath.toString());
34
- return new node_opcua_variant_1.Variant({ dataType: node_opcua_variant_1.DataType.StatusCode, value: node_opcua_status_code_1.StatusCodes.BadNodeClassInvalid });
78
+ debugLog("resolveOperand: cannot find variable here but got nodeClass", NodeClass[nodeClass], browsePath.toString());
79
+ return new Variant({ dataType: DataType.StatusCode, value: StatusCodes.BadNodeClassInvalid });
35
80
  }
36
81
  const value = context.readNodeValue(target);
37
82
  return value;
38
83
  }
39
84
  else {
40
- if (!(operand instanceof node_opcua_types_1.AttributeOperand)) {
85
+ if (!(operand instanceof AttributeOperand)) {
41
86
  throw new Error("expecting an AttributeOperand");
42
87
  }
43
88
  warningLog("AttributeOperand is not yet implemented");
44
- return new node_opcua_variant_1.Variant({ dataType: node_opcua_variant_1.DataType.Null });
89
+ return new Variant({ dataType: DataType.Null });
45
90
  }
46
91
  }
47
92
  //# sourceMappingURL=resolve_operand.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"resolve_operand.js","sourceRoot":"","sources":["../source/resolve_operand.ts"],"names":[],"mappings":";;AAuBA,wCA4BC;AAnDD,iEAAkD;AAClD,uDAAkF;AAElF,uGAAgG;AAChG,mEAAqD;AACrD,uDAA4E;AAC5E,2DAAuD;AAGvD,MAAM,UAAU,GAAG,IAAA,kCAAe,EAAC,QAAQ,CAAC,CAAC;AAC7C,MAAM,QAAQ,GAAG,IAAA,gCAAa,EAAC,QAAQ,CAAC,CAAC;AACzC,MAAM,OAAO,GAAG,IAAA,iCAAc,EAAC,QAAQ,CAAC,CAAC;AAEzC,kGAAkG;AAClG,gFAAgF;AAChF,oHAAoH;AACpH,yDAAyD;AACzD,yBAAyB;AACzB,2DAA2D;AAC3D,QAAQ;AACR,gDAAgD;AAChD,IAAI;AAEJ,SAAgB,cAAc,CAAC,OAAsB,EAAE,OAAkD;IACrG,IAAI,OAAO,YAAY,yCAAsB,EAAE,CAAC;QAC5C,MAAM,UAAU,GAAG,IAAA,+EAAoC,EAAC,EAAE,MAAM,EAAE,OAAO,CAAC,WAAW,EAAE,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;QAE7G,MAAM,MAAM,GAAkB,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QAC7D,IAAI,CAAC,MAAM,EAAE,CAAC;YACV,OAAO,IAAI,4BAAO,CAAC,EAAE,QAAQ,EAAE,6BAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;YAChD,8FAA8F;QAClG,CAAC;QACD,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAC/C,IAAI,SAAS,KAAK,iCAAS,CAAC,QAAQ,EAAE,CAAC;YACnC,OAAO;gBACH,QAAQ,CACJ,6DAA6D,EAC7D,iCAAS,CAAC,SAAS,CAAC,EACpB,UAAU,CAAC,QAAQ,EAAE,CACxB,CAAC;YACN,OAAO,IAAI,4BAAO,CAAC,EAAE,QAAQ,EAAE,6BAAQ,CAAC,UAAU,EAAE,KAAK,EAAE,oCAAW,CAAC,mBAAmB,EAAE,CAAC,CAAC;QAClG,CAAC;QACD,MAAM,KAAK,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QAC5C,OAAO,KAAK,CAAC;IACjB,CAAC;SAAM,CAAC;QACJ,IAAI,CAAC,CAAC,OAAO,YAAY,mCAAgB,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACrD,CAAC;QACD,UAAU,CAAC,yCAAyC,CAAC,CAAC;QACtD,OAAO,IAAI,4BAAO,CAAC,EAAE,QAAQ,EAAE,6BAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"resolve_operand.js","sourceRoot":"","sources":["../source/resolve_operand.ts"],"names":[],"mappings":"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"}
@@ -18,3 +18,4 @@ export declare function constructSelectClause(arrayOfNames: string | string[] |
18
18
  *
19
19
  */
20
20
  export declare function constructEventFilter(arrayOfNames: (QualifiedNameOptions | string)[][] | (QualifiedNameOptions | string)[] | QualifiedNameOptions | string[] | string, whereClause?: ContentFilterOptions | ContentFilterElement): EventFilter;
21
+ //# sourceMappingURL=tools_event_filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools_event_filter.d.ts","sourceRoot":"","sources":["../source/tools_event_filter.ts"],"names":[],"mappings":"AAIA,OAAO,EAAqC,KAAK,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAEzH,OAAO,EAAiB,oBAAoB,EAAE,KAAK,oBAAoB,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAUnI,wBAAgB,yBAAyB,CACrC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,oBAAoB,GAAG,CAAC,oBAAoB,GAAG,MAAM,CAAC,EAAE,GAChF,aAAa,EAAE,CAMjB;AACD,wBAAgB,qBAAqB,CACjC,YAAY,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,oBAAoB,GAAG,CAAC,oBAAoB,GAAG,MAAM,CAAC,EAAE,GAAG,CAAC,oBAAoB,GAAG,MAAM,CAAC,EAAE,EAAE,GACjI,sBAAsB,EAAE,CA+C1B;AACD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAChC,YAAY,EACN,CAAC,oBAAoB,GAAG,MAAM,CAAC,EAAE,EAAE,GACnC,CAAC,oBAAoB,GAAG,MAAM,CAAC,EAAE,GACjC,oBAAoB,GACpB,MAAM,EAAE,GACR,MAAM,EACZ,WAAW,CAAC,EAAE,oBAAoB,GAAG,oBAAoB,GAC1D,WAAW,CAWb"}
@@ -1,23 +1,18 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.constructSimpleBrowsePath = constructSimpleBrowsePath;
4
- exports.constructSelectClause = constructSelectClause;
5
- exports.constructEventFilter = constructEventFilter;
6
1
  /**
7
2
  * @module node-opcua-service-filter
8
3
  */
9
- const node_opcua_constants_1 = require("node-opcua-constants");
10
- const node_opcua_data_model_1 = require("node-opcua-data-model");
11
- const imports_js_1 = require("./imports.js");
4
+ import { ObjectTypeIds } from "node-opcua-constants";
5
+ import { AttributeIds, coerceQualifiedName } from "node-opcua-data-model";
6
+ import { ContentFilter, ContentFilterElement, EventFilter, SimpleAttributeOperand } from "./imports.js";
12
7
  function coerceQualifiedName2(a) {
13
8
  if (typeof a === "string")
14
- return (0, node_opcua_data_model_1.coerceQualifiedName)(a);
9
+ return coerceQualifiedName(a);
15
10
  a.namespaceIndex = a.namespaceIndex || 0; // need a namespaceIndex
16
- return (0, node_opcua_data_model_1.coerceQualifiedName)(a);
11
+ return coerceQualifiedName(a);
17
12
  }
18
13
  // A bare QualifiedNameOptions is accepted, and always was: the last line coerces a
19
14
  // single non-array value. Only the signature said otherwise.
20
- function constructSimpleBrowsePath(a) {
15
+ export function constructSimpleBrowsePath(a) {
21
16
  if (typeof a === "string") {
22
17
  return constructSimpleBrowsePath(a.split("."));
23
18
  }
@@ -25,7 +20,7 @@ function constructSimpleBrowsePath(a) {
25
20
  return a.map(coerceQualifiedName2);
26
21
  return [coerceQualifiedName2(a)];
27
22
  }
28
- function constructSelectClause(arrayOfNames) {
23
+ export function constructSelectClause(arrayOfNames) {
29
24
  if (!Array.isArray(arrayOfNames)) {
30
25
  return constructSelectClause([arrayOfNames]);
31
26
  }
@@ -53,19 +48,19 @@ function constructSelectClause(arrayOfNames) {
53
48
  // browsePath[] QualifiedName empty
54
49
  // attributeId IntegerId Id of the NodeId Attribute
55
50
  //
56
- return new imports_js_1.SimpleAttributeOperand({
57
- attributeId: node_opcua_data_model_1.AttributeIds.NodeId,
51
+ return new SimpleAttributeOperand({
52
+ attributeId: AttributeIds.NodeId,
58
53
  browsePath: null,
59
54
  indexRange: undefined, // NumericRange
60
- typeDefinitionId: node_opcua_constants_1.ObjectTypeIds.ConditionType // i=2782
55
+ typeDefinitionId: ObjectTypeIds.ConditionType // i=2782
61
56
  });
62
57
  }
63
58
  else
64
- return new imports_js_1.SimpleAttributeOperand({
65
- attributeId: node_opcua_data_model_1.AttributeIds.Value,
59
+ return new SimpleAttributeOperand({
60
+ attributeId: AttributeIds.Value,
66
61
  browsePath,
67
62
  indexRange: undefined, // NumericRange
68
- typeDefinitionId: node_opcua_constants_1.ObjectTypeIds.BaseEventType // i=2041
63
+ typeDefinitionId: ObjectTypeIds.BaseEventType // i=2041
69
64
  });
70
65
  });
71
66
  return selectClauses;
@@ -85,12 +80,12 @@ function constructSelectClause(arrayOfNames) {
85
80
  * constructEventFilter([ ["SourceName",{namespaceIndex:2 , "MyData"} ]]);
86
81
  *
87
82
  */
88
- function constructEventFilter(arrayOfNames, whereClause) {
83
+ export function constructEventFilter(arrayOfNames, whereClause) {
89
84
  const selectClauses = constructSelectClause(arrayOfNames);
90
- if (whereClause instanceof imports_js_1.ContentFilterElement) {
91
- whereClause = new imports_js_1.ContentFilter({ elements: [whereClause] });
85
+ if (whereClause instanceof ContentFilterElement) {
86
+ whereClause = new ContentFilter({ elements: [whereClause] });
92
87
  }
93
- const filter = new imports_js_1.EventFilter({
88
+ const filter = new EventFilter({
94
89
  selectClauses,
95
90
  whereClause
96
91
  });
@@ -1 +1 @@
1
- {"version":3,"file":"tools_event_filter.js","sourceRoot":"","sources":["../source/tools_event_filter.ts"],"names":[],"mappings":";;AAgBA,8DAQC;AACD,sDAiDC;AAgBD,oDAmBC;AA7GD;;GAEG;AACH,+DAAqD;AACrD,iEAAyH;AAEzH,6CAAmI;AAEnI,SAAS,oBAAoB,CAAC,CAAgC;IAC1D,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,IAAA,2CAAmB,EAAC,CAAC,CAAC,CAAC;IACzD,CAAC,CAAC,cAAc,GAAG,CAAC,CAAC,cAAc,IAAI,CAAC,CAAC,CAAC,wBAAwB;IAClE,OAAO,IAAA,2CAAmB,EAAC,CAAC,CAAC,CAAC;AAClC,CAAC;AAED,mFAAmF;AACnF,6DAA6D;AAC7D,SAAgB,yBAAyB,CACrC,CAA+E;IAE/E,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;QACxB,OAAO,yBAAyB,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IACnD,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IACzD,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC;AACrC,CAAC;AACD,SAAgB,qBAAqB,CACjC,YAAgI;IAEhI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QAC/B,OAAO,qBAAqB,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;IACjD,CAAC;IACD,+BAA+B;IAC/B,MAAM,WAAW,GAAG,YAAY,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;IAEhE,mBAAmB;IACnB,iHAAiH;IACjH,4GAA4G;IAE5G,MAAM,0BAA0B,GAAG,CAAC,UAAkC,EAAE,EAAE,CACtE,UAAU,CAAC,MAAM,KAAK,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,cAAc,KAAK,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC;IAE3H,OAAO;IACP,+GAA+G;IAC/G,wGAAwG;IACxG,8FAA8F;IAC9F,MAAM,aAAa,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,UAAkC,EAAE,EAAE;QACzE,IAAI,0BAA0B,CAAC,UAAU,CAAC,EAAE,CAAC;YACzC,eAAe;YACf,EAAE;YACF,kGAAkG;YAClG,kFAAkF;YAClF,gFAAgF;YAChF,EAAE;YACF,0BAA0B;YAC1B,2CAA2C;YAC3C,gEAAgE;YAChE,qCAAqC;YACrC,0DAA0D;YAC1D,EAAE;YACF,OAAO,IAAI,mCAAsB,CAAC;gBAC9B,WAAW,EAAE,oCAAY,CAAC,MAAM;gBAChC,UAAU,EAAE,IAAI;gBAChB,UAAU,EAAE,SAAS,EAAE,gBAAgB;gBACvC,gBAAgB,EAAE,oCAAa,CAAC,aAAa,CAAC,SAAS;aAC1D,CAAC,CAAC;QACP,CAAC;;YACG,OAAO,IAAI,mCAAsB,CAAC;gBAC9B,WAAW,EAAE,oCAAY,CAAC,KAAK;gBAC/B,UAAU;gBACV,UAAU,EAAE,SAAS,EAAE,gBAAgB;gBACvC,gBAAgB,EAAE,oCAAa,CAAC,aAAa,CAAC,SAAS;aAC1D,CAAC,CAAC;IACX,CAAC,CAAC,CAAC;IACH,OAAO,aAAa,CAAC;AACzB,CAAC;AACD;;;;;;;;;;;;;;GAcG;AACH,SAAgB,oBAAoB,CAChC,YAKY,EACZ,WAAyD;IAEzD,MAAM,aAAa,GAAG,qBAAqB,CAAC,YAAY,CAAC,CAAC;IAE1D,IAAI,WAAW,YAAY,iCAAoB,EAAE,CAAC;QAC9C,WAAW,GAAG,IAAI,0BAAa,CAAC,EAAE,QAAQ,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;IACjE,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,wBAAW,CAAC;QAC3B,aAAa;QACb,WAAW;KACd,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"tools_event_filter.js","sourceRoot":"","sources":["../source/tools_event_filter.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "node-opcua-service-filter",
3
- "version": "2.183.0",
3
+ "type": "module",
4
+ "version": "2.184.0",
4
5
  "description": "pure nodejs OPCUA SDK - module service-filter",
5
6
  "main": "./dist/index.js",
6
7
  "types": "./dist/index.d.ts",
@@ -14,23 +15,23 @@
14
15
  "node": ">=22.13.0"
15
16
  },
16
17
  "dependencies": {
17
- "node-opcua-address-space-base": "2.183.0",
18
- "node-opcua-assert": "2.183.0",
19
- "node-opcua-basic-types": "2.183.0",
20
- "node-opcua-constants": "2.183.0",
21
- "node-opcua-data-model": "2.183.0",
22
- "node-opcua-data-value": "2.183.0",
23
- "node-opcua-debug": "2.183.0",
24
- "node-opcua-extension-object": "2.183.0",
25
- "node-opcua-nodeid": "2.183.0",
26
- "node-opcua-service-translate-browse-path": "2.183.0",
27
- "node-opcua-status-code": "2.183.0",
28
- "node-opcua-types": "2.183.0",
29
- "node-opcua-variant": "2.183.0"
18
+ "node-opcua-address-space-base": "2.184.0",
19
+ "node-opcua-assert": "2.184.0",
20
+ "node-opcua-basic-types": "2.184.0",
21
+ "node-opcua-constants": "2.184.0",
22
+ "node-opcua-data-model": "2.184.0",
23
+ "node-opcua-data-value": "2.184.0",
24
+ "node-opcua-debug": "2.184.0",
25
+ "node-opcua-extension-object": "2.184.0",
26
+ "node-opcua-nodeid": "2.184.0",
27
+ "node-opcua-service-translate-browse-path": "2.184.0",
28
+ "node-opcua-status-code": "2.184.0",
29
+ "node-opcua-types": "2.184.0",
30
+ "node-opcua-variant": "2.184.0"
30
31
  },
31
32
  "devDependencies": {
32
- "node-opcua-numeric-range": "2.183.0",
33
- "node-opcua-packet-analyzer": "2.183.0"
33
+ "node-opcua-numeric-range": "2.184.0",
34
+ "node-opcua-packet-analyzer": "2.184.0"
34
35
  },
35
36
  "author": "Etienne Rossignon",
36
37
  "license": "MIT",
@@ -47,7 +48,7 @@
47
48
  "internet of things"
48
49
  ],
49
50
  "homepage": "http://node-opcua.github.io/",
50
- "gitHead": "d9a9af54d162f0fbb8d287e168aaeeda2d5c38b7",
51
+ "gitHead": "441a5c63e3a4202eb8de8597acac77a3a49248b7",
51
52
  "files": [
52
53
  "dist",
53
54
  "source"
@@ -22,7 +22,7 @@ export function checkSelectClause(parentNode: BaseNode, selectClause: SimpleAttr
22
22
  //
23
23
  const addressSpace = parentNode.addressSpace;
24
24
 
25
- // c8 ignore next
25
+ /* c8 ignore next */
26
26
  if (selectClause.typeDefinitionId.isEmpty()) {
27
27
  return StatusCodes.Good;
28
28
  }
@@ -34,11 +34,20 @@ export function checkSelectClause(parentNode: BaseNode, selectClause: SimpleAttr
34
34
  }
35
35
  // ... and that node must be an ObjectType (an EventType)
36
36
  if (eventTypeNode.nodeClass !== NodeClass.ObjectType) {
37
- // c8 ignore next
37
+ /* c8 ignore next */
38
38
  doDebug && debugLog(" checkSelectClause", eventTypeNode.toString());
39
39
  return StatusCodes.BadTypeMismatch;
40
40
  }
41
41
 
42
+ // OPC 10000-4 7.4.4.5: an empty browsePath does not mean "nothing to do" here - it denotes the
43
+ // instance of typeDefinitionId itself (e.g. the ConditionId of an Alarms and Conditions event).
44
+ // typeDefinitionId has already been checked above to resolve to an existing EventType, so the
45
+ // operand is valid and must be reported Good; it is extractEventField's job, at delivery time, to
46
+ // resolve it against the actual event instance.
47
+ if (!selectClause.browsePath || selectClause.browsePath.length === 0) {
48
+ return StatusCodes.Good;
49
+ }
50
+
42
51
  // navigate to the innerNode specified by the browsePath [ QualifiedName]
43
52
  const browsePath = constructBrowsePathFromQualifiedName(eventTypeNode, selectClause.browsePath);
44
53
  const browsePathResult = addressSpace.browsePath(browsePath);
@@ -89,12 +89,12 @@ function evaluateOperand<TIn, T>(
89
89
  }
90
90
 
91
91
  function checkOfType(filterContext: FilterContext, ofType: ExtensionObject | null): boolean {
92
- // c8 ignore next
92
+ /* c8 ignore next */
93
93
  if (!ofType || !(ofType instanceof LiteralOperand)) {
94
94
  warningLog("checkOfType : unsupported case ! ofType is not a LiteralOperand , ofType = ", ofType?.toString());
95
95
  return false;
96
96
  }
97
- // c8 ignore next
97
+ /* c8 ignore next */
98
98
  if (ofType.value.dataType !== DataType.NodeId) {
99
99
  warningLog(`invalid operand type (expecting NodeId); got ${DataType[ofType.value.dataType]}`);
100
100
  return false;
@@ -1,14 +1,8 @@
1
1
  import { assert } from "node-opcua-assert";
2
- import { AttributeIds } from "node-opcua-data-model";
3
- import { make_warningLog } from "node-opcua-debug";
4
- import { resolveNodeId, sameNodeId } from "node-opcua-nodeid";
5
2
  import { SimpleAttributeOperand } from "node-opcua-types";
6
- import { DataType, Variant } from "node-opcua-variant";
3
+ import type { Variant } from "node-opcua-variant";
7
4
  import type { FilterContext } from "./filter_context.js";
8
- import { resolveOperand } from "./resolve_operand.js";
9
-
10
- const warningLog = make_warningLog("FILTER");
11
- const conditionTypeNodeId = resolveNodeId("ConditionType");
5
+ import { resolveConditionIdOperand, resolveOperand } from "./resolve_operand.js";
12
6
 
13
7
  /**
14
8
  *
@@ -19,31 +13,11 @@ export function extractEventField(context: FilterContext, operand: SimpleAttribu
19
13
 
20
14
  operand.browsePath = operand.browsePath || [];
21
15
 
22
- if (operand.browsePath.length === 0 && operand.attributeId === AttributeIds.NodeId) {
23
- // "ns=0;i=2782" => ConditionType
24
- // "ns=0;i=2041" => BaseEventType
25
- if (!sameNodeId(operand.typeDefinitionId, conditionTypeNodeId)) {
26
- // not a ConditionType
27
- // but could be on of its derived type. for instance ns=0;i=2881 => AcknowledgeableConditionType
28
- if (!context.isSubtypeOf(operand.typeDefinitionId, conditionTypeNodeId)) {
29
- warningLog(" ", operand.typeDefinitionId.toString());
30
- warningLog(`this case is not handled yet : selectClause.typeDefinitionId = ${operand.typeDefinitionId.toString()}`);
31
- warningLog(operand.toString());
32
- return new Variant({ dataType: DataType.NodeId, value: context.eventSource });
33
- }
34
- }
35
-
36
- const eventSourceTypeDefinition = context.getTypeDefinition(context.eventSource);
37
- if (!eventSourceTypeDefinition) {
38
- // eventSource is a EventType class
39
- return new Variant();
40
- }
41
-
42
- if (!context.isSubtypeOf(eventSourceTypeDefinition, conditionTypeNodeId)) {
43
- return new Variant();
44
- }
45
- // Yeh : our EventType is a Condition Type !
46
- return new Variant({ dataType: DataType.NodeId, value: context.eventSource });
16
+ // the ConditionId shape (empty browsePath, attributeId NodeId) is resolved the same way here
17
+ // (delivery) and in resolveOperand (where-clause evaluation) - see resolveConditionIdOperand.
18
+ const conditionIdValue = resolveConditionIdOperand(context, operand);
19
+ if (conditionIdValue) {
20
+ return conditionIdValue;
47
21
  }
48
22
  return resolveOperand(context, operand);
49
23
  }
@@ -1,6 +1,6 @@
1
- import { NodeClass } from "node-opcua-data-model";
1
+ import { AttributeIds, NodeClass } from "node-opcua-data-model";
2
2
  import { checkDebugFlag, make_debugLog, make_warningLog } from "node-opcua-debug";
3
- import type { NodeId } from "node-opcua-nodeid";
3
+ import { type NodeId, resolveNodeId, sameNodeId } from "node-opcua-nodeid";
4
4
  import { constructBrowsePathFromQualifiedName } from "node-opcua-service-translate-browse-path";
5
5
  import { StatusCodes } from "node-opcua-status-code";
6
6
  import { AttributeOperand, SimpleAttributeOperand } from "node-opcua-types";
@@ -10,6 +10,52 @@ import type { FilterContext } from "./filter_context.js";
10
10
  const warningLog = make_warningLog("FILTER");
11
11
  const debugLog = make_debugLog("FILTER");
12
12
  const doDebug = checkDebugFlag("FILTER");
13
+ const conditionTypeNodeId = resolveNodeId("ConditionType");
14
+
15
+ /**
16
+ * OPC 10000-4 7.4.4.5: a SimpleAttributeOperand with an empty browsePath denotes the instance of
17
+ * typeDefinitionId itself, not "nothing to do". A ConditionId operand (typeDefinitionId
18
+ * ConditionType or a subtype, attributeId NodeId, empty browsePath) resolves to the event's own
19
+ * condition instance NodeId - this is what every Alarms and Conditions client sends, in both the
20
+ * select clause (delivery, via extractEventField) and the where clause (evaluation, via
21
+ * resolveOperand below). FEAT-58 taught the select-clause validation this; both consumers share
22
+ * this one resolution so they never drift apart again.
23
+ *
24
+ * Returns undefined when the operand does not match this shape, so the caller falls back to its
25
+ * normal browsePath resolution.
26
+ */
27
+ export function resolveConditionIdOperand(context: FilterContext, operand: SimpleAttributeOperand): Variant | undefined {
28
+ if (operand.browsePath && operand.browsePath.length > 0) {
29
+ return undefined;
30
+ }
31
+ if (operand.attributeId !== AttributeIds.NodeId) {
32
+ return undefined;
33
+ }
34
+ // "ns=0;i=2782" => ConditionType
35
+ // "ns=0;i=2041" => BaseEventType
36
+ if (!sameNodeId(operand.typeDefinitionId, conditionTypeNodeId)) {
37
+ // not a ConditionType
38
+ // but could be on of its derived type. for instance ns=0;i=2881 => AcknowledgeableConditionType
39
+ if (!context.isSubtypeOf(operand.typeDefinitionId, conditionTypeNodeId)) {
40
+ warningLog(" ", operand.typeDefinitionId.toString());
41
+ warningLog(`this case is not handled yet : selectClause.typeDefinitionId = ${operand.typeDefinitionId.toString()}`);
42
+ warningLog(operand.toString());
43
+ return new Variant({ dataType: DataType.NodeId, value: context.eventSource });
44
+ }
45
+ }
46
+
47
+ const eventSourceTypeDefinition = context.getTypeDefinition(context.eventSource);
48
+ if (!eventSourceTypeDefinition) {
49
+ // eventSource is a EventType class
50
+ return new Variant();
51
+ }
52
+
53
+ if (!context.isSubtypeOf(eventSourceTypeDefinition, conditionTypeNodeId)) {
54
+ return new Variant();
55
+ }
56
+ // Yeh : our EventType is a Condition Type !
57
+ return new Variant({ dataType: DataType.NodeId, value: context.eventSource });
58
+ }
13
59
 
14
60
  // export function readOperand(context: FilterContext, operand: SimpleAttributeOperand): Variant {
15
61
  // // navigate to the innerNode specified by the browsePath [ QualifiedName]
@@ -23,6 +69,11 @@ const doDebug = checkDebugFlag("FILTER");
23
69
 
24
70
  export function resolveOperand(context: FilterContext, operand: SimpleAttributeOperand | AttributeOperand): Variant {
25
71
  if (operand instanceof SimpleAttributeOperand) {
72
+ const conditionIdValue = resolveConditionIdOperand(context, operand);
73
+ if (conditionIdValue) {
74
+ return conditionIdValue;
75
+ }
76
+
26
77
  const browsePath = constructBrowsePathFromQualifiedName({ nodeId: context.eventSource }, operand.browsePath);
27
78
 
28
79
  const target: NodeId | null = context.browsePath(browsePath);