@machhub-dev/sdk-ts 0.0.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.
Files changed (112) hide show
  1. package/LICENSE +21 -0
  2. package/dist/cjs/classes/auth.d.ts +18 -0
  3. package/dist/cjs/classes/auth.js +90 -0
  4. package/dist/cjs/classes/collection.d.ts +18 -0
  5. package/dist/cjs/classes/collection.js +43 -0
  6. package/dist/cjs/classes/flow.d.ts +6 -0
  7. package/dist/cjs/classes/flow.js +12 -0
  8. package/dist/cjs/classes/function.d.ts +10 -0
  9. package/dist/cjs/classes/function.js +29 -0
  10. package/dist/cjs/classes/historian.d.ts +12 -0
  11. package/dist/cjs/classes/historian.js +40 -0
  12. package/dist/cjs/classes/tag.d.ts +10 -0
  13. package/dist/cjs/classes/tag.js +25 -0
  14. package/dist/cjs/client.d.ts +13 -0
  15. package/dist/cjs/client.js +35 -0
  16. package/dist/cjs/config.d.ts +21 -0
  17. package/dist/cjs/config.js +37 -0
  18. package/dist/cjs/example/functions-file-config.d.ts +0 -0
  19. package/dist/cjs/example/functions-file-config.js +1 -0
  20. package/dist/cjs/example/functions.d.ts +1 -0
  21. package/dist/cjs/example/functions.js +18 -0
  22. package/dist/cjs/http-client.d.ts +10 -0
  23. package/dist/cjs/http-client.js +62 -0
  24. package/dist/cjs/index.d.ts +6 -0
  25. package/dist/cjs/index.js +7 -0
  26. package/dist/cjs/sdk-ts-clean.d.ts +108 -0
  27. package/dist/cjs/sdk-ts-clean.js +294 -0
  28. package/dist/cjs/sdk-ts.d.ts +71 -0
  29. package/dist/cjs/sdk-ts.js +227 -0
  30. package/dist/cjs/services/http.service.d.ts +41 -0
  31. package/dist/cjs/services/http.service.js +178 -0
  32. package/dist/cjs/services/mqtt.service.d.ts +15 -0
  33. package/dist/cjs/services/mqtt.service.js +103 -0
  34. package/dist/cjs/services/nats.service.d.ts +78 -0
  35. package/dist/cjs/services/nats.service.js +237 -0
  36. package/dist/cjs/types/auth.models.d.ts +52 -0
  37. package/dist/cjs/types/auth.models.js +100 -0
  38. package/dist/cjs/types/recordID.models.d.ts +7 -0
  39. package/dist/cjs/types/recordID.models.js +32 -0
  40. package/dist/cjs/types/response.models.d.ts +4 -0
  41. package/dist/cjs/types/response.models.js +2 -0
  42. package/dist/cjs/types/tag.models.d.ts +4 -0
  43. package/dist/cjs/types/tag.models.js +2 -0
  44. package/dist/cjs/utils/appConfig.d.ts +5 -0
  45. package/dist/cjs/utils/appConfig.js +62 -0
  46. package/dist/cjs/websocket-client.d.ts +15 -0
  47. package/dist/cjs/websocket-client.js +96 -0
  48. package/dist/classes/auth.d.ts +18 -0
  49. package/dist/classes/auth.js +86 -0
  50. package/dist/classes/collection.d.ts +18 -0
  51. package/dist/classes/collection.js +39 -0
  52. package/dist/classes/flow.d.ts +6 -0
  53. package/dist/classes/flow.js +8 -0
  54. package/dist/classes/function.d.ts +10 -0
  55. package/dist/classes/function.js +25 -0
  56. package/dist/classes/historian.d.ts +12 -0
  57. package/dist/classes/historian.js +36 -0
  58. package/dist/classes/tag.d.ts +10 -0
  59. package/dist/classes/tag.js +21 -0
  60. package/dist/client.d.ts +13 -0
  61. package/dist/client.js +31 -0
  62. package/dist/config.d.ts +21 -0
  63. package/dist/config.js +33 -0
  64. package/dist/example/functions-file-config.d.ts +0 -0
  65. package/dist/example/functions-file-config.js +1 -0
  66. package/dist/example/functions.d.ts +1 -0
  67. package/dist/example/functions.js +16 -0
  68. package/dist/http-client.d.ts +10 -0
  69. package/dist/http-client.js +58 -0
  70. package/dist/index.d.ts +6 -0
  71. package/dist/index.js +2 -0
  72. package/dist/sdk-ts-clean.d.ts +108 -0
  73. package/dist/sdk-ts-clean.js +290 -0
  74. package/dist/sdk-ts.d.ts +71 -0
  75. package/dist/sdk-ts.js +223 -0
  76. package/dist/services/http.service.d.ts +41 -0
  77. package/dist/services/http.service.js +173 -0
  78. package/dist/services/mqtt.service.d.ts +15 -0
  79. package/dist/services/mqtt.service.js +96 -0
  80. package/dist/services/nats.service.d.ts +78 -0
  81. package/dist/services/nats.service.js +233 -0
  82. package/dist/types/auth.models.d.ts +52 -0
  83. package/dist/types/auth.models.js +97 -0
  84. package/dist/types/recordID.models.d.ts +7 -0
  85. package/dist/types/recordID.models.js +27 -0
  86. package/dist/types/response.models.d.ts +4 -0
  87. package/dist/types/response.models.js +1 -0
  88. package/dist/types/tag.models.d.ts +4 -0
  89. package/dist/types/tag.models.js +1 -0
  90. package/dist/utils/appConfig.d.ts +5 -0
  91. package/dist/utils/appConfig.js +26 -0
  92. package/dist/websocket-client.d.ts +15 -0
  93. package/dist/websocket-client.js +92 -0
  94. package/package.json +33 -0
  95. package/src/classes/auth.ts +103 -0
  96. package/src/classes/collection.ts +55 -0
  97. package/src/classes/flow.ts +13 -0
  98. package/src/classes/function.ts +34 -0
  99. package/src/classes/historian.ts +49 -0
  100. package/src/classes/tag.ts +30 -0
  101. package/src/example/functions.ts +21 -0
  102. package/src/index.ts +8 -0
  103. package/src/sdk-ts.ts +255 -0
  104. package/src/services/http.service.ts +239 -0
  105. package/src/services/mqtt.service.ts +114 -0
  106. package/src/services/nats.service.ts +262 -0
  107. package/src/types/auth.models.ts +157 -0
  108. package/src/types/recordID.models.ts +33 -0
  109. package/src/types/response.models.ts +4 -0
  110. package/src/types/tag.models.ts +4 -0
  111. package/src/utils/appConfig.ts +30 -0
  112. package/tsconfig.json +14 -0
@@ -0,0 +1,71 @@
1
+ import { Collection } from "./classes/collection";
2
+ import { Historian } from "./classes/historian";
3
+ import { Tag } from "./classes/tag";
4
+ import { Function } from "./classes/function";
5
+ import { Flow } from "./classes/flow";
6
+ import { Auth } from "./classes/auth";
7
+ export interface SDKConfig {
8
+ application_id: string;
9
+ httpUrl?: string;
10
+ mqttUrl?: string;
11
+ natsUrl?: string;
12
+ }
13
+ export declare class SDK {
14
+ private http;
15
+ private mqtt;
16
+ private nats;
17
+ private _historian;
18
+ private _tag;
19
+ private _function;
20
+ private _flow;
21
+ private _auth;
22
+ /**
23
+ * Initializes the SDK with the required clients.
24
+ *
25
+ * Example usage:
26
+ * ```typescript
27
+ * import { SDK, type SDKConfig } from '@machhub-dev/sdk-ts';
28
+ *
29
+ * const config: SDKConfig = {
30
+ * application_id: 'your-app-id',
31
+ * httpUrl: 'http://localhost:80', // optional (default = http://localhost:80)
32
+ * mqttUrl: 'ws://localhost:180', // optional (default = ws://localhost:180)
33
+ * natsUrl: 'ws://localhost:7500', // optional (default = ws://localhost:7500)
34
+ * };
35
+ *
36
+ * const sdk = new SDK();
37
+ * await sdk.Initialize(config);
38
+ * ```
39
+ *
40
+ * @param config {SDKConfig} The configuration object containing initialization parameters. See SDKConfig for details.
41
+ * @returns {Promise<boolean>} Resolves to true if initialization is successful.
42
+ */
43
+ Initialize(config: SDKConfig): Promise<boolean>;
44
+ /**
45
+ * Getter for `auth`. Ensures `auth` is accessed only after initialization.
46
+ */
47
+ get auth(): Auth;
48
+ /**
49
+ * Getter for `historian`. Ensures `historian` is accessed only after initialization.
50
+ */
51
+ get historian(): Historian;
52
+ /**
53
+ * Getter for `tag`. Ensures `tag` is accessed only after initialization.
54
+ */
55
+ get tag(): Tag;
56
+ /**
57
+ * Getter for `function`. Ensures `function` is accessed only after initialization.
58
+ */
59
+ get function(): Function;
60
+ /**
61
+ * Getter for `flow`. Ensures `flow` is accessed only after initialization.
62
+ */
63
+ get flow(): Flow;
64
+ /**
65
+ * Creates a collection instance to interact with the specified table/collection.
66
+ * Throws an error if the SDK is not initialized.
67
+ * @param collectionName {string} The collection/table name.
68
+ * @returns {Collection} An instance of Collection.
69
+ */
70
+ collection(collectionName: string): Collection;
71
+ }
package/dist/sdk-ts.js ADDED
@@ -0,0 +1,223 @@
1
+ import { HTTPService } from "./services/http.service";
2
+ import { MQTTService } from "./services/mqtt.service";
3
+ import { NATSService } from "./services/nats.service";
4
+ import { getAppConfig } from "./utils/appConfig";
5
+ import { Collection } from "./classes/collection";
6
+ import { Historian } from "./classes/historian";
7
+ import { Tag } from "./classes/tag";
8
+ import { Function } from "./classes/function";
9
+ import { Flow } from "./classes/flow";
10
+ import { Auth } from "./classes/auth";
11
+ const MACHHUB_SDK_PATH = "machhub";
12
+ // Core HTTP client class
13
+ class HTTPClient {
14
+ /**
15
+ * Creates a new HTTPClient instance
16
+ * @param applicationID The ID for your application (required)
17
+ * @param httpUrl The base URL for HTTP connection (default = http://localhost:80)
18
+ */
19
+ constructor(applicationID, httpUrl = "http://localhost:80") {
20
+ if (!applicationID) {
21
+ const config = getAppConfig();
22
+ if (config != undefined) {
23
+ applicationID = config.application_id;
24
+ }
25
+ else {
26
+ throw new Error("Failed to get Configuration.");
27
+ }
28
+ if (!applicationID) {
29
+ throw new Error("Application ID is required. Set it via the APP_ID environment variable or pass it as a parameter.");
30
+ }
31
+ }
32
+ this.httpService = new HTTPService(httpUrl, MACHHUB_SDK_PATH, applicationID);
33
+ }
34
+ /**
35
+ * Gets server info
36
+ */
37
+ async getInfo() {
38
+ return this.httpService.request.get("info");
39
+ }
40
+ }
41
+ // Core MQTT client class
42
+ class MQTTClient {
43
+ constructor(mqttService) {
44
+ this.mqttService = mqttService;
45
+ }
46
+ /**
47
+ * Creates a new MQTTClient instance
48
+ * @param applicationID The ID for your application
49
+ * @param mqttUrl The base URL for MQTT connection (default = ws://localhost:180)
50
+ */
51
+ static async getInstance(applicationID, mqttUrl = "ws://localhost:180") {
52
+ // if (!applicationID) {
53
+ // applicationID = process.env.APP_ID;
54
+ // if (!applicationID) {
55
+ // throw new Error("Application ID is required. Set it via the APP_ID environment variable or pass it as a parameter.");
56
+ // }
57
+ // }
58
+ if (!this.instance) {
59
+ const mqttService = await MQTTService.getInstance(mqttUrl);
60
+ this.instance = new MQTTClient(mqttService); // Use the constructor to initialize the instance
61
+ }
62
+ return this.instance;
63
+ }
64
+ /**
65
+ * Subscribes to live tag data updates
66
+ * @param topic The tag topic
67
+ * @param callback The callback function for data updates
68
+ */
69
+ async subscribeLiveData(topic, callback) {
70
+ return this.mqttService.addTopicHandler(topic, callback);
71
+ }
72
+ /**
73
+ * Publishes a message to a specific topic
74
+ * @param topic The topic to publish to
75
+ * @param data The data to publish
76
+ */
77
+ async publish(topic, data) {
78
+ return this.mqttService.publish(topic, data);
79
+ }
80
+ }
81
+ // Core NATS client class
82
+ class NATSClient {
83
+ constructor(natsService) {
84
+ this.natsService = natsService;
85
+ }
86
+ /**
87
+ * Creates a new NATSClient instance
88
+ * @param applicationID The ID for your application
89
+ * @param natsUrl The base URL for NATS connection (default = ws://localhost:7500)
90
+ */
91
+ static async getInstance(applicationID, natsUrl = "ws://localhost:7500") {
92
+ if (!this.instance) {
93
+ const natsService = await NATSService.getInstance(natsUrl);
94
+ this.instance = new NATSClient(natsService);
95
+ }
96
+ return this.instance;
97
+ }
98
+ /**
99
+ * Subscribes to subject updates
100
+ * @param subject The subject to subscribe to
101
+ * @param callback The callback function for data updates
102
+ */
103
+ async subscribe(subject, callback) {
104
+ return this.natsService.addSubjectHandler(subject, callback);
105
+ }
106
+ /**
107
+ * Publishes a message to a specific subject
108
+ * @param subject The subject to publish to
109
+ * @param data The data to publish
110
+ */
111
+ async publish(subject, data) {
112
+ return this.natsService.publish(subject, data);
113
+ }
114
+ }
115
+ // SDK Class
116
+ export class SDK {
117
+ constructor() {
118
+ this.http = null;
119
+ this.mqtt = null;
120
+ this.nats = null;
121
+ this._historian = null;
122
+ this._tag = null;
123
+ this._function = null;
124
+ this._flow = null;
125
+ this._auth = null;
126
+ }
127
+ /**
128
+ * Initializes the SDK with the required clients.
129
+ *
130
+ * Example usage:
131
+ * ```typescript
132
+ * import { SDK, type SDKConfig } from '@machhub-dev/sdk-ts';
133
+ *
134
+ * const config: SDKConfig = {
135
+ * application_id: 'your-app-id',
136
+ * httpUrl: 'http://localhost:80', // optional (default = http://localhost:80)
137
+ * mqttUrl: 'ws://localhost:180', // optional (default = ws://localhost:180)
138
+ * natsUrl: 'ws://localhost:7500', // optional (default = ws://localhost:7500)
139
+ * };
140
+ *
141
+ * const sdk = new SDK();
142
+ * await sdk.Initialize(config);
143
+ * ```
144
+ *
145
+ * @param config {SDKConfig} The configuration object containing initialization parameters. See SDKConfig for details.
146
+ * @returns {Promise<boolean>} Resolves to true if initialization is successful.
147
+ */
148
+ async Initialize(config) {
149
+ try {
150
+ const { application_id, httpUrl, mqttUrl, natsUrl } = config;
151
+ this.http = new HTTPClient(application_id, httpUrl);
152
+ this.mqtt = await MQTTClient.getInstance(application_id, mqttUrl);
153
+ this.nats = await NATSClient.getInstance(application_id, natsUrl);
154
+ this._historian = new Historian(this.http["httpService"], this.mqtt["mqttService"]);
155
+ this._tag = new Tag(this.http["httpService"], this.mqtt["mqttService"]);
156
+ this._function = new Function(this.http["httpService"], this.nats["natsService"]);
157
+ this._flow = new Flow(this.http["httpService"]);
158
+ this._auth = new Auth(this.http["httpService"]);
159
+ }
160
+ catch (error) {
161
+ console.error("Failed to initialize:", error);
162
+ return false;
163
+ }
164
+ return true;
165
+ }
166
+ /**
167
+ * Getter for `auth`. Ensures `auth` is accessed only after initialization.
168
+ */
169
+ get auth() {
170
+ if (!this._auth) {
171
+ throw new Error("SDK is not initialized. Call `Initialize` before accessing `auth`.");
172
+ }
173
+ return this._auth;
174
+ }
175
+ /**
176
+ * Getter for `historian`. Ensures `historian` is accessed only after initialization.
177
+ */
178
+ get historian() {
179
+ if (!this._historian) {
180
+ throw new Error("SDK is not initialized. Call `Initialize` before accessing `historian`.");
181
+ }
182
+ return this._historian;
183
+ }
184
+ /**
185
+ * Getter for `tag`. Ensures `tag` is accessed only after initialization.
186
+ */
187
+ get tag() {
188
+ if (!this._tag) {
189
+ throw new Error("SDK is not initialized. Call `Initialize` before accessing `tag`.");
190
+ }
191
+ return this._tag;
192
+ }
193
+ /**
194
+ * Getter for `function`. Ensures `function` is accessed only after initialization.
195
+ */
196
+ get function() {
197
+ if (!this._function) {
198
+ throw new Error("SDK is not initialized. Call `Initialize` before accessing `function`.");
199
+ }
200
+ return this._function;
201
+ }
202
+ /**
203
+ * Getter for `flow`. Ensures `flow` is accessed only after initialization.
204
+ */
205
+ get flow() {
206
+ if (!this._flow) {
207
+ throw new Error("SDK is not initialized. Call `Initialize` before accessing `flow`.");
208
+ }
209
+ return this._flow;
210
+ }
211
+ /**
212
+ * Creates a collection instance to interact with the specified table/collection.
213
+ * Throws an error if the SDK is not initialized.
214
+ * @param collectionName {string} The collection/table name.
215
+ * @returns {Collection} An instance of Collection.
216
+ */
217
+ collection(collectionName) {
218
+ if (!this.http) {
219
+ throw new Error("SDK is not initialized. Call `Initialize` before accessing collection.");
220
+ }
221
+ return new Collection(this.http["httpService"], this.mqtt ? this.mqtt["mqttService"] : null, collectionName);
222
+ }
223
+ }
@@ -0,0 +1,41 @@
1
+ export declare class HTTPException extends Error {
2
+ status: number;
3
+ statusText: string;
4
+ body: string;
5
+ constructor(status: number, statusText: string, body: string);
6
+ get message(): string;
7
+ }
8
+ export declare class HTTPService {
9
+ private url;
10
+ private applicationID;
11
+ constructor(url: string, prefix?: string, applicationID?: string);
12
+ get request(): RequestParameters;
13
+ }
14
+ declare class RequestParameters {
15
+ private base;
16
+ private applicationID;
17
+ query?: Record<string, string>;
18
+ init?: RequestInit;
19
+ headers?: Record<string, string>;
20
+ constructor(base: URL, applicationID: string, query?: Record<string, string>);
21
+ private withQuery;
22
+ private parseInit;
23
+ withBody(body: BodyInit): RequestParameters;
24
+ includeCredentials(): RequestParameters;
25
+ includeSameOriginCredentials(): RequestParameters;
26
+ keepAlive(): RequestParameters;
27
+ followRedirect(): RequestParameters;
28
+ errorOnRedirect(): RequestParameters;
29
+ setHeader(key: string, value: string): RequestParameters;
30
+ setBearerToken(token: string): RequestParameters;
31
+ withAccessToken(): RequestParameters;
32
+ withDomain(): RequestParameters;
33
+ withContentType(mime: string): RequestParameters;
34
+ withJSON(body: Record<string, unknown>): RequestParameters;
35
+ get<ReturnType>(path: string, query?: Record<string, string>): Promise<ReturnType>;
36
+ post<ReturnType>(path: string, query?: Record<string, string>, body?: FormData | Record<string, string>): Promise<ReturnType>;
37
+ put<ReturnType>(path: string, query?: Record<string, string>): Promise<ReturnType>;
38
+ delete<ReturnType>(path: string, query?: Record<string, string>): Promise<ReturnType>;
39
+ patch<ReturnType>(path: string, query?: Record<string, string>): Promise<ReturnType>;
40
+ }
41
+ export {};
@@ -0,0 +1,173 @@
1
+ export class HTTPException extends Error {
2
+ constructor(status, statusText, body) {
3
+ super();
4
+ this.status = status;
5
+ this.statusText = statusText;
6
+ this.body = body;
7
+ }
8
+ get message() {
9
+ return `(EXCEPTION) ${this.statusText} - ${this.body}`;
10
+ }
11
+ }
12
+ export class HTTPService {
13
+ constructor(url, prefix, applicationID) {
14
+ if (prefix == null)
15
+ prefix = "";
16
+ this.url = new URL(prefix, url);
17
+ this.applicationID = "domains:" + applicationID;
18
+ }
19
+ get request() {
20
+ return new RequestParameters(this.url, this.applicationID);
21
+ }
22
+ }
23
+ class RequestParameters {
24
+ constructor(base, applicationID, query) {
25
+ this.base = base;
26
+ this.applicationID = applicationID;
27
+ this.query = query;
28
+ this.withDomain(); // Ensure withDomain() is called by default
29
+ this.withAccessToken(); // Ensure withAccessToken() is called by default
30
+ }
31
+ withQuery(path, query) {
32
+ const newPath = [this.base.pathname, path].map(pathPart => pathPart.replace(/(^\/|\/$)/g, "")).join("/");
33
+ const newURL = new URL(newPath, this.base);
34
+ for (const key in query) {
35
+ newURL.searchParams.append(key, query[key]);
36
+ }
37
+ return newURL;
38
+ }
39
+ parseInit(method) {
40
+ if (method == null && this.headers == null)
41
+ return;
42
+ let tempInit = Object.assign({}, this.init);
43
+ if (tempInit == null) {
44
+ tempInit = {};
45
+ }
46
+ if (method != null && tempInit != null)
47
+ tempInit.method = method;
48
+ if (this.headers != null && tempInit != null) {
49
+ tempInit.headers = Object.assign({}, this.headers);
50
+ }
51
+ return tempInit;
52
+ }
53
+ withBody(body) {
54
+ if (this.init == null) {
55
+ this.init = {};
56
+ }
57
+ this.init.body = body;
58
+ return this;
59
+ }
60
+ includeCredentials() {
61
+ if (this.init == null) {
62
+ this.init = {};
63
+ }
64
+ this.init.credentials = "include";
65
+ return this;
66
+ }
67
+ includeSameOriginCredentials() {
68
+ if (this.init == null) {
69
+ this.init = {};
70
+ }
71
+ this.init.credentials = "same-origin";
72
+ return this;
73
+ }
74
+ keepAlive() {
75
+ if (this.init == null) {
76
+ this.init = {};
77
+ }
78
+ this.init.keepalive = true;
79
+ return this;
80
+ }
81
+ followRedirect() {
82
+ if (this.init == null) {
83
+ this.init = {};
84
+ }
85
+ this.init.redirect = "follow";
86
+ return this;
87
+ }
88
+ errorOnRedirect() {
89
+ if (this.init == null) {
90
+ this.init = {};
91
+ }
92
+ this.init.redirect = "error";
93
+ return this;
94
+ }
95
+ setHeader(key, value) {
96
+ if (this.headers == null) {
97
+ this.headers = {
98
+ key: value
99
+ };
100
+ }
101
+ this.headers[key] = value;
102
+ return this;
103
+ }
104
+ setBearerToken(token) {
105
+ this.setHeader("Authorization", `Bearer ${token}`);
106
+ return this;
107
+ }
108
+ withAccessToken() {
109
+ const tkn = localStorage.getItem("x-machhub-auth-tkn");
110
+ this.setHeader("Authorization", `Bearer ${tkn}`);
111
+ return this;
112
+ }
113
+ withDomain() {
114
+ this.setHeader("Domain", this.applicationID);
115
+ return this;
116
+ }
117
+ withContentType(mime) {
118
+ this.setHeader("Content-Type", mime);
119
+ return this;
120
+ }
121
+ withJSON(body) {
122
+ const bd = JSON.stringify(body);
123
+ return this.withBody(bd).withContentType("application/json");
124
+ }
125
+ async get(path, query) {
126
+ const response = await fetch(this.withQuery(path, query), this.parseInit());
127
+ if (!response.ok) {
128
+ throw new HTTPException(response.status, response.statusText, await response.text());
129
+ }
130
+ return response.json();
131
+ }
132
+ async post(path, query, body) {
133
+ const init = this.parseInit("POST") || {};
134
+ if (body) {
135
+ if (body instanceof FormData) {
136
+ init.body = body;
137
+ }
138
+ else {
139
+ init.body = JSON.stringify(body);
140
+ init.headers = {
141
+ ...init.headers,
142
+ 'Content-Type': 'application/json'
143
+ };
144
+ }
145
+ }
146
+ const response = await fetch(this.withQuery(path, query), init);
147
+ if (!response.ok) {
148
+ throw new HTTPException(response.status, response.statusText, await response.text());
149
+ }
150
+ return response.json();
151
+ }
152
+ async put(path, query) {
153
+ const response = await fetch(this.withQuery(path, query), this.parseInit("PUT"));
154
+ if (!response.ok) {
155
+ throw new HTTPException(response.status, response.statusText, await response.text());
156
+ }
157
+ return response.json();
158
+ }
159
+ async delete(path, query) {
160
+ const response = await fetch(this.withQuery(path, query), this.parseInit("DELETE"));
161
+ if (!response.ok) {
162
+ throw new HTTPException(response.status, response.statusText, await response.text());
163
+ }
164
+ return response.json();
165
+ }
166
+ async patch(path, query) {
167
+ const response = await fetch(this.withQuery(path, query), this.parseInit("PATCH"));
168
+ if (!response.ok) {
169
+ throw new HTTPException(response.status, response.statusText, await response.text());
170
+ }
171
+ return response.json();
172
+ }
173
+ }
@@ -0,0 +1,15 @@
1
+ import mqtt from 'mqtt';
2
+ export declare class MQTTService {
3
+ private url;
4
+ client: mqtt.MqttClient;
5
+ private static instance;
6
+ private subscribedTopics;
7
+ constructor(url: string);
8
+ static getInstance(url?: string): Promise<MQTTService>;
9
+ static resetInstance(): void;
10
+ addTopicHandler(topic: string, handler: (message: unknown) => void): void;
11
+ clearTopics(): void;
12
+ publish(topic: string, message: unknown): boolean;
13
+ private attachMessageListener;
14
+ private parseMessage;
15
+ }
@@ -0,0 +1,96 @@
1
+ import mqtt from 'mqtt';
2
+ export class MQTTService {
3
+ constructor(url) {
4
+ this.subscribedTopics = [];
5
+ this.url = url;
6
+ }
7
+ static async getInstance(url = "ws://localhost:180") {
8
+ if (!this.instance || !this.instance.client) {
9
+ this.instance = new MQTTService(url);
10
+ // Ensure the URL is set correctly
11
+ this.instance.url = url;
12
+ // Initialize the MQTT client
13
+ this.instance.client = mqtt.connect(this.instance.url, { protocolVersion: 5 });
14
+ this.instance.attachMessageListener();
15
+ // console.log("MQTT Client initialized with URL:", this.instance.url);
16
+ }
17
+ return this.instance;
18
+ }
19
+ // Method to reset the instance
20
+ static resetInstance() {
21
+ if (this.instance) {
22
+ this.instance.client.end();
23
+ this.instance = undefined;
24
+ }
25
+ }
26
+ // addTopicHandler Adds a topic and handler to the subscribed list
27
+ addTopicHandler(topic, handler) {
28
+ try {
29
+ this.subscribedTopics.push({ topic, handler });
30
+ if (topic == "")
31
+ return;
32
+ console.log("New Subscription Handler:", topic);
33
+ this.client.subscribe(topic, { qos: 2 }, (err) => {
34
+ if (err) {
35
+ console.error(`Failed to subscribe to topic ${topic}:`, err);
36
+ }
37
+ });
38
+ }
39
+ catch (e) {
40
+ console.error(`Failed to subscribe to topic ${topic}:`, e);
41
+ }
42
+ }
43
+ // clearTopics clears all the topics subscribed to
44
+ clearTopics() {
45
+ this.subscribedTopics = [];
46
+ }
47
+ // Publishes a message to a specific topic
48
+ publish(topic, message) {
49
+ try {
50
+ const payload = JSON.stringify(message);
51
+ console.log("Publishing to", topic, "with payload:", payload);
52
+ this.client.publish(topic, payload, {
53
+ qos: 2,
54
+ retain: true,
55
+ properties: {
56
+ contentType: "json",
57
+ },
58
+ }, (err) => {
59
+ if (err) {
60
+ console.error(`Failed to publish message to ${topic}:`, err);
61
+ }
62
+ });
63
+ }
64
+ catch (e) {
65
+ console.error(`Failed to publish to topic ${topic}:`, e);
66
+ throw e;
67
+ }
68
+ return true;
69
+ }
70
+ attachMessageListener() {
71
+ this.client.on('connect', () => {
72
+ console.log("MQTT connected to", this.url);
73
+ });
74
+ this.client.on('error', (error) => {
75
+ console.error("MQTT connection error:", error);
76
+ });
77
+ this.client.on('message', (topic, message) => {
78
+ for (const subscribedTopic of this.subscribedTopics) {
79
+ if (topic === subscribedTopic.topic) {
80
+ const parsedMessage = this.parseMessage(message);
81
+ subscribedTopic.handler(parsedMessage);
82
+ break;
83
+ }
84
+ }
85
+ });
86
+ }
87
+ parseMessage(message) {
88
+ try {
89
+ return JSON.parse(message.toString());
90
+ }
91
+ catch (error) {
92
+ console.error("Error parsing message:", error);
93
+ return null;
94
+ }
95
+ }
96
+ }