codenotch-react 1.0.54 → 1.0.56

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.
@@ -14,7 +14,7 @@ export declare class Auml extends React.Component<IAumlProps, IAumlState> {
14
14
  componentWillUnmount(): void;
15
15
  progress(s: SpaRenderStatus): void;
16
16
  getLogo(): React.JSX.Element;
17
- getMode(theme: boolean | undefined): "dark" | "light";
17
+ getMode(theme: boolean | undefined): "light" | "dark";
18
18
  retrieveInputs(): {
19
19
  [k: string]: string;
20
20
  };
@@ -26,4 +26,4 @@ export declare class Auml extends React.Component<IAumlProps, IAumlState> {
26
26
  refreshExpiredToken(): Promise<void>;
27
27
  }
28
28
  export {};
29
- //# sourceMappingURL=auml.d.ts.map
29
+ //# sourceMappingURL=Auml.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Auml.d.ts","sourceRoot":"","sources":["../../src/components/Auml.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,eAAe,EAAE,MAAM,0EAA0E,CAAC;AAS3G,UAAU,UAAU;IAChB,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,UAAU;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,gBAAgB,EAAE,OAAO,CAAC;CAC7B;AAED,qBAAa,IAAK,SAAQ,KAAK,CAAC,SAAS,CAAC,UAAU,EAAE,UAAU,CAAC;IAE7D,kBAAkB,EAAE,MAAM,CAAC,OAAO,GAAG,SAAS,CAAC;gBAEnC,KAAK,EAAE,UAAU;IAQ7B,iBAAiB;IAmCjB,oBAAoB;IAQpB,QAAQ,CAAC,CAAC,EAAE,eAAe;IAO3B,OAAO;IAYP,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS;IAclC,cAAc;;;IAMd,wBAAwB,IAAI,MAAM,GAAG,IAAI;IAoCzC,2BAA2B,CAAC,kBAAkB,EAAE,MAAM,GAAG,MAAM;IAO/D,QAAQ,CAAC,EAAE,EAAE,MAAM;IAmBnB,QAAQ,CAAC,KAAK,EAAE,MAAM;IAsBtB,MAAM;IA2CA,mBAAmB;CAqC5B"}
@@ -150,12 +150,12 @@ export interface UserInfo {
150
150
  aumlManifest = appManifestObj.auml;
151
151
  }
152
152
  catch { }
153
- return (react_1.default.createElement("div", { className: "app" },
153
+ return react_1.default.createElement("div", { className: "app" },
154
154
  react_1.default.createElement(SpaRenderWithBrowserRouter_1.SpaRenderWithBrowserRouter, { appDescription: this.props.value, tenant: tenant, serviceName: serviceName, packageVersions: packageVersions, user: user, languages: languages, onProgress: (s) => this.progress(s), input: inputs, theme: theme, manifest: aumlManifest, inspectorEnabled: this.state.inspectorEnabled, children: [] }),
155
155
  !this.state.loaded &&
156
156
  react_1.default.createElement("div", { className: `app-loading ${this.getMode(theme)}` },
157
157
  this.getLogo(),
158
- react_1.default.createElement("i", { className: "fas fa-circle-notch fa-spin" }))));
158
+ react_1.default.createElement("i", { className: "fas fa-circle-notch fa-spin" })));
159
159
  }
160
160
  async refreshExpiredToken() {
161
161
  console.log("Token will expire soon, requesting a new one...");
@@ -0,0 +1,27 @@
1
+ import React from "react";
2
+ interface ICodeEditorProps {
3
+ style?: React.CSSProperties;
4
+ className?: string;
5
+ value?: string;
6
+ language?: string;
7
+ readOnly?: boolean;
8
+ onChange?: (value: string) => void;
9
+ }
10
+ /**
11
+ * Light version of Monaco Editor in an iframe.
12
+ */
13
+ export default class CodeEditor extends React.Component<ICodeEditorProps> {
14
+ private isIframeReady;
15
+ private onChangeTimeoutHandle;
16
+ refFrame: React.RefObject<HTMLIFrameElement>;
17
+ setValue(value: string): void;
18
+ componentDidMount(): void;
19
+ componentWillUnmount(): void;
20
+ componentDidUpdate(prevProps: ICodeEditorProps): void;
21
+ private handleMessage;
22
+ private postToIframe;
23
+ private writeIframe;
24
+ render(): React.JSX.Element;
25
+ }
26
+ export {};
27
+ //# sourceMappingURL=CodeEditor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CodeEditor.d.ts","sourceRoot":"","sources":["../../src/components/CodeEditor.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,UAAU,gBAAgB;IACtB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,KAAK,CAAC,SAAS,CAAC,gBAAgB,CAAC;IACrE,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,qBAAqB,CAAa;IAC1C,QAAQ,qCAAwC;IAEhD,QAAQ,CAAC,KAAK,EAAE,MAAM;IAStB,iBAAiB,IAAI,IAAI;IAKzB,oBAAoB,IAAI,IAAI;IAI5B,kBAAkB,CAAC,SAAS,EAAE,gBAAgB,GAAG,IAAI;IAoBrD,OAAO,CAAC,aAAa;IAgCrB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,WAAW;IA4EnB,MAAM;CAeT"}
@@ -0,0 +1,170 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const react_1 = __importDefault(require("react"));
7
+ const __1 = require("..");
8
+ /**
9
+ * Light version of Monaco Editor in an iframe.
10
+ */
11
+ class CodeEditor extends react_1.default.Component {
12
+ constructor() {
13
+ super(...arguments);
14
+ this.isIframeReady = false;
15
+ this.onChangeTimeoutHandle = null;
16
+ this.refFrame = react_1.default.createRef();
17
+ }
18
+ setValue(value) {
19
+ if (this.isIframeReady) {
20
+ this.postToIframe({
21
+ type: 'update',
22
+ value: value,
23
+ });
24
+ }
25
+ }
26
+ componentDidMount() {
27
+ window.addEventListener('message', this.handleMessage);
28
+ this.writeIframe();
29
+ }
30
+ componentWillUnmount() {
31
+ window.removeEventListener('message', this.handleMessage);
32
+ }
33
+ componentDidUpdate(prevProps) {
34
+ const changed = (prevProps.value !== this.props.value ||
35
+ prevProps.language !== this.props.language ||
36
+ prevProps.readOnly !== this.props.readOnly);
37
+ if (changed && this.isIframeReady) {
38
+ let isDark = (0, __1.useCodenotch)().getTheme() === 'dark';
39
+ this.postToIframe({
40
+ type: 'update',
41
+ value: this.props.value ?? '',
42
+ language: this.props.language || 'plaintext',
43
+ readOnly: !!this.props.readOnly,
44
+ theme: isDark ? 'vs-dark' : 'vs'
45
+ });
46
+ }
47
+ }
48
+ handleMessage(event) {
49
+ const data = event.data;
50
+ if (!data || typeof data !== 'object')
51
+ return;
52
+ if (data.__from !== 'MonacoIframe')
53
+ return;
54
+ switch (data.type) {
55
+ case 'ready': {
56
+ this.isIframeReady = true;
57
+ // send initial payload
58
+ this.postToIframe({
59
+ type: 'init',
60
+ value: this.props.value ?? '',
61
+ language: this.props.language || 'plaintext',
62
+ readOnly: !!this.props.readOnly,
63
+ theme: (0, __1.useCodenotch)().getTheme() === 'dark' ? 'vs-dark' : 'vs'
64
+ });
65
+ break;
66
+ }
67
+ case 'change': {
68
+ const next = String(data.value ?? '');
69
+ if (this.onChangeTimeoutHandle) {
70
+ clearTimeout(this.onChangeTimeoutHandle);
71
+ }
72
+ this.onChangeTimeoutHandle = setTimeout(() => {
73
+ this.props.onChange?.(next);
74
+ }, 300);
75
+ break;
76
+ }
77
+ }
78
+ }
79
+ ;
80
+ postToIframe(message) {
81
+ const w = this.refFrame.current?.contentWindow;
82
+ if (!w)
83
+ return;
84
+ w.postMessage({ __from: 'MonacoIframe', ...message }, '*');
85
+ }
86
+ writeIframe() {
87
+ const iframe = this.refFrame.current;
88
+ if (!iframe)
89
+ return;
90
+ const vsBase = 'https://cdn.jsdelivr.net/npm/monaco-editor@0.55.1/min/vs';
91
+ const html = `<!DOCTYPE html>
92
+ <html>
93
+ <head>
94
+ <meta charset="utf-8" />
95
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
96
+ <style>
97
+ html, body, #container { height: 100%; width: 100%; margin: 0; padding: 0; overflow: hidden; }
98
+ </style>
99
+ <script>
100
+ (function(){
101
+ var vsBase = ${JSON.stringify(vsBase)};
102
+ // AMD loader
103
+ var s = document.createElement('script');
104
+ s.src = vsBase + '/loader.js';
105
+ s.onload = function(){
106
+ // Configure and load monaco
107
+ window.require.config({ paths: { vs: vsBase } });
108
+ window.require(['vs/editor/editor.main'], function(){
109
+ var editor;
110
+
111
+ function post(msg){ parent.postMessage(Object.assign({__from:'MonacoIframe'}, msg), '*'); }
112
+
113
+ function ensureEditor(){
114
+ if (editor) return editor;
115
+ editor = monaco.editor.create(document.getElementById('container'), {
116
+ value: '',
117
+ language: 'plaintext',
118
+ theme: 'vs',
119
+ automaticLayout: true,
120
+ minimap: { enabled: false },
121
+ scrollBeyondLastLine: true,
122
+ wordWrap: "on"
123
+ });
124
+ editor.onDidChangeModelContent(function(){
125
+ var v = editor.getValue();
126
+ post({ type: 'change', value: v });
127
+ });
128
+ return editor;
129
+ }
130
+
131
+ window.addEventListener('message', function(ev){
132
+ var data = ev.data || {}; if (data.__from !== 'MonacoIframe') return;
133
+ if (data.type === 'init' || data.type === 'update'){
134
+ var ed = ensureEditor();
135
+ if (typeof data.value === 'string' && ed.getValue() !== data.value){ ed.setValue(data.value); }
136
+ if (typeof data.language === 'string') { monaco.editor.setModelLanguage(ed.getModel(), data.language); }
137
+ if (typeof data.theme === 'string') { monaco.editor.setTheme(data.theme); }
138
+ if (typeof data.readOnly === 'boolean') { ed.updateOptions({ readOnly: data.readOnly }); }
139
+ }
140
+ });
141
+
142
+ // Signal ready after monaco is loaded
143
+ post({ type: 'ready' });
144
+ });
145
+ };
146
+ document.head.appendChild(s);
147
+ })();
148
+ </script>
149
+ </head>
150
+ <body>
151
+ <div id="container"></div>
152
+ </body>
153
+ </html>`;
154
+ const doc = iframe.contentWindow?.document;
155
+ if (!doc)
156
+ return;
157
+ doc.open();
158
+ doc.write(html);
159
+ doc.close();
160
+ }
161
+ render() {
162
+ let style = this.props.style || {};
163
+ style.width = style.width || '100%';
164
+ style.height = style.height || '100%';
165
+ style.border = style.border || '0';
166
+ style.outline = style.outline || '0';
167
+ return react_1.default.createElement("iframe", { style: style, title: "Codenotch", ref: this.refFrame, className: this.props.className, sandbox: "allow-scripts allow-same-origin" });
168
+ }
169
+ }
170
+ exports.default = CodeEditor;
@@ -0,0 +1,9 @@
1
+ import { IProcessCallbacks, IProcessResult } from "../models/Misc";
2
+ /**
3
+ * static class mainly containing a method to start processes
4
+ */
5
+ export default class ProcessUtils {
6
+ static startProcess(subscribeFunc: (processInstanceId: string, callbacks: IProcessCallbacks) => Promise<void>, clusterUrl: string, tenantName: string, projectName: string, processId: string, processInput: any, processInstanceId?: string, startNodeId?: string, token?: string): Promise<IProcessResult>;
7
+ private static launchMainProcess;
8
+ }
9
+ //# sourceMappingURL=ProcessUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProcessUtils.d.ts","sourceRoot":"","sources":["../../src/core/ProcessUtils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEnE;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,YAAY;WAET,YAAY,CAAC,aAAa,EAAE,CAAC,iBAAiB,EAAE,MAAM,EAAE,SAAS,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,iBAAiB,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;mBAsCpS,iBAAiB;CAsCzC"}
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const uuid_1 = require("uuid");
4
+ /**
5
+ * static class mainly containing a method to start processes
6
+ */
7
+ class ProcessUtils {
8
+ static async startProcess(subscribeFunc, clusterUrl, tenantName, projectName, processId, processInput, processInstanceId, startNodeId, token) {
9
+ let instanceId = processInstanceId ? processInstanceId : (0, uuid_1.v4)();
10
+ return new Promise(async (resolve, reject) => {
11
+ try {
12
+ // Another class/component is responsible for listening to processes' states and calling back when they finish
13
+ await subscribeFunc(instanceId, {
14
+ onCallback: (callback) => {
15
+ //TODO check redirect ?
16
+ },
17
+ onOver: (processResult) => {
18
+ // The process has finished
19
+ resolve(processResult);
20
+ },
21
+ });
22
+ // Create a new process instance
23
+ await ProcessUtils.launchMainProcess(clusterUrl, tenantName, projectName, processId, processInput, instanceId, startNodeId, token);
24
+ }
25
+ catch (err) {
26
+ console.error(err);
27
+ let processResult = {
28
+ isError: true,
29
+ processInstanceId: instanceId,
30
+ output: {},
31
+ errorMessage: err.message
32
+ };
33
+ resolve(processResult);
34
+ }
35
+ });
36
+ }
37
+ static async launchMainProcess(clusterUrl, tenantName, projectName, processId, processInput, processInstanceId, startNodeId, token) {
38
+ console.log("launching main process");
39
+ let input = processInput ? processInput : {};
40
+ // We launch the process with an http request
41
+ let url = `${clusterUrl}/${projectName.toLowerCase()}/processes/${processId}/instances`;
42
+ let body = {
43
+ id: processInstanceId,
44
+ input: input,
45
+ startNode: startNodeId
46
+ };
47
+ let requestHeaders = new Headers();
48
+ requestHeaders.set('Content-Type', 'application/json');
49
+ if (token && token !== "") {
50
+ requestHeaders.set(`${tenantName}AccessToken`, token);
51
+ }
52
+ const response = await fetch(url, {
53
+ method: 'POST',
54
+ credentials: 'include', // forward auth cookiesbody
55
+ body: JSON.stringify(body),
56
+ headers: requestHeaders
57
+ });
58
+ if (!response.ok) {
59
+ // Something went wrong
60
+ let errorMessage = await response.text();
61
+ throw new Error(errorMessage);
62
+ }
63
+ }
64
+ }
65
+ exports.default = ProcessUtils;
@@ -0,0 +1,30 @@
1
+ import { IProcessCallbacks, ICodenotchSignal } from "../models/Misc";
2
+ export declare class SignalR {
3
+ private _connection;
4
+ private _hubUrl;
5
+ private _accessToken;
6
+ private _signalCallbacks;
7
+ private _processCallbacks;
8
+ private _inactivityTimer;
9
+ private _unsubscribeTimers;
10
+ private _isConnecting;
11
+ private _pendingConnectionPromises;
12
+ private _keepAlive;
13
+ constructor(clusterUrl: string, serviceName: string, keepAlive: boolean, accessToken?: string);
14
+ connect(): Promise<void>;
15
+ private resolvePendingRequests;
16
+ private rejectPendingRequests;
17
+ private ensureConnected;
18
+ private onSignalReceived;
19
+ private getSignalPaths;
20
+ private onProcessCallbackReceived;
21
+ private onProcessOverReceived;
22
+ subscribeToProcessInstance(processInstanceId: string, callbacks: IProcessCallbacks): Promise<void>;
23
+ subscribeToSignal(signalId: string, callback: (signal: ICodenotchSignal) => void): Promise<() => Promise<void>>;
24
+ unsubscribeFromSignal(signalId: string, subscriptionId: string): Promise<void>;
25
+ private unsubscribeFromServerIfNoMoreSubscriptions;
26
+ private unsubscribeSignalServer;
27
+ private disconnectIfInactive;
28
+ disconnect(): void;
29
+ }
30
+ //# sourceMappingURL=SignalR.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SignalR.d.ts","sourceRoot":"","sources":["../../src/core/SignalR.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAkB,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAIrF,qBAAa,OAAO;IAEhB,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAAqB;IAIzC,OAAO,CAAC,gBAAgB,CAAwF;IAGhH,OAAO,CAAC,iBAAiB,CAAmD;IAE5E,OAAO,CAAC,gBAAgB,CAAwB;IAChD,OAAO,CAAC,kBAAkB,CAA4C;IAEtE,OAAO,CAAC,aAAa,CAAkB;IACvC,OAAO,CAAC,0BAA0B,CAAsE;IAGxG,OAAO,CAAC,UAAU,CAAU;gBAET,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,MAAM;IAY9F,OAAO;IAmEb,OAAO,CAAC,sBAAsB;IAa9B,OAAO,CAAC,qBAAqB;YAaf,eAAe;IA6B7B,OAAO,CAAC,gBAAgB;IAqCxB,OAAO,CAAC,cAAc;IAsBtB,OAAO,CAAC,yBAAyB;IASjC,OAAO,CAAC,qBAAqB;IAcvB,0BAA0B,CAAC,iBAAiB,EAAE,MAAM,EAAE,SAAS,EAAE,iBAAiB;IAuBlF,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,GAAG,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IA4C/G,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM;IAkBpE,OAAO,CAAC,0CAA0C;YAYpC,uBAAuB;IAOrC,OAAO,CAAC,oBAAoB;IAarB,UAAU,IAAI,IAAI;CAY5B"}
@@ -0,0 +1,245 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SignalR = void 0;
4
+ const signalr_1 = require("@microsoft/signalr");
5
+ const uuid_1 = require("uuid");
6
+ class SignalR {
7
+ constructor(clusterUrl, serviceName, keepAlive, accessToken) {
8
+ this._unsubscribeTimers = {};
9
+ this._isConnecting = false;
10
+ this._pendingConnectionPromises = [];
11
+ this._hubUrl = `${clusterUrl}/${serviceName}/exec`;
12
+ this._accessToken = accessToken;
13
+ this._connection = null;
14
+ this._signalCallbacks = {};
15
+ this._processCallbacks = {};
16
+ this._inactivityTimer = null;
17
+ this._keepAlive = keepAlive;
18
+ }
19
+ async connect() {
20
+ console.log(`SignalR establishing connection...`);
21
+ this._isConnecting = true;
22
+ // Here we inject the access token if defined
23
+ let options = this._accessToken ? { accessTokenFactory: () => this._accessToken } : {};
24
+ // Skip negotiation and only use websockets
25
+ // This allows us to have multiple SignalR server without sticky sessions
26
+ // But it won't work in the rare cases where websockets are not supported
27
+ options.skipNegotiation = true;
28
+ options.transport = signalr_1.HttpTransportType.WebSockets;
29
+ //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 ?
30
+ this._connection = new signalr_1.HubConnectionBuilder()
31
+ .withUrl(this._hubUrl, options)
32
+ .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
33
+ .configureLogging(signalr_1.LogLevel.Error)
34
+ .build();
35
+ this._connection.off("ReceiveSignal");
36
+ this._connection.off("ReceiveLog");
37
+ this._connection.off("ReceiveCallback");
38
+ this._connection.off("ReceiveProcessOver");
39
+ // On Signal
40
+ this._connection.on("ReceiveSignal", (signal) => this.onSignalReceived(signal));
41
+ // On log
42
+ this._connection.on("ReceiveLog", (log) => {
43
+ console.log(log);
44
+ });
45
+ // On callback received from process
46
+ //TODO only used to set wec content and redirect, do we still need those ?
47
+ this._connection.on("ReceiveCallback", (callback) => this.onProcessCallbackReceived(callback));
48
+ // On process completed
49
+ this._connection.on("ReceiveProcessOver", (processResult) => this.onProcessOverReceived(processResult));
50
+ this._connection.onclose((error) => console.log(`disconnected: ${error ? error.message : "no error"}`));
51
+ this._connection.onreconnected(() => this.resolvePendingRequests());
52
+ try {
53
+ await this._connection.start();
54
+ console.log(`SignalR connection established`);
55
+ this.resolvePendingRequests();
56
+ this._isConnecting = false;
57
+ }
58
+ catch (err) {
59
+ console.log(`SignalR connection error: ${err}`);
60
+ this.rejectPendingRequests(err);
61
+ this._isConnecting = false;
62
+ }
63
+ }
64
+ resolvePendingRequests() {
65
+ if (this._pendingConnectionPromises.length > 0) {
66
+ console.log(`Resolving ${this._pendingConnectionPromises.length} pending connection promises`);
67
+ }
68
+ for (let p of this._pendingConnectionPromises) {
69
+ p?.resolve();
70
+ }
71
+ }
72
+ rejectPendingRequests(error) {
73
+ if (this._pendingConnectionPromises.length > 0) {
74
+ console.log(`Rejecting ${this._pendingConnectionPromises.length} pending connection promises`);
75
+ }
76
+ for (let p of this._pendingConnectionPromises) {
77
+ p?.reject(error);
78
+ }
79
+ }
80
+ async ensureConnected() {
81
+ if (this._inactivityTimer) {
82
+ // cancel disconnection
83
+ clearTimeout(this._inactivityTimer);
84
+ this._inactivityTimer = null;
85
+ }
86
+ if (this._connection && this._connection.state === signalr_1.HubConnectionState.Connected) {
87
+ return Promise.resolve();
88
+ }
89
+ console.log(`SignalR not currently connected, waiting on connection...`);
90
+ const connectionPromise = new Promise((resolve, reject) => {
91
+ this._pendingConnectionPromises.push({ resolve, reject });
92
+ });
93
+ if (!this._isConnecting) {
94
+ this.connect();
95
+ }
96
+ // Return a promise that will resolve when the connection is established
97
+ return connectionPromise;
98
+ }
99
+ onSignalReceived(signal) {
100
+ try {
101
+ console.log(`Received signal '${signal.signalId}'`);
102
+ console.log(signal);
103
+ // parse the eventual data in the signal
104
+ if (signal.data) {
105
+ try {
106
+ signal.data = JSON.parse(signal.data);
107
+ }
108
+ catch {
109
+ // Data is not json but might still be valid
110
+ }
111
+ }
112
+ // If signal id contains multiple paths, trigger each one
113
+ var signalPaths = this.getSignalPaths(signal.signalId);
114
+ for (let p of signalPaths) {
115
+ if (this._signalCallbacks[p]) {
116
+ for (let callback of Object.values(this._signalCallbacks[p])) {
117
+ callback(signal);
118
+ }
119
+ }
120
+ }
121
+ }
122
+ catch (ex) {
123
+ console.log(`An exception occured during 'ReceiveSignal' callback:`);
124
+ console.log(ex);
125
+ }
126
+ }
127
+ getSignalPaths(signalId) {
128
+ // Signals can be segmented using '.', each segment corresponds to a more specific subject
129
+ // Subscribers can subscribe to a very specific signal or to a more general topic
130
+ // eg. Signal ref : invoice.update.0000-1111-2222-3333, will be received by subscribers on:
131
+ // -> 'invoice'
132
+ // -> 'invoice.update'
133
+ // -> 'invoice.update.0000-1111-2222-3333'
134
+ var signalPaths = [];
135
+ if (!signalId || signalId === '')
136
+ return signalPaths;
137
+ var segments = signalId.split('.');
138
+ for (let i = 0; i < segments.length; i++) {
139
+ signalPaths.push(segments.slice(0, i + 1).join('.')); // "path" from index 0 to i
140
+ }
141
+ return signalPaths;
142
+ }
143
+ onProcessCallbackReceived(callback) {
144
+ // Trigger the corresponding callback (set in ProcessUtils before launching the process)
145
+ if (this._processCallbacks[callback.processInstanceId]) {
146
+ this._processCallbacks[callback.processInstanceId].onCallback(callback);
147
+ }
148
+ }
149
+ onProcessOverReceived(processResult) {
150
+ // Trigger the corresponding callback (set in ProcessUtils before launching the process)
151
+ if (this._processCallbacks[processResult.processInstanceId]) {
152
+ this._processCallbacks[processResult.processInstanceId].onOver(processResult);
153
+ // Clean it, now that the process is over we should not receive anymore callbacks
154
+ delete this._processCallbacks[processResult.processInstanceId];
155
+ this.disconnectIfInactive();
156
+ }
157
+ }
158
+ async subscribeToProcessInstance(processInstanceId, callbacks) {
159
+ if (this._processCallbacks[processInstanceId]) {
160
+ // Already subscribed
161
+ return;
162
+ }
163
+ await this.ensureConnected();
164
+ try {
165
+ await this._connection.invoke("SubscribeToInstanceEvents", processInstanceId);
166
+ // Setup callbacks
167
+ this._processCallbacks[processInstanceId] = callbacks;
168
+ }
169
+ catch (err) {
170
+ console.error(`Couldn't subscribe to process '${processInstanceId}', : ${err}`);
171
+ }
172
+ }
173
+ async subscribeToSignal(signalId, callback) {
174
+ console.log(`subscribeToSignal: signalId:${signalId}`);
175
+ if (!signalId || signalId === "")
176
+ return () => Promise.resolve();
177
+ await this.ensureConnected();
178
+ if (this._unsubscribeTimers[signalId]) {
179
+ // cancel eventual unsubscription
180
+ clearTimeout(this._unsubscribeTimers[signalId]);
181
+ delete this._unsubscribeTimers[signalId];
182
+ }
183
+ if (!this._signalCallbacks[signalId]) {
184
+ // Create the subscription
185
+ try {
186
+ await this._connection.invoke("SubscribeToSignal", signalId);
187
+ // Remember which signals we are subscribed so we don't subscribe twice
188
+ if (!this._signalCallbacks[signalId]) {
189
+ this._signalCallbacks[signalId] = {};
190
+ }
191
+ }
192
+ catch (err) {
193
+ throw `Couldn't subscribe to signal '${signalId}', : ${err}`;
194
+ }
195
+ }
196
+ // Generate a new id to keep track of each subscription
197
+ let subscriptionId = (0, uuid_1.v4)();
198
+ this._signalCallbacks[signalId][subscriptionId] = callback;
199
+ // Return the unsubscribe function
200
+ return async () => await this.unsubscribeFromSignal(signalId, subscriptionId);
201
+ }
202
+ async unsubscribeFromSignal(signalId, subscriptionId) {
203
+ console.log(`unsubscribeFromSignal: signalId:${signalId}, subscriptionId:${subscriptionId}`);
204
+ if (!this._signalCallbacks[signalId]) {
205
+ return;
206
+ }
207
+ delete this._signalCallbacks[signalId][subscriptionId];
208
+ // 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
209
+ this.unsubscribeFromServerIfNoMoreSubscriptions(signalId);
210
+ // If no more subscriptions, we can disconnect from the server
211
+ this.disconnectIfInactive();
212
+ }
213
+ unsubscribeFromServerIfNoMoreSubscriptions(signalId) {
214
+ if (Object.keys(this._signalCallbacks[signalId]).length === 0) {
215
+ delete this._signalCallbacks[signalId];
216
+ // No more subscriptions for this signal, we can unsubscribe from the server
217
+ // 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
218
+ this._unsubscribeTimers[signalId] = setTimeout(() => this.unsubscribeSignalServer(signalId), 1 * 60 * 1000);
219
+ }
220
+ }
221
+ async unsubscribeSignalServer(signalId) {
222
+ console.log(`unsubscribeSignalServer: signalId:${signalId}`);
223
+ await this._connection.invoke("UnsubscribeFromSignal", signalId);
224
+ }
225
+ disconnectIfInactive() {
226
+ if (this._keepAlive)
227
+ return;
228
+ if (Object.keys(this._signalCallbacks).length === 0 && Object.keys(this._processCallbacks).length === 0) {
229
+ // No more subscriptions, disconnect from the server after a little while (5 minutes) to save resources
230
+ this._inactivityTimer = setTimeout(() => this.disconnect(), 5 * 60 * 1000);
231
+ console.log("SignalR has no more active subscriptions, will disconnect in 5 minutes...");
232
+ }
233
+ }
234
+ disconnect() {
235
+ if (this._connection) {
236
+ this._connection.off("ReceiveCallback");
237
+ this._connection.off("ReceiveProcessOver");
238
+ this._connection.off("ReceiveSignal");
239
+ this._connection.off("ReceiveLog");
240
+ this._connection.stop();
241
+ this._connection = null;
242
+ }
243
+ }
244
+ }
245
+ exports.SignalR = SignalR;
package/dist/index.d.ts CHANGED
@@ -1,51 +1,18 @@
1
- export interface ICodenotchEnv {
2
- clusterUrl?: string;
3
- serviceName?: string;
4
- tenantName?: string;
5
- accessToken?: string;
6
- baseUrl?: string;
7
- i18n?: {
8
- [language: string]: {
9
- [key: string]: string;
10
- };
11
- };
12
- currentLanguage?: string;
13
- [key: string]: any;
14
- }
15
- export interface ICodenotchApi {
16
- ENV: ICodenotchEnv;
17
- requestSioql: (sioql: string, verbose?: boolean) => Promise<any>;
18
- startProcess: (processName: string) => Promise<{
19
- success: boolean;
20
- }>;
21
- onSignal: (signalId: string, callback: () => void) => {
22
- dispose: () => void;
23
- };
24
- showDialog: (node: JSX.Element) => ICodenotchDialog;
25
- }
26
- export interface ICodenotchDialog {
27
- id: string;
28
- close: () => void;
29
- }
30
- declare const CODENOTCH_ENV: ICodenotchEnv;
31
- /**
32
- * Parse URL parameters and return them as an object
33
- * @returns {Object} An object containing the URL parameters as key-value pairs
34
- */
35
- export declare function parseUrlParams(): {
36
- [key: string]: string;
37
- };
1
+ import { ICodenotchApi, ICodenotchDialog, ICodenotchEnv } from "./models/Codenotch";
2
+ import { Auml } from "./components/Auml";
3
+ import CodeEditor from "./components/CodeEditor";
4
+ declare const env: ICodenotchEnv;
38
5
  /**
39
6
  * Setup Codenotch environment from the given object
40
7
  * @param env An object containing the Codenotch environment variables as key-value pairs. This can be obtained from URL parameters or any other source.
41
8
  * @returns {void}
42
9
  */
43
- export declare function setupCodenotchEnv(env: any): void;
44
- export declare function i18n(key: string, ...args: any[]): string;
10
+ declare function setupCodenotchEnv(env: any): void;
11
+ declare function i18n(key: string, ...args: any[]): string;
45
12
  /**
46
13
  * Return Codenotch API
47
14
  * @returns {ICodenotchApi} Codenotch API
48
15
  */
49
- export declare function useCodenotch(): ICodenotchApi;
50
- export { CODENOTCH_ENV };
16
+ declare function useCodenotch(): ICodenotchApi;
17
+ export { env as CODENOTCH_ENV, i18n, useCodenotch, setupCodenotchEnv, ICodenotchEnv, ICodenotchApi, ICodenotchDialog, Auml, CodeEditor };
51
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,aAAa;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE;QAAE,CAAC,QAAQ,EAAE,MAAM,GAAG;YAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IACzD,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC1B,GAAG,EAAE,aAAa,CAAC;IACnB,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;IACjE,YAAY,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACrE,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK;QAAE,OAAO,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;IAC9E,UAAU,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,OAAO,KAAK,gBAAgB,CAAC;CACvD;AAED,MAAM,WAAW,gBAAgB;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,QAAA,MAAM,aAAa,EAAE,aAAkB,CAAC;AAExC;;;GAGG;AACH,wBAAgB,cAAc,IAAI;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAW1D;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CA4ChD;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,MAAM,CAoCxD;AAED;;;GAGG;AACH,wBAAgB,YAAY,IAAI,aAAa,CAwH5C;AAGD,OAAO,EAAE,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEpF,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,UAAU,MAAM,yBAAyB,CAAC;AAIjD,QAAA,MAAM,GAAG,EAAE,aAAkB,CAAC;AAO9B;;;;GAIG;AACH,iBAAS,iBAAiB,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CAgDzC;AAED,iBAAS,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,MAAM,CAoCjD;AAED;;;GAGG;AACH,iBAAS,YAAY,IAAI,aAAa,CAsKrC;AAED,OAAO,EACH,GAAG,IAAI,aAAa,EACpB,IAAI,EACJ,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,IAAI,EACJ,UAAU,EACb,CAAC"}
package/dist/index.js CHANGED
@@ -3,30 +3,24 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.CODENOTCH_ENV = void 0;
7
- exports.parseUrlParams = parseUrlParams;
8
- exports.setupCodenotchEnv = setupCodenotchEnv;
6
+ exports.CodeEditor = exports.Auml = exports.CODENOTCH_ENV = void 0;
9
7
  exports.i18n = i18n;
10
8
  exports.useCodenotch = useCodenotch;
9
+ exports.setupCodenotchEnv = setupCodenotchEnv;
11
10
  const react_dom_1 = __importDefault(require("react-dom"));
12
- const CODENOTCH_ENV = {};
13
- exports.CODENOTCH_ENV = CODENOTCH_ENV;
14
- /**
15
- * Parse URL parameters and return them as an object
16
- * @returns {Object} An object containing the URL parameters as key-value pairs
17
- */
18
- function parseUrlParams() {
19
- let result = {};
20
- if (typeof window !== 'undefined') {
21
- const params = new URL(window.location.href).searchParams;
22
- params.forEach((value, key) => {
23
- if (result[key] === undefined) {
24
- result[key] = value;
25
- }
26
- });
27
- }
28
- return result;
29
- }
11
+ const SignalR_1 = require("./core/SignalR");
12
+ const ProcessUtils_1 = __importDefault(require("./core/ProcessUtils"));
13
+ const uuid_1 = require("uuid");
14
+ const Auml_1 = require("./components/Auml");
15
+ Object.defineProperty(exports, "Auml", { enumerable: true, get: function () { return Auml_1.Auml; } });
16
+ const CodeEditor_1 = __importDefault(require("./components/CodeEditor"));
17
+ exports.CodeEditor = CodeEditor_1.default;
18
+ var signalR = undefined;
19
+ const env = {};
20
+ exports.CODENOTCH_ENV = env;
21
+ const MISSING_CLUSTER_URL_ERROR = "Codenotch cluster URL is not defined. Please set it in the Codenotch configuration.";
22
+ const MISSING_SERVICE_NAME_ERROR = "Codenotch service name is not defined. Please set it in the Codenotch configuration.";
23
+ const MISSING_TENANT_NAME_ERROR = "Codenotch tenant name is not defined. Please set it in the Codenotch configuration.";
30
24
  /**
31
25
  * Setup Codenotch environment from the given object
32
26
  * @param env An object containing the Codenotch environment variables as key-value pairs. This can be obtained from URL parameters or any other source.
@@ -56,37 +50,40 @@ function setupCodenotchEnv(env) {
56
50
  console.warn(`Codenotch environment variable ${key} is not a valid JSON string. Using raw value.`);
57
51
  }
58
52
  }
59
- CODENOTCH_ENV.i18n = CODENOTCH_ENV.i18n ?? {};
60
- CODENOTCH_ENV.i18n[language] = CODENOTCH_ENV.i18n[language] ?? {};
61
- CODENOTCH_ENV.i18n[language][keyName] = keyValue;
53
+ env.i18n = env.i18n ?? {};
54
+ env.i18n[language] = env.i18n[language] ?? {};
55
+ env.i18n[language][keyName] = keyValue;
62
56
  }
63
57
  else {
64
- CODENOTCH_ENV[key] = env[key];
58
+ env[key] = env[key];
65
59
  console.log(`Codenotch environment variable ${key} set to ${env[key]}`);
66
60
  }
67
61
  });
68
- if (CODENOTCH_ENV.currentLanguage === undefined) {
62
+ if (env.language === undefined) {
69
63
  // If current language is not defined, we set it to the first language found in i18n
70
64
  if (i18nLanguages.size > 0) {
71
- CODENOTCH_ENV.currentLanguage = Array.from(i18nLanguages)[0];
72
- console.log(`Codenotch current language set to ${CODENOTCH_ENV.currentLanguage}`);
65
+ env.language = Array.from(i18nLanguages)[0];
66
+ console.log(`Codenotch current language set to ${env.language}`);
73
67
  }
74
68
  }
69
+ if (env.clusterUrl && env.serviceName) {
70
+ signalR = new SignalR_1.SignalR(env.clusterUrl, env.serviceName, false, env.accessToken);
71
+ }
75
72
  }
76
73
  function i18n(key, ...args) {
77
74
  try {
78
- if (CODENOTCH_ENV.i18n === undefined || Object.keys(CODENOTCH_ENV.i18n).length === 0) {
75
+ if (env.i18n === undefined || Object.keys(env.i18n).length === 0) {
79
76
  console.warn("Codenotch i18n is not defined. Please set it in the Codenotch configuration.");
80
77
  return key;
81
78
  }
82
- let language = CODENOTCH_ENV.currentLanguage ?? "en";
83
- let isLanguageExists = CODENOTCH_ENV.i18n[language] !== undefined;
79
+ let language = env.language ?? "en";
80
+ let isLanguageExists = env.i18n[language] !== undefined;
84
81
  if (isLanguageExists === false) {
85
- let fallbackLanguage = Object.keys(CODENOTCH_ENV.i18n)[0];
82
+ let fallbackLanguage = Object.keys(env.i18n)[0];
86
83
  console.warn(`Codenotch i18n language ${language} is not defined. Falling back to ${fallbackLanguage}. Please set the correct language in the Codenotch configuration.`);
87
84
  language = fallbackLanguage;
88
85
  }
89
- let dico = CODENOTCH_ENV.i18n[language];
86
+ let dico = env.i18n[language];
90
87
  let value = dico[key];
91
88
  if (typeof value !== "string") {
92
89
  console.warn(`Codenotch i18n key ${key} is not defined for language ${language}. Please set it in the Codenotch configuration.`);
@@ -111,53 +108,76 @@ function i18n(key, ...args) {
111
108
  */
112
109
  function useCodenotch() {
113
110
  return {
114
- ENV: CODENOTCH_ENV,
115
- requestSioql: async (sioql, verbose) => {
116
- if (CODENOTCH_ENV.clusterUrl === undefined) {
117
- throw new Error("Codenotch cluster URL is not defined. Please set it in the Codenotch configuration.");
118
- }
119
- if (CODENOTCH_ENV.serviceName === undefined) {
120
- throw new Error("Codenotch service name is not defined. Please set it in the Codenotch configuration.");
121
- }
122
- let url = `${CODENOTCH_ENV.clusterUrl}/${CODENOTCH_ENV.serviceName}/sioql`;
123
- if (verbose) {
124
- url += "?v=true";
111
+ env: env,
112
+ uuid: () => (0, uuid_1.v4)(),
113
+ getProjectFileUrl: (relativePath) => {
114
+ if (env.clusterUrl === undefined)
115
+ throw new Error(MISSING_CLUSTER_URL_ERROR);
116
+ if (env.serviceName === undefined)
117
+ throw new Error(MISSING_SERVICE_NAME_ERROR);
118
+ relativePath = relativePath.replace(/\\/g, "/");
119
+ if (relativePath.startsWith("/"))
120
+ relativePath = relativePath.substring(1);
121
+ let url = `${env.clusterUrl}/${env.serviceName}/project/file?name=""&path=${encodeURIComponent(relativePath)}`;
122
+ return url;
123
+ },
124
+ getProjectFile: async (relativePath) => {
125
+ let url = useCodenotch().getProjectFileUrl(relativePath);
126
+ let resp = await fetch(url);
127
+ if (resp.status.toString().startsWith('2') === false) {
128
+ throw new Error(`Failed to fetch file content: ${resp.status} ${resp.statusText}`);
125
129
  }
130
+ let content = await resp.text();
131
+ return content;
132
+ },
133
+ requestSioql: async (sioql, verbose) => {
134
+ if (env.clusterUrl === undefined)
135
+ throw new Error(MISSING_CLUSTER_URL_ERROR);
136
+ if (env.serviceName === undefined)
137
+ throw new Error(MISSING_SERVICE_NAME_ERROR);
126
138
  const request = {
127
139
  method: 'POST',
128
140
  mode: 'cors',
129
141
  credentials: 'same-origin',
130
- headers: {
131
- 'Content-Type': 'application/json'
132
- }
142
+ headers: { 'Content-Type': 'application/json' },
143
+ body: `"${sioql.replace(/\"/g, '\\\"')}"`
133
144
  };
134
- if (CODENOTCH_ENV.accessToken && CODENOTCH_ENV.accessToken !== "") {
135
- if (CODENOTCH_ENV.tenantName === undefined) {
136
- throw new Error("Codenotch tenant name is not defined. Please set it in the Codenotch configuration.");
137
- }
145
+ if (`${env.accessToken ?? ''}`.trim() !== "") {
146
+ if (env.tenantName === undefined)
147
+ throw new Error(MISSING_TENANT_NAME_ERROR);
138
148
  request.headers = {
139
- ...request.headers,
140
- [`${CODENOTCH_ENV.tenantName}AccessToken`]: CODENOTCH_ENV.accessToken
149
+ ...request.headers, [`${env.tenantName}AccessToken`]: env.accessToken
141
150
  };
142
151
  }
143
- request.body = `"${sioql.replace(/\"/g, '\\\"')}"`;
144
- const response = await fetch(url, request);
152
+ const response = await fetch(`${env.clusterUrl}/${env.serviceName}/sioql${verbose ? "?v=true" : ""}`, request);
145
153
  if (!response.ok) {
146
154
  const error = await response.text();
147
155
  throw new Error(error);
148
156
  }
149
157
  return await response.json();
150
158
  },
151
- startProcess: async (processName) => {
152
- return { success: true };
159
+ startProcess: async (processName, inputs, startNodeId) => {
160
+ if (env.clusterUrl === undefined)
161
+ throw new Error(MISSING_CLUSTER_URL_ERROR);
162
+ if (env.serviceName === undefined)
163
+ throw new Error(MISSING_SERVICE_NAME_ERROR);
164
+ if (env.tenantName === undefined)
165
+ throw new Error(MISSING_TENANT_NAME_ERROR);
166
+ if (signalR === undefined)
167
+ throw new Error("SignalR not available. Cannot start process.");
168
+ return ProcessUtils_1.default.startProcess((processInstanceId, callbacks) => signalR.subscribeToProcessInstance(processInstanceId, callbacks), env.clusterUrl, env.tenantName, env.serviceName, processName, inputs, undefined, startNodeId ?? 'start', env.accessToken);
153
169
  },
154
- onSignal: (signalId, callback) => {
155
- console.log(`Listening to signal ${signalId}`);
156
- return {
157
- dispose: () => {
158
- console.log(`Stopped listening to signal ${signalId}`);
159
- }
160
- };
170
+ getUrlParams: () => {
171
+ let result = {};
172
+ if (typeof window !== 'undefined') {
173
+ const params = new URL(window.location.href).searchParams;
174
+ params.forEach((value, key) => {
175
+ if (result[key] === undefined) {
176
+ result[key] = value;
177
+ }
178
+ });
179
+ }
180
+ return result;
161
181
  },
162
182
  showDialog: (node) => {
163
183
  let dialogId = "codenotch-dialog-" + Math.random().toString(36).substring(2, 9);
@@ -210,6 +230,36 @@ function useCodenotch() {
210
230
  dialogElement.showModal();
211
231
  });
212
232
  return result;
233
+ },
234
+ listenSignal: async (signalId, callback) => {
235
+ if (!signalR) {
236
+ throw new Error("SignalR not available. Cannot listen to signal.");
237
+ }
238
+ let unsubscribeFunc = await signalR.subscribeToSignal(signalId, callback);
239
+ return {
240
+ dispose: () => {
241
+ unsubscribeFunc();
242
+ }
243
+ };
244
+ },
245
+ setTheme: (theme) => {
246
+ if (env.theme === theme)
247
+ return;
248
+ if (env.theme)
249
+ document.documentElement.classList.remove(env.theme);
250
+ env.theme = theme;
251
+ document.documentElement.classList.add(theme);
252
+ },
253
+ setLanguage: (lang) => {
254
+ if (env.language === lang)
255
+ return;
256
+ env.language = lang;
257
+ },
258
+ getLanguage: () => {
259
+ return env.language;
260
+ },
261
+ getTheme: () => {
262
+ return env.theme;
213
263
  }
214
264
  };
215
265
  }
@@ -0,0 +1,38 @@
1
+ import { ICodenotchSignal, IDisposable, IProcessResult } from "./Misc";
2
+ export interface ICodenotchEnv {
3
+ appName?: string;
4
+ clusterUrl?: string;
5
+ serviceName?: string;
6
+ tenantName?: string;
7
+ accessToken?: string;
8
+ baseUrl?: string;
9
+ i18n?: {
10
+ [language: string]: {
11
+ [key: string]: string;
12
+ };
13
+ };
14
+ language?: string;
15
+ theme?: 'light' | 'dark';
16
+ }
17
+ export interface ICodenotchApi {
18
+ readonly env: ICodenotchEnv;
19
+ readonly requestSioql: (sioql: string, verbose?: boolean) => Promise<any>;
20
+ readonly startProcess: (processName: string, inputs: any, startNodeId?: string) => Promise<IProcessResult>;
21
+ readonly showDialog: (node: JSX.Element) => ICodenotchDialog;
22
+ readonly getProjectFile: (relativePath: string) => Promise<string | undefined>;
23
+ readonly getProjectFileUrl: (relativePath: string) => string;
24
+ readonly listenSignal: (signalId: string, callback: (data: ICodenotchSignal) => void) => Promise<IDisposable>;
25
+ readonly setTheme: (theme: 'light' | 'dark') => void;
26
+ readonly getTheme: () => 'light' | 'dark' | undefined;
27
+ readonly setLanguage: (lang: string) => void;
28
+ readonly getLanguage: () => string | undefined;
29
+ readonly getUrlParams: () => {
30
+ [key: string]: string;
31
+ };
32
+ readonly uuid: () => string;
33
+ }
34
+ export interface ICodenotchDialog {
35
+ id: string;
36
+ close: () => void;
37
+ }
38
+ //# sourceMappingURL=Codenotch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Codenotch.d.ts","sourceRoot":"","sources":["../../src/models/Codenotch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAEvE,MAAM,WAAW,aAAa;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE;QAAE,CAAC,QAAQ,EAAE,MAAM,GAAG;YAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,aAAa;IAC1B,QAAQ,CAAC,GAAG,EAAE,aAAa,CAAC;IAE5B,QAAQ,CAAC,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1E,QAAQ,CAAC,YAAY,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAC3G,QAAQ,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,OAAO,KAAK,gBAAgB,CAAC;IAC7D,QAAQ,CAAC,cAAc,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC/E,QAAQ,CAAC,iBAAiB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,MAAM,CAAC;IAC7D,QAAQ,CAAC,YAAY,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,gBAAgB,KAAK,IAAI,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAC9G,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,KAAK,IAAI,CAAC;IACrD,QAAQ,CAAC,QAAQ,EAAE,MAAM,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IACtD,QAAQ,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,QAAQ,CAAC,WAAW,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IAC/C,QAAQ,CAAC,YAAY,EAAE,MAAM;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IACvD,QAAQ,CAAC,IAAI,EAAE,MAAM,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,IAAI,CAAC;CACrB"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,18 @@
1
+ export interface IProcessCallbacks {
2
+ onOver: (processResult: IProcessResult) => void;
3
+ onCallback: (callback: any) => void;
4
+ }
5
+ export interface IProcessResult {
6
+ processInstanceId: string;
7
+ output: any;
8
+ isError: boolean;
9
+ errorMessage: string;
10
+ }
11
+ export interface ICodenotchSignal {
12
+ signalId: string;
13
+ data: any;
14
+ }
15
+ export interface IDisposable {
16
+ dispose: () => void;
17
+ }
18
+ //# sourceMappingURL=Misc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Misc.d.ts","sourceRoot":"","sources":["../../src/models/Misc.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAE9B,MAAM,EAAE,CAAC,aAAa,EAAE,cAAc,KAAK,IAAI,CAAC;IAChD,UAAU,EAAC,CAAE,QAAQ,EAAE,GAAG,KAAK,IAAI,CAAA;CACtC;AAED,MAAM,WAAW,cAAc;IAE3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,GAAG,CAAC;IACZ,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAE7B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,GAAG,CAAC;CACb;AAED,MAAM,WAAW,WAAW;IACxB,OAAO,EAAE,MAAM,IAAI,CAAC;CACvB"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codenotch-react",
3
- "version": "1.0.54",
3
+ "version": "1.0.56",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "author": "Codenotch SA",
@@ -14,13 +14,16 @@
14
14
  "dist/**/*"
15
15
  ],
16
16
  "dependencies": {
17
+ "@echino/echino.ui.core": "^0.13.128",
17
18
  "@echino/echino.ui.framework": "1.1.61",
18
- "@echino/echino.ui.core": "^0.13.128"
19
+ "@microsoft/signalr": "^5.0.6",
20
+ "uuid": "^8.2.0"
19
21
  },
20
22
  "devDependencies": {
21
23
  "@types/node": "^25.3.2",
22
24
  "@types/react": "^16.14.69",
23
25
  "@types/react-dom": "^16.9.25",
26
+ "@types/uuid": "8.0.0",
24
27
  "react-dom": "^16.14.0",
25
28
  "typescript": "^5.9.3"
26
29
  },
@@ -1 +0,0 @@
1
- {"version":3,"file":"auml.d.ts","sourceRoot":"","sources":["../src/auml.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,eAAe,EAAE,MAAM,0EAA0E,CAAC;AAS3G,UAAU,UAAU;IAChB,KAAK,EAAE,MAAM,CAAC;CACjB;AACD,UAAU,UAAU;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,gBAAgB,EAAE,OAAO,CAAC;CAC7B;AAED,qBAAa,IAAK,SAAQ,KAAK,CAAC,SAAS,CAAC,UAAU,EAAE,UAAU,CAAC;IAE7D,kBAAkB,EAAE,MAAM,CAAC,OAAO,GAAG,SAAS,CAAC;gBAEnC,KAAK,EAAE,UAAU;IAQ7B,iBAAiB;IAmCjB,oBAAoB;IAQpB,QAAQ,CAAC,CAAC,EAAE,eAAe;IAO3B,OAAO;IAYP,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS;IAclC,cAAc;;;IAMd,wBAAwB,IAAI,MAAM,GAAG,IAAI;IAoCzC,2BAA2B,CAAC,kBAAkB,EAAE,MAAM,GAAG,MAAM;IAO/D,QAAQ,CAAC,EAAE,EAAE,MAAM;IAmBnB,QAAQ,CAAC,KAAK,EAAE,MAAM;IAsBtB,MAAM;IAiDA,mBAAmB;CAqC5B"}