node-opcua-alias-name-server 2.176.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 (51) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +361 -0
  3. package/dist/add_alias.d.ts +73 -0
  4. package/dist/add_alias.js +262 -0
  5. package/dist/add_alias.js.map +1 -0
  6. package/dist/address_space_alias_store.d.ts +130 -0
  7. package/dist/address_space_alias_store.js +360 -0
  8. package/dist/address_space_alias_store.js.map +1 -0
  9. package/dist/alias_hierarchy.d.ts +45 -0
  10. package/dist/alias_hierarchy.js +135 -0
  11. package/dist/alias_hierarchy.js.map +1 -0
  12. package/dist/alias_index.d.ts +60 -0
  13. package/dist/alias_index.js +119 -0
  14. package/dist/alias_index.js.map +1 -0
  15. package/dist/alias_name_archive.d.ts +45 -0
  16. package/dist/alias_name_archive.js +75 -0
  17. package/dist/alias_name_archive.js.map +1 -0
  18. package/dist/bind_alias_category.d.ts +173 -0
  19. package/dist/bind_alias_category.js +417 -0
  20. package/dist/bind_alias_category.js.map +1 -0
  21. package/dist/bind_configuration_methods.d.ts +44 -0
  22. package/dist/bind_configuration_methods.js +175 -0
  23. package/dist/bind_configuration_methods.js.map +1 -0
  24. package/dist/bind_find_alias.d.ts +61 -0
  25. package/dist/bind_find_alias.js +227 -0
  26. package/dist/bind_find_alias.js.map +1 -0
  27. package/dist/index.d.ts +18 -0
  28. package/dist/index.js +64 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/install_alias_names.d.ts +229 -0
  31. package/dist/install_alias_names.js +146 -0
  32. package/dist/install_alias_names.js.map +1 -0
  33. package/dist/last_change.d.ts +87 -0
  34. package/dist/last_change.js +174 -0
  35. package/dist/last_change.js.map +1 -0
  36. package/dist/well_known.d.ts +88 -0
  37. package/dist/well_known.js +93 -0
  38. package/dist/well_known.js.map +1 -0
  39. package/package.json +54 -0
  40. package/source/add_alias.ts +318 -0
  41. package/source/address_space_alias_store.ts +417 -0
  42. package/source/alias_hierarchy.ts +141 -0
  43. package/source/alias_index.ts +127 -0
  44. package/source/alias_name_archive.ts +84 -0
  45. package/source/bind_alias_category.ts +546 -0
  46. package/source/bind_configuration_methods.ts +219 -0
  47. package/source/bind_find_alias.ts +290 -0
  48. package/source/index.ts +74 -0
  49. package/source/install_alias_names.ts +342 -0
  50. package/source/last_change.ts +201 -0
  51. package/source/well_known.ts +101 -0
@@ -0,0 +1,61 @@
1
+ /**
2
+ * @module node-opcua-alias-name-server
3
+ *
4
+ * The `FindAlias` (clause 6.3.2) and `FindAliasVerbose` (clause 6.3.3) Method
5
+ * handlers.
6
+ *
7
+ * The two Methods are identical in every respect except the DataType they
8
+ * return, so both are produced from one implementation: whatever the FindAlias
9
+ * suite proves is proved for FindAliasVerbose too.
10
+ */
11
+ import type { ISessionContext, UAMethod } from "node-opcua-address-space-base";
12
+ import { type AliasEntry, type IAliasStore } from "node-opcua-alias-name-common";
13
+ import { type NodeId } from "node-opcua-nodeid";
14
+ import type { CallMethodResultOptions } from "node-opcua-service-call";
15
+ import { type Variant } from "node-opcua-variant";
16
+ /**
17
+ * Orders results before they are returned.
18
+ *
19
+ * Clause 6.3.2 requires the Server to return "what it recommends as the best
20
+ * match first", and says the criteria are Server specific — the examples it
21
+ * gives (ServerStatus of the Server holding the Node, load balancing) only mean
22
+ * anything once more than one Server is involved. A Server publishing its own
23
+ * aliases has no basis to prefer one of its own Nodes over another, so the
24
+ * default preserves discovery order, which is at least deterministic and
25
+ * therefore stable across calls. Replace it when the Server does have a basis.
26
+ */
27
+ export type AliasComparator = (a: AliasEntry, b: AliasEntry) => number;
28
+ /** The default: keep discovery order (a stable no-op comparator). */
29
+ export declare const insertionOrderComparator: AliasComparator;
30
+ export interface FindAliasBindingOptions {
31
+ /** Where the aliases come from. */
32
+ store: IAliasStore;
33
+ /**
34
+ * Beyond this many results the call fails with `Bad_ResponseTooLarge`
35
+ * (clause 6.3.2 Table 4).
36
+ */
37
+ maxResults: number;
38
+ /** Result ordering; defaults to {@link insertionOrderComparator}. */
39
+ comparator?: AliasComparator;
40
+ /**
41
+ * Read gate. Return false to answer `Bad_UserAccessDenied`
42
+ * (clause 6.3.2 Table 4). Defaults to allowing everyone, matching a Server
43
+ * that publishes its aliases openly.
44
+ *
45
+ * Receives the category the Method was called on, so a Server with
46
+ * per-customer or per-tenant categories can answer "may this user see *this*
47
+ * category" rather than only "may this user read aliases at all". May return
48
+ * a Promise: the handler is async anyway, so a permission lookup that hits a
49
+ * database costs nothing structurally.
50
+ */
51
+ isReadAllowed?: (context: ISessionContext, categoryNodeId: NodeId) => boolean | Promise<boolean>;
52
+ }
53
+ /**
54
+ * Build a handler for `FindAlias` or `FindAliasVerbose`.
55
+ *
56
+ * `this` is the Method node, so the category searched is the Method's parent —
57
+ * that is what makes one handler serve every instance of
58
+ * `AliasNameCategoryType`, including vendor subcategories created through the
59
+ * `<SubAliasNameCategories>` placeholder.
60
+ */
61
+ export declare function makeFindAliasHandler(options: FindAliasBindingOptions, verbose: boolean): (this: UAMethod, inputArguments: Variant[], context: ISessionContext) => Promise<CallMethodResultOptions>;
@@ -0,0 +1,227 @@
1
+ "use strict";
2
+ /**
3
+ * @module node-opcua-alias-name-server
4
+ *
5
+ * The `FindAlias` (clause 6.3.2) and `FindAliasVerbose` (clause 6.3.3) Method
6
+ * handlers.
7
+ *
8
+ * The two Methods are identical in every respect except the DataType they
9
+ * return, so both are produced from one implementation: whatever the FindAlias
10
+ * suite proves is proved for FindAliasVerbose too.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.insertionOrderComparator = void 0;
14
+ exports.makeFindAliasHandler = makeFindAliasHandler;
15
+ const node_opcua_alias_name_common_1 = require("node-opcua-alias-name-common");
16
+ const node_opcua_nodeid_1 = require("node-opcua-nodeid");
17
+ const node_opcua_status_code_1 = require("node-opcua-status-code");
18
+ const node_opcua_types_1 = require("node-opcua-types");
19
+ const node_opcua_variant_1 = require("node-opcua-variant");
20
+ /** The default: keep discovery order (a stable no-op comparator). */
21
+ const insertionOrderComparator = () => 0;
22
+ exports.insertionOrderComparator = insertionOrderComparator;
23
+ /** Read `AliasNameSearchPattern` (argument 0). */
24
+ function readPattern(inputArguments) {
25
+ const value = inputArguments?.[0]?.value;
26
+ if (value === null || value === undefined) {
27
+ // clause 6.3.2 gives no meaning to a null pattern; treat it as "match
28
+ // everything" would silently dump the whole hierarchy, so reject it
29
+ return null;
30
+ }
31
+ return typeof value === "string" ? value : null;
32
+ }
33
+ /** Read `ReferenceTypeFilter` (argument 1). */
34
+ function readReferenceTypeFilter(inputArguments) {
35
+ const value = inputArguments?.[1]?.value;
36
+ return value instanceof node_opcua_nodeid_1.NodeId ? value : undefined;
37
+ }
38
+ /**
39
+ * Merge entries that share an AliasName.
40
+ *
41
+ * `AliasNameDataType` is "an array of ExpandedNodeId for a single AliasName"
42
+ * (clause 7.2), so the non-verbose Method reports one entry per distinct name
43
+ * with all of its targets. The verbose form does *not* merge: its
44
+ * `AliasNameCategoryId` names the category that held the alias, which differs
45
+ * between entries.
46
+ */
47
+ function mergeByAliasName(entries) {
48
+ const byName = new Map();
49
+ // Membership is kept in a Set per name rather than rescanning the growing
50
+ // array: with a linear scan, a name shared by many entries makes this
51
+ // quadratic in the size of the result set.
52
+ const seenTargets = new Map();
53
+ for (const entry of entries) {
54
+ const existing = byName.get(entry.aliasName);
55
+ if (!existing) {
56
+ byName.set(entry.aliasName, { ...entry, referencedNodes: [...entry.referencedNodes] });
57
+ seenTargets.set(entry.aliasName, new Set(entry.referencedNodes.map((n) => n.toString())));
58
+ continue;
59
+ }
60
+ // written alongside byName above, so it is always present
61
+ const seen = seenTargets.get(entry.aliasName) ?? new Set();
62
+ seenTargets.set(entry.aliasName, seen);
63
+ for (const node of entry.referencedNodes) {
64
+ const key = node.toString();
65
+ if (!seen.has(key)) {
66
+ seen.add(key);
67
+ existing.referencedNodes.push(node);
68
+ }
69
+ }
70
+ }
71
+ return [...byName.values()];
72
+ }
73
+ /**
74
+ * Resolve each entry's AliasName namespace index, once per call.
75
+ *
76
+ * The namespace reported is the one the alias was published in, taken from the
77
+ * store. Using the *category's* namespace instead would put every alias on the
78
+ * three well-known categories into namespace 0, which is reserved for the OPC
79
+ * Foundation and is not what clause 6.2 intends. A store that does not know its
80
+ * namespace falls back to the Server's own, never to 0.
81
+ *
82
+ * Clients ignore the namespace when comparing AliasNames (clause 6.2), so this
83
+ * is not a matching concern — it is a matter of reporting truthfully.
84
+ */
85
+ function makeNamespaceResolver(category) {
86
+ const addressSpace = category.addressSpace;
87
+ const ownNamespaceIndex = addressSpace.getOwnNamespace().index;
88
+ const cache = new Map();
89
+ return (entry) => {
90
+ if (!entry.aliasNameNamespaceUri) {
91
+ return ownNamespaceIndex;
92
+ }
93
+ const cached = cache.get(entry.aliasNameNamespaceUri);
94
+ if (cached !== undefined) {
95
+ return cached;
96
+ }
97
+ const index = addressSpace.getNamespaceIndex(entry.aliasNameNamespaceUri);
98
+ // an unregistered URI resolves to -1; reporting the Server's own
99
+ // namespace is closer to the truth than reporting namespace 0
100
+ const resolved = index >= 0 ? index : ownNamespaceIndex;
101
+ cache.set(entry.aliasNameNamespaceUri, resolved);
102
+ return resolved;
103
+ };
104
+ }
105
+ /**
106
+ * Build a handler for `FindAlias` or `FindAliasVerbose`.
107
+ *
108
+ * `this` is the Method node, so the category searched is the Method's parent —
109
+ * that is what makes one handler serve every instance of
110
+ * `AliasNameCategoryType`, including vendor subcategories created through the
111
+ * `<SubAliasNameCategories>` placeholder.
112
+ */
113
+ function makeFindAliasHandler(options, verbose) {
114
+ const comparator = options.comparator ?? exports.insertionOrderComparator;
115
+ return async function findAliasHandler(inputArguments, context) {
116
+ const category = this.parent;
117
+ if (!category) {
118
+ return { statusCode: node_opcua_status_code_1.StatusCodes.BadInternalError };
119
+ }
120
+ // The gate is consulted per category, and each category at most once per
121
+ // call. Memoised because a recursive search reaches the same category
122
+ // through every alias it holds, and the rule may hit a database.
123
+ const gate = options.isReadAllowed;
124
+ const decisions = new Map();
125
+ const mayRead = async (categoryNodeId) => {
126
+ if (!gate) {
127
+ return true;
128
+ }
129
+ const key = categoryNodeId.toString();
130
+ const cached = decisions.get(key);
131
+ if (cached !== undefined) {
132
+ return cached;
133
+ }
134
+ const allowed = await gate(context, categoryNodeId);
135
+ decisions.set(key, allowed);
136
+ return allowed;
137
+ };
138
+ // A direct call on a category the caller may not read is
139
+ // Bad_UserAccessDenied: there is nothing left to filter, so silence
140
+ // would be a lie rather than a non-disclosure.
141
+ if (!(await mayRead(category.nodeId))) {
142
+ return { statusCode: node_opcua_status_code_1.StatusCodes.BadUserAccessDenied };
143
+ }
144
+ const pattern = readPattern(inputArguments);
145
+ if (pattern === null) {
146
+ return { statusCode: node_opcua_status_code_1.StatusCodes.BadInvalidArgument };
147
+ }
148
+ const query = {
149
+ pattern,
150
+ referenceTypeFilter: readReferenceTypeFilter(inputArguments),
151
+ categoryNodeId: category.nodeId,
152
+ maxResults: options.maxResults,
153
+ // Handed the same memoised closure the filter below uses, so the
154
+ // rule is evaluated at most once per category per call however many
155
+ // times it is consulted. Passed only when a gate is configured, so
156
+ // an ungated Server takes exactly the path it took before.
157
+ isVisible: gate ? mayRead : undefined
158
+ };
159
+ let found;
160
+ try {
161
+ found = await options.store.find(query);
162
+ }
163
+ catch (err) {
164
+ if (err instanceof node_opcua_alias_name_common_1.InvalidLikePatternError) {
165
+ // clause 6.3.2 Table 4: "The input string is not a valid search string"
166
+ return { statusCode: node_opcua_status_code_1.StatusCodes.BadInvalidArgument };
167
+ }
168
+ throw err;
169
+ }
170
+ // clause 6.3.2 Table 4: too large to return, "try new filter and repeat find".
171
+ //
172
+ // Applied to what the store produced, *before* filtering and merging.
173
+ // The store stops collecting one entry past the cap, so a count that
174
+ // reaches it means "there may be more"; reducing the count first would
175
+ // report a truncated scan as a complete answer. The code names no
176
+ // category, so it discloses nothing a gated caller should not see.
177
+ if (found.length > options.maxResults) {
178
+ return { statusCode: node_opcua_status_code_1.StatusCodes.BadResponseTooLarge };
179
+ }
180
+ // A nested category the caller may not read is omitted, and the call
181
+ // still succeeds: an error, or a count that changed, would confirm the
182
+ // category exists. Absence is the only answer that discloses nothing.
183
+ //
184
+ // The store was given the same predicate and should already have skipped
185
+ // these, so this is normally a no-op. It stays as a backstop: an injected
186
+ // store written by someone else may ignore `isVisible`, and the cost of
187
+ // that must be a wasted scan, never a leak.
188
+ const visible = [];
189
+ for (const entry of found) {
190
+ if (await mayRead(entry.categoryNodeId)) {
191
+ visible.push(entry);
192
+ }
193
+ }
194
+ // Filtering happens before the verbose/plain split, so FindAliasVerbose
195
+ // cannot reveal a ServerUri or an AliasNameCategoryId for a category
196
+ // that FindAlias would have hidden.
197
+ const results = verbose ? visible : mergeByAliasName(visible);
198
+ // sort() is stable in modern JavaScript, so a comparator that returns 0
199
+ // leaves discovery order untouched
200
+ const ordered = [...results].sort(comparator);
201
+ // No match is Good with an empty AliasNodeList (clause 6.3.2 Table 3),
202
+ // never an error.
203
+ const namespaceIndexOf = makeNamespaceResolver(category);
204
+ const value = verbose
205
+ ? ordered.map((entry) => new node_opcua_types_1.AliasNameVerboseDataType({
206
+ aliasName: { name: entry.aliasName, namespaceIndex: namespaceIndexOf(entry) },
207
+ referencedNodes: entry.referencedNodes,
208
+ serverUris: entry.serverUris,
209
+ aliasNameCategoryId: entry.categoryNodeId
210
+ }))
211
+ : ordered.map((entry) => new node_opcua_types_1.AliasNameDataType({
212
+ aliasName: { name: entry.aliasName, namespaceIndex: namespaceIndexOf(entry) },
213
+ referencedNodes: entry.referencedNodes
214
+ }));
215
+ return {
216
+ statusCode: node_opcua_status_code_1.StatusCodes.Good,
217
+ outputArguments: [
218
+ {
219
+ dataType: node_opcua_variant_1.DataType.ExtensionObject,
220
+ arrayType: node_opcua_variant_1.VariantArrayType.Array,
221
+ value
222
+ }
223
+ ]
224
+ };
225
+ };
226
+ }
227
+ //# sourceMappingURL=bind_find_alias.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bind_find_alias.js","sourceRoot":"","sources":["../source/bind_find_alias.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @module node-opcua-alias-name-server
3
+ *
4
+ * Server-side OPC 10000-17 (AliasNames).
5
+ *
6
+ * Publishes **this Server's own** AliasNames. Aggregating AliasNames collected
7
+ * from other Servers (Annex B, Annex C) and the Annex D PubSub change
8
+ * notification are out of scope.
9
+ */
10
+ export { type AddAliasOptions, AliasNameError, addAlias, findAlias, removeAlias } from "./add_alias.js";
11
+ export { AddressSpaceAliasStore, type AddressSpaceAliasStoreOptions } from "./address_space_alias_store.js";
12
+ export { aliasesOf, collectAllCategories, collectCategories, findAliasNameCategoryType, findAliasNameType, isAliasName, isAliasNameCategory, presentWellKnownCategories } from "./alias_hierarchy.js";
13
+ export { ALIAS_NAME_ARCHIVE_VERSION, type AliasNameArchive, readAliasNameArchive, writeAliasNameArchive } from "./alias_name_archive.js";
14
+ export { type AddAliasCategoryOptions, addAliasCategory, type BindAliasCategoryOptions, bindAliasCategory, ensureLastChangeProperty, ensureOptionalMethod, findMethodByDeclaration, getInstalledAliasNames, type InstalledAliasNames, removeAliasCategory } from "./bind_alias_category.js";
15
+ export { type AliasComparator, type FindAliasBindingOptions, insertionOrderComparator, makeFindAliasHandler } from "./bind_find_alias.js";
16
+ export { ALIAS_SERVER_CAPABILITY_ID, advertiseAliasCapability, type CategoryProvider, DEFAULT_MAX_RESULTS, defaultCategoryProvider, type InstallAliasNamesOptions, type InstallAliasNamesResult, type IServerForAliasNames, installAliasNames, installAliasNamesOnAddressSpace } from "./install_alias_names.js";
17
+ export { LAST_CHANGE_BROWSE_NAME, LastChangeTracker, type LastChangeTrackerOptions } from "./last_change.js";
18
+ export { ALIAS_FOR, ALIAS_NAME_CATEGORY_TYPE, ALIAS_NAME_TYPE, ALIAS_SERVER_CAPABILITY, MethodDeclarations, PUBLISHED_DATA_SET_TYPE, WellKnownCategories, WellKnownLastChange, WellKnownOptionalMethods } from "./well_known.js";
package/dist/index.js ADDED
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ /**
3
+ * @module node-opcua-alias-name-server
4
+ *
5
+ * Server-side OPC 10000-17 (AliasNames).
6
+ *
7
+ * Publishes **this Server's own** AliasNames. Aggregating AliasNames collected
8
+ * from other Servers (Annex B, Annex C) and the Annex D PubSub change
9
+ * notification are out of scope.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.WellKnownOptionalMethods = exports.WellKnownLastChange = exports.WellKnownCategories = exports.PUBLISHED_DATA_SET_TYPE = exports.MethodDeclarations = exports.ALIAS_SERVER_CAPABILITY = exports.ALIAS_NAME_TYPE = exports.ALIAS_NAME_CATEGORY_TYPE = exports.ALIAS_FOR = exports.LastChangeTracker = exports.LAST_CHANGE_BROWSE_NAME = exports.installAliasNamesOnAddressSpace = exports.installAliasNames = exports.defaultCategoryProvider = exports.DEFAULT_MAX_RESULTS = exports.advertiseAliasCapability = exports.ALIAS_SERVER_CAPABILITY_ID = exports.makeFindAliasHandler = exports.insertionOrderComparator = exports.removeAliasCategory = exports.getInstalledAliasNames = exports.findMethodByDeclaration = exports.ensureOptionalMethod = exports.ensureLastChangeProperty = exports.bindAliasCategory = exports.addAliasCategory = exports.writeAliasNameArchive = exports.readAliasNameArchive = exports.ALIAS_NAME_ARCHIVE_VERSION = exports.presentWellKnownCategories = exports.isAliasNameCategory = exports.isAliasName = exports.findAliasNameType = exports.findAliasNameCategoryType = exports.collectCategories = exports.collectAllCategories = exports.aliasesOf = exports.AddressSpaceAliasStore = exports.removeAlias = exports.findAlias = exports.addAlias = exports.AliasNameError = void 0;
13
+ var add_alias_js_1 = require("./add_alias.js");
14
+ Object.defineProperty(exports, "AliasNameError", { enumerable: true, get: function () { return add_alias_js_1.AliasNameError; } });
15
+ Object.defineProperty(exports, "addAlias", { enumerable: true, get: function () { return add_alias_js_1.addAlias; } });
16
+ Object.defineProperty(exports, "findAlias", { enumerable: true, get: function () { return add_alias_js_1.findAlias; } });
17
+ Object.defineProperty(exports, "removeAlias", { enumerable: true, get: function () { return add_alias_js_1.removeAlias; } });
18
+ var address_space_alias_store_js_1 = require("./address_space_alias_store.js");
19
+ Object.defineProperty(exports, "AddressSpaceAliasStore", { enumerable: true, get: function () { return address_space_alias_store_js_1.AddressSpaceAliasStore; } });
20
+ var alias_hierarchy_js_1 = require("./alias_hierarchy.js");
21
+ Object.defineProperty(exports, "aliasesOf", { enumerable: true, get: function () { return alias_hierarchy_js_1.aliasesOf; } });
22
+ Object.defineProperty(exports, "collectAllCategories", { enumerable: true, get: function () { return alias_hierarchy_js_1.collectAllCategories; } });
23
+ Object.defineProperty(exports, "collectCategories", { enumerable: true, get: function () { return alias_hierarchy_js_1.collectCategories; } });
24
+ Object.defineProperty(exports, "findAliasNameCategoryType", { enumerable: true, get: function () { return alias_hierarchy_js_1.findAliasNameCategoryType; } });
25
+ Object.defineProperty(exports, "findAliasNameType", { enumerable: true, get: function () { return alias_hierarchy_js_1.findAliasNameType; } });
26
+ Object.defineProperty(exports, "isAliasName", { enumerable: true, get: function () { return alias_hierarchy_js_1.isAliasName; } });
27
+ Object.defineProperty(exports, "isAliasNameCategory", { enumerable: true, get: function () { return alias_hierarchy_js_1.isAliasNameCategory; } });
28
+ Object.defineProperty(exports, "presentWellKnownCategories", { enumerable: true, get: function () { return alias_hierarchy_js_1.presentWellKnownCategories; } });
29
+ var alias_name_archive_js_1 = require("./alias_name_archive.js");
30
+ Object.defineProperty(exports, "ALIAS_NAME_ARCHIVE_VERSION", { enumerable: true, get: function () { return alias_name_archive_js_1.ALIAS_NAME_ARCHIVE_VERSION; } });
31
+ Object.defineProperty(exports, "readAliasNameArchive", { enumerable: true, get: function () { return alias_name_archive_js_1.readAliasNameArchive; } });
32
+ Object.defineProperty(exports, "writeAliasNameArchive", { enumerable: true, get: function () { return alias_name_archive_js_1.writeAliasNameArchive; } });
33
+ var bind_alias_category_js_1 = require("./bind_alias_category.js");
34
+ Object.defineProperty(exports, "addAliasCategory", { enumerable: true, get: function () { return bind_alias_category_js_1.addAliasCategory; } });
35
+ Object.defineProperty(exports, "bindAliasCategory", { enumerable: true, get: function () { return bind_alias_category_js_1.bindAliasCategory; } });
36
+ Object.defineProperty(exports, "ensureLastChangeProperty", { enumerable: true, get: function () { return bind_alias_category_js_1.ensureLastChangeProperty; } });
37
+ Object.defineProperty(exports, "ensureOptionalMethod", { enumerable: true, get: function () { return bind_alias_category_js_1.ensureOptionalMethod; } });
38
+ Object.defineProperty(exports, "findMethodByDeclaration", { enumerable: true, get: function () { return bind_alias_category_js_1.findMethodByDeclaration; } });
39
+ Object.defineProperty(exports, "getInstalledAliasNames", { enumerable: true, get: function () { return bind_alias_category_js_1.getInstalledAliasNames; } });
40
+ Object.defineProperty(exports, "removeAliasCategory", { enumerable: true, get: function () { return bind_alias_category_js_1.removeAliasCategory; } });
41
+ var bind_find_alias_js_1 = require("./bind_find_alias.js");
42
+ Object.defineProperty(exports, "insertionOrderComparator", { enumerable: true, get: function () { return bind_find_alias_js_1.insertionOrderComparator; } });
43
+ Object.defineProperty(exports, "makeFindAliasHandler", { enumerable: true, get: function () { return bind_find_alias_js_1.makeFindAliasHandler; } });
44
+ var install_alias_names_js_1 = require("./install_alias_names.js");
45
+ Object.defineProperty(exports, "ALIAS_SERVER_CAPABILITY_ID", { enumerable: true, get: function () { return install_alias_names_js_1.ALIAS_SERVER_CAPABILITY_ID; } });
46
+ Object.defineProperty(exports, "advertiseAliasCapability", { enumerable: true, get: function () { return install_alias_names_js_1.advertiseAliasCapability; } });
47
+ Object.defineProperty(exports, "DEFAULT_MAX_RESULTS", { enumerable: true, get: function () { return install_alias_names_js_1.DEFAULT_MAX_RESULTS; } });
48
+ Object.defineProperty(exports, "defaultCategoryProvider", { enumerable: true, get: function () { return install_alias_names_js_1.defaultCategoryProvider; } });
49
+ Object.defineProperty(exports, "installAliasNames", { enumerable: true, get: function () { return install_alias_names_js_1.installAliasNames; } });
50
+ Object.defineProperty(exports, "installAliasNamesOnAddressSpace", { enumerable: true, get: function () { return install_alias_names_js_1.installAliasNamesOnAddressSpace; } });
51
+ var last_change_js_1 = require("./last_change.js");
52
+ Object.defineProperty(exports, "LAST_CHANGE_BROWSE_NAME", { enumerable: true, get: function () { return last_change_js_1.LAST_CHANGE_BROWSE_NAME; } });
53
+ Object.defineProperty(exports, "LastChangeTracker", { enumerable: true, get: function () { return last_change_js_1.LastChangeTracker; } });
54
+ var well_known_js_1 = require("./well_known.js");
55
+ Object.defineProperty(exports, "ALIAS_FOR", { enumerable: true, get: function () { return well_known_js_1.ALIAS_FOR; } });
56
+ Object.defineProperty(exports, "ALIAS_NAME_CATEGORY_TYPE", { enumerable: true, get: function () { return well_known_js_1.ALIAS_NAME_CATEGORY_TYPE; } });
57
+ Object.defineProperty(exports, "ALIAS_NAME_TYPE", { enumerable: true, get: function () { return well_known_js_1.ALIAS_NAME_TYPE; } });
58
+ Object.defineProperty(exports, "ALIAS_SERVER_CAPABILITY", { enumerable: true, get: function () { return well_known_js_1.ALIAS_SERVER_CAPABILITY; } });
59
+ Object.defineProperty(exports, "MethodDeclarations", { enumerable: true, get: function () { return well_known_js_1.MethodDeclarations; } });
60
+ Object.defineProperty(exports, "PUBLISHED_DATA_SET_TYPE", { enumerable: true, get: function () { return well_known_js_1.PUBLISHED_DATA_SET_TYPE; } });
61
+ Object.defineProperty(exports, "WellKnownCategories", { enumerable: true, get: function () { return well_known_js_1.WellKnownCategories; } });
62
+ Object.defineProperty(exports, "WellKnownLastChange", { enumerable: true, get: function () { return well_known_js_1.WellKnownLastChange; } });
63
+ Object.defineProperty(exports, "WellKnownOptionalMethods", { enumerable: true, get: function () { return well_known_js_1.WellKnownOptionalMethods; } });
64
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../source/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAEH,+CAAwG;AAAzE,8GAAA,cAAc,OAAA;AAAE,wGAAA,QAAQ,OAAA;AAAE,yGAAA,SAAS,OAAA;AAAE,2GAAA,WAAW,OAAA;AAC/E,+EAA4G;AAAnG,sIAAA,sBAAsB,OAAA;AAC/B,2DAS8B;AAR1B,+GAAA,SAAS,OAAA;AACT,0HAAA,oBAAoB,OAAA;AACpB,uHAAA,iBAAiB,OAAA;AACjB,+HAAA,yBAAyB,OAAA;AACzB,uHAAA,iBAAiB,OAAA;AACjB,iHAAA,WAAW,OAAA;AACX,yHAAA,mBAAmB,OAAA;AACnB,gIAAA,0BAA0B,OAAA;AAE9B,iEAKiC;AAJ7B,mIAAA,0BAA0B,OAAA;AAE1B,6HAAA,oBAAoB,OAAA;AACpB,8HAAA,qBAAqB,OAAA;AAEzB,mEAWkC;AAT9B,0HAAA,gBAAgB,OAAA;AAEhB,2HAAA,iBAAiB,OAAA;AACjB,kIAAA,wBAAwB,OAAA;AACxB,8HAAA,oBAAoB,OAAA;AACpB,iIAAA,uBAAuB,OAAA;AACvB,gIAAA,sBAAsB,OAAA;AAEtB,6HAAA,mBAAmB,OAAA;AAEvB,2DAK8B;AAF1B,8HAAA,wBAAwB,OAAA;AACxB,0HAAA,oBAAoB,OAAA;AAExB,mEAWkC;AAV9B,oIAAA,0BAA0B,OAAA;AAC1B,kIAAA,wBAAwB,OAAA;AAExB,6HAAA,mBAAmB,OAAA;AACnB,iIAAA,uBAAuB,OAAA;AAIvB,2HAAA,iBAAiB,OAAA;AACjB,yIAAA,+BAA+B,OAAA;AAEnC,mDAI0B;AAHtB,yHAAA,uBAAuB,OAAA;AACvB,mHAAA,iBAAiB,OAAA;AAGrB,iDAUyB;AATrB,0GAAA,SAAS,OAAA;AACT,yHAAA,wBAAwB,OAAA;AACxB,gHAAA,eAAe,OAAA;AACf,wHAAA,uBAAuB,OAAA;AACvB,mHAAA,kBAAkB,OAAA;AAClB,wHAAA,uBAAuB,OAAA;AACvB,oHAAA,mBAAmB,OAAA;AACnB,oHAAA,mBAAmB,OAAA;AACnB,yHAAA,wBAAwB,OAAA"}
@@ -0,0 +1,229 @@
1
+ /**
2
+ * @module node-opcua-alias-name-server
3
+ *
4
+ * Install OPC 10000-17 AliasName support on a Server.
5
+ *
6
+ * Every node-opcua Server that loads the standard nodeset already exposes
7
+ * `Aliases`, `TagVariables` and `Topics`, each carrying a MANDATORY `FindAlias`
8
+ * Method that is bound to nothing. A conformance tester therefore sees the SDK
9
+ * advertise the AliasName feature and then fail its only required Method. This
10
+ * binds them.
11
+ */
12
+ import type { IAddressSpace, ISessionContext, UAObject } from "node-opcua-address-space-base";
13
+ import type { IAliasStore, LikeOptions } from "node-opcua-alias-name-common";
14
+ import type { NodeId } from "node-opcua-nodeid";
15
+ import { type BindAliasCategoryOptions } from "./bind_alias_category.js";
16
+ import type { AliasComparator } from "./bind_find_alias.js";
17
+ import { LastChangeTracker } from "./last_change.js";
18
+ import { DEFAULT_MAX_RESULTS } from "./well_known.js";
19
+ export { DEFAULT_MAX_RESULTS };
20
+ /**
21
+ * Supplies the `AliasNameCategoryType` instances to bind.
22
+ *
23
+ * Defaults to {@link defaultCategoryProvider}, which walks down from `Aliases`.
24
+ * Replace it when the category set is not a static tree — one category per
25
+ * customer, one per upstream Server, categories that appear and disappear at
26
+ * runtime. May be asynchronous, since the set may have to be fetched.
27
+ *
28
+ * A provider only decides *what installation binds*. Categories created after
29
+ * installation are bound with {@link bindAliasCategory}, or created already
30
+ * bound with {@link addAliasCategory}.
31
+ */
32
+ export type CategoryProvider = (addressSpace: IAddressSpace) => UAObject[] | Promise<UAObject[]>;
33
+ /**
34
+ * The default provider: every `AliasNameCategoryType` instance at or below
35
+ * `Aliases`, plus any roots named in `additionalCategoryRoots`.
36
+ *
37
+ * `additionalCategoryRoots` is expressed through this rather than as a parallel
38
+ * mechanism, so a custom provider can reuse it — `defaultCategoryProvider(roots)`
39
+ * composes with whatever else the Server knows about.
40
+ */
41
+ export declare function defaultCategoryProvider(additionalRoots?: Array<NodeId | UAObject>): CategoryProvider;
42
+ export interface InstallAliasNamesOptions {
43
+ /**
44
+ * Where aliases come from. Defaults to an {@link AddressSpaceAliasStore},
45
+ * which reads them straight out of the address space — so a Server whose
46
+ * NodeSet2.xml already models `AliasNameType` instances needs no options at
47
+ * all.
48
+ */
49
+ store?: IAliasStore;
50
+ /** Result cap per call (clause 6.3.2 Table 4). Defaults to {@link DEFAULT_MAX_RESULTS}. */
51
+ maxResults?: number;
52
+ /**
53
+ * Also bind `FindAliasVerbose` (clause 6.3.3, conformance unit
54
+ * AliasName FindAliasVerbose). On by default: it costs one extra Method per
55
+ * category and is what lets a Client see which category held a hit.
56
+ */
57
+ verbose?: boolean;
58
+ /**
59
+ * Also expose `AddAliasesToCategory` and `DeleteAliasesFromCategory`
60
+ * (clauses 6.3.4 and 6.3.5, conformance unit *AliasName Configuration
61
+ * Support*, CU 5874).
62
+ *
63
+ * **Off by default**: both Methods are Optional, and a write surface that
64
+ * appears without being asked for is a surface nobody reviewed. Turning it
65
+ * on is not by itself dangerous — every call is denied until
66
+ * {@link isWriteAllowed} says otherwise — but the Methods do become visible
67
+ * to a browsing Client.
68
+ */
69
+ configurationMethods?: boolean;
70
+ /** Passed to the `Like` matcher used by the default store. */
71
+ likeOptions?: LikeOptions;
72
+ /** Result ordering (clause 6.3.2, "best match first"). */
73
+ comparator?: AliasComparator;
74
+ /**
75
+ * Read gate, consulted **per category** and allowed to be asynchronous.
76
+ * Defaults to allowing everyone, so a Server that simply publishes its
77
+ * aliases is unaffected.
78
+ *
79
+ * A direct call on a denied category answers `Bad_UserAccessDenied`; a
80
+ * denied category reached by a recursive search is omitted and the call
81
+ * still returns `Good`, so nothing reveals that it exists.
82
+ *
83
+ * OPC 10000-17 defines no security model — four `Bad_UserAccessDenied` rows,
84
+ * no Security clause, no Roles, and no `RolePermissions` on any Part 17 node
85
+ * in the standard nodeset — so every Server has to supply its own rule.
86
+ */
87
+ isReadAllowed?: (context: ISessionContext, categoryNodeId: NodeId) => boolean | Promise<boolean>;
88
+ /**
89
+ * Write gate for the configuration Methods, mirroring
90
+ * {@link isReadAllowed}. **Defaults to denying everyone**: the write surface
91
+ * is the one place where a permissive default would be a security defect
92
+ * rather than a convenience.
93
+ */
94
+ isWriteAllowed?: (context: ISessionContext, categoryNodeId: NodeId) => boolean | Promise<boolean>;
95
+ /**
96
+ * File backing the persisted `LastChange` values (clause 6.3.1: *"The
97
+ * LastChange shall be persisted"*).
98
+ *
99
+ * Without it, every restart resets `LastChange` to zero — and a Client that
100
+ * sees a value older than the one it cached is required by clause 6.3.1 to
101
+ * clear its cache. So an unpersisted Server silently orders every connected
102
+ * Client to discard a still-valid cache on every restart. Set this on any
103
+ * Server that Clients cache against.
104
+ *
105
+ * The file is small JSON: a version and a map of category NodeId to
106
+ * VersionTime. Writes are atomic.
107
+ */
108
+ persistencePath?: string;
109
+ /**
110
+ * Add a `LastChange` Property to every category, not only the `Aliases` root.
111
+ *
112
+ * On by default. `LastChange` is Optional on `AliasNameCategoryType` and the
113
+ * shipped nodeset instantiates it only on the root, which clause 9.2 makes
114
+ * mandatory — but the clause 6.3.1 rollup is only observable where the
115
+ * Property exists, so a Client watching one branch needs it there. Turn it
116
+ * off to keep the address space exactly as the nodeset ships it.
117
+ */
118
+ lastChangeOnAllCategories?: boolean;
119
+ /**
120
+ * Supplies "now" as a VersionTime, for tests that need to pin it. A
121
+ * VersionTime has one-second resolution, which is otherwise awkward to
122
+ * assert against.
123
+ */
124
+ nowVersionTime?: () => number;
125
+ /**
126
+ * Extra roots to search for `AliasNameCategoryType` instances.
127
+ *
128
+ * Categories are discovered by walking down from `Aliases`, which is where
129
+ * clause 9.1 puts them. Name a category here if the Server models one
130
+ * outside that hierarchy, otherwise its MANDATORY `FindAlias` stays unbound.
131
+ *
132
+ * Ignored when {@link categoryProvider} is supplied — compose it in with
133
+ * {@link defaultCategoryProvider} instead of passing both.
134
+ */
135
+ additionalCategoryRoots?: Array<NodeId | UAObject>;
136
+ /**
137
+ * Replace category discovery entirely. See {@link CategoryProvider}.
138
+ */
139
+ categoryProvider?: CategoryProvider;
140
+ /**
141
+ * Declare the `ALIAS` ServerCapability (OPC 10000-12 Annex D Table D.1).
142
+ * **On by default.**
143
+ *
144
+ * A Server that does not advertise it is never discovered by anything
145
+ * looking for alias-capable Servers, and nothing reports the failure — so
146
+ * leaving it to each caller to remember means it will sometimes be
147
+ * forgotten, invisibly. Installing the feature and declaring it are the same
148
+ * decision, so they happen together.
149
+ *
150
+ * **Call `installAliasNames` before `server.start()`.** The address space
151
+ * exists from `initialize()` onwards, and mDNS/LDS registration reads the
152
+ * capability list during `start()` — afterwards the list is still correct
153
+ * for anything reading `ServerConfiguration`, but the registration has
154
+ * already gone out without it.
155
+ *
156
+ * Set false if the Server manages its own capability list.
157
+ */
158
+ advertiseCapability?: boolean;
159
+ }
160
+ export interface InstallAliasNamesResult {
161
+ /** The store that was used — the injected one, or the default. */
162
+ store: IAliasStore;
163
+ /** Every `AliasNameCategoryType` instance that had its Methods bound. */
164
+ categories: NodeId[];
165
+ /** True when this call did the work; false when AliasNames were already installed. */
166
+ installed: boolean;
167
+ /**
168
+ * Keeps `LastChange` correct across the hierarchy, and persists it
169
+ * (clause 6.3.1).
170
+ */
171
+ lastChange?: LastChangeTracker;
172
+ /**
173
+ * The options every category was bound with.
174
+ *
175
+ * Pass these to {@link bindAliasCategory} to bind a category created later
176
+ * exactly as the installed ones were bound, without reassembling them by
177
+ * hand and risking a different store or result cap.
178
+ */
179
+ bindingOptions: BindAliasCategoryOptions;
180
+ }
181
+ /** The server-like object we need: the address space, and the capability list. */
182
+ export interface IServerForAliasNames {
183
+ engine: {
184
+ addressSpace: IAddressSpace | null;
185
+ };
186
+ /**
187
+ * The Server's OPC 10000-12 Annex D capability identifiers — on an
188
+ * `OPCUAServer` this is `capabilitiesForMDNS`. Optional so a caller can pass
189
+ * anything address-space-shaped; when present, `ALIAS` is added to it.
190
+ */
191
+ capabilitiesForMDNS?: string[];
192
+ }
193
+ /**
194
+ * The `ALIAS` ServerCapability identifier (OPC 10000-12 Annex D Table D.1).
195
+ *
196
+ * Part 17's prose writes it `Alias`; Part 12 Annex D is the normative source and
197
+ * writes `ALIAS`, matched case-insensitively.
198
+ */
199
+ export declare const ALIAS_SERVER_CAPABILITY_ID = "ALIAS";
200
+ /**
201
+ * Add `ALIAS` to a Server's Annex D capability list, in place.
202
+ *
203
+ * Idempotent, case-insensitive, and replaces the `NA` placeholder rather than
204
+ * producing the meaningless `["NA", "ALIAS"]`.
205
+ *
206
+ * @returns true when the list was changed.
207
+ */
208
+ export declare function advertiseAliasCapability(capabilities: string[]): boolean;
209
+ /**
210
+ * Install AliasName support on a Server.
211
+ *
212
+ * Call it **between `initialize()` and `start()`**: the address space exists
213
+ * from `initialize()`, and the `ALIAS` capability has to be in place before
214
+ * `start()` performs the mDNS/LDS registration that reads it.
215
+ *
216
+ * ```ts
217
+ * await server.initialize();
218
+ * await installAliasNames(server);
219
+ * await server.start();
220
+ * ```
221
+ */
222
+ export declare function installAliasNames(server: IServerForAliasNames, options?: InstallAliasNamesOptions): Promise<InstallAliasNamesResult>;
223
+ /**
224
+ * Install AliasName support directly on an address space.
225
+ *
226
+ * The two-tier form used elsewhere in the SDK: this one needs no Server, so it
227
+ * can be driven from a test or from a tool that only has an address space.
228
+ */
229
+ export declare function installAliasNamesOnAddressSpace(addressSpace: IAddressSpace, options?: InstallAliasNamesOptions): Promise<InstallAliasNamesResult>;