@machhub-dev/sdk-ts 1.0.4 → 1.0.6
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/cjs/sdk-ts.d.ts +0 -4
- package/dist/cjs/sdk-ts.js +7 -47
- package/dist/sdk-ts.d.ts +0 -4
- package/dist/sdk-ts.js +7 -47
- package/package.json +1 -3
- package/src/sdk-ts.ts +13 -62
- package/src/classes/function.ts +0 -34
- package/src/example/functions.ts +0 -21
- package/src/services/nats.service.ts +0 -293
package/dist/cjs/sdk-ts.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Collection } from "./classes/collection.js";
|
|
2
2
|
import { Historian } from "./classes/historian.js";
|
|
3
3
|
import { Tag } from "./classes/tag.js";
|
|
4
|
-
import { Function } from "./classes/function.js";
|
|
5
4
|
import { Flow } from "./classes/flow.js";
|
|
6
5
|
import { Auth } from "./classes/auth.js";
|
|
7
6
|
export interface SDKConfig {
|
|
@@ -9,12 +8,10 @@ export interface SDKConfig {
|
|
|
9
8
|
developer_key?: string;
|
|
10
9
|
httpUrl?: string;
|
|
11
10
|
mqttUrl?: string;
|
|
12
|
-
natsUrl?: string;
|
|
13
11
|
}
|
|
14
12
|
export declare class SDK {
|
|
15
13
|
private http;
|
|
16
14
|
private mqtt;
|
|
17
|
-
private nats;
|
|
18
15
|
private _historian;
|
|
19
16
|
private _tag;
|
|
20
17
|
private _function;
|
|
@@ -39,7 +36,6 @@ export declare class SDK {
|
|
|
39
36
|
* application_id: 'your-app-id',
|
|
40
37
|
* httpUrl: 'http://localhost:6188', // optional (default = http://localhost:6188)
|
|
41
38
|
* mqttUrl: 'ws://localhost:180', // optional (default = ws://localhost:180)
|
|
42
|
-
* natsUrl: 'ws://localhost:7500', // optional (default = ws://localhost:7500)
|
|
43
39
|
* };
|
|
44
40
|
*
|
|
45
41
|
* const sdk = new SDK();
|
package/dist/cjs/sdk-ts.js
CHANGED
|
@@ -3,11 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.SDK = void 0;
|
|
4
4
|
const http_service_js_1 = require("./services/http.service.js");
|
|
5
5
|
const mqtt_service_js_1 = require("./services/mqtt.service.js");
|
|
6
|
-
const nats_service_js_1 = require("./services/nats.service.js");
|
|
7
6
|
const collection_js_1 = require("./classes/collection.js");
|
|
8
7
|
const historian_js_1 = require("./classes/historian.js");
|
|
9
8
|
const tag_js_1 = require("./classes/tag.js");
|
|
10
|
-
const function_js_1 = require("./classes/function.js");
|
|
11
9
|
const flow_js_1 = require("./classes/flow.js");
|
|
12
10
|
const auth_js_1 = require("./classes/auth.js");
|
|
13
11
|
const MACHHUB_SDK_PATH = "machhub";
|
|
@@ -68,46 +66,11 @@ class MQTTClient {
|
|
|
68
66
|
return this.mqttService.publish(topic, data);
|
|
69
67
|
}
|
|
70
68
|
}
|
|
71
|
-
// Core NATS client class
|
|
72
|
-
class NATSClient {
|
|
73
|
-
constructor(natsService) {
|
|
74
|
-
this.natsService = natsService;
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Creates a new NATSClient instance
|
|
78
|
-
* @param applicationID The ID for your application
|
|
79
|
-
* @param natsUrl The base URL for NATS connection (default = ws://localhost:7500)
|
|
80
|
-
*/
|
|
81
|
-
static async getInstance(applicationID, natsUrl = "ws://localhost:7500") {
|
|
82
|
-
if (!this.instance) {
|
|
83
|
-
const natsService = await nats_service_js_1.NATSService.getInstance(natsUrl);
|
|
84
|
-
this.instance = new NATSClient(natsService);
|
|
85
|
-
}
|
|
86
|
-
return this.instance;
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Subscribes to subject updates
|
|
90
|
-
* @param subject The subject to subscribe to
|
|
91
|
-
* @param callback The callback function for data updates
|
|
92
|
-
*/
|
|
93
|
-
async subscribe(subject, callback) {
|
|
94
|
-
return this.natsService.addSubjectHandler(subject, callback);
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Publishes a message to a specific subject
|
|
98
|
-
* @param subject The subject to publish to
|
|
99
|
-
* @param data The data to publish
|
|
100
|
-
*/
|
|
101
|
-
async publish(subject, data) {
|
|
102
|
-
return this.natsService.publish(subject, data);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
69
|
// SDK Class
|
|
106
70
|
class SDK {
|
|
107
71
|
constructor() {
|
|
108
72
|
this.http = null;
|
|
109
73
|
this.mqtt = null;
|
|
110
|
-
this.nats = null;
|
|
111
74
|
this._historian = null;
|
|
112
75
|
this._tag = null;
|
|
113
76
|
this._function = null;
|
|
@@ -138,7 +101,6 @@ class SDK {
|
|
|
138
101
|
* application_id: 'your-app-id',
|
|
139
102
|
* httpUrl: 'http://localhost:6188', // optional (default = http://localhost:6188)
|
|
140
103
|
* mqttUrl: 'ws://localhost:180', // optional (default = ws://localhost:180)
|
|
141
|
-
* natsUrl: 'ws://localhost:7500', // optional (default = ws://localhost:7500)
|
|
142
104
|
* };
|
|
143
105
|
*
|
|
144
106
|
* const sdk = new SDK();
|
|
@@ -164,12 +126,15 @@ class SDK {
|
|
|
164
126
|
const application_id = config.application_id ||
|
|
165
127
|
this.extractApplicationIDFromRuntimeID(envCfg.runtimeID);
|
|
166
128
|
this.applicationID = application_id;
|
|
167
|
-
// Determine the hostname - use window.location
|
|
129
|
+
// Determine the hostname - use window.location in browser, otherwise fallback to localhost
|
|
168
130
|
const hostname = typeof window !== 'undefined' ? window.location.hostname : 'localhost';
|
|
169
131
|
const secured = typeof window !== 'undefined' ? window.location.protocol === 'https:' : false;
|
|
170
132
|
let host = hostname;
|
|
171
133
|
if (envCfg.hostingMode === 'port' || !envCfg.hostingMode) {
|
|
172
|
-
host
|
|
134
|
+
// In browser, use window.location.host which includes the port only when non-standard
|
|
135
|
+
// (e.g. "localhost:6190" for local dev, "machhub.dev" when behind a reverse proxy on 443)
|
|
136
|
+
// In non-browser environments, fall back to hostname:envCfg.port
|
|
137
|
+
host = typeof window !== 'undefined' ? window.location.host : `${hostname}:${envCfg.port}`;
|
|
173
138
|
}
|
|
174
139
|
else if (envCfg.hostingMode === 'path') {
|
|
175
140
|
host += envCfg.pathHosted;
|
|
@@ -180,17 +145,12 @@ class SDK {
|
|
|
180
145
|
if (!config.mqttUrl) {
|
|
181
146
|
config.mqttUrl = `${secured ? 'wss' : 'ws'}://${host}/mqtt`;
|
|
182
147
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
}
|
|
186
|
-
const { httpUrl, mqttUrl, natsUrl } = config;
|
|
187
|
-
console.log("SDK Config:", { application_id: this.applicationID, httpUrl, mqttUrl, natsUrl, developer_key: config.developer_key?.split('').map((_, i) => i < config.developer_key.length - 4 ? '*' : config.developer_key[i]).join('') });
|
|
148
|
+
const { httpUrl, mqttUrl } = config;
|
|
149
|
+
console.log("SDK Config:", { application_id: this.applicationID, httpUrl, mqttUrl, developer_key: config.developer_key?.split('').map((_, i) => i < config.developer_key.length - 4 ? '*' : config.developer_key[i]).join('') });
|
|
188
150
|
this.http = new HTTPClient(this.applicationID, httpUrl, config.developer_key, envCfg.runtimeID);
|
|
189
151
|
this.mqtt = await MQTTClient.getInstance(this.applicationID, mqttUrl, config.developer_key);
|
|
190
|
-
this.nats = await NATSClient.getInstance(this.applicationID, natsUrl);
|
|
191
152
|
this._historian = new historian_js_1.Historian(this.http["httpService"], this.mqtt["mqttService"]);
|
|
192
153
|
this._tag = new tag_js_1.Tag(this.http["httpService"], this.mqtt["mqttService"]);
|
|
193
|
-
this._function = new function_js_1.Function(this.http["httpService"], this.nats["natsService"]);
|
|
194
154
|
this._flow = new flow_js_1.Flow(this.http["httpService"]);
|
|
195
155
|
this._auth = new auth_js_1.Auth(this.http["httpService"], this.applicationID);
|
|
196
156
|
}
|
package/dist/sdk-ts.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Collection } from "./classes/collection.js";
|
|
2
2
|
import { Historian } from "./classes/historian.js";
|
|
3
3
|
import { Tag } from "./classes/tag.js";
|
|
4
|
-
import { Function } from "./classes/function.js";
|
|
5
4
|
import { Flow } from "./classes/flow.js";
|
|
6
5
|
import { Auth } from "./classes/auth.js";
|
|
7
6
|
export interface SDKConfig {
|
|
@@ -9,12 +8,10 @@ export interface SDKConfig {
|
|
|
9
8
|
developer_key?: string;
|
|
10
9
|
httpUrl?: string;
|
|
11
10
|
mqttUrl?: string;
|
|
12
|
-
natsUrl?: string;
|
|
13
11
|
}
|
|
14
12
|
export declare class SDK {
|
|
15
13
|
private http;
|
|
16
14
|
private mqtt;
|
|
17
|
-
private nats;
|
|
18
15
|
private _historian;
|
|
19
16
|
private _tag;
|
|
20
17
|
private _function;
|
|
@@ -39,7 +36,6 @@ export declare class SDK {
|
|
|
39
36
|
* application_id: 'your-app-id',
|
|
40
37
|
* httpUrl: 'http://localhost:6188', // optional (default = http://localhost:6188)
|
|
41
38
|
* mqttUrl: 'ws://localhost:180', // optional (default = ws://localhost:180)
|
|
42
|
-
* natsUrl: 'ws://localhost:7500', // optional (default = ws://localhost:7500)
|
|
43
39
|
* };
|
|
44
40
|
*
|
|
45
41
|
* const sdk = new SDK();
|
package/dist/sdk-ts.js
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { HTTPService } from "./services/http.service.js";
|
|
2
2
|
import { MQTTService } from "./services/mqtt.service.js";
|
|
3
|
-
import { NATSService } from "./services/nats.service.js";
|
|
4
3
|
import { Collection } from "./classes/collection.js";
|
|
5
4
|
import { Historian } from "./classes/historian.js";
|
|
6
5
|
import { Tag } from "./classes/tag.js";
|
|
7
|
-
import { Function } from "./classes/function.js";
|
|
8
6
|
import { Flow } from "./classes/flow.js";
|
|
9
7
|
import { Auth } from "./classes/auth.js";
|
|
10
8
|
const MACHHUB_SDK_PATH = "machhub";
|
|
@@ -65,46 +63,11 @@ class MQTTClient {
|
|
|
65
63
|
return this.mqttService.publish(topic, data);
|
|
66
64
|
}
|
|
67
65
|
}
|
|
68
|
-
// Core NATS client class
|
|
69
|
-
class NATSClient {
|
|
70
|
-
constructor(natsService) {
|
|
71
|
-
this.natsService = natsService;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Creates a new NATSClient instance
|
|
75
|
-
* @param applicationID The ID for your application
|
|
76
|
-
* @param natsUrl The base URL for NATS connection (default = ws://localhost:7500)
|
|
77
|
-
*/
|
|
78
|
-
static async getInstance(applicationID, natsUrl = "ws://localhost:7500") {
|
|
79
|
-
if (!this.instance) {
|
|
80
|
-
const natsService = await NATSService.getInstance(natsUrl);
|
|
81
|
-
this.instance = new NATSClient(natsService);
|
|
82
|
-
}
|
|
83
|
-
return this.instance;
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Subscribes to subject updates
|
|
87
|
-
* @param subject The subject to subscribe to
|
|
88
|
-
* @param callback The callback function for data updates
|
|
89
|
-
*/
|
|
90
|
-
async subscribe(subject, callback) {
|
|
91
|
-
return this.natsService.addSubjectHandler(subject, callback);
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Publishes a message to a specific subject
|
|
95
|
-
* @param subject The subject to publish to
|
|
96
|
-
* @param data The data to publish
|
|
97
|
-
*/
|
|
98
|
-
async publish(subject, data) {
|
|
99
|
-
return this.natsService.publish(subject, data);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
66
|
// SDK Class
|
|
103
67
|
export class SDK {
|
|
104
68
|
constructor() {
|
|
105
69
|
this.http = null;
|
|
106
70
|
this.mqtt = null;
|
|
107
|
-
this.nats = null;
|
|
108
71
|
this._historian = null;
|
|
109
72
|
this._tag = null;
|
|
110
73
|
this._function = null;
|
|
@@ -135,7 +98,6 @@ export class SDK {
|
|
|
135
98
|
* application_id: 'your-app-id',
|
|
136
99
|
* httpUrl: 'http://localhost:6188', // optional (default = http://localhost:6188)
|
|
137
100
|
* mqttUrl: 'ws://localhost:180', // optional (default = ws://localhost:180)
|
|
138
|
-
* natsUrl: 'ws://localhost:7500', // optional (default = ws://localhost:7500)
|
|
139
101
|
* };
|
|
140
102
|
*
|
|
141
103
|
* const sdk = new SDK();
|
|
@@ -161,12 +123,15 @@ export class SDK {
|
|
|
161
123
|
const application_id = config.application_id ||
|
|
162
124
|
this.extractApplicationIDFromRuntimeID(envCfg.runtimeID);
|
|
163
125
|
this.applicationID = application_id;
|
|
164
|
-
// Determine the hostname - use window.location
|
|
126
|
+
// Determine the hostname - use window.location in browser, otherwise fallback to localhost
|
|
165
127
|
const hostname = typeof window !== 'undefined' ? window.location.hostname : 'localhost';
|
|
166
128
|
const secured = typeof window !== 'undefined' ? window.location.protocol === 'https:' : false;
|
|
167
129
|
let host = hostname;
|
|
168
130
|
if (envCfg.hostingMode === 'port' || !envCfg.hostingMode) {
|
|
169
|
-
host
|
|
131
|
+
// In browser, use window.location.host which includes the port only when non-standard
|
|
132
|
+
// (e.g. "localhost:6190" for local dev, "machhub.dev" when behind a reverse proxy on 443)
|
|
133
|
+
// In non-browser environments, fall back to hostname:envCfg.port
|
|
134
|
+
host = typeof window !== 'undefined' ? window.location.host : `${hostname}:${envCfg.port}`;
|
|
170
135
|
}
|
|
171
136
|
else if (envCfg.hostingMode === 'path') {
|
|
172
137
|
host += envCfg.pathHosted;
|
|
@@ -177,17 +142,12 @@ export class SDK {
|
|
|
177
142
|
if (!config.mqttUrl) {
|
|
178
143
|
config.mqttUrl = `${secured ? 'wss' : 'ws'}://${host}/mqtt`;
|
|
179
144
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}
|
|
183
|
-
const { httpUrl, mqttUrl, natsUrl } = config;
|
|
184
|
-
console.log("SDK Config:", { application_id: this.applicationID, httpUrl, mqttUrl, natsUrl, developer_key: config.developer_key?.split('').map((_, i) => i < config.developer_key.length - 4 ? '*' : config.developer_key[i]).join('') });
|
|
145
|
+
const { httpUrl, mqttUrl } = config;
|
|
146
|
+
console.log("SDK Config:", { application_id: this.applicationID, httpUrl, mqttUrl, developer_key: config.developer_key?.split('').map((_, i) => i < config.developer_key.length - 4 ? '*' : config.developer_key[i]).join('') });
|
|
185
147
|
this.http = new HTTPClient(this.applicationID, httpUrl, config.developer_key, envCfg.runtimeID);
|
|
186
148
|
this.mqtt = await MQTTClient.getInstance(this.applicationID, mqttUrl, config.developer_key);
|
|
187
|
-
this.nats = await NATSClient.getInstance(this.applicationID, natsUrl);
|
|
188
149
|
this._historian = new Historian(this.http["httpService"], this.mqtt["mqttService"]);
|
|
189
150
|
this._tag = new Tag(this.http["httpService"], this.mqtt["mqttService"]);
|
|
190
|
-
this._function = new Function(this.http["httpService"], this.nats["natsService"]);
|
|
191
151
|
this._flow = new Flow(this.http["httpService"]);
|
|
192
152
|
this._auth = new Auth(this.http["httpService"], this.applicationID);
|
|
193
153
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@machhub-dev/sdk-ts",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "MACHHUB TYPESCRIPT SDK",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"machhub",
|
|
@@ -20,8 +20,6 @@
|
|
|
20
20
|
"build": "npx tsc && npx tsc --module CommonJS --outDir dist/cjs"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@nats-io/nats-core": "^3.0.2",
|
|
24
|
-
"@nats-io/transport-node": "^3.0.2",
|
|
25
23
|
"jwt-decode": "^4.0.0",
|
|
26
24
|
"mqtt": "^5.10.4",
|
|
27
25
|
"safe-buffer": "^5.2.1",
|
package/src/sdk-ts.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { HTTPService } from "./services/http.service.js";
|
|
2
2
|
import { MQTTService } from "./services/mqtt.service.js";
|
|
3
|
-
import { NATSService } from "./services/nats.service.js";
|
|
4
3
|
import { Collection } from "./classes/collection.js";
|
|
5
4
|
import { Historian } from "./classes/historian.js";
|
|
6
5
|
import { Tag } from "./classes/tag.js";
|
|
7
|
-
import { Function } from "./classes/function.js";
|
|
8
6
|
import { Flow } from "./classes/flow.js";
|
|
9
7
|
import { Auth } from "./classes/auth.js";
|
|
10
8
|
|
|
@@ -78,60 +76,17 @@ class MQTTClient {
|
|
|
78
76
|
}
|
|
79
77
|
}
|
|
80
78
|
|
|
81
|
-
// Core NATS client class
|
|
82
|
-
class NATSClient {
|
|
83
|
-
private natsService: NATSService;
|
|
84
|
-
private static instance: NATSClient | undefined;
|
|
85
|
-
|
|
86
|
-
private constructor(natsService: NATSService) {
|
|
87
|
-
this.natsService = natsService;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Creates a new NATSClient instance
|
|
92
|
-
* @param applicationID The ID for your application
|
|
93
|
-
* @param natsUrl The base URL for NATS connection (default = ws://localhost:7500)
|
|
94
|
-
*/
|
|
95
|
-
static async getInstance(applicationID?: string, natsUrl: string = "ws://localhost:7500"): Promise<NATSClient> {
|
|
96
|
-
if (!this.instance) {
|
|
97
|
-
const natsService = await NATSService.getInstance(natsUrl);
|
|
98
|
-
this.instance = new NATSClient(natsService);
|
|
99
|
-
}
|
|
100
|
-
return this.instance;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Subscribes to subject updates
|
|
105
|
-
* @param subject The subject to subscribe to
|
|
106
|
-
* @param callback The callback function for data updates
|
|
107
|
-
*/
|
|
108
|
-
async subscribe(subject: string, callback: (data: any) => void): Promise<any> {
|
|
109
|
-
return this.natsService.addSubjectHandler(subject, callback);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Publishes a message to a specific subject
|
|
114
|
-
* @param subject The subject to publish to
|
|
115
|
-
* @param data The data to publish
|
|
116
|
-
*/
|
|
117
|
-
async publish(subject: string, data: any): Promise<any> {
|
|
118
|
-
return this.natsService.publish(subject, data);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
79
|
export interface SDKConfig {
|
|
123
80
|
application_id: string;
|
|
124
81
|
developer_key?: string;
|
|
125
82
|
httpUrl?: string;
|
|
126
83
|
mqttUrl?: string;
|
|
127
|
-
natsUrl?: string;
|
|
128
84
|
}
|
|
129
85
|
|
|
130
86
|
// SDK Class
|
|
131
87
|
export class SDK {
|
|
132
88
|
private http: HTTPClient | null = null;
|
|
133
89
|
private mqtt: MQTTClient | null = null;
|
|
134
|
-
private nats: NATSClient | null = null;
|
|
135
90
|
private _historian: Historian | null = null;
|
|
136
91
|
private _tag: Tag | null = null;
|
|
137
92
|
private _function: Function | null = null;
|
|
@@ -162,7 +117,6 @@ export class SDK {
|
|
|
162
117
|
* application_id: 'your-app-id',
|
|
163
118
|
* httpUrl: 'http://localhost:6188', // optional (default = http://localhost:6188)
|
|
164
119
|
* mqttUrl: 'ws://localhost:180', // optional (default = ws://localhost:180)
|
|
165
|
-
* natsUrl: 'ws://localhost:7500', // optional (default = ws://localhost:7500)
|
|
166
120
|
* };
|
|
167
121
|
*
|
|
168
122
|
* const sdk = new SDK();
|
|
@@ -186,20 +140,23 @@ export class SDK {
|
|
|
186
140
|
const envCfg = await getEnvConfig();
|
|
187
141
|
|
|
188
142
|
// Extract application_id from runtimeID if not provided in config
|
|
189
|
-
const application_id = config.application_id ||
|
|
190
|
-
|
|
191
|
-
|
|
143
|
+
const application_id = config.application_id ||
|
|
144
|
+
this.extractApplicationIDFromRuntimeID(envCfg.runtimeID);
|
|
145
|
+
|
|
192
146
|
this.applicationID = application_id;
|
|
193
147
|
|
|
194
|
-
// Determine the hostname - use window.location
|
|
148
|
+
// Determine the hostname - use window.location in browser, otherwise fallback to localhost
|
|
195
149
|
const hostname = typeof window !== 'undefined' ? window.location.hostname : 'localhost';
|
|
196
150
|
const secured = typeof window !== 'undefined' ? window.location.protocol === 'https:' : false;
|
|
197
151
|
|
|
198
|
-
let host = hostname
|
|
152
|
+
let host = hostname;
|
|
199
153
|
if (envCfg.hostingMode === 'port' || !envCfg.hostingMode) {
|
|
200
|
-
host
|
|
154
|
+
// In browser, use window.location.host which includes the port only when non-standard
|
|
155
|
+
// (e.g. "localhost:6190" for local dev, "machhub.dev" when behind a reverse proxy on 443)
|
|
156
|
+
// In non-browser environments, fall back to hostname:envCfg.port
|
|
157
|
+
host = typeof window !== 'undefined' ? window.location.host : `${hostname}:${envCfg.port}`;
|
|
201
158
|
} else if (envCfg.hostingMode === 'path') {
|
|
202
|
-
host += envCfg.pathHosted
|
|
159
|
+
host += envCfg.pathHosted;
|
|
203
160
|
}
|
|
204
161
|
|
|
205
162
|
if (!config.httpUrl) {
|
|
@@ -210,21 +167,15 @@ export class SDK {
|
|
|
210
167
|
config.mqttUrl = `${secured ? 'wss' : 'ws'}://${host}/mqtt`;
|
|
211
168
|
}
|
|
212
169
|
|
|
213
|
-
|
|
214
|
-
config.natsUrl = `${secured ? 'wss' : 'ws'}://${host}/nats`;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
const { httpUrl, mqttUrl, natsUrl } = config;
|
|
170
|
+
const { httpUrl, mqttUrl } = config;
|
|
218
171
|
|
|
219
|
-
console.log("SDK Config:", { application_id: this.applicationID, httpUrl, mqttUrl,
|
|
172
|
+
console.log("SDK Config:", { application_id: this.applicationID, httpUrl, mqttUrl, developer_key: config.developer_key?.split('').map((_, i) => i < config!.developer_key!.length - 4 ? '*' : config!.developer_key![i]).join('') });
|
|
220
173
|
|
|
221
174
|
this.http = new HTTPClient(this.applicationID, httpUrl, config.developer_key, envCfg.runtimeID);
|
|
222
175
|
this.mqtt = await MQTTClient.getInstance(this.applicationID, mqttUrl, config.developer_key);
|
|
223
|
-
this.nats = await NATSClient.getInstance(this.applicationID, natsUrl);
|
|
224
176
|
|
|
225
177
|
this._historian = new Historian(this.http["httpService"], this.mqtt["mqttService"]);
|
|
226
178
|
this._tag = new Tag(this.http["httpService"], this.mqtt["mqttService"]);
|
|
227
|
-
this._function = new Function(this.http["httpService"], this.nats["natsService"]);
|
|
228
179
|
this._flow = new Flow(this.http["httpService"]);
|
|
229
180
|
this._auth = new Auth(this.http["httpService"], this.applicationID);
|
|
230
181
|
} catch (error: any) {
|
|
@@ -355,7 +306,7 @@ async function findConfigEndpoint(): Promise<string> {
|
|
|
355
306
|
'Accept': 'application/json',
|
|
356
307
|
},
|
|
357
308
|
signal: AbortSignal.timeout(2000)
|
|
358
|
-
}).catch(() => {console.log("ERR"); return null}); // Catch fetch errors silently
|
|
309
|
+
}).catch(() => { console.log("ERR"); return null }); // Catch fetch errors silently
|
|
359
310
|
|
|
360
311
|
if (!testResponse || !testResponse.ok) {
|
|
361
312
|
continue; // Skip to next candidate
|
package/src/classes/function.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { HTTPService } from "../services/http.service.js";
|
|
2
|
-
import { NATSService } from "../services/nats.service.js";
|
|
3
|
-
|
|
4
|
-
export class Function {
|
|
5
|
-
private httpService: HTTPService;
|
|
6
|
-
private natsService: NATSService | null;
|
|
7
|
-
|
|
8
|
-
constructor(httpService: HTTPService, natsService: NATSService) {
|
|
9
|
-
this.httpService = httpService;
|
|
10
|
-
this.natsService = natsService;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
public async executeFunction(function_type: string, function_name: string, payload: any): Promise<any> {
|
|
14
|
-
return await this.httpService.request.withJSON({
|
|
15
|
-
function_type: function_type,
|
|
16
|
-
function_name: function_name,
|
|
17
|
-
payload: payload,
|
|
18
|
-
}).post("function/execute");
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
public async addFunction(name: string, func: (data: Record<string,any>) => Record<string,any>): Promise<any> {
|
|
22
|
-
if (!this.natsService) {
|
|
23
|
-
throw new Error("NATS service not connected");
|
|
24
|
-
}
|
|
25
|
-
return this.natsService.addFunction(name, func);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
public async initializeFunctions(): Promise<any> {
|
|
29
|
-
if (!this.natsService) {
|
|
30
|
-
throw new Error("NATS service not connected");
|
|
31
|
-
}
|
|
32
|
-
return this.natsService.initializeFunctions();
|
|
33
|
-
}
|
|
34
|
-
}
|
package/src/example/functions.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { SDK, SDKConfig } from "../index.js";
|
|
2
|
-
|
|
3
|
-
let sdk = new SDK();
|
|
4
|
-
let config: SDKConfig = {
|
|
5
|
-
application_id: "machhub_admin",
|
|
6
|
-
natsUrl: "nats://localhost:4222",
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
(async () => {
|
|
10
|
-
await sdk.Initialize(config);
|
|
11
|
-
|
|
12
|
-
function add10(data: Record<string,any>): Record<string,any>{
|
|
13
|
-
data.result = data.a + 10;
|
|
14
|
-
console.log("Function add executed with data:", data);
|
|
15
|
-
return data
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
sdk.function.addFunction("add", add10);
|
|
19
|
-
|
|
20
|
-
await sdk.function.initializeFunctions();
|
|
21
|
-
})();
|
|
@@ -1,293 +0,0 @@
|
|
|
1
|
-
import { NatsConnection, Subscription, wsconnect } from "@nats-io/nats-core";
|
|
2
|
-
import { connect } from "@nats-io/transport-node";
|
|
3
|
-
|
|
4
|
-
const HEALTH_SUBJECT = "runtime.typescript.health";
|
|
5
|
-
|
|
6
|
-
interface SubscribedSubject {
|
|
7
|
-
subject: string;
|
|
8
|
-
handler: (message: unknown) => void;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export class NATSService {
|
|
12
|
-
private url!: string;
|
|
13
|
-
private functions: Record<string, (data: Record<string, any>) => Promise<Record<string, any>> | Record<string, any>> = {};
|
|
14
|
-
private connection: NatsConnection | null = null;
|
|
15
|
-
private static instance: NATSService | undefined;
|
|
16
|
-
private subscribedSubjects: SubscribedSubject[] = [];
|
|
17
|
-
private subscriptions: Subscription[] = [];
|
|
18
|
-
private readonly EXEC_FUNCTION_SUBJECT = "runtime.exec.typescript.*";
|
|
19
|
-
|
|
20
|
-
constructor(url: string) {
|
|
21
|
-
this.url = url;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Returns a singleton instance of NATSService.
|
|
26
|
-
*/
|
|
27
|
-
static async getInstance(url: string = "ws://localhost:7500"): Promise<NATSService> {
|
|
28
|
-
if (!this.instance || !this.instance.connection) {
|
|
29
|
-
this.instance = new NATSService(url);
|
|
30
|
-
await this.instance.connect();
|
|
31
|
-
}
|
|
32
|
-
return this.instance;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Resets the singleton instance.
|
|
37
|
-
*/
|
|
38
|
-
public static resetInstance(): void {
|
|
39
|
-
if (this.instance) {
|
|
40
|
-
this.instance.connection?.close();
|
|
41
|
-
this.instance = undefined;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Connects to the NATS broker.
|
|
47
|
-
*/
|
|
48
|
-
private async connect(): Promise<void> {
|
|
49
|
-
let retries = 0;
|
|
50
|
-
const maxRetries = 10;
|
|
51
|
-
|
|
52
|
-
while (!this.connection && retries < maxRetries) {
|
|
53
|
-
try {
|
|
54
|
-
// NATSService.log(`Connecting to NATS server (${this.url})...`);
|
|
55
|
-
if (this.url.startsWith("nats")) {
|
|
56
|
-
this.connection = await connect({ servers: this.url });
|
|
57
|
-
} else if (this.url.startsWith("ws")) {
|
|
58
|
-
this.connection = await wsconnect({ servers: this.url });
|
|
59
|
-
} else {
|
|
60
|
-
NATSService.log("ERROR - Unsupported protocol : ", this.url.split("://")[0]);
|
|
61
|
-
}
|
|
62
|
-
this.connection?.publish(HEALTH_SUBJECT, JSON.stringify(true));
|
|
63
|
-
// NATSService.log(`Published message: true to ${HEALTH_SUBJECT}`);
|
|
64
|
-
// NATSService.log("Connected to NATS server");
|
|
65
|
-
} catch (err: any) {
|
|
66
|
-
NATSService.log("Caught an error during connection attempt:", err); // Debugging log
|
|
67
|
-
retries++;
|
|
68
|
-
console.error(`Failed to connect to NATS server. Retrying (${retries}/${maxRetries})...`, err);
|
|
69
|
-
if (retries >= maxRetries) {
|
|
70
|
-
throw new Error("Max retries reached. Unable to connect to NATS server.");
|
|
71
|
-
}
|
|
72
|
-
await new Promise((resolve) => setTimeout(resolve, 5000));
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (!this.connection) {
|
|
77
|
-
throw new Error("Failed to establish a connection to the NATS server.");
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Adds a subject and handler to the subscribed list.
|
|
83
|
-
* @param subject {string} The subject to subscribe to.
|
|
84
|
-
* @param handler {(message: unknown) => void} The handler function for incoming messages.
|
|
85
|
-
*/
|
|
86
|
-
public addSubjectHandler(subject: string, handler: (message: unknown) => void): void {
|
|
87
|
-
try {
|
|
88
|
-
this.subscribedSubjects.push({ subject, handler });
|
|
89
|
-
NATSService.log("New Subscription Handler:", subject);
|
|
90
|
-
|
|
91
|
-
const sub = this.connection?.subscribe(subject, {
|
|
92
|
-
callback: (err, msg) => {
|
|
93
|
-
if (err) {
|
|
94
|
-
console.error(`Error handling message for subject ${subject}:`, err);
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
const parsedMessage = this.parseMessage(msg.data);
|
|
98
|
-
handler(parsedMessage);
|
|
99
|
-
},
|
|
100
|
-
});
|
|
101
|
-
if (sub) this.subscriptions.push(sub);
|
|
102
|
-
} catch (e) {
|
|
103
|
-
console.error(`Failed to subscribe to subject ${subject}:`, e);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Subscribes to the EXEC_FUNCTION_SUBJECT and executes registered functions.
|
|
109
|
-
*/
|
|
110
|
-
public initializeFunctions(): boolean {
|
|
111
|
-
if (!this.connection) {
|
|
112
|
-
throw new Error("No active connection. Please connect to the NATS server first.");
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const sub = this.connection.subscribe(this.EXEC_FUNCTION_SUBJECT, {
|
|
116
|
-
callback: (err, msg) => {
|
|
117
|
-
if (err) {
|
|
118
|
-
console.error("Error handling message:", err);
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
try {
|
|
123
|
-
const dataStr = Buffer.from(msg.data).toString('utf-8');
|
|
124
|
-
const data = JSON.parse(dataStr) as Record<string, any>;
|
|
125
|
-
const subjectParts = msg.subject.split(".");
|
|
126
|
-
if (subjectParts.length !== 4) {
|
|
127
|
-
msg.respond(JSON.stringify({ error: "Invalid subject format" }));
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const functionName = subjectParts[3];
|
|
132
|
-
this.executeFunction(functionName, data)
|
|
133
|
-
.then((result) => {
|
|
134
|
-
msg.respond(JSON.stringify(result));
|
|
135
|
-
})
|
|
136
|
-
.catch((e: any) => {
|
|
137
|
-
console.log("Error executing function '" + functionName + "': ", e);
|
|
138
|
-
msg.respond(JSON.stringify({ status: "failed", error: e.message }));
|
|
139
|
-
});
|
|
140
|
-
} catch (parseError: any) {
|
|
141
|
-
console.error("Error parsing function execution message:", parseError);
|
|
142
|
-
msg.respond(JSON.stringify({
|
|
143
|
-
status: "failed",
|
|
144
|
-
error: `Failed to parse message: ${parseError.message}`
|
|
145
|
-
}));
|
|
146
|
-
}
|
|
147
|
-
},
|
|
148
|
-
});
|
|
149
|
-
if (sub) this.subscriptions.push(sub);
|
|
150
|
-
|
|
151
|
-
NATSService.log(`Subscribed to '${this.EXEC_FUNCTION_SUBJECT}'`);
|
|
152
|
-
return true;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Adds a new function to the registry.
|
|
157
|
-
* @param functionName {string} The name of the function to add.
|
|
158
|
-
* @param func {(data: Record<string, any>) => Promise<Record<string, any>> | Record<string, any>} The function implementation.
|
|
159
|
-
* @throws TypeError if the provided argument is not a function.
|
|
160
|
-
*/
|
|
161
|
-
public addFunction(
|
|
162
|
-
functionName: string,
|
|
163
|
-
func: (data: Record<string, any>) => Promise<Record<string, any>> | Record<string, any>
|
|
164
|
-
): void {
|
|
165
|
-
if (typeof func !== "function") {
|
|
166
|
-
throw new TypeError(`The provided argument '${functionName}' is not a function.`);
|
|
167
|
-
}
|
|
168
|
-
this.functions[functionName] = func;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Executes a registered function by name with the provided arguments.
|
|
173
|
-
* @param functionName {string} The name of the function to execute.
|
|
174
|
-
* @param arg {Record<string, any>} The arguments to pass to the function. (JSON)
|
|
175
|
-
* @returns {Promise<Record<string, any>>} The result of the function execution. (JSON)
|
|
176
|
-
* @throws Error if the function is not found.
|
|
177
|
-
*/
|
|
178
|
-
public async executeFunction(
|
|
179
|
-
functionName: string,
|
|
180
|
-
arg: Record<string, any>
|
|
181
|
-
): Promise<Record<string, any>> {
|
|
182
|
-
const func = this.functions[functionName];
|
|
183
|
-
if (!func) {
|
|
184
|
-
throw new Error(`Function '${functionName}' not found`);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
return await func(arg);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Clears all subscribed subjects.
|
|
192
|
-
*/
|
|
193
|
-
public clearSubjects(): void {
|
|
194
|
-
this.subscribedSubjects = [];
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Publishes a message to a specific subject.
|
|
199
|
-
* @param subject {string} The subject to publish to.
|
|
200
|
-
* @param message {unknown} The message to publish.
|
|
201
|
-
* @returns {boolean} True if the message was published successfully.
|
|
202
|
-
*/
|
|
203
|
-
public publish(subject: string, message: unknown): boolean {
|
|
204
|
-
try {
|
|
205
|
-
const payload = JSON.stringify(message);
|
|
206
|
-
NATSService.log("Publishing to", subject, "with payload:", payload);
|
|
207
|
-
|
|
208
|
-
this.connection?.publish(subject, payload);
|
|
209
|
-
} catch (e) {
|
|
210
|
-
console.error(`Failed to publish to subject ${subject}:`, e);
|
|
211
|
-
throw e;
|
|
212
|
-
}
|
|
213
|
-
return true;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Retrieves all registered functions.
|
|
218
|
-
* @returns {Record<string, (data: Record<string, any>) => Record<string, any>} An object containing all registered functions.
|
|
219
|
-
*/
|
|
220
|
-
public getAllFunctions(): Record<string, (data: Record<string, any>) => Record<string, any>> {
|
|
221
|
-
return this.functions;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
public static log(message?: any, ...optionalParams: any[]) {
|
|
225
|
-
console.log("[TYPESCRIPT] >", message, ...optionalParams);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Prints the names of all available functions to the console.
|
|
230
|
-
*/
|
|
231
|
-
public printFunctions(): void {
|
|
232
|
-
NATSService.log("Available functions: ", Object.keys(this.functions).join(", "));
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Parses a message buffer into a JSON object or returns raw data.
|
|
237
|
-
* @param message {Uint8Array} The message buffer.
|
|
238
|
-
* @returns {unknown} The parsed message (JSON object) or the raw string if parsing fails.
|
|
239
|
-
*/
|
|
240
|
-
private parseMessage(message: Uint8Array): unknown {
|
|
241
|
-
try {
|
|
242
|
-
const messageStr = Buffer.from(message).toString('utf-8');
|
|
243
|
-
// Check if the message is empty
|
|
244
|
-
if (!messageStr || messageStr.trim().length === 0) {
|
|
245
|
-
NATSService.log("Received empty message");
|
|
246
|
-
return null;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// Try to parse as JSON
|
|
250
|
-
return JSON.parse(messageStr);
|
|
251
|
-
} catch (error) {
|
|
252
|
-
// If JSON parsing fails, check if it's binary data or non-JSON content
|
|
253
|
-
const messageStr = Buffer.from(message).toString('utf-8');
|
|
254
|
-
|
|
255
|
-
// Check if it looks like binary data (contains non-printable characters)
|
|
256
|
-
const isBinary = message.some(byte => byte < 32 && byte !== 9 && byte !== 10 && byte !== 13);
|
|
257
|
-
|
|
258
|
-
if (isBinary) {
|
|
259
|
-
NATSService.log("Received binary data, returning as Uint8Array");
|
|
260
|
-
return message; // Return raw binary data
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// If it's a plain string (not JSON), return as is
|
|
264
|
-
NATSService.log("Failed to parse message as JSON, returning as string:", messageStr.substring(0, 100));
|
|
265
|
-
console.error("Error parsing message:", error);
|
|
266
|
-
return messageStr;
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
/**
|
|
271
|
-
* Gracefully unsubscribes from all NATS subscriptions and closes the connection.
|
|
272
|
-
*/
|
|
273
|
-
public async shutdown(): Promise<void> {
|
|
274
|
-
NATSService.log("Shutting down NATSService...");
|
|
275
|
-
for (const sub of this.subscriptions) {
|
|
276
|
-
try {
|
|
277
|
-
sub.unsubscribe();
|
|
278
|
-
} catch (e) {
|
|
279
|
-
NATSService.log("Error unsubscribing:", e);
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
this.subscriptions = [];
|
|
283
|
-
if (this.connection) {
|
|
284
|
-
try {
|
|
285
|
-
await this.connection.drain();
|
|
286
|
-
await this.connection.close();
|
|
287
|
-
} catch (e) {
|
|
288
|
-
NATSService.log("Error closing NATS connection:", e);
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
NATSService.log("NATSService shutdown complete.");
|
|
292
|
-
}
|
|
293
|
-
}
|