mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 10:02:05 +00:00
refactor(MQTT Node): Refactor, fix duplicate triggers, and add Unit tests (#9847)
Co-authored-by: Elias Meire <elias@meire.dev>
This commit is contained in:
committed by
GitHub
parent
e51de9d391
commit
164ec72c0d
@@ -1,6 +1,6 @@
|
||||
import type { IClientPublishOptions } from 'mqtt';
|
||||
import type {
|
||||
IExecuteFunctions,
|
||||
ICredentialDataDecryptedObject,
|
||||
ICredentialsDecrypted,
|
||||
ICredentialTestFunctions,
|
||||
INodeCredentialTestResult,
|
||||
@@ -8,10 +8,10 @@ import type {
|
||||
INodeType,
|
||||
INodeTypeDescription,
|
||||
} from 'n8n-workflow';
|
||||
import { randomString } from 'n8n-workflow';
|
||||
|
||||
import * as mqtt from 'mqtt';
|
||||
import { formatPrivateKey } from '@utils/utilities';
|
||||
import { createClient, type MqttCredential } from './GenericFunctions';
|
||||
|
||||
type PublishOption = Pick<IClientPublishOptions, 'qos' | 'retain'>;
|
||||
|
||||
export class Mqtt implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
@@ -110,63 +110,11 @@ export class Mqtt implements INodeType {
|
||||
this: ICredentialTestFunctions,
|
||||
credential: ICredentialsDecrypted,
|
||||
): Promise<INodeCredentialTestResult> {
|
||||
const credentials = credential.data as ICredentialDataDecryptedObject;
|
||||
const credentials = credential.data as unknown as MqttCredential;
|
||||
|
||||
try {
|
||||
const protocol = (credentials.protocol as string) || 'mqtt';
|
||||
const host = credentials.host as string;
|
||||
const brokerUrl = `${protocol}://${host}`;
|
||||
const port = (credentials.port as number) || 1883;
|
||||
const clientId =
|
||||
(credentials.clientId as string) || `mqttjs_${randomString(8).toLowerCase()}`;
|
||||
const clean = credentials.clean as boolean;
|
||||
const ssl = credentials.ssl as boolean;
|
||||
const ca = formatPrivateKey(credentials.ca as string);
|
||||
const cert = formatPrivateKey(credentials.cert as string);
|
||||
const key = formatPrivateKey(credentials.key as string);
|
||||
const rejectUnauthorized = credentials.rejectUnauthorized as boolean;
|
||||
|
||||
let client: mqtt.MqttClient;
|
||||
|
||||
if (!ssl) {
|
||||
const clientOptions: mqtt.IClientOptions = {
|
||||
port,
|
||||
clean,
|
||||
clientId,
|
||||
};
|
||||
|
||||
if (credentials.username && credentials.password) {
|
||||
clientOptions.username = credentials.username as string;
|
||||
clientOptions.password = credentials.password as string;
|
||||
}
|
||||
client = mqtt.connect(brokerUrl, clientOptions);
|
||||
} else {
|
||||
const clientOptions: mqtt.IClientOptions = {
|
||||
port,
|
||||
clean,
|
||||
clientId,
|
||||
ca,
|
||||
cert,
|
||||
key,
|
||||
rejectUnauthorized,
|
||||
};
|
||||
if (credentials.username && credentials.password) {
|
||||
clientOptions.username = credentials.username as string;
|
||||
clientOptions.password = credentials.password as string;
|
||||
}
|
||||
|
||||
client = mqtt.connect(brokerUrl, clientOptions);
|
||||
}
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
client.on('connect', (test) => {
|
||||
resolve(test);
|
||||
client.end();
|
||||
});
|
||||
client.on('error', (error) => {
|
||||
client.end();
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
const client = await createClient(credentials);
|
||||
client.end();
|
||||
} catch (error) {
|
||||
return {
|
||||
status: 'Error',
|
||||
@@ -182,87 +130,27 @@ export class Mqtt implements INodeType {
|
||||
};
|
||||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const credentials = (await this.getCredentials('mqtt')) as unknown as MqttCredential;
|
||||
const client = await createClient(credentials);
|
||||
|
||||
const publishPromises = [];
|
||||
const items = this.getInputData();
|
||||
const length = items.length;
|
||||
const credentials = await this.getCredentials('mqtt');
|
||||
|
||||
const protocol = (credentials.protocol as string) || 'mqtt';
|
||||
const host = credentials.host as string;
|
||||
const brokerUrl = `${protocol}://${host}`;
|
||||
const port = (credentials.port as number) || 1883;
|
||||
const clientId = (credentials.clientId as string) || `mqttjs_${randomString(8).toLowerCase()}`;
|
||||
const clean = credentials.clean as boolean;
|
||||
const ssl = credentials.ssl as boolean;
|
||||
const ca = credentials.ca as string;
|
||||
const cert = credentials.cert as string;
|
||||
const key = credentials.key as string;
|
||||
const rejectUnauthorized = credentials.rejectUnauthorized as boolean;
|
||||
|
||||
let client: mqtt.MqttClient;
|
||||
|
||||
if (!ssl) {
|
||||
const clientOptions: mqtt.IClientOptions = {
|
||||
port,
|
||||
clean,
|
||||
clientId,
|
||||
};
|
||||
|
||||
if (credentials.username && credentials.password) {
|
||||
clientOptions.username = credentials.username as string;
|
||||
clientOptions.password = credentials.password as string;
|
||||
}
|
||||
|
||||
client = mqtt.connect(brokerUrl, clientOptions);
|
||||
} else {
|
||||
const clientOptions: mqtt.IClientOptions = {
|
||||
port,
|
||||
clean,
|
||||
clientId,
|
||||
ca,
|
||||
cert,
|
||||
key,
|
||||
rejectUnauthorized,
|
||||
};
|
||||
if (credentials.username && credentials.password) {
|
||||
clientOptions.username = credentials.username as string;
|
||||
clientOptions.password = credentials.password as string;
|
||||
}
|
||||
|
||||
client = mqtt.connect(brokerUrl, clientOptions);
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const topic = this.getNodeParameter('topic', i) as string;
|
||||
const options = this.getNodeParameter('options', i) as unknown as PublishOption;
|
||||
const sendInputData = this.getNodeParameter('sendInputData', i) as boolean;
|
||||
const message = sendInputData
|
||||
? JSON.stringify(items[i].json)
|
||||
: (this.getNodeParameter('message', i) as string);
|
||||
publishPromises.push(client.publishAsync(topic, message, options));
|
||||
}
|
||||
|
||||
const sendInputData = this.getNodeParameter('sendInputData', 0) as boolean;
|
||||
await Promise.all(publishPromises);
|
||||
|
||||
const data = await new Promise((resolve, reject) => {
|
||||
client.on('connect', () => {
|
||||
for (let i = 0; i < length; i++) {
|
||||
let message;
|
||||
const topic = this.getNodeParameter('topic', i) as string;
|
||||
const options = this.getNodeParameter('options', i);
|
||||
// wait for the in-flight messages to be acked.
|
||||
// needed for messages with QoS 1 & 2
|
||||
await client.endAsync();
|
||||
|
||||
try {
|
||||
if (sendInputData) {
|
||||
message = JSON.stringify(items[i].json);
|
||||
} else {
|
||||
message = this.getNodeParameter('message', i) as string;
|
||||
}
|
||||
client.publish(topic, message, options);
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
}
|
||||
//wait for the in-flight messages to be acked.
|
||||
//needed for messages with QoS 1 & 2
|
||||
client.end(false, {}, () => {
|
||||
resolve([items]);
|
||||
});
|
||||
|
||||
client.on('error', (e) => {
|
||||
reject(e);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return data as INodeExecutionData[][];
|
||||
return [items];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user