@syncbridge/net 0.4.1

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/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ Copyright (c) 2025 Panates (Panates Teknoloji Yatirim A.S.). All rights reserved.
2
+
3
+ This software and associated documentation files (the "Software") are
4
+ the proprietary property of Panates and are protected by copyright laws
5
+ and international copyright treaties.
6
+
7
+ Unauthorized copying, distribution, modification, reverse engineering,
8
+ or use of this software, in whole or in part, is strictly prohibited
9
+ without the express written permission of Panates.
10
+
11
+ This Software is provided solely for use in accordance with the terms
12
+ of a valid license agreement. Any unauthorized use may result in
13
+ civil and/or criminal penalties.
14
+
15
+ For licensing inquiries, please contact: info@panates.com
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # SyncBridge ICU Connectors
@@ -0,0 +1,48 @@
1
+ import { Buffer } from 'node:buffer';
2
+ import net from 'node:net';
3
+ import tls from 'node:tls';
4
+ import { Backoff } from 'backoff';
5
+ import { AsyncEventEmitter, EventMap } from 'node-events-async';
6
+ import reconnectCore from 'reconnect-core';
7
+ export declare class TcpClient<T extends TcpClient.Events = TcpClient.Events> extends AsyncEventEmitter<EventMap<T>> {
8
+ protected _connectionManager?: ReturnType<typeof socketReconnect>;
9
+ protected _socket?: net.Socket;
10
+ host: string;
11
+ port: number;
12
+ connectTimeout?: number;
13
+ reconnectOptions: TcpClient.ReconnectOptions;
14
+ constructor(args?: TcpClient.Options);
15
+ get connected(): boolean;
16
+ get socket(): net.Socket | undefined;
17
+ connect(): void;
18
+ disconnect(): Promise<void>;
19
+ write(data: string | Buffer): void;
20
+ }
21
+ export declare namespace TcpClient {
22
+ interface Options {
23
+ host: string;
24
+ port: number;
25
+ connectTimeout?: number;
26
+ keepAlive?: boolean;
27
+ reconnect?: ReconnectOptions;
28
+ tls?: tls.TlsOptions;
29
+ }
30
+ interface ReconnectOptions {
31
+ strategy?: 'fibonacci' | 'exponential' | Backoff;
32
+ immediate?: boolean | undefined;
33
+ failAfter?: number | undefined;
34
+ randomisationFactor?: number | undefined;
35
+ initialDelay?: number | undefined;
36
+ maxDelay?: number | undefined;
37
+ }
38
+ interface Events {
39
+ connect: [socket: net.Socket];
40
+ disconnect: [error: Error | undefined];
41
+ reconnecting: [n: number, delay: number];
42
+ reconnect: [socket: net.Socket];
43
+ data: [data: Buffer];
44
+ error: [error: Error];
45
+ }
46
+ }
47
+ declare const socketReconnect: reconnectCore.CustomModule<net.NetConnectOpts, net.Socket>;
48
+ export {};
@@ -0,0 +1,131 @@
1
+ import net from 'node:net';
2
+ import { AsyncEventEmitter } from 'node-events-async';
3
+ import reconnectCore from 'reconnect-core';
4
+ export class TcpClient extends AsyncEventEmitter {
5
+ _connectionManager;
6
+ _socket;
7
+ host;
8
+ port;
9
+ connectTimeout;
10
+ reconnectOptions;
11
+ constructor(args) {
12
+ super();
13
+ this.reconnectOptions = args?.reconnect || {};
14
+ this.reconnectOptions.initialDelay =
15
+ this.reconnectOptions.initialDelay ?? 2000;
16
+ this.reconnectOptions.maxDelay = this.reconnectOptions.maxDelay ?? 10000;
17
+ this.reconnectOptions.strategy =
18
+ this.reconnectOptions.strategy ?? 'fibonacci';
19
+ this.host = args?.host || 'localhost';
20
+ this.port = args?.port || 0;
21
+ this.connectTimeout = args?.connectTimeout;
22
+ }
23
+ get connected() {
24
+ return !!this._connectionManager?.connected;
25
+ }
26
+ get socket() {
27
+ return this._socket;
28
+ }
29
+ connect() {
30
+ if (this.connected)
31
+ return;
32
+ let reconnecting = false;
33
+ const connectionManager = (this._connectionManager = socketReconnect({
34
+ ...this.reconnectOptions,
35
+ timeout: this.connectTimeout,
36
+ })
37
+ .on('error', (error) => {
38
+ if (!connectionManager.reconnect)
39
+ return;
40
+ error = error instanceof AggregateError ? error.errors[0] : error;
41
+ if (error.code === 'ECONNREFUSED')
42
+ error.message = `Connection refused to ${error.address}:${error.port}`;
43
+ this.emit('error', error);
44
+ })
45
+ .on('connect', (socket) => {
46
+ if (this._socket !== socket) {
47
+ this._socket = socket;
48
+ socket.on('data', (chunk) => this.emit('data', chunk));
49
+ }
50
+ if (reconnecting)
51
+ this.emit('reconnect', socket);
52
+ reconnecting = false;
53
+ this.emit('connect', socket);
54
+ })
55
+ .on('reconnect', (n, delay) => {
56
+ if (n === 0 && delay === 0)
57
+ return;
58
+ reconnecting = true;
59
+ this.emit('reconnecting', n, delay);
60
+ })
61
+ .on('disconnect', err => {
62
+ this._socket = undefined;
63
+ if (connectionManager.reconnect) {
64
+ if (err)
65
+ err.message = `TCP socket connection lost: ${err.message}`;
66
+ else
67
+ err = new Error('TCP socket connection lost');
68
+ this.emit('disconnect', err);
69
+ }
70
+ else
71
+ this.emit('disconnect');
72
+ }));
73
+ connectionManager.connect({
74
+ host: this.host,
75
+ port: this.port,
76
+ timeout: this.connectTimeout,
77
+ // keepAlive: this.
78
+ });
79
+ }
80
+ async disconnect() {
81
+ if (!this._connectionManager)
82
+ return;
83
+ const connectionManager = this._connectionManager;
84
+ this._connectionManager = undefined;
85
+ /** istanbul ignore else */
86
+ if (connectionManager.connected) {
87
+ connectionManager.reconnect = false;
88
+ return new Promise(resolve => {
89
+ connectionManager.once('disconnect', async () => {
90
+ connectionManager.reset();
91
+ this._connectionManager = undefined;
92
+ resolve();
93
+ });
94
+ connectionManager.disconnect();
95
+ connectionManager.reset();
96
+ });
97
+ }
98
+ else {
99
+ connectionManager.disconnect();
100
+ connectionManager.reset();
101
+ }
102
+ }
103
+ write(data) {
104
+ if (!this._socket)
105
+ throw new Error(`Can't write while TCP socket is not connected`);
106
+ this._socket.write(data);
107
+ }
108
+ }
109
+ const socketReconnect = reconnectCore(args => {
110
+ // implement tls
111
+ const socket = net.connect({
112
+ ...args,
113
+ timeout: undefined,
114
+ });
115
+ if (args.timeout) {
116
+ const timer = setTimeout(() => {
117
+ socket.destroy(new Error('Connection timed out'));
118
+ }, args.timeout).unref();
119
+ const onConnect = () => {
120
+ clearTimeout(timer);
121
+ socket.removeListener('error', onError);
122
+ };
123
+ const onError = () => {
124
+ socket.removeListener('connect', onConnect);
125
+ clearTimeout(timer);
126
+ };
127
+ socket.once('connect', onConnect);
128
+ socket.once('error', onError);
129
+ }
130
+ return socket;
131
+ });
@@ -0,0 +1,35 @@
1
+ import { Buffer } from 'node:buffer';
2
+ import { IoClientBaseComponent } from '@syncbridge/builtins';
3
+ import { TcpClient } from '../classes/tcp-client.js';
4
+ import { TcpClientReconnectVariables, TcpClientTlsVariables, TcpClientVariables } from './tcp-client.variables.js';
5
+ /**
6
+ * TcpClient component
7
+ */
8
+ export declare class TcpClientComponent<TEvents extends TcpClientComponent.Events = TcpClientComponent.Events> extends IoClientBaseComponent<TEvents> {
9
+ readonly protocol: string;
10
+ protected _client: TcpClient;
11
+ protected _stopping?: boolean;
12
+ protected _address?: any;
13
+ values: TcpClientVariables;
14
+ get connected(): boolean;
15
+ protected _init(): Promise<void>;
16
+ protected _start(abortSignal: AbortSignal): Promise<void>;
17
+ protected _stop(): Promise<void>;
18
+ write(data: string | Buffer): void;
19
+ }
20
+ /**
21
+ * @namespace
22
+ */
23
+ export declare namespace TcpClientComponent {
24
+ interface Events extends IoClientBaseComponent.Events {
25
+ connect: [];
26
+ disconnect: [error: Error | undefined];
27
+ reconnecting: [n: number, delay: number];
28
+ }
29
+ const Variables: typeof TcpClientVariables;
30
+ type Variables = TcpClientVariables;
31
+ const ReconnectVariables: typeof TcpClientReconnectVariables;
32
+ type ReconnectVariables = TcpClientReconnectVariables;
33
+ const TlsVariables: typeof TcpClientTlsVariables;
34
+ type TlsVariables = TcpClientTlsVariables;
35
+ }
@@ -0,0 +1,102 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import { IoClientBaseComponent } from '@syncbridge/builtins';
3
+ import { Component, ServiceStatus } from '@syncbridge/common';
4
+ import colors from 'ansi-colors';
5
+ import { TcpClient } from '../classes/tcp-client.js';
6
+ import { TcpClientReconnectVariables, TcpClientTlsVariables, TcpClientVariables, } from './tcp-client.variables.js';
7
+ /**
8
+ * TcpClient component
9
+ */
10
+ let TcpClientComponent = class TcpClientComponent extends IoClientBaseComponent {
11
+ protocol = 'tcp';
12
+ _stopping;
13
+ _address;
14
+ get connected() {
15
+ return this._client.connected;
16
+ }
17
+ async _init() {
18
+ await super._init();
19
+ this._client = new TcpClient({
20
+ host: this.values.host || 'localhost',
21
+ port: this.values.port || 0,
22
+ connectTimeout: this.values.connectTimeout,
23
+ keepAlive: this.values.keepAlive,
24
+ reconnect: this.values.reconnect,
25
+ tls: this.values.tls,
26
+ });
27
+ /* On connect */
28
+ this._client.on('connect', (socket) => {
29
+ this._address = { ...socket.address() };
30
+ this._address.toString = function () {
31
+ return `${this.address}:${this.port}`;
32
+ }.bind(this._address);
33
+ setImmediate(() => {
34
+ this.logger?.info(`TCP socket connected to ${colors.cyan(this._client.host + ':' + this._client.port)}`);
35
+ this.setStatus(ServiceStatus.started);
36
+ this.emit('connect');
37
+ });
38
+ });
39
+ /* On disconnect */
40
+ this._client.on('disconnect', (err) => {
41
+ if (this._stopping)
42
+ this.emit('disconnect');
43
+ else {
44
+ err = err || new Error('TCP socket disconnected');
45
+ this.logger?.error(err);
46
+ this.setStatus(ServiceStatus.unhealthy, err.message);
47
+ this.emit('disconnect');
48
+ }
49
+ });
50
+ /* On data */
51
+ this._client.on('data', (chunk) => {
52
+ this.emit('data', chunk, this._address);
53
+ });
54
+ /* On error */
55
+ this._client.on('error', (err) => {
56
+ this.emit('error', err);
57
+ });
58
+ /* On reconnecting */
59
+ this._client.on('reconnecting', (n, delay) => {
60
+ this.logger?.error(`Connection failed (${colors.cyan(String(n + 1))}). Will be retried after ${colors.cyan(delay + 'ms')}`);
61
+ this.emit('reconnecting', n, delay);
62
+ });
63
+ }
64
+ async _start(abortSignal) {
65
+ await super._start(abortSignal);
66
+ this._stopping = false;
67
+ this.logger?.info(`TCP socket connecting to ${colors.cyan(this._client.host + ':' + this._client.port)}`);
68
+ this._client.connect();
69
+ }
70
+ async _stop() {
71
+ this._stopping = true;
72
+ await this._client.disconnect();
73
+ }
74
+ write(data) {
75
+ if (!this.connected) {
76
+ throw new Error(`Can't write while TCP socket is not connected`);
77
+ }
78
+ this.emit('transmit', data, this._address);
79
+ this._client.write(data);
80
+ }
81
+ };
82
+ __decorate([
83
+ Component.UseVariables(),
84
+ __metadata("design:type", TcpClientVariables)
85
+ ], TcpClientComponent.prototype, "values", void 0);
86
+ TcpClientComponent = __decorate([
87
+ Component({
88
+ className: 'TcpClient',
89
+ displayName: 'TCP Client',
90
+ description: 'TCP client component',
91
+ tags: ['tcp', 'client', 'socket', 'connection'],
92
+ })
93
+ ], TcpClientComponent);
94
+ export { TcpClientComponent };
95
+ /**
96
+ * @namespace
97
+ */
98
+ (function (TcpClientComponent) {
99
+ TcpClientComponent.Variables = TcpClientVariables;
100
+ TcpClientComponent.ReconnectVariables = TcpClientReconnectVariables;
101
+ TcpClientComponent.TlsVariables = TcpClientTlsVariables;
102
+ })(TcpClientComponent || (TcpClientComponent = {}));
@@ -0,0 +1,31 @@
1
+ import { IoClientBaseComponent } from '@syncbridge/builtins';
2
+ /**
3
+ * TLS variables
4
+ */
5
+ export declare class TcpClientTlsVariables {
6
+ servername?: string;
7
+ key: string;
8
+ cert: string;
9
+ ca?: string;
10
+ passphrase?: string;
11
+ rejectUnauthorized: boolean;
12
+ }
13
+ /**
14
+ * Reconnect variables
15
+ */
16
+ export declare class TcpClientReconnectVariables {
17
+ strategy: 'exponential' | 'fibonacci';
18
+ initialDelay: number;
19
+ maxDelay: number;
20
+ }
21
+ /**
22
+ * Variables
23
+ */
24
+ export declare class TcpClientVariables extends IoClientBaseComponent.Variables {
25
+ host: string;
26
+ port: number;
27
+ keepAlive: boolean;
28
+ connectTimeout: number;
29
+ reconnect: TcpClientReconnectVariables;
30
+ tls: TcpClientTlsVariables;
31
+ }
@@ -0,0 +1,140 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import { IoClientBaseComponent } from '@syncbridge/builtins';
3
+ import { DefineVariable, VariableType } from '@syncbridge/common';
4
+ /**
5
+ * TLS variables
6
+ */
7
+ export class TcpClientTlsVariables {
8
+ }
9
+ __decorate([
10
+ DefineVariable({
11
+ label: 'SNI',
12
+ description: 'SNI (Server Name Indication)',
13
+ }),
14
+ __metadata("design:type", String)
15
+ ], TcpClientTlsVariables.prototype, "servername", void 0);
16
+ __decorate([
17
+ DefineVariable({
18
+ label: 'Key',
19
+ description: 'Private keys in PEM format',
20
+ required: true,
21
+ }),
22
+ __metadata("design:type", String)
23
+ ], TcpClientTlsVariables.prototype, "key", void 0);
24
+ __decorate([
25
+ DefineVariable({
26
+ label: 'Cert',
27
+ description: 'Cert chains in PEM format',
28
+ required: true,
29
+ }),
30
+ __metadata("design:type", String)
31
+ ], TcpClientTlsVariables.prototype, "cert", void 0);
32
+ __decorate([
33
+ DefineVariable({
34
+ label: 'CA certificates',
35
+ description: 'Optionally override the trusted CA certificates. Default is to trust the well-known CAs ' +
36
+ "curated by Mozilla. Mozilla's CAs are completely replaced when CAs are explicitly specified " +
37
+ 'using this option.',
38
+ required: true,
39
+ }),
40
+ __metadata("design:type", String)
41
+ ], TcpClientTlsVariables.prototype, "ca", void 0);
42
+ __decorate([
43
+ DefineVariable({
44
+ type: VariableType.Secret,
45
+ label: 'Passphrase',
46
+ description: 'Passphrase to decrypt the private key',
47
+ }),
48
+ __metadata("design:type", String)
49
+ ], TcpClientTlsVariables.prototype, "passphrase", void 0);
50
+ __decorate([
51
+ DefineVariable({
52
+ label: 'Reject unauthorized',
53
+ description: 'If true will reject any connection which is not authorized with the list of supplied CAs',
54
+ default: true,
55
+ }),
56
+ __metadata("design:type", Boolean)
57
+ ], TcpClientTlsVariables.prototype, "rejectUnauthorized", void 0);
58
+ /**
59
+ * Reconnect variables
60
+ */
61
+ export class TcpClientReconnectVariables {
62
+ }
63
+ __decorate([
64
+ DefineVariable({
65
+ type: VariableType.Enum,
66
+ label: 'Reconnection strategy',
67
+ enumValues: ['exponential', 'fibonacci'],
68
+ default: 'exponential',
69
+ }),
70
+ __metadata("design:type", String)
71
+ ], TcpClientReconnectVariables.prototype, "strategy", void 0);
72
+ __decorate([
73
+ DefineVariable({
74
+ label: 'Initial delay',
75
+ description: 'Initial delay in milliseconds',
76
+ default: 2000,
77
+ }),
78
+ __metadata("design:type", Number)
79
+ ], TcpClientReconnectVariables.prototype, "initialDelay", void 0);
80
+ __decorate([
81
+ DefineVariable({
82
+ label: 'Maximum delay',
83
+ description: 'Maximum delay in milliseconds',
84
+ default: 10000,
85
+ }),
86
+ __metadata("design:type", Number)
87
+ ], TcpClientReconnectVariables.prototype, "maxDelay", void 0);
88
+ /**
89
+ * Variables
90
+ */
91
+ export class TcpClientVariables extends IoClientBaseComponent.Variables {
92
+ }
93
+ __decorate([
94
+ DefineVariable({
95
+ label: 'Host',
96
+ description: 'Hostname or IP address to be connected to',
97
+ required: true,
98
+ }),
99
+ __metadata("design:type", String)
100
+ ], TcpClientVariables.prototype, "host", void 0);
101
+ __decorate([
102
+ DefineVariable({
103
+ label: 'Port',
104
+ description: 'Port number of target listener',
105
+ required: true,
106
+ minValue: 1,
107
+ maxValue: 65535,
108
+ }),
109
+ __metadata("design:type", Number)
110
+ ], TcpClientVariables.prototype, "port", void 0);
111
+ __decorate([
112
+ DefineVariable({
113
+ label: 'Keep alive',
114
+ description: 'Enables keep-alive on the TCP socket',
115
+ default: false,
116
+ }),
117
+ __metadata("design:type", Boolean)
118
+ ], TcpClientVariables.prototype, "keepAlive", void 0);
119
+ __decorate([
120
+ DefineVariable({
121
+ label: 'Connect timeout',
122
+ description: 'Connection timeout in milliseconds',
123
+ default: 10000,
124
+ }),
125
+ __metadata("design:type", Number)
126
+ ], TcpClientVariables.prototype, "connectTimeout", void 0);
127
+ __decorate([
128
+ DefineVariable({
129
+ label: 'Reconnect',
130
+ description: 'Reconnect options',
131
+ }),
132
+ __metadata("design:type", TcpClientReconnectVariables)
133
+ ], TcpClientVariables.prototype, "reconnect", void 0);
134
+ __decorate([
135
+ DefineVariable({
136
+ label: 'TLS',
137
+ description: 'TLS options',
138
+ }),
139
+ __metadata("design:type", TcpClientTlsVariables)
140
+ ], TcpClientVariables.prototype, "tls", void 0);
@@ -0,0 +1,23 @@
1
+ import { IoClientBaseComponent } from '@syncbridge/builtins';
2
+ import { ComponentBase } from '@syncbridge/common';
3
+ import { TcpServerTlsVariables, TcpServerVariables } from './tcp-server.variables.js';
4
+ /**
5
+ * TcpServer component
6
+ * todo
7
+ */
8
+ export declare class TcpServerComponent<TEvents extends TcpServerComponent.Events = TcpServerComponent.Events> extends ComponentBase<TEvents> {
9
+ values: TcpServerVariables;
10
+ protected _start(abortSignal: AbortSignal): Promise<void>;
11
+ protected _stop(): Promise<void>;
12
+ }
13
+ /**
14
+ * @namespace
15
+ */
16
+ export declare namespace TcpServerComponent {
17
+ interface Events extends IoClientBaseComponent.Events {
18
+ }
19
+ const Variables: typeof TcpServerVariables;
20
+ type Variables = TcpServerVariables;
21
+ const TlsVariables: typeof TcpServerTlsVariables;
22
+ type TlsVariables = TcpServerTlsVariables;
23
+ }
@@ -0,0 +1,32 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import { Component, ComponentBase } from '@syncbridge/common';
3
+ import { TcpServerTlsVariables, TcpServerVariables, } from './tcp-server.variables.js';
4
+ /**
5
+ * TcpServer component
6
+ * todo
7
+ */
8
+ let TcpServerComponent = class TcpServerComponent extends ComponentBase {
9
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
10
+ async _start(abortSignal) { }
11
+ async _stop() { }
12
+ };
13
+ __decorate([
14
+ Component.UseVariables(),
15
+ __metadata("design:type", TcpServerVariables)
16
+ ], TcpServerComponent.prototype, "values", void 0);
17
+ TcpServerComponent = __decorate([
18
+ Component({
19
+ className: 'TcpServer',
20
+ displayName: 'TCP Server',
21
+ description: 'TCP server component',
22
+ tags: ['tcp', 'server', 'socket'],
23
+ })
24
+ ], TcpServerComponent);
25
+ export { TcpServerComponent };
26
+ /**
27
+ * @namespace
28
+ */
29
+ (function (TcpServerComponent) {
30
+ TcpServerComponent.Variables = TcpServerVariables;
31
+ TcpServerComponent.TlsVariables = TcpServerTlsVariables;
32
+ })(TcpServerComponent || (TcpServerComponent = {}));
@@ -0,0 +1,16 @@
1
+ import { TransmitLogger } from '@syncbridge/builtins';
2
+ import { TcpClientTlsVariables } from './tcp-client.variables.js';
3
+ /**
4
+ * TLS variables
5
+ */
6
+ export declare class TcpServerTlsVariables extends TcpClientTlsVariables {
7
+ requestCert: boolean;
8
+ }
9
+ /**
10
+ * Variables
11
+ */
12
+ export declare class TcpServerVariables {
13
+ port: number;
14
+ tls: TcpServerTlsVariables;
15
+ communicationLogs?: TransmitLogger.Variables;
16
+ }
@@ -0,0 +1,46 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import { TransmitLogger } from '@syncbridge/builtins';
3
+ import { DefineVariable } from '@syncbridge/common';
4
+ import { TcpClientTlsVariables } from './tcp-client.variables.js';
5
+ /**
6
+ * TLS variables
7
+ */
8
+ export class TcpServerTlsVariables extends TcpClientTlsVariables {
9
+ }
10
+ __decorate([
11
+ DefineVariable({
12
+ label: 'Request cert',
13
+ description: 'If true the server will request a certificate from clients that connect and attempt to verify that certificate',
14
+ default: false,
15
+ }),
16
+ __metadata("design:type", Boolean)
17
+ ], TcpServerTlsVariables.prototype, "requestCert", void 0);
18
+ /**
19
+ * Variables
20
+ */
21
+ export class TcpServerVariables {
22
+ }
23
+ __decorate([
24
+ DefineVariable({
25
+ label: 'Port',
26
+ description: 'Port number to be listen',
27
+ required: true,
28
+ minValue: 1,
29
+ maxValue: 65535,
30
+ }),
31
+ __metadata("design:type", Number)
32
+ ], TcpServerVariables.prototype, "port", void 0);
33
+ __decorate([
34
+ DefineVariable({
35
+ label: 'TLS',
36
+ description: 'TLS options',
37
+ }),
38
+ __metadata("design:type", TcpServerTlsVariables)
39
+ ], TcpServerVariables.prototype, "tls", void 0);
40
+ __decorate([
41
+ DefineVariable({
42
+ label: 'Communication Logs',
43
+ description: 'Stores communication logs if enabled',
44
+ }),
45
+ __metadata("design:type", TransmitLogger.Variables)
46
+ ], TcpServerVariables.prototype, "communicationLogs", void 0);
@@ -0,0 +1,29 @@
1
+ import { Buffer } from 'node:buffer';
2
+ import dgram from 'node:dgram';
3
+ import { IoClientBaseComponent } from '@syncbridge/builtins';
4
+ import { UdpClientVariables } from './udp-client.variables.js';
5
+ /**
6
+ * UdpClient component
7
+ */
8
+ export declare class UdpClientComponent<TEvents extends UdpClientComponent.Events = UdpClientComponent.Events> extends IoClientBaseComponent<TEvents> {
9
+ readonly protocol: string;
10
+ socket: dgram.Socket & {
11
+ readonly isBroadcastEnabled: boolean;
12
+ };
13
+ protected _stopping?: boolean;
14
+ values: UdpClientVariables;
15
+ protected _start(abortSignal: AbortSignal): Promise<void>;
16
+ protected _stop(): Promise<void>;
17
+ write(data: string | Buffer, port?: number, host?: string): void;
18
+ }
19
+ /**
20
+ * @namespace
21
+ */
22
+ export declare namespace UdpClientComponent {
23
+ interface Events extends IoClientBaseComponent.Events {
24
+ data: [data: Buffer, info: dgram.RemoteInfo];
25
+ write: [data: Buffer | string];
26
+ }
27
+ const Variables: typeof UdpClientVariables;
28
+ type Variables = UdpClientVariables;
29
+ }
@@ -0,0 +1,119 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import dgram from 'node:dgram';
3
+ import { IoClientBaseComponent } from '@syncbridge/builtins';
4
+ import { Component, ServiceStatus } from '@syncbridge/common';
5
+ import { UdpClientVariables } from './udp-client.variables.js';
6
+ /**
7
+ * UdpClient component
8
+ */
9
+ let UdpClientComponent = class UdpClientComponent extends IoClientBaseComponent {
10
+ protocol = 'udp';
11
+ _stopping;
12
+ async _start(abortSignal) {
13
+ await super._start(abortSignal);
14
+ this._stopping = false;
15
+ this.socket = dgram.createSocket('udp4');
16
+ let isBroadcastEnabled = false;
17
+ Object.defineProperty(this.socket, 'isBroadcastEnabled', {
18
+ get() {
19
+ return isBroadcastEnabled;
20
+ },
21
+ });
22
+ const oldSetBroadcast = this.socket.setBroadcast;
23
+ this.socket.setBroadcast = (value) => {
24
+ isBroadcastEnabled = value;
25
+ oldSetBroadcast.call(this.socket, value);
26
+ };
27
+ this.socket.on('connect', () => {
28
+ this.emit('connect');
29
+ this.setStatus(ServiceStatus.started);
30
+ });
31
+ this.socket.on('listening', () => {
32
+ const { bindInterface } = this.values;
33
+ const port = this.socket.address().port;
34
+ this.emit('listening', port);
35
+ this.logger?.info(`UDP socket listening on port ${port}` +
36
+ (bindInterface ? ` interface ${bindInterface}` : ''));
37
+ this.setStatus(ServiceStatus.started);
38
+ });
39
+ this.socket.on('message', (msg, info) => {
40
+ if (info.address === '127.0.0.1')
41
+ return;
42
+ // todo logger
43
+ // this.logger.debug(
44
+ // `Data received from ${colors.cyan(info.address + ':' + info.port)} (${msg.length} bytes)`,
45
+ // {
46
+ // host: info.address,
47
+ // port: info.port,
48
+ // size: msg.length,
49
+ // },
50
+ // );
51
+ const info2 = {
52
+ ...info,
53
+ toString() {
54
+ return `${this.address}:${this.port}`;
55
+ },
56
+ };
57
+ this.emit('data', msg, info2);
58
+ });
59
+ if (this.values.bindInterface) {
60
+ this.socket.bind(this.values.port || 0, this.values.bindInterface);
61
+ }
62
+ if (this.values.port) {
63
+ this.socket.connect(this.values.port, this.values.host);
64
+ }
65
+ else
66
+ this.setStatus(ServiceStatus.started);
67
+ }
68
+ async _stop() {
69
+ this._stopping = true;
70
+ await new Promise(resolve => {
71
+ this.socket.close(resolve);
72
+ this._stopping = false;
73
+ });
74
+ }
75
+ write(data, port, host) {
76
+ host = host || this.values.host;
77
+ port = port || this.values.port;
78
+ if (!host)
79
+ throw new Error('You must provide "host" variable to send message over UDP socket');
80
+ this.socket.send(data, port, host);
81
+ const info2 = {
82
+ address: host,
83
+ port: port,
84
+ size: data.length,
85
+ toString() {
86
+ return `${this.address}:${this.port}`;
87
+ },
88
+ };
89
+ this.emit('transmit', data, info2);
90
+ // todo logger
91
+ // if (this.socket.isBroadcastEnabled)
92
+ // this.logger.debug(
93
+ // `Broadcast message sent ${colors.cyan(host + ':' + port)} (${data.length} bytes)`,
94
+ // );
95
+ // else
96
+ // this.logger.debug(
97
+ // `Message sent to ${colors.cyan(host + ':' + port)} (${data.length} bytes)`,
98
+ // );
99
+ }
100
+ };
101
+ __decorate([
102
+ Component.UseVariables(),
103
+ __metadata("design:type", UdpClientVariables)
104
+ ], UdpClientComponent.prototype, "values", void 0);
105
+ UdpClientComponent = __decorate([
106
+ Component({
107
+ className: 'UdpClient',
108
+ displayName: 'UDP Client',
109
+ description: 'UDP client component',
110
+ tags: ['udp', 'client', 'socket', 'connection'],
111
+ })
112
+ ], UdpClientComponent);
113
+ export { UdpClientComponent };
114
+ /**
115
+ * @namespace
116
+ */
117
+ (function (UdpClientComponent) {
118
+ UdpClientComponent.Variables = UdpClientVariables;
119
+ })(UdpClientComponent || (UdpClientComponent = {}));
@@ -0,0 +1,10 @@
1
+ import { IoClientBaseComponent } from '@syncbridge/builtins';
2
+ /**
3
+ * Variables
4
+ */
5
+ export declare class UdpClientVariables extends IoClientBaseComponent.Variables {
6
+ port?: number;
7
+ host?: string;
8
+ bindInterface?: string;
9
+ }
10
+ export declare function getInterfaceAddresses(): string[];
@@ -0,0 +1,48 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import os from 'node:os';
3
+ import { IoClientBaseComponent } from '@syncbridge/builtins';
4
+ import { DefineVariable, VariableType } from '@syncbridge/common';
5
+ /**
6
+ * Variables
7
+ */
8
+ export class UdpClientVariables extends IoClientBaseComponent.Variables {
9
+ }
10
+ __decorate([
11
+ DefineVariable({
12
+ label: 'Port',
13
+ description: 'Port number of target listener',
14
+ minValue: 1,
15
+ maxValue: 65535,
16
+ }),
17
+ __metadata("design:type", Number)
18
+ ], UdpClientVariables.prototype, "port", void 0);
19
+ __decorate([
20
+ DefineVariable({
21
+ label: 'Host',
22
+ description: 'Hostname or IP address which udp messages will send to',
23
+ }),
24
+ __metadata("design:type", String)
25
+ ], UdpClientVariables.prototype, "host", void 0);
26
+ __decorate([
27
+ DefineVariable({
28
+ label: 'Bind Interface',
29
+ description: 'Interface address to bind to. If not specified, will bind to all available addresses',
30
+ type: VariableType.Enum,
31
+ enumValues: getInterfaceAddresses(),
32
+ }),
33
+ __metadata("design:type", String)
34
+ ], UdpClientVariables.prototype, "bindInterface", void 0);
35
+ export function getInterfaceAddresses() {
36
+ const interfaces = os.networkInterfaces();
37
+ const addresses = [];
38
+ for (const ifaces of Object.values(interfaces)) {
39
+ if (!ifaces)
40
+ continue;
41
+ for (const iface of ifaces) {
42
+ if (iface.family === 'IPv4' && !iface.internal) {
43
+ addresses.push(iface.address);
44
+ }
45
+ }
46
+ }
47
+ return addresses;
48
+ }
@@ -0,0 +1,29 @@
1
+ import { Buffer } from 'node:buffer';
2
+ import dgram from 'node:dgram';
3
+ import { IoClientBaseComponent } from '@syncbridge/builtins';
4
+ import { UdpListenerVariables } from './udp-listener.variables.js';
5
+ /**
6
+ * UdpClient component
7
+ */
8
+ export declare class UdpListenerComponent<TEvents extends UdpListenerComponent.Events = UdpListenerComponent.Events> extends IoClientBaseComponent<TEvents> {
9
+ readonly protocol: string;
10
+ socket: dgram.Socket & {
11
+ readonly isBroadcastEnabled: boolean;
12
+ };
13
+ protected _stopping?: boolean;
14
+ values: UdpListenerVariables;
15
+ protected _start(abortSignal: AbortSignal): Promise<void>;
16
+ protected _stop(): Promise<void>;
17
+ write(data: string | Buffer, port?: number, host?: string): void;
18
+ }
19
+ /**
20
+ * @namespace
21
+ */
22
+ export declare namespace UdpListenerComponent {
23
+ interface Events extends IoClientBaseComponent.Events {
24
+ data: [data: Buffer, info: dgram.RemoteInfo];
25
+ write: [data: Buffer | string];
26
+ }
27
+ const Variables: typeof UdpListenerVariables;
28
+ type Variables = UdpListenerVariables;
29
+ }
@@ -0,0 +1,116 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import dgram from 'node:dgram';
3
+ import { IoClientBaseComponent } from '@syncbridge/builtins';
4
+ import { Component, ServiceStatus } from '@syncbridge/common';
5
+ import { UdpListenerVariables } from './udp-listener.variables.js';
6
+ /**
7
+ * UdpClient component
8
+ */
9
+ let UdpListenerComponent = class UdpListenerComponent extends IoClientBaseComponent {
10
+ protocol = 'udp';
11
+ _stopping;
12
+ async _start(abortSignal) {
13
+ await super._start(abortSignal);
14
+ this._stopping = false;
15
+ this.socket = dgram.createSocket('udp4');
16
+ let isBroadcastEnabled = false;
17
+ Object.defineProperty(this.socket, 'isBroadcastEnabled', {
18
+ get() {
19
+ return isBroadcastEnabled;
20
+ },
21
+ });
22
+ const oldSetBroadcast = this.socket.setBroadcast;
23
+ this.socket.setBroadcast = (value) => {
24
+ isBroadcastEnabled = value;
25
+ oldSetBroadcast.call(this.socket, value);
26
+ };
27
+ this.socket.on('listening', () => {
28
+ const { bindInterface, multicastInterface } = this.values;
29
+ if (this.values.broadcast) {
30
+ this.logger?.debug(`Broadcast mode enabled`);
31
+ this.socket.setBroadcast(true);
32
+ }
33
+ if (this.values.multicastGroups)
34
+ this.values.multicastGroups.forEach(group => {
35
+ this.logger?.debug(`Joining multicast group ${group}`);
36
+ this.socket.addMembership(group, multicastInterface);
37
+ });
38
+ const port = this.socket.address().port;
39
+ this.emit('listening', port);
40
+ this.logger?.info(`UDP socket listening on port ${port}` +
41
+ (bindInterface ? ` interface ${bindInterface}` : ''));
42
+ this.setStatus(ServiceStatus.started);
43
+ });
44
+ this.socket.on('message', (msg, info) => {
45
+ if (info.address === '127.0.0.1')
46
+ return;
47
+ // todo logger
48
+ // this.logger.debug(
49
+ // `Data received from ${colors.cyan(info.address + ':' + info.port)} (${msg.length} bytes)`,
50
+ // {
51
+ // host: info.address,
52
+ // port: info.port,
53
+ // size: msg.length,
54
+ // },
55
+ // );
56
+ const info2 = {
57
+ ...info,
58
+ toString() {
59
+ return `${this.address}:${this.port}`;
60
+ },
61
+ };
62
+ this.emit('data', msg, info2);
63
+ });
64
+ this.socket.bind(this.values.port, this.values.bindInterface || '0.0.0.0');
65
+ }
66
+ async _stop() {
67
+ this._stopping = true;
68
+ await new Promise(resolve => {
69
+ this.socket.close(resolve);
70
+ this._stopping = false;
71
+ });
72
+ }
73
+ write(data, port, host) {
74
+ port = port || this.values.port;
75
+ if (!host)
76
+ throw new Error('You must provide "host" variable to send message over UDP socket');
77
+ this.socket.send(data, port, host);
78
+ const info2 = {
79
+ address: host,
80
+ port: port,
81
+ size: data.length,
82
+ toString() {
83
+ return `${this.address}:${this.port}`;
84
+ },
85
+ };
86
+ this.emit('transmit', data, info2);
87
+ // todo logger
88
+ // if (this.socket.isBroadcastEnabled)
89
+ // this.logger.debug(
90
+ // `Broadcast message sent ${colors.cyan(host + ':' + port)} (${data.length} bytes)`,
91
+ // );
92
+ // else
93
+ // this.logger.debug(
94
+ // `Message sent to ${colors.cyan(host + ':' + port)} (${data.length} bytes)`,
95
+ // );
96
+ }
97
+ };
98
+ __decorate([
99
+ Component.UseVariables(),
100
+ __metadata("design:type", UdpListenerVariables)
101
+ ], UdpListenerComponent.prototype, "values", void 0);
102
+ UdpListenerComponent = __decorate([
103
+ Component({
104
+ className: 'UdpListener',
105
+ displayName: 'UDP Listener',
106
+ description: 'UDP listener component',
107
+ tags: ['udp', 'server', 'connection'],
108
+ })
109
+ ], UdpListenerComponent);
110
+ export { UdpListenerComponent };
111
+ /**
112
+ * @namespace
113
+ */
114
+ (function (UdpListenerComponent) {
115
+ UdpListenerComponent.Variables = UdpListenerVariables;
116
+ })(UdpListenerComponent || (UdpListenerComponent = {}));
@@ -0,0 +1,11 @@
1
+ import { IoClientBaseComponent } from '@syncbridge/builtins';
2
+ /**
3
+ * Variables
4
+ */
5
+ export declare class UdpListenerVariables extends IoClientBaseComponent.Variables {
6
+ port: number;
7
+ broadcast?: boolean;
8
+ multicastGroups?: string[];
9
+ bindInterface?: string;
10
+ multicastInterface?: string;
11
+ }
@@ -0,0 +1,53 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import { IoClientBaseComponent } from '@syncbridge/builtins';
3
+ import { DefineVariable, VariableType } from '@syncbridge/common';
4
+ import { getInterfaceAddresses } from './udp-client.variables.js';
5
+ /**
6
+ * Variables
7
+ */
8
+ export class UdpListenerVariables extends IoClientBaseComponent.Variables {
9
+ }
10
+ __decorate([
11
+ DefineVariable({
12
+ label: 'Port',
13
+ description: 'Port number of target listener',
14
+ required: true,
15
+ minValue: 1,
16
+ maxValue: 65535,
17
+ }),
18
+ __metadata("design:type", Number)
19
+ ], UdpListenerVariables.prototype, "port", void 0);
20
+ __decorate([
21
+ DefineVariable({
22
+ label: 'Broadcast',
23
+ description: "Sets the SO_BROADCAST socket option. When set to true, UDP packets may be sent to a local interface's broadcast address.",
24
+ }),
25
+ __metadata("design:type", Boolean)
26
+ ], UdpListenerVariables.prototype, "broadcast", void 0);
27
+ __decorate([
28
+ DefineVariable({
29
+ label: 'Multicast Groups',
30
+ description: 'Multicast groups to be joined',
31
+ type: VariableType.String,
32
+ isArray: true,
33
+ }),
34
+ __metadata("design:type", Array)
35
+ ], UdpListenerVariables.prototype, "multicastGroups", void 0);
36
+ __decorate([
37
+ DefineVariable({
38
+ label: 'Bind Interface',
39
+ description: 'Interface address to bind to. If not specified, will bind to all available addresses',
40
+ type: VariableType.Enum,
41
+ enumValues: getInterfaceAddresses(),
42
+ }),
43
+ __metadata("design:type", String)
44
+ ], UdpListenerVariables.prototype, "bindInterface", void 0);
45
+ __decorate([
46
+ DefineVariable({
47
+ label: 'Multicast Interface',
48
+ description: 'Interface address to bind for multicast packages',
49
+ type: VariableType.Enum,
50
+ enumValues: getInterfaceAddresses(),
51
+ }),
52
+ __metadata("design:type", String)
53
+ ], UdpListenerVariables.prototype, "multicastInterface", void 0);
@@ -0,0 +1,4 @@
1
+ export * from './components/tcp-client.component.js';
2
+ export * from './components/tcp-server.component.js';
3
+ export * from './components/udp-client.component.js';
4
+ export * from './components/udp-listener.component.js';
package/components.js ADDED
@@ -0,0 +1,4 @@
1
+ export * from './components/tcp-client.component.js';
2
+ export * from './components/tcp-server.component.js';
3
+ export * from './components/udp-client.component.js';
4
+ export * from './components/udp-listener.component.js';
package/constants.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import { AuthorMetadata } from '@syncbridge/common';
2
+ export declare const version = "1";
3
+ export declare const noOp: () => undefined;
4
+ export declare const panatesAuthor: AuthorMetadata;
package/constants.js ADDED
@@ -0,0 +1,7 @@
1
+ export const version = '0.4.1';
2
+ export const noOp = () => undefined;
3
+ export const panatesAuthor = {
4
+ name: 'Panates Technology AS',
5
+ email: 'info@panates.com',
6
+ url: 'https://www.panates.com',
7
+ };
package/index.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ import * as components from './components.js';
2
+ export { components };
3
+ export * from './components.js';
4
+ declare const cfg: import("@syncbridge/common").IExtensionPackage;
5
+ export default cfg;
package/index.js ADDED
@@ -0,0 +1,9 @@
1
+ import { makeExtensionPackage } from '@syncbridge/common';
2
+ import * as components from './components.js';
3
+ export { components };
4
+ export * from './components.js';
5
+ const cfg = makeExtensionPackage({
6
+ processors: [],
7
+ components: Object.values(components),
8
+ });
9
+ export default cfg;
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@syncbridge/net",
3
+ "version": "0.4.1",
4
+ "description": "SyncBridge builtin net (socket) extensions",
5
+ "author": "Panates Inc",
6
+ "license": "UNLICENSED",
7
+ "dependencies": {
8
+ "@ngrok/ngrok": "^1.7.0",
9
+ "@pinggy/pinggy": "^0.3.2",
10
+ "@serialport/bindings-interface": "^1.2.2",
11
+ "@sqb/connect": "^4.19.6",
12
+ "@sqb/oracle": "^4.21.1",
13
+ "@sqb/postgres": "^4.21.1",
14
+ "ansi-colors": "^4.1.3",
15
+ "backoff": "^2.5.0",
16
+ "date-fns": "^4.1.0",
17
+ "fast-tokenizer": "^1.9.0",
18
+ "file-stream-rotator": "^1.0.0",
19
+ "hl7v2": "^1.7.0",
20
+ "hl7v2-net": "^1.7.0",
21
+ "kafkajs": "^2.2.4",
22
+ "lightning-pool": "^4.12.0",
23
+ "node-events-async": "^1.5.0",
24
+ "oracledb": "^6.10.0",
25
+ "putil-varhelpers": "^1.7.0",
26
+ "reconnect-core": "^1.3.0",
27
+ "serialport": "^13.0.0"
28
+ },
29
+ "peerDependencies": {
30
+ "@syncbridge/common": "^0.4.1",
31
+ "@syncbridge/builtins": "^0.4.1",
32
+ "@sqb/builder": ">=4.19.6 <5",
33
+ "@sqb/connect": ">=4.19.6 <5"
34
+ },
35
+ "exports": {
36
+ ".": {
37
+ "types": "./index.d.ts",
38
+ "default": "./index.js"
39
+ },
40
+ "./package.json": "./package.json"
41
+ },
42
+ "type": "module",
43
+ "module": "./index.js",
44
+ "types": "./index.d.ts",
45
+ "engines": {
46
+ "node": ">=20.0"
47
+ },
48
+ "publishConfig": {
49
+ "access": "public"
50
+ }
51
+ }