@codenotch/codenotch.react 1.0.82 → 2.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/dist/components/CodeEditor.d.ts +1 -1
- package/dist/components/CodeEditor.d.ts.map +1 -1
- package/dist/components/CodeEditor.js +66 -64
- package/dist/index.d.ts +67 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +134 -113
- package/dist/models/Codenotch.d.ts +28 -131
- package/dist/models/Codenotch.d.ts.map +1 -1
- package/package.json +45 -44
- package/src/components/CodeEditor.tsx +204 -203
- package/src/index.ts +399 -385
- package/src/models/Codenotch.ts +29 -148
- package/README.md +0 -145
- package/dist/components/Auml.d.ts +0 -46
- package/dist/components/Auml.d.ts.map +0 -1
- package/dist/components/Auml.js +0 -208
- package/dist/models/AppManifestModels.d.ts +0 -46
- package/dist/models/AppManifestModels.d.ts.map +0 -1
- package/dist/models/AppManifestModels.js +0 -2
- package/dist/models/ProjectManifestModels.d.ts +0 -126
- package/dist/models/ProjectManifestModels.d.ts.map +0 -1
- package/dist/models/ProjectManifestModels.js +0 -158
- package/dist/utils/I18nUtils.d.ts +0 -7
- package/dist/utils/I18nUtils.d.ts.map +0 -1
- package/dist/utils/I18nUtils.js +0 -37
- package/src/core/ProcessUtils.ts +0 -86
- package/src/core/SignalR.ts +0 -375
package/src/core/SignalR.ts
DELETED
|
@@ -1,375 +0,0 @@
|
|
|
1
|
-
import { HttpTransportType, HubConnectionBuilder, HubConnectionState, LogLevel } from "@microsoft/signalr";
|
|
2
|
-
import { v4 } from "uuid";
|
|
3
|
-
import { IProcessCallbacks, ICodenotchSignal } from "../models/Misc";
|
|
4
|
-
import { IProcessResult } from "../models/Codenotch";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export class SignalR {
|
|
9
|
-
|
|
10
|
-
private _connection: signalR.HubConnection | null;
|
|
11
|
-
private _hubUrl: string;
|
|
12
|
-
private _accessToken: string | undefined;
|
|
13
|
-
|
|
14
|
-
// The callbacks coming from components when a signal is received
|
|
15
|
-
// Also used on the root component to keep track of which signals we listen to
|
|
16
|
-
private _signalCallbacks: {[signalId: string]: {[subscriptionId: string]: (signal: ICodenotchSignal) => void} };
|
|
17
|
-
|
|
18
|
-
// Store callbacks of ongoing processes
|
|
19
|
-
private _processCallbacks: {[processInstanceId: string]: IProcessCallbacks};
|
|
20
|
-
|
|
21
|
-
private _inactivityTimer: NodeJS.Timeout | null;
|
|
22
|
-
private _unsubscribeTimers: {[signalId: string]: NodeJS.Timeout} = {};
|
|
23
|
-
|
|
24
|
-
private _isConnecting: boolean = false;
|
|
25
|
-
private _pendingConnectionPromises: Array<{ resolve: () => void; reject: (error: Error) => void }> = [];
|
|
26
|
-
|
|
27
|
-
// Determines if connection should be kept alive even if there are no subscriptions
|
|
28
|
-
private _keepAlive: boolean;
|
|
29
|
-
|
|
30
|
-
public constructor(clusterUrl: string, serviceName: string, keepAlive: boolean, accessToken?: string)
|
|
31
|
-
{
|
|
32
|
-
this._hubUrl = `${clusterUrl}/${serviceName}/exec`;
|
|
33
|
-
this._accessToken = accessToken;
|
|
34
|
-
this._connection = null;
|
|
35
|
-
this._signalCallbacks = {};
|
|
36
|
-
this._processCallbacks = {};
|
|
37
|
-
|
|
38
|
-
this._inactivityTimer = null;
|
|
39
|
-
this._keepAlive = keepAlive;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async connect() {
|
|
43
|
-
|
|
44
|
-
console.log(`SignalR establishing connection...`)
|
|
45
|
-
|
|
46
|
-
this._isConnecting = true;
|
|
47
|
-
|
|
48
|
-
// Here we inject the access token if defined
|
|
49
|
-
let options: signalR.IHttpConnectionOptions = this._accessToken ? { accessTokenFactory: () => this._accessToken! } : {};
|
|
50
|
-
|
|
51
|
-
// Skip negotiation and only use websockets
|
|
52
|
-
// This allows us to have multiple SignalR server without sticky sessions
|
|
53
|
-
// But it won't work in the rare cases where websockets are not supported
|
|
54
|
-
options.skipNegotiation = true;
|
|
55
|
-
options.transport = HttpTransportType.WebSockets;
|
|
56
|
-
//TODO if the server has multi instances, and the one we are connected fails, do sticky sessions prevent us from connecting to a healthy instance ?
|
|
57
|
-
|
|
58
|
-
this._connection = new HubConnectionBuilder()
|
|
59
|
-
.withUrl(this._hubUrl, options)
|
|
60
|
-
.withAutomaticReconnect([0, 1000, 3000, 5000, 10000, 30000, 60000, 90000]) // If the server is a single instance and decide to change node, it might take a little while
|
|
61
|
-
.configureLogging(LogLevel.Error)
|
|
62
|
-
.build();
|
|
63
|
-
|
|
64
|
-
this._connection.off("ReceiveSignal");
|
|
65
|
-
this._connection.off("ReceiveLog");
|
|
66
|
-
this._connection.off("ReceiveCallback");
|
|
67
|
-
this._connection.off("ReceiveProcessOver");
|
|
68
|
-
|
|
69
|
-
// On Signal
|
|
70
|
-
this._connection.on("ReceiveSignal", (signal: ICodenotchSignal) => this.onSignalReceived(signal));
|
|
71
|
-
|
|
72
|
-
// On log
|
|
73
|
-
this._connection.on("ReceiveLog", (log: string) => {
|
|
74
|
-
console.log(log);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
// On callback received from process
|
|
78
|
-
//TODO only used to set wec content and redirect, do we still need those ?
|
|
79
|
-
this._connection.on("ReceiveCallback", (callback) => this.onProcessCallbackReceived(callback));
|
|
80
|
-
|
|
81
|
-
// On process completed
|
|
82
|
-
this._connection.on("ReceiveProcessOver", (processResult: IProcessResult) => this.onProcessOverReceived(processResult));
|
|
83
|
-
|
|
84
|
-
this._connection.onclose(
|
|
85
|
-
(error) => console.log(`disconnected: ${error ? error.message : "no error"}`)
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
this._connection.onreconnected(
|
|
89
|
-
() => this.resolvePendingRequests()
|
|
90
|
-
);
|
|
91
|
-
|
|
92
|
-
try
|
|
93
|
-
{
|
|
94
|
-
await this._connection.start();
|
|
95
|
-
console.log(`SignalR connection established`)
|
|
96
|
-
|
|
97
|
-
this.resolvePendingRequests();
|
|
98
|
-
this._isConnecting = false;
|
|
99
|
-
}
|
|
100
|
-
catch(err: any)
|
|
101
|
-
{
|
|
102
|
-
console.log(`SignalR connection error: ${err}`)
|
|
103
|
-
|
|
104
|
-
this.rejectPendingRequests(err);
|
|
105
|
-
this._isConnecting = false;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
private resolvePendingRequests()
|
|
110
|
-
{
|
|
111
|
-
if(this._pendingConnectionPromises.length > 0)
|
|
112
|
-
{
|
|
113
|
-
console.log(`Resolving ${this._pendingConnectionPromises.length} pending connection promises`);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
for(let p of this._pendingConnectionPromises)
|
|
117
|
-
{
|
|
118
|
-
p?.resolve();
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
private rejectPendingRequests(error: Error): void {
|
|
123
|
-
|
|
124
|
-
if(this._pendingConnectionPromises.length > 0)
|
|
125
|
-
{
|
|
126
|
-
console.log(`Rejecting ${this._pendingConnectionPromises.length} pending connection promises`);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
for(let p of this._pendingConnectionPromises)
|
|
130
|
-
{
|
|
131
|
-
p?.reject(error);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
private async ensureConnected() {
|
|
136
|
-
|
|
137
|
-
if(this._inactivityTimer)
|
|
138
|
-
{
|
|
139
|
-
// cancel disconnection
|
|
140
|
-
clearTimeout(this._inactivityTimer);
|
|
141
|
-
this._inactivityTimer = null;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
if(this._connection && this._connection.state === HubConnectionState.Connected)
|
|
145
|
-
{
|
|
146
|
-
return Promise.resolve();
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
console.log(`SignalR not currently connected, waiting on connection...`)
|
|
150
|
-
|
|
151
|
-
const connectionPromise = new Promise<void>((resolve, reject) => {
|
|
152
|
-
this._pendingConnectionPromises.push({ resolve, reject });
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
if (!this._isConnecting) {
|
|
156
|
-
this.connect();
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Return a promise that will resolve when the connection is established
|
|
160
|
-
return connectionPromise;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
private onSignalReceived(signal: ICodenotchSignal) {
|
|
165
|
-
try {
|
|
166
|
-
console.log(`Received signal '${signal.signalId}'`)
|
|
167
|
-
console.log(signal);
|
|
168
|
-
|
|
169
|
-
// parse the eventual data in the signal
|
|
170
|
-
if(signal.data)
|
|
171
|
-
{
|
|
172
|
-
try
|
|
173
|
-
{
|
|
174
|
-
signal.data = JSON.parse(signal.data);
|
|
175
|
-
}
|
|
176
|
-
catch {
|
|
177
|
-
// Data is not json but might still be valid
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// If signal id contains multiple paths, trigger each one
|
|
182
|
-
var signalPaths = this.getSignalPaths(signal.signalId);
|
|
183
|
-
|
|
184
|
-
for(let p of signalPaths)
|
|
185
|
-
{
|
|
186
|
-
if(this._signalCallbacks[p])
|
|
187
|
-
{
|
|
188
|
-
for(let callback of Object.values(this._signalCallbacks[p]))
|
|
189
|
-
{
|
|
190
|
-
callback(signal);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
catch (ex) {
|
|
196
|
-
console.log(`An exception occured during 'ReceiveSignal' callback:`);
|
|
197
|
-
console.log(ex);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
private getSignalPaths(signalId: string): string[]
|
|
202
|
-
{
|
|
203
|
-
// Signals can be segmented using '.', each segment corresponds to a more specific subject
|
|
204
|
-
// Subscribers can subscribe to a very specific signal or to a more general topic
|
|
205
|
-
// eg. Signal ref : invoice.update.0000-1111-2222-3333, will be received by subscribers on:
|
|
206
|
-
// -> 'invoice'
|
|
207
|
-
// -> 'invoice.update'
|
|
208
|
-
// -> 'invoice.update.0000-1111-2222-3333'
|
|
209
|
-
var signalPaths:string[] = [];
|
|
210
|
-
|
|
211
|
-
if(!signalId || signalId === '')
|
|
212
|
-
return signalPaths;
|
|
213
|
-
|
|
214
|
-
var segments = signalId.split('.');
|
|
215
|
-
for (let i = 0; i < segments.length; i++)
|
|
216
|
-
{
|
|
217
|
-
signalPaths.push(segments.slice(0, i + 1).join('.')); // "path" from index 0 to i
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
return signalPaths;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
private onProcessCallbackReceived(callback: {processInstanceId: string }) {
|
|
224
|
-
|
|
225
|
-
// Trigger the corresponding callback (set in ProcessUtils before launching the process)
|
|
226
|
-
if(this._processCallbacks[callback.processInstanceId])
|
|
227
|
-
{
|
|
228
|
-
this._processCallbacks[callback.processInstanceId].onCallback(callback)
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
private onProcessOverReceived(processResult: IProcessResult) {
|
|
233
|
-
|
|
234
|
-
// Trigger the corresponding callback (set in ProcessUtils before launching the process)
|
|
235
|
-
if(this._processCallbacks[processResult.processInstanceId])
|
|
236
|
-
{
|
|
237
|
-
this._processCallbacks[processResult.processInstanceId].onOver(processResult)
|
|
238
|
-
|
|
239
|
-
// Clean it, now that the process is over we should not receive anymore callbacks
|
|
240
|
-
delete this._processCallbacks[processResult.processInstanceId];
|
|
241
|
-
|
|
242
|
-
this.disconnectIfInactive();
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
async subscribeToProcessInstance(processInstanceId: string, callbacks: IProcessCallbacks) {
|
|
247
|
-
|
|
248
|
-
if(this._processCallbacks[processInstanceId])
|
|
249
|
-
{
|
|
250
|
-
// Already subscribed
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
await this.ensureConnected();
|
|
255
|
-
|
|
256
|
-
try
|
|
257
|
-
{
|
|
258
|
-
await this._connection!.invoke("SubscribeToInstanceEvents", processInstanceId);
|
|
259
|
-
|
|
260
|
-
// Setup callbacks
|
|
261
|
-
this._processCallbacks[processInstanceId] = callbacks;
|
|
262
|
-
}
|
|
263
|
-
catch(err)
|
|
264
|
-
{
|
|
265
|
-
console.error(`Couldn't subscribe to process '${processInstanceId}', : ${err}`)
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
async subscribeToSignal(signalId: string, callback: (signal: ICodenotchSignal) => void): Promise<() => Promise<void>> {
|
|
270
|
-
|
|
271
|
-
console.log(`subscribeToSignal: signalId:${signalId}`);
|
|
272
|
-
|
|
273
|
-
if (!signalId || signalId === "")
|
|
274
|
-
return () => Promise.resolve();
|
|
275
|
-
|
|
276
|
-
await this.ensureConnected();
|
|
277
|
-
|
|
278
|
-
if(this._unsubscribeTimers[signalId])
|
|
279
|
-
{
|
|
280
|
-
// cancel eventual unsubscription
|
|
281
|
-
clearTimeout(this._unsubscribeTimers[signalId]);
|
|
282
|
-
delete this._unsubscribeTimers[signalId];
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
if(!this._signalCallbacks[signalId])
|
|
286
|
-
{
|
|
287
|
-
// Create the subscription
|
|
288
|
-
try
|
|
289
|
-
{
|
|
290
|
-
await this._connection!.invoke("SubscribeToSignal", signalId);
|
|
291
|
-
|
|
292
|
-
// Remember which signals we are subscribed so we don't subscribe twice
|
|
293
|
-
if(!this._signalCallbacks[signalId])
|
|
294
|
-
{
|
|
295
|
-
this._signalCallbacks[signalId] = {};
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
}
|
|
299
|
-
catch(err)
|
|
300
|
-
{
|
|
301
|
-
throw `Couldn't subscribe to signal '${signalId}', : ${err}`;
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
// Generate a new id to keep track of each subscription
|
|
306
|
-
let subscriptionId = v4();
|
|
307
|
-
this._signalCallbacks[signalId][subscriptionId] = callback;
|
|
308
|
-
|
|
309
|
-
// Return the unsubscribe function
|
|
310
|
-
return async () => await this.unsubscribeFromSignal(signalId, subscriptionId);
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
async unsubscribeFromSignal(signalId: string, subscriptionId: string)
|
|
314
|
-
{
|
|
315
|
-
console.log(`unsubscribeFromSignal: signalId:${signalId}, subscriptionId:${subscriptionId}`);
|
|
316
|
-
|
|
317
|
-
if(!this._signalCallbacks[signalId])
|
|
318
|
-
{
|
|
319
|
-
return;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
delete this._signalCallbacks[signalId][subscriptionId];
|
|
323
|
-
|
|
324
|
-
// From this point we won't send events to the component who just unsubscribed, but we are still subscribed to the signal on the server so we'll recieve new signals
|
|
325
|
-
this.unsubscribeFromServerIfNoMoreSubscriptions(signalId);
|
|
326
|
-
|
|
327
|
-
// If no more subscriptions, we can disconnect from the server
|
|
328
|
-
this.disconnectIfInactive();
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
private unsubscribeFromServerIfNoMoreSubscriptions(signalId: string)
|
|
332
|
-
{
|
|
333
|
-
if(Object.keys(this._signalCallbacks[signalId]).length === 0)
|
|
334
|
-
{
|
|
335
|
-
delete this._signalCallbacks[signalId];
|
|
336
|
-
|
|
337
|
-
// No more subscriptions for this signal, we can unsubscribe from the server
|
|
338
|
-
// but in order to not send too many requests, we will wait a little bit before actually unsubscribing, the client might come back to the tab that need this signal in a few seconds
|
|
339
|
-
this._unsubscribeTimers[signalId] = setTimeout(() => this.unsubscribeSignalServer(signalId), 1 * 60 * 1000);
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
private async unsubscribeSignalServer(signalId: string)
|
|
344
|
-
{
|
|
345
|
-
console.log(`unsubscribeSignalServer: signalId:${signalId}`);
|
|
346
|
-
|
|
347
|
-
await this._connection!.invoke("UnsubscribeFromSignal", signalId);
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
private disconnectIfInactive()
|
|
351
|
-
{
|
|
352
|
-
if(this._keepAlive)
|
|
353
|
-
return;
|
|
354
|
-
|
|
355
|
-
if(Object.keys(this._signalCallbacks).length === 0 && Object.keys(this._processCallbacks).length === 0)
|
|
356
|
-
{
|
|
357
|
-
// No more subscriptions, disconnect from the server after a little while (5 minutes) to save resources
|
|
358
|
-
this._inactivityTimer = setTimeout(() => this.disconnect(), 5 * 60 * 1000);
|
|
359
|
-
console.log("SignalR has no more active subscriptions, will disconnect in 5 minutes...");
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
public disconnect(): void {
|
|
364
|
-
|
|
365
|
-
if (this._connection) {
|
|
366
|
-
this._connection.off("ReceiveCallback");
|
|
367
|
-
this._connection.off("ReceiveProcessOver");
|
|
368
|
-
this._connection.off("ReceiveSignal");
|
|
369
|
-
this._connection.off("ReceiveLog");
|
|
370
|
-
|
|
371
|
-
this._connection.stop();
|
|
372
|
-
this._connection = null;
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
}
|