@fiqch/n8n-nodes-fiq-opcua
Version:
n8n custom node for reading and writing OPC UA data (FactoryIQ)
171 lines • 6.15 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.OpcUaConnectionPool = void 0;
const vendor_1 = require("../../../vendor");
class OpcUaConnectionPool {
constructor() {
this.pools = new Map();
}
static getInstance() {
if (!this.instance) {
this.instance = new OpcUaConnectionPool();
}
return this.instance;
}
async getConnection(credentials) {
const key = this.createKey(credentials);
let pool = this.pools.get(key) || [];
for (const conn of pool) {
if (!conn.inUse && conn.session && !conn.session.isReconnecting) {
try {
if (conn.session.isChannelValid && conn.session.isChannelValid()) {
conn.inUse = true;
return conn;
}
}
catch (error) {
const index = pool.indexOf(conn);
if (index > -1) {
pool.splice(index, 1);
}
}
}
}
if (pool.length < 3) {
try {
const newConn = await this.createConnection(credentials, key);
newConn.inUse = true;
pool.push(newConn);
this.pools.set(key, pool);
return newConn;
}
catch (error) {
throw error;
}
}
const conn = pool[0];
conn.inUse = true;
return conn;
}
releaseConnection(connection) {
if (connection) {
connection.inUse = false;
}
}
createKey(credentials) {
const endpointUrl = credentials.endpointUrl;
const authenticationType = credentials.authenticationType || 'anonymous';
const username = credentials.username || '';
return `${endpointUrl}|${authenticationType}|${username}`;
}
async createConnection(credentials, key) {
const endpointUrl = credentials.endpointUrl;
const securityPolicy = credentials.securityPolicy || 'None';
const securityMode = credentials.securityMode || 'None';
const authenticationType = credentials.authenticationType || 'anonymous';
let securityPolicyEnum;
let securityModeEnum;
switch (securityPolicy) {
case 'Basic256Sha256':
securityPolicyEnum = vendor_1.SecurityPolicy.Basic256Sha256;
break;
case 'Basic256':
securityPolicyEnum = vendor_1.SecurityPolicy.Basic256;
break;
case 'Basic128Rsa15':
securityPolicyEnum = vendor_1.SecurityPolicy.Basic128Rsa15;
break;
case 'Aes128_Sha256_RsaOaep':
securityPolicyEnum = vendor_1.SecurityPolicy.Aes128_Sha256_RsaOaep;
break;
case 'Aes256_Sha256_RsaPss':
securityPolicyEnum = vendor_1.SecurityPolicy.Aes256_Sha256_RsaPss;
break;
default:
securityPolicyEnum = vendor_1.SecurityPolicy.None;
}
switch (securityMode) {
case 'Sign':
securityModeEnum = vendor_1.MessageSecurityMode.Sign;
break;
case 'SignAndEncrypt':
case 'Sign & Encrypt':
securityModeEnum = vendor_1.MessageSecurityMode.SignAndEncrypt;
break;
default:
securityModeEnum = vendor_1.MessageSecurityMode.None;
}
const randomSuffix = Math.random().toString(36).substring(2, 10);
const clientName = `n8n-opcua-pool-${randomSuffix}`;
const clientOptions = {
securityPolicy: securityPolicyEnum,
securityMode: securityModeEnum,
connectionStrategy: {
initialDelay: 1000,
maxRetry: 3,
maxDelay: 10000,
},
clientName,
requestedSessionTimeout: 60000,
endpointMustExist: false,
securityOptions: {
rejectUnauthorized: false
}
};
if (authenticationType === 'x509') {
if (credentials.certificate && credentials.privateKey) {
clientOptions.certificateData = Buffer.from(credentials.certificate);
clientOptions.privateKeyData = Buffer.from(credentials.privateKey);
}
else {
throw new Error('X509 authentication requires both certificate and private key.');
}
}
const client = vendor_1.OPCUAClient.create(clientOptions);
await client.connect(endpointUrl);
let userIdentity;
if (authenticationType === 'usernamePassword') {
userIdentity = {
type: vendor_1.UserTokenType.UserName,
userName: credentials.username,
password: credentials.password,
};
}
else if (authenticationType === 'x509') {
userIdentity = {
type: vendor_1.UserTokenType.Certificate,
certificateData: credentials.certificate,
privateKey: credentials.privateKey,
};
}
else {
userIdentity = undefined;
}
const session = await client.createSession(userIdentity);
return {
client,
session,
inUse: false,
key
};
}
async shutdown() {
for (const pool of this.pools.values()) {
for (const conn of pool) {
try {
if (conn.session) {
await conn.session.close();
}
if (conn.client) {
await conn.client.disconnect();
}
}
catch (error) {
}
}
}
this.pools.clear();
}
}
exports.OpcUaConnectionPool = OpcUaConnectionPool;
//# sourceMappingURL=ConnectionPool.js.map