@furlow/pipes 1.0.1 → 1.0.3
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.
- package/dist/database/index.js +145 -10
- package/dist/database/index.js.map +1 -1
- package/dist/index.js +239 -34
- package/dist/index.js.map +1 -1
- package/dist/mqtt/index.js +18 -3
- package/dist/mqtt/index.js.map +1 -1
- package/dist/tcp/index.d.ts +1 -0
- package/dist/tcp/index.js +44 -11
- package/dist/tcp/index.js.map +1 -1
- package/dist/webhook/index.js +6 -2
- package/dist/webhook/index.js.map +1 -1
- package/dist/websocket/index.d.ts +1 -0
- package/dist/websocket/index.js +26 -8
- package/dist/websocket/index.js.map +1 -1
- package/package.json +2 -2
package/dist/mqtt/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/mqtt/index.ts"],"sourcesContent":["/**\n * MQTT pipe for IoT and real-time integrations\n */\n\nimport mqtt, { MqttClient, IClientOptions, IClientPublishOptions } from 'mqtt';\nimport type { Pipe, PipeResponse, MqttPipeConfig, MqttQoS } from '../types.js';\n\nexport interface MqttPipeOptions {\n name: string;\n config: MqttPipeConfig;\n}\n\nexport type MqttMessageHandler = (\n topic: string,\n payload: Buffer | string | Record<string, unknown>,\n packet: unknown\n) => void | Promise<void>;\n\nexport class MqttPipe implements Pipe {\n public readonly name: string;\n public readonly type = 'mqtt';\n private client: MqttClient | null = null;\n private config: MqttPipeConfig;\n private connected = false;\n private reconnectAttempts = 0;\n private messageHandlers: Map<string, MqttMessageHandler[]> = new Map();\n private wildcardHandlers: Map<string, MqttMessageHandler[]> = new Map();\n\n constructor(options: MqttPipeOptions) {\n this.name = options.name;\n this.config = options.config;\n }\n\n /**\n * Connect to the MQTT broker\n */\n async connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n const protocol = this.config.protocol ?? 'mqtt';\n const port = this.config.port ?? (protocol === 'mqtts' || protocol === 'wss' ? 8883 : 1883);\n const url = `${protocol}://${this.config.broker}:${port}`;\n\n const options: IClientOptions = {\n keepalive: this.config.keepalive ?? 60,\n clean: this.config.clean ?? true,\n reconnectPeriod: this.config.reconnect?.enabled !== false\n ? this.parseDuration(this.config.reconnect?.delay ?? '5s')\n : 0,\n };\n\n // Authentication\n if (this.config.auth) {\n if (this.config.auth.username) options.username = this.config.auth.username;\n if (this.config.auth.password) options.password = this.config.auth.password;\n if (this.config.auth.clientId) options.clientId = this.config.auth.clientId;\n }\n\n // Last Will and Testament\n if (this.config.will) {\n options.will = {\n topic: this.config.will.topic,\n payload: Buffer.from(this.config.will.payload),\n qos: this.config.will.qos ?? 0,\n retain: this.config.will.retain ?? false,\n };\n }\n\n try {\n this.client = mqtt.connect(url, options);\n\n this.client.on('connect', () => {\n this.connected = true;\n this.reconnectAttempts = 0;\n this.emit('connected', {});\n resolve();\n });\n\n this.client.on('message', (topic, payload, packet) => {\n this.handleMessage(topic, payload, packet);\n });\n\n this.client.on('error', (error) => {\n if (!this.connected) {\n reject(error);\n }\n this.emit('error', error);\n });\n\n this.client.on('close', () => {\n this.connected = false;\n this.emit('disconnected', {});\n });\n\n this.client.on('reconnect', () => {\n this.reconnectAttempts++;\n this.emit('reconnecting', { attempts: this.reconnectAttempts });\n });\n\n this.client.on('offline', () => {\n this.connected = false;\n this.emit('offline', {});\n });\n\n } catch (error) {\n reject(error);\n }\n });\n }\n\n /**\n * Disconnect from the broker\n */\n async disconnect(): Promise<void> {\n return new Promise((resolve) => {\n if (this.client) {\n this.client.end(false, {}, () => {\n this.client = null;\n this.connected = false;\n resolve();\n });\n } else {\n resolve();\n }\n });\n }\n\n /**\n * Check if connected\n */\n isConnected(): boolean {\n return this.connected && this.client?.connected === true;\n }\n\n /**\n * Subscribe to a topic\n */\n async subscribe(\n topic: string,\n options: { qos?: MqttQoS } = {}\n ): Promise<PipeResponse> {\n if (!this.isConnected()) {\n return { success: false, error: 'Not connected' };\n }\n\n return new Promise((resolve) => {\n this.client!.subscribe(topic, { qos: options.qos ?? 0 }, (error, granted) => {\n if (error) {\n resolve({ success: false, error: error.message });\n } else {\n resolve({ success: true, data: granted });\n }\n });\n });\n }\n\n /**\n * Unsubscribe from a topic\n */\n async unsubscribe(topic: string): Promise<PipeResponse> {\n if (!this.isConnected()) {\n return { success: false, error: 'Not connected' };\n }\n\n return new Promise((resolve) => {\n this.client!.unsubscribe(topic, {}, (error) => {\n if (error) {\n resolve({ success: false, error: error.message });\n } else {\n resolve({ success: true });\n }\n });\n });\n }\n\n /**\n * Publish a message to a topic\n */\n async publish(\n topic: string,\n message: string | Buffer | Record<string, unknown>,\n options: { qos?: MqttQoS; retain?: boolean } = {}\n ): Promise<PipeResponse> {\n if (!this.isConnected()) {\n return { success: false, error: 'Not connected' };\n }\n\n const payload = typeof message === 'object' && !Buffer.isBuffer(message)\n ? JSON.stringify(message)\n : message;\n\n const publishOptions: IClientPublishOptions = {\n qos: options.qos ?? 0,\n retain: options.retain ?? false,\n };\n\n return new Promise((resolve) => {\n this.client!.publish(topic, payload, publishOptions, (error) => {\n if (error) {\n resolve({ success: false, error: error.message });\n } else {\n resolve({ success: true });\n }\n });\n });\n }\n\n /**\n * Register a handler for a specific topic\n * Supports MQTT wildcards: + (single level), # (multi level)\n */\n on(topic: string, handler: MqttMessageHandler): void {\n if (topic.includes('+') || topic.includes('#')) {\n // Wildcard topic - store in wildcardHandlers\n const handlers = this.wildcardHandlers.get(topic) ?? [];\n handlers.push(handler);\n this.wildcardHandlers.set(topic, handlers);\n } else {\n // Exact topic\n const handlers = this.messageHandlers.get(topic) ?? [];\n handlers.push(handler);\n this.messageHandlers.set(topic, handlers);\n }\n }\n\n /**\n * Remove a handler\n */\n off(topic: string, handler: MqttMessageHandler): void {\n const map = topic.includes('+') || topic.includes('#')\n ? this.wildcardHandlers\n : this.messageHandlers;\n\n const handlers = map.get(topic) ?? [];\n const index = handlers.indexOf(handler);\n if (index !== -1) {\n handlers.splice(index, 1);\n }\n }\n\n /**\n * Emit to handlers\n */\n private emit(event: string, data: unknown): void {\n const handlers = this.messageHandlers.get(event) ?? [];\n for (const handler of handlers) {\n try {\n handler(event, data as Buffer, {});\n } catch (error) {\n console.error(`MQTT handler error for \"${event}\":`, error);\n }\n }\n }\n\n /**\n * Handle incoming messages\n */\n private handleMessage(topic: string, payload: Buffer, packet: unknown): void {\n // Parse payload\n let parsedPayload: Buffer | string | Record<string, unknown> = payload;\n try {\n const str = payload.toString();\n parsedPayload = JSON.parse(str);\n } catch {\n parsedPayload = payload.toString();\n }\n\n // Call exact topic handlers\n const exactHandlers = this.messageHandlers.get(topic) ?? [];\n for (const handler of exactHandlers) {\n try {\n handler(topic, parsedPayload, packet);\n } catch (error) {\n console.error(`MQTT handler error for topic \"${topic}\":`, error);\n }\n }\n\n // Check wildcard handlers\n for (const [pattern, handlers] of this.wildcardHandlers) {\n if (this.topicMatches(pattern, topic)) {\n for (const handler of handlers) {\n try {\n handler(topic, parsedPayload, packet);\n } catch (error) {\n console.error(`MQTT wildcard handler error for pattern \"${pattern}\":`, error);\n }\n }\n }\n }\n\n // Emit to generic message handlers\n this.emit('message', { topic, payload: parsedPayload, packet });\n }\n\n /**\n * Check if a topic matches a pattern with MQTT wildcards\n */\n private topicMatches(pattern: string, topic: string): boolean {\n const patternParts = pattern.split('/');\n const topicParts = topic.split('/');\n\n for (let i = 0; i < patternParts.length; i++) {\n const patternPart = patternParts[i];\n\n // Multi-level wildcard matches everything remaining\n if (patternPart === '#') {\n return true;\n }\n\n // Topic is shorter than pattern\n if (i >= topicParts.length) {\n return false;\n }\n\n // Single-level wildcard matches any single level\n if (patternPart === '+') {\n continue;\n }\n\n // Exact match required\n if (patternPart !== topicParts[i]) {\n return false;\n }\n }\n\n // Pattern and topic should be same length (unless # was used)\n return patternParts.length === topicParts.length;\n }\n\n /**\n * Parse duration string to milliseconds\n */\n private parseDuration(duration: string): number {\n const match = duration.match(/^(\\d+)(ms|s|m|h)?$/);\n if (!match) return 5000;\n\n const value = parseInt(match[1]!, 10);\n const unit = match[2] ?? 's';\n\n switch (unit) {\n case 'ms':\n return value;\n case 's':\n return value * 1000;\n case 'm':\n return value * 60 * 1000;\n case 'h':\n return value * 60 * 60 * 1000;\n default:\n return value * 1000;\n }\n }\n}\n\n/**\n * Create an MQTT pipe\n */\nexport function createMqttPipe(options: MqttPipeOptions): MqttPipe {\n return new MqttPipe(options);\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/mqtt/index.ts"],"sourcesContent":["/**\n * MQTT pipe for IoT and real-time integrations\n */\n\nimport mqtt, { MqttClient, IClientOptions, IClientPublishOptions } from 'mqtt';\nimport type { Pipe, PipeResponse, MqttPipeConfig, MqttQoS } from '../types.js';\n\nexport interface MqttPipeOptions {\n name: string;\n config: MqttPipeConfig;\n}\n\nexport type MqttMessageHandler = (\n topic: string,\n payload: Buffer | string | Record<string, unknown>,\n packet: unknown\n) => void | Promise<void>;\n\nexport class MqttPipe implements Pipe {\n public readonly name: string;\n public readonly type = 'mqtt';\n private client: MqttClient | null = null;\n private config: MqttPipeConfig;\n private connected = false;\n private reconnectAttempts = 0;\n private messageHandlers: Map<string, MqttMessageHandler[]> = new Map();\n private wildcardHandlers: Map<string, MqttMessageHandler[]> = new Map();\n\n constructor(options: MqttPipeOptions) {\n this.name = options.name;\n this.config = options.config;\n }\n\n /**\n * Connect to the MQTT broker\n */\n async connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n const protocol = this.config.protocol ?? 'mqtt';\n const port = this.config.port ?? (protocol === 'mqtts' || protocol === 'wss' ? 8883 : 1883);\n const url = `${protocol}://${this.config.broker}:${port}`;\n\n const options: IClientOptions = {\n keepalive: this.config.keepalive ?? 60,\n clean: this.config.clean ?? true,\n reconnectPeriod: this.config.reconnect?.enabled !== false\n ? this.parseDuration(this.config.reconnect?.delay ?? '5s')\n : 0,\n };\n\n // Authentication\n if (this.config.auth) {\n if (this.config.auth.username) options.username = this.config.auth.username;\n if (this.config.auth.password) options.password = this.config.auth.password;\n if (this.config.auth.clientId) options.clientId = this.config.auth.clientId;\n }\n\n // Last Will and Testament\n if (this.config.will) {\n options.will = {\n topic: this.config.will.topic,\n payload: Buffer.from(this.config.will.payload),\n qos: this.config.will.qos ?? 0,\n retain: this.config.will.retain ?? false,\n };\n }\n\n try {\n this.client = mqtt.connect(url, options);\n\n this.client.on('connect', () => {\n this.connected = true;\n this.reconnectAttempts = 0;\n this.emit('connected', {});\n resolve();\n });\n\n this.client.on('message', (topic, payload, packet) => {\n this.handleMessage(topic, payload, packet);\n });\n\n this.client.on('error', (error) => {\n if (!this.connected) {\n reject(error);\n }\n this.emit('error', error);\n });\n\n this.client.on('close', () => {\n this.connected = false;\n this.emit('disconnected', {});\n });\n\n this.client.on('reconnect', () => {\n this.reconnectAttempts++;\n this.emit('reconnecting', { attempts: this.reconnectAttempts });\n });\n\n this.client.on('offline', () => {\n this.connected = false;\n this.emit('offline', {});\n });\n\n } catch (error) {\n reject(error);\n }\n });\n }\n\n /**\n * Disconnect from the broker\n */\n async disconnect(): Promise<void> {\n return new Promise((resolve) => {\n if (this.client) {\n this.client.end(false, {}, () => {\n this.client = null;\n this.connected = false;\n resolve();\n });\n } else {\n resolve();\n }\n });\n }\n\n /**\n * Check if connected\n */\n isConnected(): boolean {\n return this.connected && this.client?.connected === true;\n }\n\n /**\n * Subscribe to a topic\n */\n async subscribe(\n topic: string,\n options: { qos?: MqttQoS } = {}\n ): Promise<PipeResponse> {\n if (!this.isConnected()) {\n return { success: false, error: 'Not connected' };\n }\n\n return new Promise((resolve) => {\n this.client!.subscribe(topic, { qos: options.qos ?? 0 }, (error, granted) => {\n if (error) {\n resolve({ success: false, error: error.message });\n } else {\n resolve({ success: true, data: granted });\n }\n });\n });\n }\n\n /**\n * Unsubscribe from a topic\n */\n async unsubscribe(topic: string): Promise<PipeResponse> {\n if (!this.isConnected()) {\n return { success: false, error: 'Not connected' };\n }\n\n return new Promise((resolve) => {\n this.client!.unsubscribe(topic, {}, (error) => {\n if (error) {\n resolve({ success: false, error: error.message });\n } else {\n resolve({ success: true });\n }\n });\n });\n }\n\n /**\n * Publish a message to a topic\n */\n async publish(\n topic: string,\n message: string | Buffer | Record<string, unknown>,\n options: { qos?: MqttQoS; retain?: boolean } = {}\n ): Promise<PipeResponse> {\n if (!this.isConnected()) {\n return { success: false, error: 'Not connected' };\n }\n\n const payload = typeof message === 'object' && !Buffer.isBuffer(message)\n ? JSON.stringify(message)\n : message;\n\n const publishOptions: IClientPublishOptions = {\n qos: options.qos ?? 0,\n retain: options.retain ?? false,\n };\n\n return new Promise((resolve) => {\n this.client!.publish(topic, payload, publishOptions, (error) => {\n if (error) {\n resolve({ success: false, error: error.message });\n } else {\n resolve({ success: true });\n }\n });\n });\n }\n\n /**\n * Register a handler for a specific topic\n * Supports MQTT wildcards: + (single level), # (multi level)\n */\n on(topic: string, handler: MqttMessageHandler): void {\n if (topic.includes('+') || topic.includes('#')) {\n // Wildcard topic - store in wildcardHandlers\n const handlers = this.wildcardHandlers.get(topic) ?? [];\n handlers.push(handler);\n this.wildcardHandlers.set(topic, handlers);\n } else {\n // Exact topic\n const handlers = this.messageHandlers.get(topic) ?? [];\n handlers.push(handler);\n this.messageHandlers.set(topic, handlers);\n }\n }\n\n /**\n * Remove a handler\n */\n off(topic: string, handler: MqttMessageHandler): void {\n const map = topic.includes('+') || topic.includes('#')\n ? this.wildcardHandlers\n : this.messageHandlers;\n\n const handlers = map.get(topic) ?? [];\n const index = handlers.indexOf(handler);\n if (index !== -1) {\n handlers.splice(index, 1);\n }\n }\n\n /**\n * Emit to handlers\n */\n private emit(event: string, data: unknown): void {\n const handlers = this.messageHandlers.get(event) ?? [];\n for (const handler of handlers) {\n try {\n const result = handler(event, data as Buffer, {});\n // Handle async handlers properly\n if (result instanceof Promise) {\n result.catch((error) => {\n console.error(`MQTT async handler error for \"${event}\":`, error);\n });\n }\n } catch (error) {\n console.error(`MQTT handler error for \"${event}\":`, error);\n }\n }\n }\n\n /**\n * Handle incoming messages\n */\n private handleMessage(topic: string, payload: Buffer, packet: unknown): void {\n // Parse payload\n let parsedPayload: Buffer | string | Record<string, unknown> = payload;\n try {\n const str = payload.toString();\n parsedPayload = JSON.parse(str);\n } catch {\n parsedPayload = payload.toString();\n }\n\n // Call exact topic handlers\n const exactHandlers = this.messageHandlers.get(topic) ?? [];\n for (const handler of exactHandlers) {\n try {\n const result = handler(topic, parsedPayload, packet);\n // Handle async handlers properly\n if (result instanceof Promise) {\n result.catch((error) => {\n console.error(`MQTT async handler error for topic \"${topic}\":`, error);\n });\n }\n } catch (error) {\n console.error(`MQTT handler error for topic \"${topic}\":`, error);\n }\n }\n\n // Check wildcard handlers\n for (const [pattern, handlers] of this.wildcardHandlers) {\n if (this.topicMatches(pattern, topic)) {\n for (const handler of handlers) {\n try {\n const result = handler(topic, parsedPayload, packet);\n // Handle async handlers properly\n if (result instanceof Promise) {\n result.catch((error) => {\n console.error(`MQTT async wildcard handler error for pattern \"${pattern}\":`, error);\n });\n }\n } catch (error) {\n console.error(`MQTT wildcard handler error for pattern \"${pattern}\":`, error);\n }\n }\n }\n }\n\n // Emit to generic message handlers\n this.emit('message', { topic, payload: parsedPayload, packet });\n }\n\n /**\n * Check if a topic matches a pattern with MQTT wildcards\n */\n private topicMatches(pattern: string, topic: string): boolean {\n const patternParts = pattern.split('/');\n const topicParts = topic.split('/');\n\n for (let i = 0; i < patternParts.length; i++) {\n const patternPart = patternParts[i];\n\n // Multi-level wildcard matches everything remaining\n if (patternPart === '#') {\n return true;\n }\n\n // Topic is shorter than pattern\n if (i >= topicParts.length) {\n return false;\n }\n\n // Single-level wildcard matches any single level\n if (patternPart === '+') {\n continue;\n }\n\n // Exact match required\n if (patternPart !== topicParts[i]) {\n return false;\n }\n }\n\n // Pattern and topic should be same length (unless # was used)\n return patternParts.length === topicParts.length;\n }\n\n /**\n * Parse duration string to milliseconds\n */\n private parseDuration(duration: string): number {\n const match = duration.match(/^(\\d+)(ms|s|m|h)?$/);\n if (!match) return 5000;\n\n const value = parseInt(match[1]!, 10);\n const unit = match[2] ?? 's';\n\n switch (unit) {\n case 'ms':\n return value;\n case 's':\n return value * 1000;\n case 'm':\n return value * 60 * 1000;\n case 'h':\n return value * 60 * 60 * 1000;\n default:\n return value * 1000;\n }\n }\n}\n\n/**\n * Create an MQTT pipe\n */\nexport function createMqttPipe(options: MqttPipeOptions): MqttPipe {\n return new MqttPipe(options);\n}\n"],"mappings":"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","names":[]}
|
package/dist/tcp/index.d.ts
CHANGED
package/dist/tcp/index.js
CHANGED
|
@@ -164,7 +164,12 @@ var UdpPipe = class {
|
|
|
164
164
|
const handlers = this.eventHandlers.get(event) ?? [];
|
|
165
165
|
for (const handler of handlers) {
|
|
166
166
|
try {
|
|
167
|
-
handler(data);
|
|
167
|
+
const result = handler(data);
|
|
168
|
+
if (result instanceof Promise) {
|
|
169
|
+
result.catch((error) => {
|
|
170
|
+
console.error(`UDP async handler error for "${event}":`, error);
|
|
171
|
+
});
|
|
172
|
+
}
|
|
168
173
|
} catch (error) {
|
|
169
174
|
console.error(`UDP handler error for "${event}":`, error);
|
|
170
175
|
}
|
|
@@ -177,7 +182,12 @@ var UdpPipe = class {
|
|
|
177
182
|
const msg = { data, rinfo };
|
|
178
183
|
for (const handler of this.messageHandlers) {
|
|
179
184
|
try {
|
|
180
|
-
handler(msg);
|
|
185
|
+
const result = handler(msg);
|
|
186
|
+
if (result instanceof Promise) {
|
|
187
|
+
result.catch((error) => {
|
|
188
|
+
console.error("UDP async message handler error:", error);
|
|
189
|
+
});
|
|
190
|
+
}
|
|
181
191
|
} catch (error) {
|
|
182
192
|
console.error("UDP message handler error:", error);
|
|
183
193
|
}
|
|
@@ -199,6 +209,7 @@ var TcpPipe = class {
|
|
|
199
209
|
connected = false;
|
|
200
210
|
reconnectAttempts = 0;
|
|
201
211
|
reconnecting = false;
|
|
212
|
+
reconnectTimer = null;
|
|
202
213
|
dataHandlers = [];
|
|
203
214
|
eventHandlers = /* @__PURE__ */ new Map();
|
|
204
215
|
constructor(options) {
|
|
@@ -280,6 +291,10 @@ var TcpPipe = class {
|
|
|
280
291
|
*/
|
|
281
292
|
async disconnect() {
|
|
282
293
|
this.reconnecting = false;
|
|
294
|
+
if (this.reconnectTimer) {
|
|
295
|
+
clearTimeout(this.reconnectTimer);
|
|
296
|
+
this.reconnectTimer = null;
|
|
297
|
+
}
|
|
283
298
|
return new Promise((resolve) => {
|
|
284
299
|
if (this.socket) {
|
|
285
300
|
this.socket.end(() => {
|
|
@@ -331,13 +346,21 @@ var TcpPipe = class {
|
|
|
331
346
|
return { success: false, error: "Not connected" };
|
|
332
347
|
}
|
|
333
348
|
return new Promise((resolve) => {
|
|
334
|
-
|
|
349
|
+
let resolved = false;
|
|
350
|
+
const cleanup = () => {
|
|
335
351
|
this.offData(handler);
|
|
352
|
+
};
|
|
353
|
+
const timer = setTimeout(() => {
|
|
354
|
+
if (resolved) return;
|
|
355
|
+
resolved = true;
|
|
356
|
+
cleanup();
|
|
336
357
|
resolve({ success: false, error: "Request timeout" });
|
|
337
358
|
}, timeout);
|
|
338
359
|
const handler = (response) => {
|
|
360
|
+
if (resolved) return;
|
|
361
|
+
resolved = true;
|
|
339
362
|
clearTimeout(timer);
|
|
340
|
-
|
|
363
|
+
cleanup();
|
|
341
364
|
resolve({ success: true, data: response });
|
|
342
365
|
};
|
|
343
366
|
this.onData(handler);
|
|
@@ -384,7 +407,12 @@ var TcpPipe = class {
|
|
|
384
407
|
const handlers = this.eventHandlers.get(event) ?? [];
|
|
385
408
|
for (const handler of handlers) {
|
|
386
409
|
try {
|
|
387
|
-
handler(data);
|
|
410
|
+
const result = handler(data);
|
|
411
|
+
if (result instanceof Promise) {
|
|
412
|
+
result.catch((error) => {
|
|
413
|
+
console.error(`TCP async handler error for "${event}":`, error);
|
|
414
|
+
});
|
|
415
|
+
}
|
|
388
416
|
} catch (error) {
|
|
389
417
|
console.error(`TCP handler error for "${event}":`, error);
|
|
390
418
|
}
|
|
@@ -396,7 +424,12 @@ var TcpPipe = class {
|
|
|
396
424
|
handleData(data) {
|
|
397
425
|
for (const handler of this.dataHandlers) {
|
|
398
426
|
try {
|
|
399
|
-
handler(data);
|
|
427
|
+
const result = handler(data);
|
|
428
|
+
if (result instanceof Promise) {
|
|
429
|
+
result.catch((error) => {
|
|
430
|
+
console.error("TCP async data handler error:", error);
|
|
431
|
+
});
|
|
432
|
+
}
|
|
400
433
|
} catch (error) {
|
|
401
434
|
console.error("TCP data handler error:", error);
|
|
402
435
|
}
|
|
@@ -418,14 +451,14 @@ var TcpPipe = class {
|
|
|
418
451
|
}
|
|
419
452
|
this.reconnecting = true;
|
|
420
453
|
this.reconnectAttempts++;
|
|
421
|
-
setTimeout(
|
|
422
|
-
|
|
423
|
-
|
|
454
|
+
this.reconnectTimer = setTimeout(() => {
|
|
455
|
+
this.reconnectTimer = null;
|
|
456
|
+
this.connect().then(() => {
|
|
424
457
|
this.emit("reconnected", { attempts: this.reconnectAttempts });
|
|
425
|
-
}
|
|
458
|
+
}).catch(() => {
|
|
426
459
|
this.reconnecting = false;
|
|
427
460
|
this.handleDisconnect();
|
|
428
|
-
}
|
|
461
|
+
});
|
|
429
462
|
}, delay);
|
|
430
463
|
}
|
|
431
464
|
/**
|
package/dist/tcp/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/tcp/index.ts","../../src/tcp/udp.ts"],"sourcesContent":["/**\n * TCP pipe for raw socket communication\n */\n\nimport { Socket, createConnection, createServer, Server } from 'net';\nimport type { Pipe, PipeResponse, TcpPipeConfig } from '../types.js';\n\nexport interface TcpPipeOptions {\n name: string;\n config: TcpPipeConfig;\n}\n\nexport type TcpDataHandler = (data: Buffer | string) => void | Promise<void>;\nexport type TcpEventHandler = (data?: unknown) => void | Promise<void>;\n\nexport class TcpPipe implements Pipe {\n public readonly name: string;\n public readonly type = 'tcp';\n private socket: Socket | null = null;\n private server: Server | null = null;\n private config: TcpPipeConfig;\n private connected = false;\n private reconnectAttempts = 0;\n private reconnecting = false;\n private dataHandlers: TcpDataHandler[] = [];\n private eventHandlers: Map<string, TcpEventHandler[]> = new Map();\n\n constructor(options: TcpPipeOptions) {\n this.name = options.name;\n this.config = options.config;\n }\n\n /**\n * Connect to a TCP server (client mode)\n */\n async connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n try {\n this.socket = createConnection({\n host: this.config.host,\n port: this.config.port,\n });\n\n this.socket.setEncoding(this.config.encoding ?? 'utf8');\n\n this.socket.on('connect', () => {\n this.connected = true;\n this.reconnectAttempts = 0;\n this.reconnecting = false;\n this.emit('connected');\n resolve();\n });\n\n this.socket.on('data', (data) => {\n this.handleData(data);\n });\n\n this.socket.on('close', () => {\n this.connected = false;\n this.emit('disconnected');\n this.handleDisconnect();\n });\n\n this.socket.on('error', (error) => {\n if (!this.connected) {\n reject(error);\n }\n this.emit('error', error);\n });\n\n this.socket.on('end', () => {\n this.connected = false;\n this.emit('end');\n });\n\n } catch (error) {\n reject(error);\n }\n });\n }\n\n /**\n * Start a TCP server (server mode)\n */\n async listen(port?: number): Promise<void> {\n return new Promise((resolve, reject) => {\n try {\n this.server = createServer((socket) => {\n socket.setEncoding(this.config.encoding ?? 'utf8');\n\n socket.on('data', (data) => {\n this.handleData(data);\n });\n\n socket.on('error', (error) => {\n this.emit('client_error', error);\n });\n\n this.emit('connection', socket);\n });\n\n this.server.on('error', (error) => {\n reject(error);\n });\n\n this.server.listen(port ?? this.config.port, () => {\n this.connected = true;\n this.emit('listening');\n resolve();\n });\n\n } catch (error) {\n reject(error);\n }\n });\n }\n\n /**\n * Disconnect / close\n */\n async disconnect(): Promise<void> {\n this.reconnecting = false;\n\n return new Promise((resolve) => {\n if (this.socket) {\n this.socket.end(() => {\n this.socket?.destroy();\n this.socket = null;\n this.connected = false;\n resolve();\n });\n } else if (this.server) {\n this.server.close(() => {\n this.server = null;\n this.connected = false;\n resolve();\n });\n } else {\n resolve();\n }\n });\n }\n\n /**\n * Check if connected\n */\n isConnected(): boolean {\n return this.connected;\n }\n\n /**\n * Send data\n */\n async send(data: Buffer | string): Promise<PipeResponse> {\n if (!this.socket || !this.connected) {\n return { success: false, error: 'Not connected' };\n }\n\n return new Promise((resolve) => {\n this.socket!.write(data, (error) => {\n if (error) {\n resolve({ success: false, error: error.message });\n } else {\n resolve({ success: true });\n }\n });\n });\n }\n\n /**\n * Send and wait for response (request-response pattern)\n */\n async request<T = string>(\n data: Buffer | string,\n options: { timeout?: number } = {}\n ): Promise<PipeResponse<T>> {\n const { timeout = 30000 } = options;\n\n if (!this.socket || !this.connected) {\n return { success: false, error: 'Not connected' };\n }\n\n return new Promise((resolve) => {\n const timer = setTimeout(() => {\n this.offData(handler);\n resolve({ success: false, error: 'Request timeout' });\n }, timeout);\n\n const handler = (response: Buffer | string) => {\n clearTimeout(timer);\n this.offData(handler);\n resolve({ success: true, data: response as T });\n };\n\n this.onData(handler);\n this.send(data);\n });\n }\n\n /**\n * Register a data handler\n */\n onData(handler: TcpDataHandler): void {\n this.dataHandlers.push(handler);\n }\n\n /**\n * Remove a data handler\n */\n offData(handler: TcpDataHandler): void {\n const index = this.dataHandlers.indexOf(handler);\n if (index !== -1) {\n this.dataHandlers.splice(index, 1);\n }\n }\n\n /**\n * Register an event handler\n */\n on(event: string, handler: TcpEventHandler): void {\n const handlers = this.eventHandlers.get(event) ?? [];\n handlers.push(handler);\n this.eventHandlers.set(event, handlers);\n }\n\n /**\n * Remove an event handler\n */\n off(event: string, handler: TcpEventHandler): void {\n const handlers = this.eventHandlers.get(event) ?? [];\n const index = handlers.indexOf(handler);\n if (index !== -1) {\n handlers.splice(index, 1);\n }\n }\n\n /**\n * Emit an event\n */\n private emit(event: string, data?: unknown): void {\n const handlers = this.eventHandlers.get(event) ?? [];\n for (const handler of handlers) {\n try {\n handler(data);\n } catch (error) {\n console.error(`TCP handler error for \"${event}\":`, error);\n }\n }\n }\n\n /**\n * Handle incoming data\n */\n private handleData(data: Buffer | string): void {\n for (const handler of this.dataHandlers) {\n try {\n handler(data);\n } catch (error) {\n console.error('TCP data handler error:', error);\n }\n }\n this.emit('data', data);\n }\n\n /**\n * Handle disconnection with reconnect logic\n */\n private handleDisconnect(): void {\n if (!this.config.reconnect?.enabled || this.reconnecting) {\n return;\n }\n\n const maxAttempts = this.config.reconnect.max_attempts ?? 10;\n const delay = this.parseDuration(this.config.reconnect.delay ?? '5s');\n\n if (this.reconnectAttempts >= maxAttempts) {\n this.emit('reconnect_failed', { attempts: this.reconnectAttempts });\n return;\n }\n\n this.reconnecting = true;\n this.reconnectAttempts++;\n\n setTimeout(async () => {\n try {\n await this.connect();\n this.emit('reconnected', { attempts: this.reconnectAttempts });\n } catch {\n this.reconnecting = false;\n this.handleDisconnect();\n }\n }, delay);\n }\n\n /**\n * Parse duration string to milliseconds\n */\n private parseDuration(duration: string): number {\n const match = duration.match(/^(\\d+)(ms|s|m|h)?$/);\n if (!match) return 5000;\n\n const value = parseInt(match[1]!, 10);\n const unit = match[2] ?? 's';\n\n switch (unit) {\n case 'ms':\n return value;\n case 's':\n return value * 1000;\n case 'm':\n return value * 60 * 1000;\n case 'h':\n return value * 60 * 60 * 1000;\n default:\n return value * 1000;\n }\n }\n}\n\n/**\n * Create a TCP pipe\n */\nexport function createTcpPipe(options: TcpPipeOptions): TcpPipe {\n return new TcpPipe(options);\n}\n\n// Re-export UDP pipe\nexport * from './udp.js';\n","/**\n * UDP pipe for datagram communication\n */\n\nimport { createSocket, Socket, RemoteInfo } from 'dgram';\nimport type { Pipe, PipeResponse, UdpPipeConfig } from '../types.js';\n\nexport interface UdpPipeOptions {\n name: string;\n config: UdpPipeConfig;\n}\n\nexport interface UdpMessage {\n data: Buffer;\n rinfo: RemoteInfo;\n}\n\nexport type UdpMessageHandler = (msg: UdpMessage) => void | Promise<void>;\nexport type UdpEventHandler = (data?: unknown) => void | Promise<void>;\n\nexport class UdpPipe implements Pipe {\n public readonly name: string;\n public readonly type = 'udp';\n private socket: Socket | null = null;\n private config: UdpPipeConfig;\n private bound = false;\n private messageHandlers: UdpMessageHandler[] = [];\n private eventHandlers: Map<string, UdpEventHandler[]> = new Map();\n\n constructor(options: UdpPipeOptions) {\n this.name = options.name;\n this.config = options.config;\n }\n\n /**\n * Bind to a port to receive messages\n */\n async bind(port?: number): Promise<void> {\n return new Promise((resolve, reject) => {\n try {\n this.socket = createSocket('udp4');\n\n this.socket.on('message', (msg, rinfo) => {\n this.handleMessage(msg, rinfo);\n });\n\n this.socket.on('error', (error) => {\n if (!this.bound) {\n reject(error);\n }\n this.emit('error', error);\n });\n\n this.socket.on('listening', () => {\n this.bound = true;\n const address = this.socket!.address();\n this.emit('listening', address);\n resolve();\n });\n\n // Setup broadcast if configured\n if (this.config.broadcast) {\n this.socket.setBroadcast(true);\n }\n\n // Bind to port\n const bindPort = port ?? this.config.port;\n const bindHost = this.config.host ?? '0.0.0.0';\n this.socket.bind(bindPort, bindHost, () => {\n // Join multicast group if configured\n if (this.config.multicast) {\n this.socket!.addMembership(this.config.multicast);\n }\n });\n\n } catch (error) {\n reject(error);\n }\n });\n }\n\n /**\n * Close the socket\n */\n async disconnect(): Promise<void> {\n return new Promise((resolve) => {\n if (this.socket) {\n this.socket.close(() => {\n this.socket = null;\n this.bound = false;\n resolve();\n });\n } else {\n resolve();\n }\n });\n }\n\n /**\n * Check if bound\n */\n isConnected(): boolean {\n return this.bound;\n }\n\n /**\n * Send data to a specific host and port\n */\n async send(\n data: Buffer | string,\n host: string,\n port: number\n ): Promise<PipeResponse> {\n if (!this.socket) {\n // Create socket if not exists (for send-only mode)\n this.socket = createSocket('udp4');\n if (this.config.broadcast) {\n this.socket.setBroadcast(true);\n }\n }\n\n const buffer = typeof data === 'string' ? Buffer.from(data) : data;\n\n return new Promise((resolve) => {\n this.socket!.send(buffer, port, host, (error) => {\n if (error) {\n resolve({ success: false, error: error.message });\n } else {\n resolve({ success: true });\n }\n });\n });\n }\n\n /**\n * Broadcast data to all hosts on the network\n */\n async broadcast(\n data: Buffer | string,\n port: number,\n address = '255.255.255.255'\n ): Promise<PipeResponse> {\n if (!this.socket) {\n this.socket = createSocket('udp4');\n this.socket.setBroadcast(true);\n }\n\n const buffer = typeof data === 'string' ? Buffer.from(data) : data;\n\n return new Promise((resolve) => {\n this.socket!.send(buffer, port, address, (error) => {\n if (error) {\n resolve({ success: false, error: error.message });\n } else {\n resolve({ success: true });\n }\n });\n });\n }\n\n /**\n * Send to multicast group\n */\n async multicast(\n data: Buffer | string,\n port: number,\n group?: string\n ): Promise<PipeResponse> {\n const multicastGroup = group ?? this.config.multicast;\n if (!multicastGroup) {\n return { success: false, error: 'No multicast group configured' };\n }\n\n return this.send(data, multicastGroup, port);\n }\n\n /**\n * Register a message handler\n */\n onMessage(handler: UdpMessageHandler): void {\n this.messageHandlers.push(handler);\n }\n\n /**\n * Remove a message handler\n */\n offMessage(handler: UdpMessageHandler): void {\n const index = this.messageHandlers.indexOf(handler);\n if (index !== -1) {\n this.messageHandlers.splice(index, 1);\n }\n }\n\n /**\n * Register an event handler\n */\n on(event: string, handler: UdpEventHandler): void {\n const handlers = this.eventHandlers.get(event) ?? [];\n handlers.push(handler);\n this.eventHandlers.set(event, handlers);\n }\n\n /**\n * Remove an event handler\n */\n off(event: string, handler: UdpEventHandler): void {\n const handlers = this.eventHandlers.get(event) ?? [];\n const index = handlers.indexOf(handler);\n if (index !== -1) {\n handlers.splice(index, 1);\n }\n }\n\n /**\n * Emit an event\n */\n private emit(event: string, data?: unknown): void {\n const handlers = this.eventHandlers.get(event) ?? [];\n for (const handler of handlers) {\n try {\n handler(data);\n } catch (error) {\n console.error(`UDP handler error for \"${event}\":`, error);\n }\n }\n }\n\n /**\n * Handle incoming messages\n */\n private handleMessage(data: Buffer, rinfo: RemoteInfo): void {\n const msg: UdpMessage = { data, rinfo };\n\n for (const handler of this.messageHandlers) {\n try {\n handler(msg);\n } catch (error) {\n console.error('UDP message handler error:', error);\n }\n }\n\n this.emit('message', msg);\n }\n}\n\n/**\n * Create a UDP pipe\n */\nexport function createUdpPipe(options: UdpPipeOptions): UdpPipe {\n return new UdpPipe(options);\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/tcp/index.ts","../../src/tcp/udp.ts"],"sourcesContent":["/**\n * TCP pipe for raw socket communication\n */\n\nimport { Socket, createConnection, createServer, Server } from 'net';\nimport type { Pipe, PipeResponse, TcpPipeConfig } from '../types.js';\n\nexport interface TcpPipeOptions {\n name: string;\n config: TcpPipeConfig;\n}\n\nexport type TcpDataHandler = (data: Buffer | string) => void | Promise<void>;\nexport type TcpEventHandler = (data?: unknown) => void | Promise<void>;\n\nexport class TcpPipe implements Pipe {\n public readonly name: string;\n public readonly type = 'tcp';\n private socket: Socket | null = null;\n private server: Server | null = null;\n private config: TcpPipeConfig;\n private connected = false;\n private reconnectAttempts = 0;\n private reconnecting = false;\n private reconnectTimer: NodeJS.Timeout | null = null;\n private dataHandlers: TcpDataHandler[] = [];\n private eventHandlers: Map<string, TcpEventHandler[]> = new Map();\n\n constructor(options: TcpPipeOptions) {\n this.name = options.name;\n this.config = options.config;\n }\n\n /**\n * Connect to a TCP server (client mode)\n */\n async connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n try {\n this.socket = createConnection({\n host: this.config.host,\n port: this.config.port,\n });\n\n this.socket.setEncoding(this.config.encoding ?? 'utf8');\n\n this.socket.on('connect', () => {\n this.connected = true;\n this.reconnectAttempts = 0;\n this.reconnecting = false;\n this.emit('connected');\n resolve();\n });\n\n this.socket.on('data', (data) => {\n this.handleData(data);\n });\n\n this.socket.on('close', () => {\n this.connected = false;\n this.emit('disconnected');\n this.handleDisconnect();\n });\n\n this.socket.on('error', (error) => {\n if (!this.connected) {\n reject(error);\n }\n this.emit('error', error);\n });\n\n this.socket.on('end', () => {\n this.connected = false;\n this.emit('end');\n });\n\n } catch (error) {\n reject(error);\n }\n });\n }\n\n /**\n * Start a TCP server (server mode)\n */\n async listen(port?: number): Promise<void> {\n return new Promise((resolve, reject) => {\n try {\n this.server = createServer((socket) => {\n socket.setEncoding(this.config.encoding ?? 'utf8');\n\n socket.on('data', (data) => {\n this.handleData(data);\n });\n\n socket.on('error', (error) => {\n this.emit('client_error', error);\n });\n\n this.emit('connection', socket);\n });\n\n this.server.on('error', (error) => {\n reject(error);\n });\n\n this.server.listen(port ?? this.config.port, () => {\n this.connected = true;\n this.emit('listening');\n resolve();\n });\n\n } catch (error) {\n reject(error);\n }\n });\n }\n\n /**\n * Disconnect / close\n */\n async disconnect(): Promise<void> {\n this.reconnecting = false;\n\n // Clear any pending reconnect timer to prevent memory leaks\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n return new Promise((resolve) => {\n if (this.socket) {\n this.socket.end(() => {\n this.socket?.destroy();\n this.socket = null;\n this.connected = false;\n resolve();\n });\n } else if (this.server) {\n this.server.close(() => {\n this.server = null;\n this.connected = false;\n resolve();\n });\n } else {\n resolve();\n }\n });\n }\n\n /**\n * Check if connected\n */\n isConnected(): boolean {\n return this.connected;\n }\n\n /**\n * Send data\n */\n async send(data: Buffer | string): Promise<PipeResponse> {\n if (!this.socket || !this.connected) {\n return { success: false, error: 'Not connected' };\n }\n\n return new Promise((resolve) => {\n this.socket!.write(data, (error) => {\n if (error) {\n resolve({ success: false, error: error.message });\n } else {\n resolve({ success: true });\n }\n });\n });\n }\n\n /**\n * Send and wait for response (request-response pattern)\n */\n async request<T = string>(\n data: Buffer | string,\n options: { timeout?: number } = {}\n ): Promise<PipeResponse<T>> {\n const { timeout = 30000 } = options;\n\n if (!this.socket || !this.connected) {\n return { success: false, error: 'Not connected' };\n }\n\n return new Promise((resolve) => {\n let resolved = false;\n\n const cleanup = () => {\n this.offData(handler);\n };\n\n const timer = setTimeout(() => {\n if (resolved) return;\n resolved = true;\n cleanup();\n resolve({ success: false, error: 'Request timeout' });\n }, timeout);\n\n const handler = (response: Buffer | string) => {\n if (resolved) return;\n resolved = true;\n clearTimeout(timer);\n cleanup();\n resolve({ success: true, data: response as T });\n };\n\n this.onData(handler);\n this.send(data);\n });\n }\n\n /**\n * Register a data handler\n */\n onData(handler: TcpDataHandler): void {\n this.dataHandlers.push(handler);\n }\n\n /**\n * Remove a data handler\n */\n offData(handler: TcpDataHandler): void {\n const index = this.dataHandlers.indexOf(handler);\n if (index !== -1) {\n this.dataHandlers.splice(index, 1);\n }\n }\n\n /**\n * Register an event handler\n */\n on(event: string, handler: TcpEventHandler): void {\n const handlers = this.eventHandlers.get(event) ?? [];\n handlers.push(handler);\n this.eventHandlers.set(event, handlers);\n }\n\n /**\n * Remove an event handler\n */\n off(event: string, handler: TcpEventHandler): void {\n const handlers = this.eventHandlers.get(event) ?? [];\n const index = handlers.indexOf(handler);\n if (index !== -1) {\n handlers.splice(index, 1);\n }\n }\n\n /**\n * Emit an event\n */\n private emit(event: string, data?: unknown): void {\n const handlers = this.eventHandlers.get(event) ?? [];\n for (const handler of handlers) {\n try {\n const result = handler(data);\n // Handle async handlers properly\n if (result instanceof Promise) {\n result.catch((error) => {\n console.error(`TCP async handler error for \"${event}\":`, error);\n });\n }\n } catch (error) {\n console.error(`TCP handler error for \"${event}\":`, error);\n }\n }\n }\n\n /**\n * Handle incoming data\n */\n private handleData(data: Buffer | string): void {\n for (const handler of this.dataHandlers) {\n try {\n const result = handler(data);\n // Handle async handlers properly\n if (result instanceof Promise) {\n result.catch((error) => {\n console.error('TCP async data handler error:', error);\n });\n }\n } catch (error) {\n console.error('TCP data handler error:', error);\n }\n }\n this.emit('data', data);\n }\n\n /**\n * Handle disconnection with reconnect logic\n */\n private handleDisconnect(): void {\n if (!this.config.reconnect?.enabled || this.reconnecting) {\n return;\n }\n\n const maxAttempts = this.config.reconnect.max_attempts ?? 10;\n const delay = this.parseDuration(this.config.reconnect.delay ?? '5s');\n\n if (this.reconnectAttempts >= maxAttempts) {\n this.emit('reconnect_failed', { attempts: this.reconnectAttempts });\n return;\n }\n\n this.reconnecting = true;\n this.reconnectAttempts++;\n\n // Track the timer so it can be cleared on disconnect\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.connect()\n .then(() => {\n this.emit('reconnected', { attempts: this.reconnectAttempts });\n })\n .catch(() => {\n this.reconnecting = false;\n this.handleDisconnect();\n });\n }, delay);\n }\n\n /**\n * Parse duration string to milliseconds\n */\n private parseDuration(duration: string): number {\n const match = duration.match(/^(\\d+)(ms|s|m|h)?$/);\n if (!match) return 5000;\n\n const value = parseInt(match[1]!, 10);\n const unit = match[2] ?? 's';\n\n switch (unit) {\n case 'ms':\n return value;\n case 's':\n return value * 1000;\n case 'm':\n return value * 60 * 1000;\n case 'h':\n return value * 60 * 60 * 1000;\n default:\n return value * 1000;\n }\n }\n}\n\n/**\n * Create a TCP pipe\n */\nexport function createTcpPipe(options: TcpPipeOptions): TcpPipe {\n return new TcpPipe(options);\n}\n\n// Re-export UDP pipe\nexport * from './udp.js';\n","/**\n * UDP pipe for datagram communication\n */\n\nimport { createSocket, Socket, RemoteInfo } from 'dgram';\nimport type { Pipe, PipeResponse, UdpPipeConfig } from '../types.js';\n\nexport interface UdpPipeOptions {\n name: string;\n config: UdpPipeConfig;\n}\n\nexport interface UdpMessage {\n data: Buffer;\n rinfo: RemoteInfo;\n}\n\nexport type UdpMessageHandler = (msg: UdpMessage) => void | Promise<void>;\nexport type UdpEventHandler = (data?: unknown) => void | Promise<void>;\n\nexport class UdpPipe implements Pipe {\n public readonly name: string;\n public readonly type = 'udp';\n private socket: Socket | null = null;\n private config: UdpPipeConfig;\n private bound = false;\n private messageHandlers: UdpMessageHandler[] = [];\n private eventHandlers: Map<string, UdpEventHandler[]> = new Map();\n\n constructor(options: UdpPipeOptions) {\n this.name = options.name;\n this.config = options.config;\n }\n\n /**\n * Bind to a port to receive messages\n */\n async bind(port?: number): Promise<void> {\n return new Promise((resolve, reject) => {\n try {\n this.socket = createSocket('udp4');\n\n this.socket.on('message', (msg, rinfo) => {\n this.handleMessage(msg, rinfo);\n });\n\n this.socket.on('error', (error) => {\n if (!this.bound) {\n reject(error);\n }\n this.emit('error', error);\n });\n\n this.socket.on('listening', () => {\n this.bound = true;\n const address = this.socket!.address();\n this.emit('listening', address);\n resolve();\n });\n\n // Setup broadcast if configured\n if (this.config.broadcast) {\n this.socket.setBroadcast(true);\n }\n\n // Bind to port\n const bindPort = port ?? this.config.port;\n const bindHost = this.config.host ?? '0.0.0.0';\n this.socket.bind(bindPort, bindHost, () => {\n // Join multicast group if configured\n if (this.config.multicast) {\n this.socket!.addMembership(this.config.multicast);\n }\n });\n\n } catch (error) {\n reject(error);\n }\n });\n }\n\n /**\n * Close the socket\n */\n async disconnect(): Promise<void> {\n return new Promise((resolve) => {\n if (this.socket) {\n this.socket.close(() => {\n this.socket = null;\n this.bound = false;\n resolve();\n });\n } else {\n resolve();\n }\n });\n }\n\n /**\n * Check if bound\n */\n isConnected(): boolean {\n return this.bound;\n }\n\n /**\n * Send data to a specific host and port\n */\n async send(\n data: Buffer | string,\n host: string,\n port: number\n ): Promise<PipeResponse> {\n if (!this.socket) {\n // Create socket if not exists (for send-only mode)\n this.socket = createSocket('udp4');\n if (this.config.broadcast) {\n this.socket.setBroadcast(true);\n }\n }\n\n const buffer = typeof data === 'string' ? Buffer.from(data) : data;\n\n return new Promise((resolve) => {\n this.socket!.send(buffer, port, host, (error) => {\n if (error) {\n resolve({ success: false, error: error.message });\n } else {\n resolve({ success: true });\n }\n });\n });\n }\n\n /**\n * Broadcast data to all hosts on the network\n */\n async broadcast(\n data: Buffer | string,\n port: number,\n address = '255.255.255.255'\n ): Promise<PipeResponse> {\n if (!this.socket) {\n this.socket = createSocket('udp4');\n this.socket.setBroadcast(true);\n }\n\n const buffer = typeof data === 'string' ? Buffer.from(data) : data;\n\n return new Promise((resolve) => {\n this.socket!.send(buffer, port, address, (error) => {\n if (error) {\n resolve({ success: false, error: error.message });\n } else {\n resolve({ success: true });\n }\n });\n });\n }\n\n /**\n * Send to multicast group\n */\n async multicast(\n data: Buffer | string,\n port: number,\n group?: string\n ): Promise<PipeResponse> {\n const multicastGroup = group ?? this.config.multicast;\n if (!multicastGroup) {\n return { success: false, error: 'No multicast group configured' };\n }\n\n return this.send(data, multicastGroup, port);\n }\n\n /**\n * Register a message handler\n */\n onMessage(handler: UdpMessageHandler): void {\n this.messageHandlers.push(handler);\n }\n\n /**\n * Remove a message handler\n */\n offMessage(handler: UdpMessageHandler): void {\n const index = this.messageHandlers.indexOf(handler);\n if (index !== -1) {\n this.messageHandlers.splice(index, 1);\n }\n }\n\n /**\n * Register an event handler\n */\n on(event: string, handler: UdpEventHandler): void {\n const handlers = this.eventHandlers.get(event) ?? [];\n handlers.push(handler);\n this.eventHandlers.set(event, handlers);\n }\n\n /**\n * Remove an event handler\n */\n off(event: string, handler: UdpEventHandler): void {\n const handlers = this.eventHandlers.get(event) ?? [];\n const index = handlers.indexOf(handler);\n if (index !== -1) {\n handlers.splice(index, 1);\n }\n }\n\n /**\n * Emit an event\n */\n private emit(event: string, data?: unknown): void {\n const handlers = this.eventHandlers.get(event) ?? [];\n for (const handler of handlers) {\n try {\n const result = handler(data);\n // Handle async handlers properly\n if (result instanceof Promise) {\n result.catch((error) => {\n console.error(`UDP async handler error for \"${event}\":`, error);\n });\n }\n } catch (error) {\n console.error(`UDP handler error for \"${event}\":`, error);\n }\n }\n }\n\n /**\n * Handle incoming messages\n */\n private handleMessage(data: Buffer, rinfo: RemoteInfo): void {\n const msg: UdpMessage = { data, rinfo };\n\n for (const handler of this.messageHandlers) {\n try {\n const result = handler(msg);\n // Handle async handlers properly\n if (result instanceof Promise) {\n result.catch((error) => {\n console.error('UDP async message handler error:', error);\n });\n }\n } catch (error) {\n console.error('UDP message handler error:', error);\n }\n }\n\n this.emit('message', msg);\n }\n}\n\n/**\n * Create a UDP pipe\n */\nexport function createUdpPipe(options: UdpPipeOptions): UdpPipe {\n return new UdpPipe(options);\n}\n"],"mappings":"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","names":[]}
|
package/dist/webhook/index.js
CHANGED
|
@@ -80,10 +80,14 @@ var WebhookPipe = class {
|
|
|
80
80
|
return receivedSignature === secret;
|
|
81
81
|
}
|
|
82
82
|
case "signature": {
|
|
83
|
-
|
|
83
|
+
const signatureValue = headers[signatureHeader.toLowerCase()];
|
|
84
|
+
if (!signatureValue) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
return this.timingSafeEqual(signatureValue, secret);
|
|
84
88
|
}
|
|
85
89
|
default:
|
|
86
|
-
return
|
|
90
|
+
return false;
|
|
87
91
|
}
|
|
88
92
|
}
|
|
89
93
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/webhook/index.ts"],"sourcesContent":["/**\n * Webhook pipe for incoming and outgoing webhooks\n */\n\nimport { createHmac } from 'node:crypto';\nimport type { Pipe, PipeResponse, WebhookPipeConfig } from '../types.js';\n\nexport interface WebhookPipeOptions {\n name: string;\n config: WebhookPipeConfig;\n}\n\nexport type WebhookHandler = (\n body: unknown,\n headers: Record<string, string>\n) => void | Promise<void>;\n\nexport class WebhookPipe implements Pipe {\n public readonly name: string;\n public readonly type = 'webhook';\n private config: WebhookPipeConfig;\n private handlers: WebhookHandler[] = [];\n\n constructor(options: WebhookPipeOptions) {\n this.name = options.name;\n this.config = options.config;\n }\n\n isConnected(): boolean {\n return true;\n }\n\n /**\n * Get the webhook path\n */\n getPath(): string {\n return this.config.path;\n }\n\n /**\n * Get the expected method\n */\n getMethod(): string {\n return this.config.method ?? 'POST';\n }\n\n /**\n * Register a handler for incoming webhooks\n */\n onWebhook(handler: WebhookHandler): () => void {\n this.handlers.push(handler);\n return () => {\n const index = this.handlers.indexOf(handler);\n if (index !== -1) {\n this.handlers.splice(index, 1);\n }\n };\n }\n\n /**\n * Handle an incoming webhook request\n */\n async handleRequest(\n body: unknown,\n headers: Record<string, string>\n ): Promise<PipeResponse> {\n // Verify signature if configured\n if (this.config.verification) {\n const valid = this.verifySignature(body, headers);\n if (!valid) {\n return { success: false, error: 'Invalid signature', status: 401 };\n }\n }\n\n // Call handlers\n for (const handler of this.handlers) {\n try {\n await handler(body, headers);\n } catch (error) {\n console.error(`Webhook handler error:`, error);\n }\n }\n\n // Check for config handlers\n if (this.config.handlers) {\n // These would be processed by the action executor\n }\n\n return { success: true, status: 200 };\n }\n\n /**\n * Verify webhook signature\n */\n private verifySignature(\n body: unknown,\n headers: Record<string, string>\n ): boolean {\n if (!this.config.verification) return true;\n\n const { type, secret, header, algorithm } = this.config.verification;\n const signatureHeader = header ?? 'x-signature';\n const receivedSignature = headers[signatureHeader.toLowerCase()];\n\n if (!receivedSignature || !secret) {\n return false;\n }\n\n const bodyString = typeof body === 'string' ? body : JSON.stringify(body);\n\n switch (type) {\n case 'hmac': {\n const algo = algorithm ?? 'sha256';\n const expectedSignature = createHmac(algo, secret)\n .update(bodyString)\n .digest('hex');\n\n // Handle both raw and prefixed signatures\n const cleanReceived = receivedSignature.replace(/^sha\\d+=/, '');\n return this.timingSafeEqual(cleanReceived, expectedSignature);\n }\n\n case 'token': {\n return receivedSignature === secret;\n }\n\n case 'signature': {\n // Custom signature verification\n //
|
|
1
|
+
{"version":3,"sources":["../../src/webhook/index.ts"],"sourcesContent":["/**\n * Webhook pipe for incoming and outgoing webhooks\n */\n\nimport { createHmac } from 'node:crypto';\nimport type { Pipe, PipeResponse, WebhookPipeConfig } from '../types.js';\n\nexport interface WebhookPipeOptions {\n name: string;\n config: WebhookPipeConfig;\n}\n\nexport type WebhookHandler = (\n body: unknown,\n headers: Record<string, string>\n) => void | Promise<void>;\n\nexport class WebhookPipe implements Pipe {\n public readonly name: string;\n public readonly type = 'webhook';\n private config: WebhookPipeConfig;\n private handlers: WebhookHandler[] = [];\n\n constructor(options: WebhookPipeOptions) {\n this.name = options.name;\n this.config = options.config;\n }\n\n isConnected(): boolean {\n return true;\n }\n\n /**\n * Get the webhook path\n */\n getPath(): string {\n return this.config.path;\n }\n\n /**\n * Get the expected method\n */\n getMethod(): string {\n return this.config.method ?? 'POST';\n }\n\n /**\n * Register a handler for incoming webhooks\n */\n onWebhook(handler: WebhookHandler): () => void {\n this.handlers.push(handler);\n return () => {\n const index = this.handlers.indexOf(handler);\n if (index !== -1) {\n this.handlers.splice(index, 1);\n }\n };\n }\n\n /**\n * Handle an incoming webhook request\n */\n async handleRequest(\n body: unknown,\n headers: Record<string, string>\n ): Promise<PipeResponse> {\n // Verify signature if configured\n if (this.config.verification) {\n const valid = this.verifySignature(body, headers);\n if (!valid) {\n return { success: false, error: 'Invalid signature', status: 401 };\n }\n }\n\n // Call handlers\n for (const handler of this.handlers) {\n try {\n await handler(body, headers);\n } catch (error) {\n console.error(`Webhook handler error:`, error);\n }\n }\n\n // Check for config handlers\n if (this.config.handlers) {\n // These would be processed by the action executor\n }\n\n return { success: true, status: 200 };\n }\n\n /**\n * Verify webhook signature\n */\n private verifySignature(\n body: unknown,\n headers: Record<string, string>\n ): boolean {\n if (!this.config.verification) return true;\n\n const { type, secret, header, algorithm } = this.config.verification;\n const signatureHeader = header ?? 'x-signature';\n const receivedSignature = headers[signatureHeader.toLowerCase()];\n\n if (!receivedSignature || !secret) {\n return false;\n }\n\n const bodyString = typeof body === 'string' ? body : JSON.stringify(body);\n\n switch (type) {\n case 'hmac': {\n const algo = algorithm ?? 'sha256';\n const expectedSignature = createHmac(algo, secret)\n .update(bodyString)\n .digest('hex');\n\n // Handle both raw and prefixed signatures\n const cleanReceived = receivedSignature.replace(/^sha\\d+=/, '');\n return this.timingSafeEqual(cleanReceived, expectedSignature);\n }\n\n case 'token': {\n return receivedSignature === secret;\n }\n\n case 'signature': {\n // Custom signature verification - fail closed by default\n // Requires both a header configuration and a secret to be provided\n const signatureValue = headers[signatureHeader.toLowerCase()];\n if (!signatureValue) {\n return false;\n }\n // Compare the provided signature with the secret using timing-safe comparison\n return this.timingSafeEqual(signatureValue, secret);\n }\n\n default:\n // Unknown verification type - fail closed for security\n return false;\n }\n }\n\n /**\n * Timing-safe string comparison\n */\n private timingSafeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false;\n }\n\n let result = 0;\n for (let i = 0; i < a.length; i++) {\n result |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return result === 0;\n }\n}\n\n/**\n * Outgoing webhook sender\n */\nexport class WebhookSender {\n /**\n * Send a Discord webhook\n */\n static async sendDiscordWebhook(\n url: string,\n options: {\n content?: string;\n username?: string;\n avatar_url?: string;\n embeds?: Record<string, unknown>[];\n }\n ): Promise<PipeResponse> {\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(options),\n });\n\n if (!response.ok) {\n return {\n success: false,\n error: `HTTP ${response.status}`,\n status: response.status,\n };\n }\n\n return { success: true, status: response.status };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n\n /**\n * Send a generic webhook\n */\n static async send(\n url: string,\n body: unknown,\n options: { headers?: Record<string, string>; method?: string } = {}\n ): Promise<PipeResponse> {\n try {\n const response = await fetch(url, {\n method: options.method ?? 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers,\n },\n body: typeof body === 'string' ? body : JSON.stringify(body),\n });\n\n let data: unknown;\n try {\n data = await response.json();\n } catch {\n data = await response.text();\n }\n\n return {\n success: response.ok,\n data,\n status: response.status,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n}\n\n/**\n * Create a webhook pipe\n */\nexport function createWebhookPipe(options: WebhookPipeOptions): WebhookPipe {\n return new WebhookPipe(options);\n}\n"],"mappings":"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","names":[]}
|
package/dist/websocket/index.js
CHANGED
|
@@ -7,6 +7,7 @@ var WebSocketPipe = class {
|
|
|
7
7
|
config;
|
|
8
8
|
reconnectAttempts = 0;
|
|
9
9
|
reconnecting = false;
|
|
10
|
+
reconnectTimer = null;
|
|
10
11
|
heartbeatInterval = null;
|
|
11
12
|
messageHandlers = /* @__PURE__ */ new Map();
|
|
12
13
|
connected = false;
|
|
@@ -54,6 +55,10 @@ var WebSocketPipe = class {
|
|
|
54
55
|
async disconnect() {
|
|
55
56
|
this.stopHeartbeat();
|
|
56
57
|
this.reconnecting = false;
|
|
58
|
+
if (this.reconnectTimer) {
|
|
59
|
+
clearTimeout(this.reconnectTimer);
|
|
60
|
+
this.reconnectTimer = null;
|
|
61
|
+
}
|
|
57
62
|
if (this.ws) {
|
|
58
63
|
this.ws.close();
|
|
59
64
|
this.ws = null;
|
|
@@ -86,13 +91,21 @@ var WebSocketPipe = class {
|
|
|
86
91
|
return { success: false, error: "Not connected" };
|
|
87
92
|
}
|
|
88
93
|
return new Promise((resolve) => {
|
|
89
|
-
|
|
94
|
+
let resolved = false;
|
|
95
|
+
const cleanup = () => {
|
|
90
96
|
this.off(responseEvent, handler);
|
|
97
|
+
};
|
|
98
|
+
const timer = setTimeout(() => {
|
|
99
|
+
if (resolved) return;
|
|
100
|
+
resolved = true;
|
|
101
|
+
cleanup();
|
|
91
102
|
resolve({ success: false, error: "Request timeout" });
|
|
92
103
|
}, timeout);
|
|
93
104
|
const handler = (response) => {
|
|
105
|
+
if (resolved) return;
|
|
106
|
+
resolved = true;
|
|
94
107
|
clearTimeout(timer);
|
|
95
|
-
|
|
108
|
+
cleanup();
|
|
96
109
|
resolve({ success: true, data: response });
|
|
97
110
|
};
|
|
98
111
|
this.on(responseEvent, handler);
|
|
@@ -124,7 +137,12 @@ var WebSocketPipe = class {
|
|
|
124
137
|
const handlers = this.messageHandlers.get(event) ?? [];
|
|
125
138
|
for (const handler of handlers) {
|
|
126
139
|
try {
|
|
127
|
-
handler(data);
|
|
140
|
+
const result = handler(data);
|
|
141
|
+
if (result instanceof Promise) {
|
|
142
|
+
result.catch((error) => {
|
|
143
|
+
console.error(`WebSocket async handler error for "${event}":`, error);
|
|
144
|
+
});
|
|
145
|
+
}
|
|
128
146
|
} catch (error) {
|
|
129
147
|
console.error(`WebSocket handler error for "${event}":`, error);
|
|
130
148
|
}
|
|
@@ -162,14 +180,14 @@ var WebSocketPipe = class {
|
|
|
162
180
|
}
|
|
163
181
|
this.reconnecting = true;
|
|
164
182
|
this.reconnectAttempts++;
|
|
165
|
-
setTimeout(
|
|
166
|
-
|
|
167
|
-
|
|
183
|
+
this.reconnectTimer = setTimeout(() => {
|
|
184
|
+
this.reconnectTimer = null;
|
|
185
|
+
this.connect().then(() => {
|
|
168
186
|
this.emit("reconnected", { attempts: this.reconnectAttempts });
|
|
169
|
-
}
|
|
187
|
+
}).catch(() => {
|
|
170
188
|
this.reconnecting = false;
|
|
171
189
|
this.handleDisconnect();
|
|
172
|
-
}
|
|
190
|
+
});
|
|
173
191
|
}, delay);
|
|
174
192
|
}
|
|
175
193
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/websocket/index.ts"],"sourcesContent":["/**\n * WebSocket pipe for bidirectional communication\n */\n\nimport WebSocket from 'ws';\nimport type { Pipe, PipeResponse, WebSocketPipeConfig } from '../types.js';\n\nexport interface WebSocketPipeOptions {\n name: string;\n config: WebSocketPipeConfig;\n}\n\nexport type WebSocketMessageHandler = (data: unknown) => void | Promise<void>;\n\nexport class WebSocketPipe implements Pipe {\n public readonly name: string;\n public readonly type = 'websocket';\n private ws: WebSocket | null = null;\n private config: WebSocketPipeConfig;\n private reconnectAttempts = 0;\n private reconnecting = false;\n private heartbeatInterval: NodeJS.Timeout | null = null;\n private messageHandlers: Map<string, WebSocketMessageHandler[]> = new Map();\n private connected = false;\n\n constructor(options: WebSocketPipeOptions) {\n this.name = options.name;\n this.config = options.config;\n }\n\n /**\n * Connect to the WebSocket server\n */\n async connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n try {\n const headers = this.config.headers as Record<string, string>;\n this.ws = new WebSocket(this.config.url, { headers });\n\n this.ws.on('open', () => {\n this.connected = true;\n this.reconnectAttempts = 0;\n this.reconnecting = false;\n this.startHeartbeat();\n resolve();\n });\n\n this.ws.on('message', (data) => {\n this.handleMessage(data);\n });\n\n this.ws.on('close', () => {\n this.connected = false;\n this.stopHeartbeat();\n this.handleDisconnect();\n });\n\n this.ws.on('error', (error) => {\n if (!this.connected) {\n reject(error);\n }\n this.emit('error', error);\n });\n\n } catch (error) {\n reject(error);\n }\n });\n }\n\n /**\n * Disconnect from the server\n */\n async disconnect(): Promise<void> {\n this.stopHeartbeat();\n this.reconnecting = false;\n\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n\n this.connected = false;\n }\n\n /**\n * Check if connected\n */\n isConnected(): boolean {\n return this.connected && this.ws?.readyState === WebSocket.OPEN;\n }\n\n /**\n * Send a message\n */\n send(data: unknown): boolean {\n if (!this.isConnected()) {\n return false;\n }\n\n const message = typeof data === 'string' ? data : JSON.stringify(data);\n this.ws!.send(message);\n return true;\n }\n\n /**\n * Send and wait for a response (request-response pattern)\n */\n async request<T = unknown>(\n data: unknown,\n options: { timeout?: number; responseEvent?: string } = {}\n ): Promise<PipeResponse<T>> {\n const { timeout = 30000, responseEvent = 'response' } = options;\n\n if (!this.isConnected()) {\n return { success: false, error: 'Not connected' };\n }\n\n return new Promise((resolve) => {\n const timer = setTimeout(() => {\n this.off(responseEvent, handler);\n resolve({ success: false, error: 'Request timeout' });\n }, timeout);\n\n const handler = (response: unknown) => {\n clearTimeout(timer);\n this.off(responseEvent, handler);\n resolve({ success: true, data: response as T });\n };\n\n this.on(responseEvent, handler);\n this.send(data);\n });\n }\n\n /**\n * Register a message handler\n */\n on(event: string, handler: WebSocketMessageHandler): void {\n const handlers = this.messageHandlers.get(event) ?? [];\n handlers.push(handler);\n this.messageHandlers.set(event, handlers);\n }\n\n /**\n * Remove a message handler\n */\n off(event: string, handler: WebSocketMessageHandler): void {\n const handlers = this.messageHandlers.get(event) ?? [];\n const index = handlers.indexOf(handler);\n if (index !== -1) {\n handlers.splice(index, 1);\n }\n }\n\n /**\n * Emit an event to handlers\n */\n private emit(event: string, data: unknown): void {\n const handlers = this.messageHandlers.get(event) ?? [];\n for (const handler of handlers) {\n try {\n handler(data);\n } catch (error) {\n console.error(`WebSocket handler error for \"${event}\":`, error);\n }\n }\n }\n\n /**\n * Handle incoming messages\n */\n private handleMessage(rawData: WebSocket.RawData): void {\n let data: unknown;\n\n try {\n const str = rawData.toString();\n data = JSON.parse(str);\n } catch {\n data = rawData.toString();\n }\n\n // Emit to 'message' handlers\n this.emit('message', data);\n\n // Check for event field in JSON messages\n if (typeof data === 'object' && data !== null && 'event' in data) {\n const event = (data as { event: string }).event;\n this.emit(event, data);\n }\n }\n\n /**\n * Handle disconnection\n */\n private handleDisconnect(): void {\n if (!this.config.reconnect?.enabled || this.reconnecting) {\n return;\n }\n\n const maxAttempts = this.config.reconnect.max_attempts ?? 10;\n const delay = this.parseDuration(this.config.reconnect.delay ?? '5s');\n\n if (this.reconnectAttempts >= maxAttempts) {\n this.emit('reconnect_failed', { attempts: this.reconnectAttempts });\n return;\n }\n\n this.reconnecting = true;\n this.reconnectAttempts++;\n\n setTimeout(async () => {\n try {\n await this.connect();\n this.emit('reconnected', { attempts: this.reconnectAttempts });\n } catch {\n this.reconnecting = false;\n this.handleDisconnect();\n }\n }, delay);\n }\n\n /**\n * Start heartbeat\n */\n private startHeartbeat(): void {\n if (!this.config.heartbeat?.interval) return;\n\n const interval = this.parseDuration(this.config.heartbeat.interval);\n const message = this.config.heartbeat.message ?? 'ping';\n\n this.heartbeatInterval = setInterval(() => {\n if (this.isConnected()) {\n this.send(message);\n }\n }, interval);\n }\n\n /**\n * Stop heartbeat\n */\n private stopHeartbeat(): void {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = null;\n }\n }\n\n /**\n * Parse duration string to milliseconds\n */\n private parseDuration(duration: string): number {\n const match = duration.match(/^(\\d+)(ms|s|m|h)?$/);\n if (!match) return 5000;\n\n const value = parseInt(match[1]!, 10);\n const unit = match[2] ?? 's';\n\n switch (unit) {\n case 'ms':\n return value;\n case 's':\n return value * 1000;\n case 'm':\n return value * 60 * 1000;\n case 'h':\n return value * 60 * 60 * 1000;\n default:\n return value * 1000;\n }\n }\n}\n\n/**\n * Create a WebSocket pipe\n */\nexport function createWebSocketPipe(options: WebSocketPipeOptions): WebSocketPipe {\n return new WebSocketPipe(options);\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/websocket/index.ts"],"sourcesContent":["/**\n * WebSocket pipe for bidirectional communication\n */\n\nimport WebSocket from 'ws';\nimport type { Pipe, PipeResponse, WebSocketPipeConfig } from '../types.js';\n\nexport interface WebSocketPipeOptions {\n name: string;\n config: WebSocketPipeConfig;\n}\n\nexport type WebSocketMessageHandler = (data: unknown) => void | Promise<void>;\n\nexport class WebSocketPipe implements Pipe {\n public readonly name: string;\n public readonly type = 'websocket';\n private ws: WebSocket | null = null;\n private config: WebSocketPipeConfig;\n private reconnectAttempts = 0;\n private reconnecting = false;\n private reconnectTimer: NodeJS.Timeout | null = null;\n private heartbeatInterval: NodeJS.Timeout | null = null;\n private messageHandlers: Map<string, WebSocketMessageHandler[]> = new Map();\n private connected = false;\n\n constructor(options: WebSocketPipeOptions) {\n this.name = options.name;\n this.config = options.config;\n }\n\n /**\n * Connect to the WebSocket server\n */\n async connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n try {\n const headers = this.config.headers as Record<string, string>;\n this.ws = new WebSocket(this.config.url, { headers });\n\n this.ws.on('open', () => {\n this.connected = true;\n this.reconnectAttempts = 0;\n this.reconnecting = false;\n this.startHeartbeat();\n resolve();\n });\n\n this.ws.on('message', (data) => {\n this.handleMessage(data);\n });\n\n this.ws.on('close', () => {\n this.connected = false;\n this.stopHeartbeat();\n this.handleDisconnect();\n });\n\n this.ws.on('error', (error) => {\n if (!this.connected) {\n reject(error);\n }\n this.emit('error', error);\n });\n\n } catch (error) {\n reject(error);\n }\n });\n }\n\n /**\n * Disconnect from the server\n */\n async disconnect(): Promise<void> {\n this.stopHeartbeat();\n this.reconnecting = false;\n\n // Clear any pending reconnect timer to prevent memory leaks\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n\n this.connected = false;\n }\n\n /**\n * Check if connected\n */\n isConnected(): boolean {\n return this.connected && this.ws?.readyState === WebSocket.OPEN;\n }\n\n /**\n * Send a message\n */\n send(data: unknown): boolean {\n if (!this.isConnected()) {\n return false;\n }\n\n const message = typeof data === 'string' ? data : JSON.stringify(data);\n this.ws!.send(message);\n return true;\n }\n\n /**\n * Send and wait for a response (request-response pattern)\n */\n async request<T = unknown>(\n data: unknown,\n options: { timeout?: number; responseEvent?: string } = {}\n ): Promise<PipeResponse<T>> {\n const { timeout = 30000, responseEvent = 'response' } = options;\n\n if (!this.isConnected()) {\n return { success: false, error: 'Not connected' };\n }\n\n return new Promise((resolve) => {\n let resolved = false;\n\n const cleanup = () => {\n this.off(responseEvent, handler);\n };\n\n const timer = setTimeout(() => {\n if (resolved) return;\n resolved = true;\n cleanup();\n resolve({ success: false, error: 'Request timeout' });\n }, timeout);\n\n const handler = (response: unknown) => {\n if (resolved) return;\n resolved = true;\n clearTimeout(timer);\n cleanup();\n resolve({ success: true, data: response as T });\n };\n\n this.on(responseEvent, handler);\n this.send(data);\n });\n }\n\n /**\n * Register a message handler\n */\n on(event: string, handler: WebSocketMessageHandler): void {\n const handlers = this.messageHandlers.get(event) ?? [];\n handlers.push(handler);\n this.messageHandlers.set(event, handlers);\n }\n\n /**\n * Remove a message handler\n */\n off(event: string, handler: WebSocketMessageHandler): void {\n const handlers = this.messageHandlers.get(event) ?? [];\n const index = handlers.indexOf(handler);\n if (index !== -1) {\n handlers.splice(index, 1);\n }\n }\n\n /**\n * Emit an event to handlers\n */\n private emit(event: string, data: unknown): void {\n const handlers = this.messageHandlers.get(event) ?? [];\n for (const handler of handlers) {\n try {\n const result = handler(data);\n // Handle async handlers properly\n if (result instanceof Promise) {\n result.catch((error) => {\n console.error(`WebSocket async handler error for \"${event}\":`, error);\n });\n }\n } catch (error) {\n console.error(`WebSocket handler error for \"${event}\":`, error);\n }\n }\n }\n\n /**\n * Handle incoming messages\n */\n private handleMessage(rawData: WebSocket.RawData): void {\n let data: unknown;\n\n try {\n const str = rawData.toString();\n data = JSON.parse(str);\n } catch {\n data = rawData.toString();\n }\n\n // Emit to 'message' handlers\n this.emit('message', data);\n\n // Check for event field in JSON messages\n if (typeof data === 'object' && data !== null && 'event' in data) {\n const event = (data as { event: string }).event;\n this.emit(event, data);\n }\n }\n\n /**\n * Handle disconnection\n */\n private handleDisconnect(): void {\n if (!this.config.reconnect?.enabled || this.reconnecting) {\n return;\n }\n\n const maxAttempts = this.config.reconnect.max_attempts ?? 10;\n const delay = this.parseDuration(this.config.reconnect.delay ?? '5s');\n\n if (this.reconnectAttempts >= maxAttempts) {\n this.emit('reconnect_failed', { attempts: this.reconnectAttempts });\n return;\n }\n\n this.reconnecting = true;\n this.reconnectAttempts++;\n\n // Track the timer so it can be cleared on disconnect\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.connect()\n .then(() => {\n this.emit('reconnected', { attempts: this.reconnectAttempts });\n })\n .catch(() => {\n this.reconnecting = false;\n this.handleDisconnect();\n });\n }, delay);\n }\n\n /**\n * Start heartbeat\n */\n private startHeartbeat(): void {\n if (!this.config.heartbeat?.interval) return;\n\n const interval = this.parseDuration(this.config.heartbeat.interval);\n const message = this.config.heartbeat.message ?? 'ping';\n\n this.heartbeatInterval = setInterval(() => {\n if (this.isConnected()) {\n this.send(message);\n }\n }, interval);\n }\n\n /**\n * Stop heartbeat\n */\n private stopHeartbeat(): void {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = null;\n }\n }\n\n /**\n * Parse duration string to milliseconds\n */\n private parseDuration(duration: string): number {\n const match = duration.match(/^(\\d+)(ms|s|m|h)?$/);\n if (!match) return 5000;\n\n const value = parseInt(match[1]!, 10);\n const unit = match[2] ?? 's';\n\n switch (unit) {\n case 'ms':\n return value;\n case 's':\n return value * 1000;\n case 'm':\n return value * 60 * 1000;\n case 'h':\n return value * 60 * 60 * 1000;\n default:\n return value * 1000;\n }\n }\n}\n\n/**\n * Create a WebSocket pipe\n */\nexport function createWebSocketPipe(options: WebSocketPipeOptions): WebSocketPipe {\n return new WebSocketPipe(options);\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@furlow/pipes",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "External integration pipes for FURLOW bot framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"furlow",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"chokidar": "^3.5.0",
|
|
63
63
|
"mqtt": "^5.3.0",
|
|
64
64
|
"ws": "^8.16.0",
|
|
65
|
-
"@furlow/core": "1.0.
|
|
65
|
+
"@furlow/core": "1.0.3"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
68
|
"@types/better-sqlite3": "^7.6.8",
|