@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.
- package/LICENSE +21 -0
- package/dist/cjs/classes/auth.d.ts +18 -0
- package/dist/cjs/classes/auth.js +90 -0
- package/dist/cjs/classes/collection.d.ts +18 -0
- package/dist/cjs/classes/collection.js +43 -0
- package/dist/cjs/classes/flow.d.ts +6 -0
- package/dist/cjs/classes/flow.js +12 -0
- package/dist/cjs/classes/function.d.ts +10 -0
- package/dist/cjs/classes/function.js +29 -0
- package/dist/cjs/classes/historian.d.ts +12 -0
- package/dist/cjs/classes/historian.js +40 -0
- package/dist/cjs/classes/tag.d.ts +10 -0
- package/dist/cjs/classes/tag.js +25 -0
- package/dist/cjs/client.d.ts +13 -0
- package/dist/cjs/client.js +35 -0
- package/dist/cjs/config.d.ts +21 -0
- package/dist/cjs/config.js +37 -0
- package/dist/cjs/example/functions-file-config.d.ts +0 -0
- package/dist/cjs/example/functions-file-config.js +1 -0
- package/dist/cjs/example/functions.d.ts +1 -0
- package/dist/cjs/example/functions.js +18 -0
- package/dist/cjs/http-client.d.ts +10 -0
- package/dist/cjs/http-client.js +62 -0
- package/dist/cjs/index.d.ts +6 -0
- package/dist/cjs/index.js +7 -0
- package/dist/cjs/sdk-ts-clean.d.ts +108 -0
- package/dist/cjs/sdk-ts-clean.js +294 -0
- package/dist/cjs/sdk-ts.d.ts +71 -0
- package/dist/cjs/sdk-ts.js +227 -0
- package/dist/cjs/services/http.service.d.ts +41 -0
- package/dist/cjs/services/http.service.js +178 -0
- package/dist/cjs/services/mqtt.service.d.ts +15 -0
- package/dist/cjs/services/mqtt.service.js +103 -0
- package/dist/cjs/services/nats.service.d.ts +78 -0
- package/dist/cjs/services/nats.service.js +237 -0
- package/dist/cjs/types/auth.models.d.ts +52 -0
- package/dist/cjs/types/auth.models.js +100 -0
- package/dist/cjs/types/recordID.models.d.ts +7 -0
- package/dist/cjs/types/recordID.models.js +32 -0
- package/dist/cjs/types/response.models.d.ts +4 -0
- package/dist/cjs/types/response.models.js +2 -0
- package/dist/cjs/types/tag.models.d.ts +4 -0
- package/dist/cjs/types/tag.models.js +2 -0
- package/dist/cjs/utils/appConfig.d.ts +5 -0
- package/dist/cjs/utils/appConfig.js +62 -0
- package/dist/cjs/websocket-client.d.ts +15 -0
- package/dist/cjs/websocket-client.js +96 -0
- package/dist/classes/auth.d.ts +18 -0
- package/dist/classes/auth.js +86 -0
- package/dist/classes/collection.d.ts +18 -0
- package/dist/classes/collection.js +39 -0
- package/dist/classes/flow.d.ts +6 -0
- package/dist/classes/flow.js +8 -0
- package/dist/classes/function.d.ts +10 -0
- package/dist/classes/function.js +25 -0
- package/dist/classes/historian.d.ts +12 -0
- package/dist/classes/historian.js +36 -0
- package/dist/classes/tag.d.ts +10 -0
- package/dist/classes/tag.js +21 -0
- package/dist/client.d.ts +13 -0
- package/dist/client.js +31 -0
- package/dist/config.d.ts +21 -0
- package/dist/config.js +33 -0
- package/dist/example/functions-file-config.d.ts +0 -0
- package/dist/example/functions-file-config.js +1 -0
- package/dist/example/functions.d.ts +1 -0
- package/dist/example/functions.js +16 -0
- package/dist/http-client.d.ts +10 -0
- package/dist/http-client.js +58 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +2 -0
- package/dist/sdk-ts-clean.d.ts +108 -0
- package/dist/sdk-ts-clean.js +290 -0
- package/dist/sdk-ts.d.ts +71 -0
- package/dist/sdk-ts.js +223 -0
- package/dist/services/http.service.d.ts +41 -0
- package/dist/services/http.service.js +173 -0
- package/dist/services/mqtt.service.d.ts +15 -0
- package/dist/services/mqtt.service.js +96 -0
- package/dist/services/nats.service.d.ts +78 -0
- package/dist/services/nats.service.js +233 -0
- package/dist/types/auth.models.d.ts +52 -0
- package/dist/types/auth.models.js +97 -0
- package/dist/types/recordID.models.d.ts +7 -0
- package/dist/types/recordID.models.js +27 -0
- package/dist/types/response.models.d.ts +4 -0
- package/dist/types/response.models.js +1 -0
- package/dist/types/tag.models.d.ts +4 -0
- package/dist/types/tag.models.js +1 -0
- package/dist/utils/appConfig.d.ts +5 -0
- package/dist/utils/appConfig.js +26 -0
- package/dist/websocket-client.d.ts +15 -0
- package/dist/websocket-client.js +92 -0
- package/package.json +33 -0
- package/src/classes/auth.ts +103 -0
- package/src/classes/collection.ts +55 -0
- package/src/classes/flow.ts +13 -0
- package/src/classes/function.ts +34 -0
- package/src/classes/historian.ts +49 -0
- package/src/classes/tag.ts +30 -0
- package/src/example/functions.ts +21 -0
- package/src/index.ts +8 -0
- package/src/sdk-ts.ts +255 -0
- package/src/services/http.service.ts +239 -0
- package/src/services/mqtt.service.ts +114 -0
- package/src/services/nats.service.ts +262 -0
- package/src/types/auth.models.ts +157 -0
- package/src/types/recordID.models.ts +33 -0
- package/src/types/response.models.ts +4 -0
- package/src/types/tag.models.ts +4 -0
- package/src/utils/appConfig.ts +30 -0
- package/tsconfig.json +14 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export declare class NATSService {
|
|
2
|
+
private url;
|
|
3
|
+
private functions;
|
|
4
|
+
private connection;
|
|
5
|
+
private static instance;
|
|
6
|
+
private subscribedSubjects;
|
|
7
|
+
private subscriptions;
|
|
8
|
+
private readonly EXEC_FUNCTION_SUBJECT;
|
|
9
|
+
constructor(url: string);
|
|
10
|
+
/**
|
|
11
|
+
* Returns a singleton instance of NATSService.
|
|
12
|
+
*/
|
|
13
|
+
static getInstance(url?: string): Promise<NATSService>;
|
|
14
|
+
/**
|
|
15
|
+
* Resets the singleton instance.
|
|
16
|
+
*/
|
|
17
|
+
static resetInstance(): void;
|
|
18
|
+
/**
|
|
19
|
+
* Connects to the NATS broker.
|
|
20
|
+
*/
|
|
21
|
+
private connect;
|
|
22
|
+
/**
|
|
23
|
+
* Adds a subject and handler to the subscribed list.
|
|
24
|
+
* @param subject {string} The subject to subscribe to.
|
|
25
|
+
* @param handler {(message: unknown) => void} The handler function for incoming messages.
|
|
26
|
+
*/
|
|
27
|
+
addSubjectHandler(subject: string, handler: (message: unknown) => void): void;
|
|
28
|
+
/**
|
|
29
|
+
* Subscribes to the EXEC_FUNCTION_SUBJECT and executes registered functions.
|
|
30
|
+
*/
|
|
31
|
+
initializeFunctions(): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Adds a new function to the registry.
|
|
34
|
+
* @param functionName {string} The name of the function to add.
|
|
35
|
+
* @param func {(data: Record<string, any>) => Promise<Record<string, any>> | Record<string, any>} The function implementation.
|
|
36
|
+
* @throws TypeError if the provided argument is not a function.
|
|
37
|
+
*/
|
|
38
|
+
addFunction(functionName: string, func: (data: Record<string, any>) => Promise<Record<string, any>> | Record<string, any>): void;
|
|
39
|
+
/**
|
|
40
|
+
* Executes a registered function by name with the provided arguments.
|
|
41
|
+
* @param functionName {string} The name of the function to execute.
|
|
42
|
+
* @param arg {Record<string, any>} The arguments to pass to the function. (JSON)
|
|
43
|
+
* @returns {Promise<Record<string, any>>} The result of the function execution. (JSON)
|
|
44
|
+
* @throws Error if the function is not found.
|
|
45
|
+
*/
|
|
46
|
+
executeFunction(functionName: string, arg: Record<string, any>): Promise<Record<string, any>>;
|
|
47
|
+
/**
|
|
48
|
+
* Clears all subscribed subjects.
|
|
49
|
+
*/
|
|
50
|
+
clearSubjects(): void;
|
|
51
|
+
/**
|
|
52
|
+
* Publishes a message to a specific subject.
|
|
53
|
+
* @param subject {string} The subject to publish to.
|
|
54
|
+
* @param message {unknown} The message to publish.
|
|
55
|
+
* @returns {boolean} True if the message was published successfully.
|
|
56
|
+
*/
|
|
57
|
+
publish(subject: string, message: unknown): boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Retrieves all registered functions.
|
|
60
|
+
* @returns {Record<string, (data: Record<string, any>) => Record<string, any>} An object containing all registered functions.
|
|
61
|
+
*/
|
|
62
|
+
getAllFunctions(): Record<string, (data: Record<string, any>) => Record<string, any>>;
|
|
63
|
+
static log(message?: any, ...optionalParams: any[]): void;
|
|
64
|
+
/**
|
|
65
|
+
* Prints the names of all available functions to the console.
|
|
66
|
+
*/
|
|
67
|
+
printFunctions(): void;
|
|
68
|
+
/**
|
|
69
|
+
* Parses a message buffer into a JSON object.
|
|
70
|
+
* @param message {Uint8Array} The message buffer.
|
|
71
|
+
* @returns {unknown} The parsed message.
|
|
72
|
+
*/
|
|
73
|
+
private parseMessage;
|
|
74
|
+
/**
|
|
75
|
+
* Gracefully unsubscribes from all NATS subscriptions and closes the connection.
|
|
76
|
+
*/
|
|
77
|
+
shutdown(): Promise<void>;
|
|
78
|
+
}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { wsconnect } from "@nats-io/nats-core";
|
|
2
|
+
import { connect } from "@nats-io/transport-node";
|
|
3
|
+
const HEALTH_SUBJECT = "runtime.typescript.health";
|
|
4
|
+
export class NATSService {
|
|
5
|
+
constructor(url) {
|
|
6
|
+
this.functions = {};
|
|
7
|
+
this.connection = null;
|
|
8
|
+
this.subscribedSubjects = [];
|
|
9
|
+
this.subscriptions = [];
|
|
10
|
+
this.EXEC_FUNCTION_SUBJECT = "runtime.exec.typescript.*";
|
|
11
|
+
this.url = url;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Returns a singleton instance of NATSService.
|
|
15
|
+
*/
|
|
16
|
+
static async getInstance(url = "ws://localhost:7500") {
|
|
17
|
+
if (!this.instance || !this.instance.connection) {
|
|
18
|
+
this.instance = new NATSService(url);
|
|
19
|
+
await this.instance.connect();
|
|
20
|
+
}
|
|
21
|
+
return this.instance;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Resets the singleton instance.
|
|
25
|
+
*/
|
|
26
|
+
static resetInstance() {
|
|
27
|
+
if (this.instance) {
|
|
28
|
+
this.instance.connection?.close();
|
|
29
|
+
this.instance = undefined;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Connects to the NATS broker.
|
|
34
|
+
*/
|
|
35
|
+
async connect() {
|
|
36
|
+
let retries = 0;
|
|
37
|
+
const maxRetries = 10;
|
|
38
|
+
while (!this.connection && retries < maxRetries) {
|
|
39
|
+
try {
|
|
40
|
+
// NATSService.log(`Connecting to NATS server (${this.url})...`);
|
|
41
|
+
if (this.url.startsWith("nats")) {
|
|
42
|
+
this.connection = await connect({ servers: this.url });
|
|
43
|
+
}
|
|
44
|
+
else if (this.url.startsWith("ws")) {
|
|
45
|
+
this.connection = await wsconnect({ servers: this.url });
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
NATSService.log("ERROR - Unsupported protocol : ", this.url.split("://")[0]);
|
|
49
|
+
}
|
|
50
|
+
this.connection?.publish(HEALTH_SUBJECT, JSON.stringify(true));
|
|
51
|
+
// NATSService.log(`Published message: true to ${HEALTH_SUBJECT}`);
|
|
52
|
+
// NATSService.log("Connected to NATS server");
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
NATSService.log("Caught an error during connection attempt:", err); // Debugging log
|
|
56
|
+
retries++;
|
|
57
|
+
console.error(`Failed to connect to NATS server. Retrying (${retries}/${maxRetries})...`, err);
|
|
58
|
+
if (retries >= maxRetries) {
|
|
59
|
+
throw new Error("Max retries reached. Unable to connect to NATS server.");
|
|
60
|
+
}
|
|
61
|
+
await new Promise((resolve) => setTimeout(resolve, 5000));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (!this.connection) {
|
|
65
|
+
throw new Error("Failed to establish a connection to the NATS server.");
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Adds a subject and handler to the subscribed list.
|
|
70
|
+
* @param subject {string} The subject to subscribe to.
|
|
71
|
+
* @param handler {(message: unknown) => void} The handler function for incoming messages.
|
|
72
|
+
*/
|
|
73
|
+
addSubjectHandler(subject, handler) {
|
|
74
|
+
try {
|
|
75
|
+
this.subscribedSubjects.push({ subject, handler });
|
|
76
|
+
NATSService.log("New Subscription Handler:", subject);
|
|
77
|
+
const sub = this.connection?.subscribe(subject, {
|
|
78
|
+
callback: (err, msg) => {
|
|
79
|
+
if (err) {
|
|
80
|
+
console.error(`Error handling message for subject ${subject}:`, err);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const parsedMessage = this.parseMessage(msg.data);
|
|
84
|
+
handler(parsedMessage);
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
if (sub)
|
|
88
|
+
this.subscriptions.push(sub);
|
|
89
|
+
}
|
|
90
|
+
catch (e) {
|
|
91
|
+
console.error(`Failed to subscribe to subject ${subject}:`, e);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Subscribes to the EXEC_FUNCTION_SUBJECT and executes registered functions.
|
|
96
|
+
*/
|
|
97
|
+
initializeFunctions() {
|
|
98
|
+
if (!this.connection) {
|
|
99
|
+
throw new Error("No active connection. Please connect to the NATS server first.");
|
|
100
|
+
}
|
|
101
|
+
const sub = this.connection.subscribe(this.EXEC_FUNCTION_SUBJECT, {
|
|
102
|
+
callback: (err, msg) => {
|
|
103
|
+
if (err) {
|
|
104
|
+
console.error("Error handling message:", err);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const data = JSON.parse(msg.data.toString());
|
|
108
|
+
const subjectParts = msg.subject.split(".");
|
|
109
|
+
if (subjectParts.length !== 4) {
|
|
110
|
+
msg.respond(JSON.stringify({ error: "Invalid subject format" }));
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const functionName = subjectParts[3];
|
|
114
|
+
this.executeFunction(functionName, data)
|
|
115
|
+
.then((result) => {
|
|
116
|
+
msg.respond(JSON.stringify(result));
|
|
117
|
+
})
|
|
118
|
+
.catch((e) => {
|
|
119
|
+
msg.respond(JSON.stringify({ status: "failed", error: e.message }));
|
|
120
|
+
});
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
if (sub)
|
|
124
|
+
this.subscriptions.push(sub);
|
|
125
|
+
NATSService.log(`Subscribed to '${this.EXEC_FUNCTION_SUBJECT}'`);
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Adds a new function to the registry.
|
|
130
|
+
* @param functionName {string} The name of the function to add.
|
|
131
|
+
* @param func {(data: Record<string, any>) => Promise<Record<string, any>> | Record<string, any>} The function implementation.
|
|
132
|
+
* @throws TypeError if the provided argument is not a function.
|
|
133
|
+
*/
|
|
134
|
+
addFunction(functionName, func) {
|
|
135
|
+
if (typeof func !== "function") {
|
|
136
|
+
throw new TypeError(`The provided argument '${functionName}' is not a function.`);
|
|
137
|
+
}
|
|
138
|
+
this.functions[functionName] = func;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Executes a registered function by name with the provided arguments.
|
|
142
|
+
* @param functionName {string} The name of the function to execute.
|
|
143
|
+
* @param arg {Record<string, any>} The arguments to pass to the function. (JSON)
|
|
144
|
+
* @returns {Promise<Record<string, any>>} The result of the function execution. (JSON)
|
|
145
|
+
* @throws Error if the function is not found.
|
|
146
|
+
*/
|
|
147
|
+
async executeFunction(functionName, arg) {
|
|
148
|
+
const func = this.functions[functionName];
|
|
149
|
+
if (!func) {
|
|
150
|
+
throw new Error(`Function '${functionName}' not found`);
|
|
151
|
+
}
|
|
152
|
+
return await func(arg);
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Clears all subscribed subjects.
|
|
156
|
+
*/
|
|
157
|
+
clearSubjects() {
|
|
158
|
+
this.subscribedSubjects = [];
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Publishes a message to a specific subject.
|
|
162
|
+
* @param subject {string} The subject to publish to.
|
|
163
|
+
* @param message {unknown} The message to publish.
|
|
164
|
+
* @returns {boolean} True if the message was published successfully.
|
|
165
|
+
*/
|
|
166
|
+
publish(subject, message) {
|
|
167
|
+
try {
|
|
168
|
+
const payload = JSON.stringify(message);
|
|
169
|
+
NATSService.log("Publishing to", subject, "with payload:", payload);
|
|
170
|
+
this.connection?.publish(subject, payload);
|
|
171
|
+
}
|
|
172
|
+
catch (e) {
|
|
173
|
+
console.error(`Failed to publish to subject ${subject}:`, e);
|
|
174
|
+
throw e;
|
|
175
|
+
}
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Retrieves all registered functions.
|
|
180
|
+
* @returns {Record<string, (data: Record<string, any>) => Record<string, any>} An object containing all registered functions.
|
|
181
|
+
*/
|
|
182
|
+
getAllFunctions() {
|
|
183
|
+
return this.functions;
|
|
184
|
+
}
|
|
185
|
+
static log(message, ...optionalParams) {
|
|
186
|
+
console.log("[TYPESCRIPT] >", message, ...optionalParams);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Prints the names of all available functions to the console.
|
|
190
|
+
*/
|
|
191
|
+
printFunctions() {
|
|
192
|
+
NATSService.log("Available functions: ", Object.keys(this.functions).join(", "));
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Parses a message buffer into a JSON object.
|
|
196
|
+
* @param message {Uint8Array} The message buffer.
|
|
197
|
+
* @returns {unknown} The parsed message.
|
|
198
|
+
*/
|
|
199
|
+
parseMessage(message) {
|
|
200
|
+
try {
|
|
201
|
+
return JSON.parse(Buffer.from(message).toString());
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
console.error("Error parsing message:", error);
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Gracefully unsubscribes from all NATS subscriptions and closes the connection.
|
|
210
|
+
*/
|
|
211
|
+
async shutdown() {
|
|
212
|
+
NATSService.log("Shutting down NATSService...");
|
|
213
|
+
for (const sub of this.subscriptions) {
|
|
214
|
+
try {
|
|
215
|
+
sub.unsubscribe();
|
|
216
|
+
}
|
|
217
|
+
catch (e) {
|
|
218
|
+
NATSService.log("Error unsubscribing:", e);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
this.subscriptions = [];
|
|
222
|
+
if (this.connection) {
|
|
223
|
+
try {
|
|
224
|
+
await this.connection.drain();
|
|
225
|
+
await this.connection.close();
|
|
226
|
+
}
|
|
227
|
+
catch (e) {
|
|
228
|
+
NATSService.log("Error closing NATS connection:", e);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
NATSService.log("NATSService shutdown complete.");
|
|
232
|
+
}
|
|
233
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { RecordID } from "./recordID.models";
|
|
2
|
+
import { BaseResponse } from "./response.models";
|
|
3
|
+
export interface LoginResponse extends BaseResponse {
|
|
4
|
+
tkn: string;
|
|
5
|
+
}
|
|
6
|
+
export interface PermissionResponse extends BaseResponse {
|
|
7
|
+
permission: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface ValidateJWTResponse extends BaseResponse {
|
|
10
|
+
valid: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface User {
|
|
13
|
+
id?: RecordID;
|
|
14
|
+
firstName: string;
|
|
15
|
+
lastName: string;
|
|
16
|
+
username: string;
|
|
17
|
+
email: string;
|
|
18
|
+
password: string;
|
|
19
|
+
number: string;
|
|
20
|
+
createdDt?: string;
|
|
21
|
+
userImage: string | ArrayBuffer | null;
|
|
22
|
+
group_ids?: string[];
|
|
23
|
+
}
|
|
24
|
+
export interface Group {
|
|
25
|
+
id?: RecordID;
|
|
26
|
+
features?: {
|
|
27
|
+
name: string;
|
|
28
|
+
action: string;
|
|
29
|
+
domain: string;
|
|
30
|
+
scope: string;
|
|
31
|
+
}[];
|
|
32
|
+
name: string;
|
|
33
|
+
user_ids: RecordID[];
|
|
34
|
+
}
|
|
35
|
+
export interface Feature {
|
|
36
|
+
name: string;
|
|
37
|
+
action: string;
|
|
38
|
+
scope: Scope;
|
|
39
|
+
}
|
|
40
|
+
export interface Permission {
|
|
41
|
+
displayName: string;
|
|
42
|
+
description: string;
|
|
43
|
+
name: string;
|
|
44
|
+
action: string;
|
|
45
|
+
scope: string;
|
|
46
|
+
}
|
|
47
|
+
export declare function machhubPermissions(): Permission[];
|
|
48
|
+
export interface ActionResponse extends BaseResponse {
|
|
49
|
+
action: "read" | "read-write" | "";
|
|
50
|
+
}
|
|
51
|
+
export type Action = "read" | "read-write";
|
|
52
|
+
export type Scope = "self" | "domain" | "all" | "nil";
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
;
|
|
2
|
+
;
|
|
3
|
+
export function machhubPermissions() {
|
|
4
|
+
return [
|
|
5
|
+
{
|
|
6
|
+
displayName: 'Applications',
|
|
7
|
+
description: 'View or manage applications all applications in MACHHUB',
|
|
8
|
+
name: 'applications',
|
|
9
|
+
action: 'nil',
|
|
10
|
+
scope: 'all'
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
displayName: 'Users',
|
|
14
|
+
description: 'View or manage user accounts in this domain',
|
|
15
|
+
name: 'users',
|
|
16
|
+
action: 'nil',
|
|
17
|
+
scope: 'domain'
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
displayName: 'Groups',
|
|
21
|
+
description: 'View or manage user groups in this domain',
|
|
22
|
+
name: 'groups',
|
|
23
|
+
action: 'nil',
|
|
24
|
+
scope: 'domain'
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
displayName: 'Manage Own API Keys',
|
|
28
|
+
description: 'View or manage API keys for own account',
|
|
29
|
+
name: 'api_keys',
|
|
30
|
+
action: 'nil',
|
|
31
|
+
scope: 'self'
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
displayName: 'Manage All API Keys',
|
|
35
|
+
description: 'View or manage all API keys in MACHHUB',
|
|
36
|
+
name: 'api_keys',
|
|
37
|
+
action: 'nil',
|
|
38
|
+
scope: 'all'
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
displayName: 'Upstreams',
|
|
42
|
+
description: 'View or manage all upstream configurations in MACHHUB',
|
|
43
|
+
name: 'upstreams',
|
|
44
|
+
action: 'nil',
|
|
45
|
+
scope: 'domain'
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
displayName: 'Manage Namespace',
|
|
49
|
+
description: 'View or manage namespaces in this domain',
|
|
50
|
+
name: 'namespace',
|
|
51
|
+
action: 'nil',
|
|
52
|
+
scope: 'domain'
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
displayName: 'Historian',
|
|
56
|
+
description: 'View or manage historian data in this domain',
|
|
57
|
+
name: 'historian',
|
|
58
|
+
action: 'nil',
|
|
59
|
+
scope: 'domain'
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
displayName: 'Collections',
|
|
63
|
+
description: 'View or manage collections in this domain',
|
|
64
|
+
name: 'collections',
|
|
65
|
+
action: 'nil',
|
|
66
|
+
scope: 'domain'
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
displayName: 'Logs',
|
|
70
|
+
description: 'View or manage system logs',
|
|
71
|
+
name: 'logs',
|
|
72
|
+
action: 'nil',
|
|
73
|
+
scope: 'all'
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
displayName: 'General Settings',
|
|
77
|
+
description: 'View or manage general system settings',
|
|
78
|
+
name: 'general_settings',
|
|
79
|
+
action: 'nil',
|
|
80
|
+
scope: 'all'
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
displayName: 'Gateway Settings',
|
|
84
|
+
description: 'View or manage gateway settings',
|
|
85
|
+
name: 'gateway',
|
|
86
|
+
action: 'nil',
|
|
87
|
+
scope: 'all'
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
displayName: 'License',
|
|
91
|
+
description: 'View or manage MACHHUB licensing details',
|
|
92
|
+
name: 'license',
|
|
93
|
+
action: 'nil',
|
|
94
|
+
scope: 'all'
|
|
95
|
+
}
|
|
96
|
+
];
|
|
97
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export function StringToRecordID(id) {
|
|
2
|
+
const splitID = id.split(":");
|
|
3
|
+
if (splitID.length != 2)
|
|
4
|
+
return emptyRecordID();
|
|
5
|
+
return {
|
|
6
|
+
Table: containsSpace(splitID[0]) ? `(${splitID[0]})` : splitID[0],
|
|
7
|
+
ID: splitID[1]
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export function RecordIDToString(recordID) {
|
|
11
|
+
if (recordID != undefined) {
|
|
12
|
+
return recordID.Table + ":" + recordID.ID;
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
return "";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function emptyRecordID() {
|
|
19
|
+
return {
|
|
20
|
+
Table: "",
|
|
21
|
+
ID: "",
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
// Helper function to check if a string contains spaces
|
|
25
|
+
function containsSpace(s) {
|
|
26
|
+
return s.includes(" ");
|
|
27
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
export function getAppConfig() {
|
|
4
|
+
console.log("getAppConfig");
|
|
5
|
+
if (typeof process !== 'undefined' && process.env && process.env.APP_CONFIG_PATH) {
|
|
6
|
+
// Node.js environment
|
|
7
|
+
console.log(process.env);
|
|
8
|
+
console.log(process.env.APP_CONFIG_PATH);
|
|
9
|
+
const configPath = process.env.APP_CONFIG_PATH || path.resolve(__dirname, '../../../sdk.config.json');
|
|
10
|
+
const rawData = fs.readFileSync(configPath, 'utf-8');
|
|
11
|
+
return JSON.parse(rawData);
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
try {
|
|
15
|
+
const configPath = path.resolve('../../../sdk.config.json');
|
|
16
|
+
console.log(configPath);
|
|
17
|
+
const rawData = fs.readFileSync(configPath, 'utf-8');
|
|
18
|
+
console.log("TEST");
|
|
19
|
+
console.log(rawData);
|
|
20
|
+
return JSON.parse(rawData);
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
throw new Error("Configuration not found. Set it via the APP_CONFIG_PATH environment variable : " + e);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ConfigManager } from './config';
|
|
2
|
+
export declare class WebSocketClient {
|
|
3
|
+
private configManager;
|
|
4
|
+
private ws;
|
|
5
|
+
private reconnectAttempts;
|
|
6
|
+
private maxReconnectAttempts;
|
|
7
|
+
private reconnectDelay;
|
|
8
|
+
constructor(configManager: ConfigManager);
|
|
9
|
+
updateConfig(): void;
|
|
10
|
+
connect(): Promise<void>;
|
|
11
|
+
disconnect(): void;
|
|
12
|
+
send(data: any): void;
|
|
13
|
+
private handleMessage;
|
|
14
|
+
private handleReconnect;
|
|
15
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
export class WebSocketClient {
|
|
2
|
+
constructor(configManager) {
|
|
3
|
+
this.ws = null;
|
|
4
|
+
this.reconnectAttempts = 0;
|
|
5
|
+
this.maxReconnectAttempts = 5;
|
|
6
|
+
this.reconnectDelay = 1000;
|
|
7
|
+
this.configManager = configManager;
|
|
8
|
+
}
|
|
9
|
+
updateConfig() {
|
|
10
|
+
// If connected, reconnect with new config
|
|
11
|
+
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
12
|
+
this.disconnect();
|
|
13
|
+
this.connect();
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
connect() {
|
|
17
|
+
return new Promise((resolve, reject) => {
|
|
18
|
+
const config = this.configManager.getConfig();
|
|
19
|
+
const wsUrl = config.wsUrl;
|
|
20
|
+
if (!wsUrl) {
|
|
21
|
+
reject(new Error('WebSocket URL not configured'));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
this.ws = new WebSocket(wsUrl);
|
|
26
|
+
this.ws.onopen = () => {
|
|
27
|
+
console.log('WebSocket connected');
|
|
28
|
+
this.reconnectAttempts = 0;
|
|
29
|
+
// Send runtime ID if available
|
|
30
|
+
if (config.runtimeId) {
|
|
31
|
+
this.send({ type: 'auth', runtimeId: config.runtimeId });
|
|
32
|
+
}
|
|
33
|
+
resolve();
|
|
34
|
+
};
|
|
35
|
+
this.ws.onmessage = (event) => {
|
|
36
|
+
try {
|
|
37
|
+
const data = JSON.parse(event.data);
|
|
38
|
+
this.handleMessage(data);
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
console.error('Failed to parse WebSocket message:', error);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
this.ws.onclose = (event) => {
|
|
45
|
+
console.log('WebSocket disconnected:', event.code, event.reason);
|
|
46
|
+
this.handleReconnect();
|
|
47
|
+
};
|
|
48
|
+
this.ws.onerror = (error) => {
|
|
49
|
+
console.error('WebSocket error:', error);
|
|
50
|
+
reject(error);
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
reject(error);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
disconnect() {
|
|
59
|
+
if (this.ws) {
|
|
60
|
+
this.ws.close();
|
|
61
|
+
this.ws = null;
|
|
62
|
+
}
|
|
63
|
+
this.reconnectAttempts = 0;
|
|
64
|
+
}
|
|
65
|
+
send(data) {
|
|
66
|
+
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
67
|
+
this.ws.send(JSON.stringify(data));
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
console.warn('WebSocket not connected, cannot send message');
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
handleMessage(data) {
|
|
74
|
+
// Handle incoming messages
|
|
75
|
+
console.log('WebSocket message received:', data);
|
|
76
|
+
}
|
|
77
|
+
handleReconnect() {
|
|
78
|
+
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
|
79
|
+
this.reconnectAttempts++;
|
|
80
|
+
const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);
|
|
81
|
+
console.log(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts})`);
|
|
82
|
+
setTimeout(() => {
|
|
83
|
+
this.connect().catch(error => {
|
|
84
|
+
console.error('Reconnection failed:', error);
|
|
85
|
+
});
|
|
86
|
+
}, delay);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
console.error('Max reconnection attempts reached');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|