@machhub-dev/sdk-ts 0.0.6 → 0.0.8

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.
@@ -19,39 +19,18 @@ export class HTTPService {
19
19
  private url: URL;
20
20
  private applicationID: string;
21
21
  private developerKey?: string;
22
+ private runtimeID?: string;
22
23
 
23
- constructor(url: string, prefix: string, applicationID: string, developerKey?: string) {
24
+ constructor(url: string, prefix: string, applicationID: string, developerKey?: string, runtimeID?: string) {
24
25
  if (prefix == null) prefix = "";
25
26
  this.url = new URL(prefix, url);
26
27
  this.applicationID = "domains:" + applicationID
27
28
  this.developerKey = developerKey
29
+ this.runtimeID = runtimeID
28
30
  }
29
31
 
30
32
  public get request(): RequestParameters {
31
- return new RequestParameters(this.url, this.applicationID, this.developerKey);
32
- }
33
-
34
- private addRuntimeHeaders(headers: Record<string, string> = {}): Record<string, string> {
35
- // Add runtime ID from cookie if available (for hosted applications)
36
- if (typeof document !== 'undefined') {
37
- const runtimeID = this.getCookie('machhub_runtime_id');
38
- if (runtimeID) {
39
- headers['X-MachHub-Runtime-ID'] = runtimeID;
40
- }
41
- }
42
-
43
- return headers;
44
- }
45
-
46
- private getCookie(name: string): string | null {
47
- if (typeof document === 'undefined') return null;
48
-
49
- const value = `; ${document.cookie}`;
50
- const parts = value.split(`; ${name}=`);
51
- if (parts.length === 2) {
52
- return parts.pop()?.split(';').shift() || null;
53
- }
54
- return null;
33
+ return new RequestParameters(this.url, this.applicationID, this.developerKey, this.runtimeID);
55
34
  }
56
35
  }
57
36
 
@@ -59,18 +38,21 @@ class RequestParameters {
59
38
  private base: URL;
60
39
  private applicationID: string;
61
40
  private developerKey?: string;
41
+ private runtimeID?: string;
62
42
  public query?: Record<string, string>;
63
43
  public init?: RequestInit;
64
44
  public headers?: Record<string, string>;
65
45
 
66
- constructor(base: URL, applicationID: string, developerKey?:string, query?: Record<string, string>) {
46
+ constructor(base: URL, applicationID: string, developerKey?: string, runtimeID?: string, query?: Record<string, string>) {
67
47
  this.base = base;
68
48
  this.applicationID = applicationID;
69
49
  this.developerKey = developerKey;
50
+ this.runtimeID = runtimeID;
70
51
  this.query = query;
71
52
  this.withDomain(); // Ensure withDomain() is called by default
72
53
  this.withAccessToken(); // Ensure withAccessToken() is called by default
73
54
  this.withDeveloperKey(); // Ensure withDeveloperKey() is called by default
55
+ this.withRuntimeID(); // Ensure withRuntimeID() is called by default
74
56
  }
75
57
 
76
58
  private withQuery(path: string, query?: Record<string, string>): URL {
@@ -170,6 +152,11 @@ class RequestParameters {
170
152
  return this;
171
153
  }
172
154
 
155
+ public withRuntimeID(): RequestParameters {
156
+ this.setHeader("X-Machhub-Runtime-Id", this.runtimeID ?? "");
157
+ return this;
158
+ }
159
+
173
160
  public withDomain(): RequestParameters {
174
161
  this.setHeader("Domain", this.applicationID);
175
162
  return this;
@@ -211,6 +198,12 @@ class RequestParameters {
211
198
  if (body) {
212
199
  if (body instanceof FormData) {
213
200
  init.body = body;
201
+ // Remove Content-Type header if it exists, let browser set it for FormData
202
+ if (init.headers && typeof init.headers === 'object') {
203
+ const headers = init.headers as Record<string, string>;
204
+ delete headers['Content-Type'];
205
+ delete headers['content-type'];
206
+ }
214
207
  } else {
215
208
  init.body = JSON.stringify(body);
216
209
  init.headers = {
@@ -50,7 +50,7 @@ export class MQTTService {
50
50
  try {
51
51
  this.subscribedTopics.push({ topic, handler });
52
52
  if (topic == "") return;
53
- console.log("New Subscription Handler:", topic);
53
+ // console.log("New Subscription Handler:", topic);
54
54
  this.client.subscribe(topic, { qos: 2 }, (err?: unknown) => {
55
55
  if (err) {
56
56
  console.error(`Failed to subscribe to topic ${topic}:`, err);
@@ -70,7 +70,7 @@ export class MQTTService {
70
70
  public publish(topic: string, message: unknown): boolean {
71
71
  try {
72
72
  const payload = JSON.stringify(message);
73
- console.log("Publishing to", topic, "with payload:", payload);
73
+ // console.log("Publishing to", topic, "with payload:", payload);
74
74
 
75
75
  this.client.publish(topic, payload, {
76
76
  qos: 2,
@@ -119,21 +119,31 @@ export class NATSService {
119
119
  return;
120
120
  }
121
121
 
122
- const data = JSON.parse(msg.data.toString()) as Record<string, any>;
123
- const subjectParts = msg.subject.split(".");
124
- if (subjectParts.length !== 4) {
125
- msg.respond(JSON.stringify({ error: "Invalid subject format" }));
126
- return;
127
- }
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
+ }
128
130
 
129
- const functionName = subjectParts[3];
130
- this.executeFunction(functionName, data)
131
- .then((result) => {
132
- msg.respond(JSON.stringify(result));
133
- })
134
- .catch((e: any) => {
135
- msg.respond(JSON.stringify({ status: "failed", error: e.message }));
136
- });
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
+ }
137
147
  },
138
148
  });
139
149
  if (sub) this.subscriptions.push(sub);
@@ -223,16 +233,37 @@ export class NATSService {
223
233
  }
224
234
 
225
235
  /**
226
- * Parses a message buffer into a JSON object.
236
+ * Parses a message buffer into a JSON object or returns raw data.
227
237
  * @param message {Uint8Array} The message buffer.
228
- * @returns {unknown} The parsed message.
238
+ * @returns {unknown} The parsed message (JSON object) or the raw string if parsing fails.
229
239
  */
230
240
  private parseMessage(message: Uint8Array): unknown {
231
241
  try {
232
- return JSON.parse(Buffer.from(message).toString());
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);
233
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));
234
265
  console.error("Error parsing message:", error);
235
- return null;
266
+ return messageStr;
236
267
  }
237
268
  }
238
269