• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

node-opcua / node-opcua / 17757485684

16 Sep 2025 07:01AM UTC coverage: 90.742% (-0.09%) from 90.83%
17757485684

push

github

erossignon
chore(package): update lock file

11078 of 14078 branches covered (78.69%)

30138 of 33213 relevant lines covered (90.74%)

337724.07 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.21
/packages/node-opcua-pseudo-session/source/basic_session_interface.ts
1
/**
2
 * @module node-opcua-pseudo-session
3
 */
4
import { assert } from "node-opcua-assert";
5✔
5
import { ByteString } from "node-opcua-basic-types";
6
import { AttributeIds, BrowseDirection, makeResultMask } from "node-opcua-data-model";
5✔
7
import { DataValue } from "node-opcua-data-value";
8
import { NodeIdLike, resolveNodeId } from "node-opcua-nodeid";
5✔
9
import { BrowseDescription, BrowseDescriptionOptions, BrowseResult } from "node-opcua-service-browse";
5✔
10
import { Argument, CallMethodRequestOptions, CallMethodResult } from "node-opcua-service-call";
11
import { ReadValueIdOptions } from "node-opcua-service-read";
12
import { WriteValueOptions } from "node-opcua-service-write";
13
import { BrowsePath, BrowsePathResult } from "node-opcua-service-translate-browse-path";
14
import { DataType, VariantArrayType } from "node-opcua-variant";
5✔
15
import { CallbackT, StatusCode, StatusCodes } from "node-opcua-status-code";
16
import { VariableIds } from "node-opcua-constants";
5✔
17
import { BrowsePathOptions, UserTokenType, X509IdentityTokenOptions } from "node-opcua-types";
18

19
export type BrowseDescriptionLike = string | BrowseDescriptionOptions;
20
export type CallMethodRequestLike = CallMethodRequestOptions;
21

22
export type ResponseCallback<T> = (err: Error | null, result?: T) => void;
23

24
export type MethodId = NodeIdLike;
25

26
export interface ArgumentDefinition {
27
    inputArguments: Argument[];
28
    outputArguments: Argument[];
29
}
30
export interface IBasicTransportSettings {
31
    maxMessageSize: number;
32
}
33

34
// #region Browse
35
export interface IBasicSessionBrowseAsyncSimple {
36
    browse(nodeToBrowse: BrowseDescriptionLike): Promise<BrowseResult>;
37
}
38

39
export interface IBasicSessionBrowseAsyncMultiple {
40
    browse(nodesToBrowse: BrowseDescriptionLike[]): Promise<BrowseResult[]>;
41
}
42
export interface IBasicSessionBrowseAsync extends IBasicSessionBrowseAsyncSimple, IBasicSessionBrowseAsyncMultiple {
43
    browse(nodeToBrowse: BrowseDescriptionLike): Promise<BrowseResult>;
44
    browse(nodesToBrowse: BrowseDescriptionLike[]): Promise<BrowseResult[]>;
45
}
46

47
export interface IBasicSessionBrowseCallback {
48
    browse(nodeToBrowse: BrowseDescriptionLike, callback: ResponseCallback<BrowseResult>): void;
49

50
    browse(nodesToBrowse: BrowseDescriptionLike[], callback: ResponseCallback<BrowseResult[]>): void;
51
}
52
export interface IBasicSessionBrowse extends IBasicSessionBrowseAsync, IBasicSessionBrowseCallback {
53
    browse(nodeToBrowse: BrowseDescriptionLike): Promise<BrowseResult>;
54
    browse(nodesToBrowse: BrowseDescriptionLike[]): Promise<BrowseResult[]>;
55
    browse(nodeToBrowse: BrowseDescriptionLike, callback: ResponseCallback<BrowseResult>): void;
56

57
    browse(nodesToBrowse: BrowseDescriptionLike[], callback: ResponseCallback<BrowseResult[]>): void;
58
}
59
// #endregion
60

61
// #region BrowseNext
62
export interface IBasicSessionBrowseNextAsyncSimple {
63
    browseNext(continuationPoint: Buffer, releaseContinuationPoints: boolean): Promise<BrowseResult>;
64
}
65
export interface IBasicSessionBrowseNextAsyncMultiple {
66
    browseNext(continuationPoints: Buffer[], releaseContinuationPoints: boolean): Promise<BrowseResult[]>;
67
}
68
export interface IBasicSessionBrowseNextAsync extends IBasicSessionBrowseNextAsyncMultiple, IBasicSessionBrowseNextAsyncSimple {
69
    browseNext(continuationPoint: Buffer, releaseContinuationPoints: boolean): Promise<BrowseResult>;
70
    browseNext(continuationPoints: Buffer[], releaseContinuationPoints: boolean): Promise<BrowseResult[]>;
71
}
72
export interface IBasicSessionBrowseNextCallback {
73
    /**
74
     *
75
     * @param continuationPoint
76
     * @param releaseContinuationPoints  a Boolean parameter with the following values:
77
     *     * `true` passed continuationPoints shall be reset to free resources in
78
     *      the Server. The continuation points are released and the results
79
     *      and diagnosticInfos arrays are empty.
80
     *     * `false` passed continuationPoints shall be used to get the next set of
81
     *      browse information.
82
     *
83
     *   A Client shall always use the continuation point returned by a Browse or
84
     *    BrowseNext response to free the resources for the continuation point in the
85
     *    Server. If the Client does not want to get the next set of browse information,
86
     *    BrowseNext shall be called with this parameter set to `true`.
87
     *
88
     */
89
    browseNext(continuationPoint: Buffer, releaseContinuationPoints: boolean, callback: ResponseCallback<BrowseResult>): void;
90

91
    browseNext(continuationPoints: Buffer[], releaseContinuationPoints: boolean, callback: ResponseCallback<BrowseResult[]>): void;
92
}
93
export interface IBasicSessionBrowseNext extends IBasicSessionBrowseNextAsync, IBasicSessionBrowseNextCallback {
94
    browseNext(continuationPoint: Buffer, releaseContinuationPoints: boolean): Promise<BrowseResult>;
95
    browseNext(continuationPoints: Buffer[], releaseContinuationPoints: boolean): Promise<BrowseResult[]>;
96
    browseNext(continuationPoint: Buffer, releaseContinuationPoints: boolean, callback: ResponseCallback<BrowseResult>): void;
97

98
    browseNext(continuationPoints: Buffer[], releaseContinuationPoints: boolean, callback: ResponseCallback<BrowseResult[]>): void;
99
}
100
// #endregion
101

102
// #region Read
103
export interface IBasicSessionReadAsyncSimple {
104
    read(nodeToRead: ReadValueIdOptions, maxAge?: number): Promise<DataValue>;
105
}
106
export interface IBasicSessionReadAsyncMultiple {
107
    read(nodesToRead: ReadValueIdOptions[], maxAge?: number): Promise<DataValue[]>;
108
}
109

110
export interface IBasicSessionReadAsync extends IBasicSessionReadAsyncSimple, IBasicSessionReadAsyncMultiple {
111
    read(nodeToRead: ReadValueIdOptions, maxAge?: number): Promise<DataValue>;
112
    read(nodesToRead: ReadValueIdOptions[], maxAge?: number): Promise<DataValue[]>;
113
}
114
export interface IBasicSessionReadCallback {
115
    read(nodeToRead: ReadValueIdOptions, maxAge: number, callback: ResponseCallback<DataValue>): void;
116
    read(nodesToRead: ReadValueIdOptions[], maxAge: number, callback: ResponseCallback<DataValue[]>): void;
117
    read(nodeToRead: ReadValueIdOptions, callback: ResponseCallback<DataValue>): void;
118
    read(nodesToRead: ReadValueIdOptions[], callback: ResponseCallback<DataValue[]>): void;
119
}
120
export interface IBasicSessionRead extends IBasicSessionReadCallback, IBasicSessionReadAsync {
121
    read(nodeToRead: ReadValueIdOptions, maxAge?: number): Promise<DataValue>;
122
    read(nodesToRead: ReadValueIdOptions[], maxAge?: number): Promise<DataValue[]>;
123
    read(nodeToRead: ReadValueIdOptions, maxAge: number, callback: ResponseCallback<DataValue>): void;
124
    read(nodesToRead: ReadValueIdOptions[], maxAge: number, callback: ResponseCallback<DataValue[]>): void;
125
    read(nodeToRead: ReadValueIdOptions, callback: ResponseCallback<DataValue>): void;
126
    read(nodesToRead: ReadValueIdOptions[], callback: ResponseCallback<DataValue[]>): void;
127
}
128
// #endregion
129

130
// #region Write
131
export interface IBasicSessionWriteAsyncSimple {
132
    write(nodeToWrite: WriteValueOptions): Promise<StatusCode>;
133
}
134
export interface IBasicSessionWriteAsyncMultiple {
135
    write(nodesToWrite: WriteValueOptions[]): Promise<StatusCode[]>;
136
}
137
export interface IBasicSessionWriteAsync extends IBasicSessionWriteAsyncSimple, IBasicSessionWriteAsyncMultiple {
138
    write(nodeToWrite: WriteValueOptions): Promise<StatusCode>;
139
    write(nodesToWrite: WriteValueOptions[]): Promise<StatusCode[]>;
140
}
141
export interface IBasicSessionWriteCallback {
142
    write(nodeToWrite: WriteValueOptions, callback: ResponseCallback<StatusCode>): void;
143
    write(nodesToWrite: WriteValueOptions[], callback: ResponseCallback<StatusCode[]>): void;
144
}
145
export interface IBasicSessionWrite extends IBasicSessionWriteCallback, IBasicSessionWriteAsync {
146
    write(nodeToWrite: WriteValueOptions): Promise<StatusCode>;
147
    write(nodesToWrite: WriteValueOptions[]): Promise<StatusCode[]>;
148
    write(nodeToWrite: WriteValueOptions, callback: ResponseCallback<StatusCode>): void;
149
    write(nodesToWrite: WriteValueOptions[], callback: ResponseCallback<StatusCode[]>): void;
150
}
151

152
// #endregion
153

154
// #region Call
155
export interface IBasicSessionCallAsyncSimple {
156
    call(methodToCall: CallMethodRequestLike): Promise<CallMethodResult>;
157
}
158
export interface IBasicSessionCallAsyncMultiple {
159
    call(methodsToCall: CallMethodRequestLike[]): Promise<CallMethodResult[]>;
160
}
161
export interface IBasicSessionCallAsync extends IBasicSessionCallAsyncSimple, IBasicSessionCallAsyncMultiple {
162
    call(methodToCall: CallMethodRequestLike): Promise<CallMethodResult>;
163
    call(methodsToCall: CallMethodRequestLike[]): Promise<CallMethodResult[]>;
164
}
165
export interface IBasicSessionCallCallback {
166
    call(methodToCall: CallMethodRequestLike, callback: (err: Error | null, result?: CallMethodResult) => void): void;
167
    call(methodsToCall: CallMethodRequestLike[], callback: (err: Error | null, results?: CallMethodResult[]) => void): void;
168
}
169

170
export interface IBasicSessionCall extends IBasicSessionCallCallback, IBasicSessionCallAsync {
171
    /**
172
     *
173
     *
174
     * @param methodToCall {CallMethodRequest} the call method request
175
     * @param callback
176
     *
177
     * @example :
178
     *
179
     * ```javascript
180
     * const methodToCall = {
181
     *     objectId: "ns=2;i=12",
182
     *     methodId: "ns=2;i=13",
183
     *     inputArguments: [
184
     *         new Variant({...}),
185
     *         new Variant({...}),
186
     *     ]
187
     * }
188
     * session.call(methodToCall,function(err,callResult) {
189
     *    if (!err) {
190
     *         console.log(" statusCode = ",callResult.statusCode);
191
     *         console.log(" inputArgumentResults[0] = ",callResult.inputArgumentResults[0].toString());
192
     *         console.log(" inputArgumentResults[1] = ",callResult.inputArgumentResults[1].toString());
193
     *         console.log(" outputArgument[0]       = ",callResult.outputArgument[0].toString()); // array of variant
194
     *    }
195
     * });
196
     * ```
197
     *
198
     *
199
     * @param methodsToCall {CallMethodRequest[]} the call method request array
200
     * @param callback
201
     *
202
     *
203
     * @example :
204
     *
205
     * ```javascript
206
     * const methodsToCall = [ {
207
     *     objectId: "ns=2;i=12",
208
     *     methodId: "ns=2;i=13",
209
     *     inputArguments: [
210
     *         new Variant({...}),
211
     *         new Variant({...}),
212
     *     ]
213
     * }];
214
     * session.call(methodsToCall,function(err,callResults) {
215
     *    if (!err) {
216
     *         const callResult = callResults[0];
217
     *         console.log(" statusCode = ",rep.statusCode);
218
     *         console.log(" inputArgumentResults[0] = ",callResult.inputArgumentResults[0].toString());
219
     *         console.log(" inputArgumentResults[1] = ",callResult.inputArgumentResults[1].toString());
220
     *         console.log(" outputArgument[0]       = ",callResult.outputArgument[0].toString()); // array of variant
221
     *    }
222
     * });
223
     * ```
224
     */
225

226
    call(methodToCall: CallMethodRequestLike): Promise<CallMethodResult>;
227
    call(methodsToCall: CallMethodRequestLike[]): Promise<CallMethodResult[]>;
228
    call(methodToCall: CallMethodRequestLike, callback: (err: Error | null, result?: CallMethodResult) => void): void;
229
    call(methodsToCall: CallMethodRequestLike[], callback: (err: Error | null, results?: CallMethodResult[]) => void): void;
230
}
231

232
// #endregion
233

234
// #region TranslateBrowsePath
235

236
export type BrowsePathLike = BrowsePathOptions;
237
export interface IBasicSessionTranslateBrowsePathAsyncSimple {
238
    translateBrowsePath(browsePath: BrowsePathLike): Promise<BrowsePathResult>;
239
}
240
export interface IBasicSessionTranslateBrowsePathAsyncMultiple {
241
    translateBrowsePath(browsePaths: BrowsePathLike[]): Promise<BrowsePathResult[]>;
242
}
243
export interface IBasicSessionTranslateBrowsePathAsync
244
    extends IBasicSessionTranslateBrowsePathAsyncSimple,
245
        IBasicSessionTranslateBrowsePathAsyncMultiple {
246
    translateBrowsePath(browsePath: BrowsePathLike): Promise<BrowsePathResult>;
247
    translateBrowsePath(browsePaths: BrowsePathLike[]): Promise<BrowsePathResult[]>;
248
}
249
export interface IBasicSessionTranslateBrowsePathCallback {
250
    translateBrowsePath(browsesPath: BrowsePathLike[], callback: ResponseCallback<BrowsePathResult[]>): void;
251
    translateBrowsePath(browsePath: BrowsePathLike, callback: ResponseCallback<BrowsePathResult>): void;
252
}
253
export interface IBasicSessionTranslateBrowsePath
254
    extends IBasicSessionTranslateBrowsePathCallback,
255
        IBasicSessionTranslateBrowsePathAsync {
256
    translateBrowsePath(browsePath: BrowsePathLike): Promise<BrowsePathResult>;
257
    translateBrowsePath(browsePaths: BrowsePathLike[]): Promise<BrowsePathResult[]>;
258
    translateBrowsePath(browsesPath: BrowsePathLike[], callback: ResponseCallback<BrowsePathResult[]>): void;
259
    translateBrowsePath(browsePath: BrowsePathLike, callback: ResponseCallback<BrowsePathResult>): void;
260
}
261

262
// #endregion
263

264
export interface IBasicSessionAsyncSimple extends 
265
        IBasicSessionBrowseAsyncSimple,
266
        IBasicSessionReadAsyncSimple,
267
        IBasicSessionWriteAsyncSimple,
268
        IBasicSessionCallAsyncSimple,
269
        IBasicSessionTranslateBrowsePathAsyncSimple {}
270

271

272
export interface IBasicSessionAsyncMultiple extends 
273
        IBasicSessionBrowseAsyncMultiple,
274
        IBasicSessionReadAsyncMultiple,
275
        IBasicSessionWriteAsyncMultiple,
276
        IBasicSessionCallAsyncMultiple,
277
        IBasicSessionTranslateBrowsePathAsyncMultiple {}
278

279
export interface IBasicSessionAsync extends  IBasicSessionBrowseAsync,
280
        IBasicSessionReadAsync,
281
        IBasicSessionWriteAsync,
282
        IBasicSessionCallAsync,
283
        IBasicSessionTranslateBrowsePathAsync {}
284
export type IVeryBasicSession = IBasicSessionAsync;
285

286
export interface IBasicSessionAsync2 extends IBasicSessionAsync, IBasicSessionBrowseNextAsync {}
287
export interface ITransportSettingProvider {
288
    getTransportSettings?: () => IBasicTransportSettings;
289
}
290

291
export interface IBasicSessionGetArgumentDefinitionCallback {
292
    getArgumentDefinition(methodId: MethodId, callback: (err: Error | null, args?: ArgumentDefinition) => void): void;
293
}
294
export interface IBasicSessionGetArgumentDefinitionAsync {
295
    getArgumentDefinition(methodId: MethodId): Promise<ArgumentDefinition>;
296
}
297
export interface IBasicSessionGetArgumentDefinition extends IBasicSessionGetArgumentDefinitionAsync, IBasicSessionGetArgumentDefinitionCallback {
298
    getArgumentDefinition(methodId: MethodId): Promise<ArgumentDefinition>;
299
    getArgumentDefinition(methodId: MethodId, callback: (err: Error | null, args?: ArgumentDefinition) => void): void;
300

301
}
302

303
export type IBasicSessionCallback = IBasicSessionReadCallback &
304
    IBasicSessionBrowseNextCallback &
305
    IBasicSessionBrowseCallback &
306
    IBasicSessionTranslateBrowsePathCallback &
307
    IBasicSessionGetArgumentDefinitionCallback &
308
    IBasicSessionWriteCallback;
309

310
export interface IBasicSession
311
    extends ITransportSettingProvider,
312
        IBasicSessionBrowse,
313
        IBasicSessionBrowseNext,
314
        IBasicSessionCall,
315
        IBasicSessionRead,
316
        IBasicSessionTranslateBrowsePath,
317
        IBasicSessionWrite,
318
        IBasicSessionGetArgumentDefinition {
319
}
320

321
export type PrivateKeyPEM = string;
322
export interface UserIdentityInfoUserName {
323
    type: UserTokenType.UserName;
324
    userName: string;
325
    password: string;
326
}
327

328
export interface UserIdentityInfoX509 extends X509IdentityTokenOptions {
329
    type: UserTokenType.Certificate;
330
    certificateData: ByteString;
331
    privateKey: PrivateKeyPEM;
332
}
333
export interface AnonymousIdentity {
334
    type: UserTokenType.Anonymous;
335
}
336

337
export type UserIdentityInfo = AnonymousIdentity | UserIdentityInfoX509 | UserIdentityInfoUserName;
338

339
export interface IBasicSessionChangeUser {
340
    changeUser(userIdentityInfo: UserIdentityInfo): Promise<StatusCode>;
341
    changeUser(userIdentityInfo: UserIdentityInfo, callback: CallbackT<StatusCode>): void;
342
}
343

344
function isValid(result: DataValue): boolean {
345
    assert(result.statusCode.isGood());
105✔
346
    if (result.value.dataType !== DataType.Null) {
105!
347
        assert(result.value.dataType === DataType.ExtensionObject);
105✔
348
        assert(result.value.arrayType === VariantArrayType.Array);
105✔
349
    }
350
    return true;
105✔
351
}
352

353
export async function getArgumentDefinitionHelper(
5✔
354
    session: IBasicSessionBrowseAsyncSimple & IBasicSessionReadAsyncMultiple,
355
    methodId: MethodId
356
): Promise<ArgumentDefinition> {
357
    const browseDescription = new BrowseDescription({
84✔
358
        browseDirection: BrowseDirection.Forward,
359
        includeSubtypes: true,
360
        nodeClassMask: 0, // makeNodeClassMask("Variable"),
361
        nodeId: methodId,
362
        referenceTypeId: resolveNodeId("HasProperty"),
363
        resultMask: makeResultMask("BrowseName")
364
    });
365

366
    const browseResult = await session.browse(browseDescription);
84✔
367
    browseResult.references = browseResult.references || [];
84!
368

369
    const inputArgumentRefArray = browseResult.references.filter((r) => r.browseName.name === "InputArguments");
105✔
370

371
    // note : InputArguments property is optional thus may be missing
372
    const inputArgumentRef = inputArgumentRefArray.length === 1 ? inputArgumentRefArray[0] : null;
84✔
373

374
    const outputArgumentRefArray = browseResult.references.filter((r) => r.browseName.name === "OutputArguments");
105✔
375

376
    // note : OutputArguments property is optional thus may be missing
377
    const outputArgumentRef = outputArgumentRefArray.length === 1 ? outputArgumentRefArray[0] : null;
84✔
378

379
    let inputArguments: Argument[] = [];
84✔
380
    let outputArguments: Argument[] = [];
84✔
381

382
    const nodesToRead = [];
84✔
383
    const actions: any[] = [];
84✔
384

385
    if (inputArgumentRef) {
84✔
386
        nodesToRead.push({
66✔
387
            attributeId: AttributeIds.Value,
388
            nodeId: inputArgumentRef.nodeId
389
        });
390
        actions.push((result: DataValue) => {
66✔
391
            if (isValid(result)) {
66!
392
                inputArguments = result.value.value as Argument[];
66✔
393
            }
394
        });
395
    }
396
    if (outputArgumentRef) {
84✔
397
        nodesToRead.push({
39✔
398
            attributeId: AttributeIds.Value,
399
            nodeId: outputArgumentRef.nodeId
400
        });
401
        actions.push((result: DataValue) => {
39✔
402
            assert(result.statusCode.isGood());
39✔
403
            if (isValid(result)) {
39!
404
                outputArguments = result.value.value as Argument[];
39✔
405
            }
406
        });
407
    }
408

409
    if (nodesToRead.length === 0) {
84✔
410
        return { inputArguments, outputArguments };
16✔
411
    }
412
    // now read the variable
413
    const dataValues = await session.read(nodesToRead);
68✔
414

415
    dataValues.forEach((dataValue, index) => {
68✔
416
        actions[index].call(null, dataValue);
105✔
417
    });
418

419
    return { inputArguments, outputArguments };
68✔
420
}
421

422
interface SessionWithCache extends IBasicSessionAsync2 {
423
    $$namespaceArray?: string[] | null;
424
}
425

426

427
type ICascadingSession = { session?: IBasicSessionReadAsyncSimple }
428
function followSession(session: IBasicSessionReadAsyncSimple & ICascadingSession): SessionWithCache {
429
    if (session.session) {
525!
430
        return followSession(session.session);
×
431
    }
432
    return session as SessionWithCache;
525✔
433
}
434

435

436
export async function readNamespaceArray(session: IBasicSessionReadAsyncSimple): Promise<string[]> {
5✔
437

438
    const sessionHoldingCache = followSession(session) as SessionWithCache;
473✔
439
    if (sessionHoldingCache.$$namespaceArray)  {
473✔
440
        return sessionHoldingCache.$$namespaceArray!;
26✔
441
    }
442
    const nodeId = resolveNodeId(VariableIds.Server_NamespaceArray);
447✔
443

444
    const dataValue = await session.read({
447✔
445
        nodeId,
446
        attributeId: AttributeIds.Value
447
    });
448
    if (dataValue.statusCode.isNotGood()) {
447✔
449
        // errorLog("namespaceArray is not populated ! Your server must expose a list of namespaces in node ", nodeId.toString());
450
        return [];
1✔
451
    }
452
    sessionHoldingCache.$$namespaceArray = dataValue.value.value; // keep a cache
446✔
453
    return sessionHoldingCache.$$namespaceArray!;
446✔
454
}
455

456
export async function clearSessionCache(session: IBasicSessionAsync2) {
5✔
457
    const sessionHoldingCache = followSession(session) as SessionWithCache;
52✔
458
    sessionHoldingCache.$$namespaceArray = undefined;
52✔
459
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc