UNPKG

lambda-live-debugger

Version:

Debug Lambda functions locally like it is running in the cloud

111 lines (110 loc) 3.37 kB
import * as iot from 'aws-iot-device-sdk'; import { splitMessageToChunks } from './utils/splitIoTMessage.mjs'; import { IoTClient, DescribeEndpointCommand } from '@aws-sdk/client-iot'; import { Logger } from './logger.mjs'; let device; const chunks = new Map(); /** * Get IoT endpoint * @param param0 * @returns */ async function getIoTEndpoint({ region, credentials, }) { const iot = new IoTClient({ region, credentials, }); const response = await iot.send(new DescribeEndpointCommand({ endpointType: 'iot:Data-ATS', })); if (!response.endpointAddress) throw new Error('IoT Endpoint address not found'); return response.endpointAddress; } let connectedPromiseResolve; const connectedPromise = new Promise((resolve) => { connectedPromiseResolve = resolve; }); /** * Connect to IoT * @param props * @returns */ async function connect(props) { const credentials = props?.credentialsProvider ? await props.credentialsProvider() : undefined; const endpoint = await getIoTEndpoint({ region: props?.region, credentials, }); device = new iot.device({ protocol: 'wss', host: endpoint, reconnectPeriod: 1, keepalive: 60, region: props?.region, accessKeyId: credentials?.accessKeyId, secretKey: credentials?.secretAccessKey, sessionToken: credentials?.sessionToken, }); if (props?.topic) { device.subscribe(props.topic, { qos: 1 }); Logger.verbose('[IoT] Subscribed to topic ', props.topic); } device.on('connect', () => { Logger.verbose('[IoT] Connected'); connectedPromiseResolve(); }); device.on('error', (err) => { Logger.error('[IoT] Error', err); }); device.on('close', () => { Logger.verbose('[IoT] Closed'); }); device.on('reconnect', () => { Logger.verbose('[IoT] Reconnecting...'); }); if (props?.onMessage) { const messageReceived = (topic, buffer) => { const chunk = JSON.parse(buffer.toString()); if (!chunk.id) { throw new Error('Invalid fragment'); } let pending = chunks.get(chunk.id); if (!pending) { pending = new Map(); chunks.set(chunk.id, pending); } pending.set(chunk.index, chunk); if (pending.size === chunk.count) { const data = [...pending.values()] .sort((a, b) => a.index - b.index) .map((item) => item.data) .join(''); chunks.delete(chunk.id); const evt = JSON.parse(data); props.onMessage(evt); } }; device.on('message', messageReceived); } await connectedPromise; return { publish: async (payload, topic) => { await connectedPromise; for (const fragment of splitMessageToChunks(payload)) { await new Promise((r) => { device.publish(topic, JSON.stringify(fragment), { qos: 1, }, () => { r(); }); }); } }, }; } export const IoTService = { connect, };