@machhub-dev/sdk-ts 0.0.8 → 0.0.10

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.
@@ -147,20 +147,30 @@ class SDK {
147
147
  if (!config.application_id)
148
148
  config = { application_id: "" };
149
149
  // console.log("Using application_id:", config.application_id);
150
- const { port, runtimeID } = await getEnvConfig();
151
- console.log("Port:", port);
150
+ const envCfg = await getEnvConfig();
151
+ // console.log("Environment Config:", envCfg);
152
+ // Determine the hostname - use window.location.hostname in browser, otherwise fallback to localhost
153
+ const hostname = typeof window !== 'undefined' ? window.location.hostname : 'localhost';
154
+ const secured = typeof window !== 'undefined' ? window.location.protocol === 'https:' : false;
155
+ let host = hostname;
156
+ if (envCfg.hostingMode === 'port' || !envCfg.hostingMode) {
157
+ host += `:${envCfg.port}`;
158
+ }
159
+ else if (envCfg.hostingMode === 'path') {
160
+ host += envCfg.pathHosted;
161
+ }
152
162
  if (!config.httpUrl) {
153
- config.httpUrl = "http://localhost:" + port;
163
+ config.httpUrl = `${secured ? 'https' : 'http'}://${host}`;
154
164
  }
155
165
  if (!config.mqttUrl) {
156
- config.mqttUrl = "ws://localhost:" + port + "/mqtt";
166
+ config.mqttUrl = `${secured ? 'wss' : 'ws'}://${host}/mqtt`;
157
167
  }
158
168
  if (!config.natsUrl) {
159
- config.natsUrl = "ws://localhost:" + port + "/nats";
169
+ config.natsUrl = `${secured ? 'wss' : 'ws'}://${host}/nats`;
160
170
  }
161
171
  const { application_id, httpUrl, mqttUrl, natsUrl } = config;
162
172
  console.log("SDK Config:", { application_id, httpUrl, mqttUrl, natsUrl, developer_key: config.developer_key?.split('').map((_, i) => i < config.developer_key.length - 4 ? '*' : config.developer_key[i]).join('') });
163
- this.http = new HTTPClient(application_id, httpUrl, config.developer_key, runtimeID);
173
+ this.http = new HTTPClient(application_id, httpUrl, config.developer_key, envCfg.runtimeID);
164
174
  this.mqtt = await MQTTClient.getInstance(application_id, mqttUrl, config.developer_key);
165
175
  this.nats = await NATSClient.getInstance(application_id, natsUrl);
166
176
  this._historian = new historian_js_1.Historian(this.http["httpService"], this.mqtt["mqttService"]);
@@ -239,10 +249,9 @@ async function getEnvConfig() {
239
249
  // Try to find the configuration endpoint by testing different base paths
240
250
  const configUrl = await findConfigEndpoint();
241
251
  const response = await fetchData(configUrl);
242
- // console.log('Response:', response);
243
252
  // console.log('runtimeID: ', response.runtimeID);
244
253
  // console.log('applicationID: ', response.runtimeID.split('XmchX')[0]);
245
- return { port: response.port, runtimeID: response.runtimeID };
254
+ return response;
246
255
  }
247
256
  catch (error) {
248
257
  // console.log('No configured runtime ID:', error);
@@ -286,6 +295,7 @@ async function findConfigEndpoint() {
286
295
  try {
287
296
  const testData = await testResponse.json();
288
297
  // Check if the response has the expected structure with a 'port' field
298
+ // TODO: Allow checks for path based hosting as well
289
299
  if (testData && typeof testData === 'object' && 'port' in testData) {
290
300
  // console.log(`Found config endpoint at: ${configUrl}`);
291
301
  return configUrl;
@@ -90,20 +90,20 @@ class MQTTService {
90
90
  this.client.on('message', (topic, message) => {
91
91
  for (const subscribedTopic of this.subscribedTopics) {
92
92
  if (topic === subscribedTopic.topic) {
93
- const parsedMessage = this.parseMessage(message);
93
+ const parsedMessage = this.parseMessage(message, topic);
94
94
  subscribedTopic.handler(parsedMessage);
95
95
  break;
96
96
  }
97
97
  }
98
98
  });
99
99
  }
100
- parseMessage(message) {
100
+ parseMessage(message, topic) {
101
101
  try {
102
102
  return JSON.parse(message.toString());
103
103
  }
104
104
  catch (error) {
105
- console.error("Error parsing message:", error);
106
- return null;
105
+ console.warn("Failed to parse message as JSON '" + topic + "' : ", message.toString());
106
+ return message.toString();
107
107
  }
108
108
  }
109
109
  }
package/dist/sdk-ts.js CHANGED
@@ -144,20 +144,30 @@ export class SDK {
144
144
  if (!config.application_id)
145
145
  config = { application_id: "" };
146
146
  // console.log("Using application_id:", config.application_id);
147
- const { port, runtimeID } = await getEnvConfig();
148
- console.log("Port:", port);
147
+ const envCfg = await getEnvConfig();
148
+ // console.log("Environment Config:", envCfg);
149
+ // Determine the hostname - use window.location.hostname in browser, otherwise fallback to localhost
150
+ const hostname = typeof window !== 'undefined' ? window.location.hostname : 'localhost';
151
+ const secured = typeof window !== 'undefined' ? window.location.protocol === 'https:' : false;
152
+ let host = hostname;
153
+ if (envCfg.hostingMode === 'port' || !envCfg.hostingMode) {
154
+ host += `:${envCfg.port}`;
155
+ }
156
+ else if (envCfg.hostingMode === 'path') {
157
+ host += envCfg.pathHosted;
158
+ }
149
159
  if (!config.httpUrl) {
150
- config.httpUrl = "http://localhost:" + port;
160
+ config.httpUrl = `${secured ? 'https' : 'http'}://${host}`;
151
161
  }
152
162
  if (!config.mqttUrl) {
153
- config.mqttUrl = "ws://localhost:" + port + "/mqtt";
163
+ config.mqttUrl = `${secured ? 'wss' : 'ws'}://${host}/mqtt`;
154
164
  }
155
165
  if (!config.natsUrl) {
156
- config.natsUrl = "ws://localhost:" + port + "/nats";
166
+ config.natsUrl = `${secured ? 'wss' : 'ws'}://${host}/nats`;
157
167
  }
158
168
  const { application_id, httpUrl, mqttUrl, natsUrl } = config;
159
169
  console.log("SDK Config:", { application_id, httpUrl, mqttUrl, natsUrl, developer_key: config.developer_key?.split('').map((_, i) => i < config.developer_key.length - 4 ? '*' : config.developer_key[i]).join('') });
160
- this.http = new HTTPClient(application_id, httpUrl, config.developer_key, runtimeID);
170
+ this.http = new HTTPClient(application_id, httpUrl, config.developer_key, envCfg.runtimeID);
161
171
  this.mqtt = await MQTTClient.getInstance(application_id, mqttUrl, config.developer_key);
162
172
  this.nats = await NATSClient.getInstance(application_id, natsUrl);
163
173
  this._historian = new Historian(this.http["httpService"], this.mqtt["mqttService"]);
@@ -235,10 +245,9 @@ async function getEnvConfig() {
235
245
  // Try to find the configuration endpoint by testing different base paths
236
246
  const configUrl = await findConfigEndpoint();
237
247
  const response = await fetchData(configUrl);
238
- // console.log('Response:', response);
239
248
  // console.log('runtimeID: ', response.runtimeID);
240
249
  // console.log('applicationID: ', response.runtimeID.split('XmchX')[0]);
241
- return { port: response.port, runtimeID: response.runtimeID };
250
+ return response;
242
251
  }
243
252
  catch (error) {
244
253
  // console.log('No configured runtime ID:', error);
@@ -282,6 +291,7 @@ async function findConfigEndpoint() {
282
291
  try {
283
292
  const testData = await testResponse.json();
284
293
  // Check if the response has the expected structure with a 'port' field
294
+ // TODO: Allow checks for path based hosting as well
285
295
  if (testData && typeof testData === 'object' && 'port' in testData) {
286
296
  // console.log(`Found config endpoint at: ${configUrl}`);
287
297
  return configUrl;
@@ -84,20 +84,20 @@ export class MQTTService {
84
84
  this.client.on('message', (topic, message) => {
85
85
  for (const subscribedTopic of this.subscribedTopics) {
86
86
  if (topic === subscribedTopic.topic) {
87
- const parsedMessage = this.parseMessage(message);
87
+ const parsedMessage = this.parseMessage(message, topic);
88
88
  subscribedTopic.handler(parsedMessage);
89
89
  break;
90
90
  }
91
91
  }
92
92
  });
93
93
  }
94
- parseMessage(message) {
94
+ parseMessage(message, topic) {
95
95
  try {
96
96
  return JSON.parse(message.toString());
97
97
  }
98
98
  catch (error) {
99
- console.error("Error parsing message:", error);
100
- return null;
99
+ console.warn("Failed to parse message as JSON '" + topic + "' : ", message.toString());
100
+ return message.toString();
101
101
  }
102
102
  }
103
103
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@machhub-dev/sdk-ts",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "description": "MACHHUB TYPESCRIPT SDK",
5
5
  "keywords": [
6
6
  "machhub",
package/src/sdk-ts.ts CHANGED
@@ -19,7 +19,7 @@ class HTTPClient {
19
19
  * @param applicationID The ID for your application (required)
20
20
  * @param httpUrl The base URL for HTTP connection (default = http://localhost:6188)
21
21
  */
22
- constructor(applicationID: string, httpUrl:string, developerKey?: string, runtimeID?: string) {
22
+ constructor(applicationID: string, httpUrl: string, developerKey?: string, runtimeID?: string) {
23
23
  this.httpService = new HTTPService(httpUrl, MACHHUB_SDK_PATH, applicationID, developerKey, runtimeID);
24
24
  }
25
25
 
@@ -45,7 +45,7 @@ class MQTTClient {
45
45
  * @param applicationID The ID for your application
46
46
  * @param mqttUrl The base URL for MQTT connection (default = ws://localhost:180)
47
47
  */
48
- static async getInstance(applicationID?: string, mqttUrl: string = "ws://localhost:180", developerKey? :string): Promise<MQTTClient> {
48
+ static async getInstance(applicationID?: string, mqttUrl: string = "ws://localhost:180", developerKey?: string): Promise<MQTTClient> {
49
49
  // if (!applicationID) {
50
50
  // applicationID = process.env.APP_ID;
51
51
  // if (!applicationID) {
@@ -172,30 +172,39 @@ export class SDK {
172
172
  if (!config.application_id) config = { application_id: "" }
173
173
  // console.log("Using application_id:", config.application_id);
174
174
 
175
+ const envCfg = await getEnvConfig();
176
+ // console.log("Environment Config:", envCfg);
175
177
 
176
- const {port, runtimeID} = await getEnvConfig();
177
- console.log("Port:", port);
178
+ // Determine the hostname - use window.location.hostname in browser, otherwise fallback to localhost
179
+ const hostname = typeof window !== 'undefined' ? window.location.hostname : 'localhost';
180
+ const secured = typeof window !== 'undefined' ? window.location.protocol === 'https:' : false;
181
+
182
+ let host = hostname
183
+ if (envCfg.hostingMode === 'port' || !envCfg.hostingMode) {
184
+ host += `:${envCfg.port}`;
185
+ } else if (envCfg.hostingMode === 'path') {
186
+ host += envCfg.pathHosted
187
+ }
178
188
 
179
189
  if (!config.httpUrl) {
180
- config.httpUrl = "http://localhost:" + port;
190
+ config.httpUrl = `${secured ? 'https' : 'http'}://${host}`;
181
191
  }
182
192
 
183
193
  if (!config.mqttUrl) {
184
- config.mqttUrl = "ws://localhost:" + port + "/mqtt";
194
+ config.mqttUrl = `${secured ? 'wss' : 'ws'}://${host}/mqtt`;
185
195
  }
186
196
 
187
197
  if (!config.natsUrl) {
188
- config.natsUrl = "ws://localhost:" + port + "/nats";
198
+ config.natsUrl = `${secured ? 'wss' : 'ws'}://${host}/nats`;
189
199
  }
190
-
191
200
  const { application_id, httpUrl, mqttUrl, natsUrl } = config;
192
201
 
193
202
  console.log("SDK Config:", { application_id, httpUrl, mqttUrl, natsUrl, developer_key: config.developer_key?.split('').map((_, i) => i < config!.developer_key!.length - 4 ? '*' : config!.developer_key![i]).join('') });
194
203
 
195
- this.http = new HTTPClient(application_id, httpUrl, config.developer_key, runtimeID);
204
+ this.http = new HTTPClient(application_id, httpUrl, config.developer_key, envCfg.runtimeID);
196
205
  this.mqtt = await MQTTClient.getInstance(application_id, mqttUrl, config.developer_key);
197
206
  this.nats = await NATSClient.getInstance(application_id, natsUrl);
198
-
207
+
199
208
  this._historian = new Historian(this.http["httpService"], this.mqtt["mqttService"]);
200
209
  this._tag = new Tag(this.http["httpService"], this.mqtt["mqttService"]);
201
210
  this._function = new Function(this.http["httpService"], this.nats["natsService"]);
@@ -273,19 +282,25 @@ export class SDK {
273
282
  }
274
283
  }
275
284
 
276
- async function getEnvConfig(): Promise<{port:string, runtimeID:string}> {
285
+ interface RUNTIME_CONFIG {
286
+ runtimeID: string;
287
+ port: string;
288
+ hostingMode?: 'port' | 'path';
289
+ pathHosted?: string;
290
+ }
291
+
292
+ async function getEnvConfig(): Promise<RUNTIME_CONFIG> {
277
293
  try {
278
294
  // Try to find the configuration endpoint by testing different base paths
279
295
  const configUrl = await findConfigEndpoint();
280
- const response = await fetchData<{port:string, runtimeID:string}>(configUrl);
281
- // console.log('Response:', response);
296
+ const response = await fetchData<RUNTIME_CONFIG>(configUrl);
282
297
  // console.log('runtimeID: ', response.runtimeID);
283
298
  // console.log('applicationID: ', response.runtimeID.split('XmchX')[0]);
284
- return { port: response.port, runtimeID: response.runtimeID};
299
+ return response;
285
300
  } catch (error) {
286
301
  // console.log('No configured runtime ID:', error);
287
302
  // TODO: Use DevPort from SDK Config or default to 61888
288
- return { port: "61888", runtimeID: ""};
303
+ return { port: "61888", runtimeID: "" };
289
304
  }
290
305
  }
291
306
 
@@ -296,15 +311,15 @@ async function getEnvConfig(): Promise<{port:string, runtimeID:string}> {
296
311
  async function findConfigEndpoint(): Promise<string> {
297
312
  const origin = window.location.origin;
298
313
  const pathname = window.location.pathname;
299
-
314
+
300
315
  // List of potential base paths to try, ordered by likelihood
301
316
  const basePaths = [
302
317
  // 1. Try origin directly (for port-based hosting like localhost:6190)
303
318
  origin,
304
-
319
+
305
320
  // 2. Try current path segments for path-based hosting
306
321
  ...generatePathCandidates(pathname),
307
-
322
+
308
323
  // 3. Try common root paths as fallback
309
324
  origin,
310
325
  ];
@@ -315,16 +330,16 @@ async function findConfigEndpoint(): Promise<string> {
315
330
  for (const basePath of uniqueBasePaths) {
316
331
  try {
317
332
  const configUrl = `${basePath}/_cfg`;
318
-
333
+
319
334
  // Test if this endpoint returns valid JSON config by making a GET request
320
- const testResponse = await fetch(configUrl, {
335
+ const testResponse = await fetch(configUrl, {
321
336
  method: 'GET',
322
337
  headers: {
323
338
  'Accept': 'application/json',
324
339
  },
325
- signal: AbortSignal.timeout(2000) // 2 second timeout
340
+ signal: AbortSignal.timeout(2000)
326
341
  });
327
-
342
+
328
343
  if (testResponse.ok) {
329
344
  // Validate that the response is JSON and contains the expected 'port' field
330
345
  const contentType = testResponse.headers.get('content-type');
@@ -332,6 +347,7 @@ async function findConfigEndpoint(): Promise<string> {
332
347
  try {
333
348
  const testData = await testResponse.json();
334
349
  // Check if the response has the expected structure with a 'port' field
350
+ // TODO: Allow checks for path based hosting as well
335
351
  if (testData && typeof testData === 'object' && 'port' in testData) {
336
352
  // console.log(`Found config endpoint at: ${configUrl}`);
337
353
  return configUrl;
@@ -102,7 +102,7 @@ export class MQTTService {
102
102
  this.client.on('message', (topic: string, message: Buffer) => {
103
103
  for (const subscribedTopic of this.subscribedTopics) {
104
104
  if (topic === subscribedTopic.topic) {
105
- const parsedMessage = this.parseMessage(message);
105
+ const parsedMessage = this.parseMessage(message, topic);
106
106
  subscribedTopic.handler(parsedMessage);
107
107
  break;
108
108
  }
@@ -110,12 +110,12 @@ export class MQTTService {
110
110
  });
111
111
  }
112
112
 
113
- private parseMessage(message: Buffer): unknown {
113
+ private parseMessage(message: Buffer, topic: string): unknown {
114
114
  try {
115
115
  return JSON.parse(message.toString());
116
116
  } catch (error) {
117
- console.error("Error parsing message:", error);
118
- return null;
117
+ console.warn("Failed to parse message as JSON '" + topic + "' : ", message.toString());
118
+ return message.toString();
119
119
  }
120
120
  }
121
121
  }