@qlik/api 1.30.0 → 1.31.0
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/api-keys.d.ts +2 -2
- package/api-keys.js +2 -2
- package/apps.d.ts +4 -2
- package/apps.js +2 -2
- package/audits.d.ts +2 -2
- package/audits.js +2 -2
- package/{auth-types-PkN9CAF_.d.ts → auth-types-DqfMuSRX.d.ts} +1 -0
- package/auth.d.ts +27 -3
- package/auth.js +8 -4
- package/automations.d.ts +2 -2
- package/automations.js +2 -2
- package/brands.d.ts +2 -2
- package/brands.js +2 -2
- package/chunks/{JIX6RMFP.js → 6ZONDHRN.js} +1 -1
- package/chunks/{TXC5XORK.js → DLKLPD7T.js} +3 -3
- package/chunks/ETNHFALU.js +61 -0
- package/chunks/{G6QUM5WQ.js → FKDGGR2O.js} +137 -45
- package/chunks/{QK4TMJ64.js → GUU3KZGK.js} +11 -1
- package/chunks/{IQBP2PKS.js → KBSD75QL.js} +1 -1
- package/chunks/{OTTC4QSX.js → LY7RP2HA.js} +7 -3
- package/chunks/{FKCZFVJL.js → M64RLKVG.js} +2074 -12
- package/chunks/{F5UDCCRD.js → PLVPW5IR.js} +1 -1
- package/chunks/{QWQLGDMI.js → UZTIZ4H5.js} +392 -372
- package/chunks/{PTDXR7AY.js → YKZ2QYHN.js} +2 -2
- package/collections.d.ts +3 -3
- package/collections.js +2 -2
- package/csp-origins.d.ts +2 -2
- package/csp-origins.js +2 -2
- package/data-assets.d.ts +2 -2
- package/data-assets.js +2 -2
- package/data-connections.d.ts +7 -7
- package/data-connections.js +2 -2
- package/data-credentials.d.ts +2 -2
- package/data-credentials.js +2 -2
- package/data-files.d.ts +2 -2
- package/data-files.js +2 -2
- package/docs/authentication.md +47 -0
- package/extensions.d.ts +2 -2
- package/extensions.js +2 -2
- package/glossaries.d.ts +2 -2
- package/glossaries.js +2 -2
- package/groups.d.ts +5 -4
- package/groups.js +2 -2
- package/identity-providers.d.ts +2 -2
- package/identity-providers.js +2 -2
- package/index.d.ts +5 -3
- package/index.js +4 -4
- package/interceptors.d.ts +2 -2
- package/{invoke-fetch-types-BXn-uSF5.d.ts → invoke-fetch-types-Cq7bjkqn.d.ts} +10 -2
- package/items.d.ts +3 -3
- package/items.js +2 -2
- package/licenses.d.ts +5 -2
- package/licenses.js +2 -2
- package/oauth-clients.d.ts +7 -2
- package/oauth-clients.js +2 -2
- package/package.json +3 -2
- package/qix.d.ts +421 -26
- package/qix.js +2 -2
- package/quotas.d.ts +2 -2
- package/quotas.js +2 -2
- package/reload-tasks.d.ts +4 -2
- package/reload-tasks.js +2 -2
- package/reloads.d.ts +4 -2
- package/reloads.js +2 -2
- package/reports.d.ts +2 -2
- package/reports.js +2 -2
- package/roles.d.ts +2 -2
- package/roles.js +2 -2
- package/spaces.d.ts +3 -7
- package/spaces.js +2 -2
- package/temp-contents.d.ts +2 -2
- package/temp-contents.js +2 -2
- package/tenants.d.ts +2 -2
- package/tenants.js +2 -2
- package/themes.d.ts +2 -2
- package/themes.js +2 -2
- package/transports.d.ts +2 -2
- package/transports.js +2 -2
- package/users.d.ts +2 -2
- package/users.js +2 -2
- package/web-integrations.d.ts +2 -2
- package/web-integrations.js +2 -2
- package/web-notifications.d.ts +2 -2
- package/web-notifications.js +2 -2
- package/webhooks.d.ts +2 -2
- package/webhooks.js +2 -2
|
@@ -1,87 +1,138 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getHumanReadableSocketClosedErrorMessage
|
|
3
|
+
} from "./ETNHFALU.js";
|
|
1
4
|
import {
|
|
2
5
|
getPlatform,
|
|
3
6
|
handleAuthenticationError,
|
|
4
7
|
invokeFetch,
|
|
5
8
|
isWindows,
|
|
6
9
|
toValidWebsocketLocationUrl
|
|
7
|
-
} from "./
|
|
10
|
+
} from "./FKDGGR2O.js";
|
|
8
11
|
import "./3RGGGGAR.js";
|
|
9
12
|
import {
|
|
10
13
|
isBrowser
|
|
11
14
|
} from "./2ZQ3ZX7F.js";
|
|
12
15
|
|
|
13
|
-
// src/qix/session
|
|
14
|
-
var
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
var closeCodeDependencyUnavailable = 4211;
|
|
25
|
-
var closeCodeEngineGeneric = 4220;
|
|
26
|
-
var closeCodeEntitlement = 4230;
|
|
27
|
-
var closeCodeNoEnginesAvailable = 4240;
|
|
28
|
-
var CloseCodeSessionReservationMissing = 4222;
|
|
29
|
-
var closeCodeMessages = {
|
|
30
|
-
[closeCodeEngineTerminating]: "The engine is in terminating state",
|
|
31
|
-
[closeCodeEngineAbnormalClosure]: "The engine is abnormally closed",
|
|
32
|
-
[closeCodeEngineProxyGeneric]: "A problem occurred in engine-proxy",
|
|
33
|
-
[closeCodeClientTimeout]: "The client has closed the connection",
|
|
34
|
-
[closeCodeBadRequest]: "The provided request is invalid and/or malformed",
|
|
35
|
-
[closeCodePermissions]: "No permission to open the app",
|
|
36
|
-
[closeCodeNotFound]: "App not found",
|
|
37
|
-
[closeCodeTooManyRequests]: "Too many requests have been sent in a given amount of time",
|
|
38
|
-
[closeCodeNetwork]: "Networking issues",
|
|
39
|
-
[closeCodeDependencyGeneric]: "A problem occurred in a dependency of engine-proxy",
|
|
40
|
-
[closeCodeDependencyUnavailable]: "A dependency is unavailable and not serving any requests",
|
|
41
|
-
[closeCodeEngineGeneric]: "A problem occurred in an engine",
|
|
42
|
-
[closeCodeEntitlement]: "You are not entitled to perform that operation",
|
|
43
|
-
[closeCodeNoEnginesAvailable]: "There are currently no engines available",
|
|
44
|
-
[CloseCodeSessionReservationMissing]: "The reserved session is missing"
|
|
45
|
-
};
|
|
46
|
-
var uknownCloseErrorMessage = "websocket closed for unknown reason";
|
|
47
|
-
function getHumanReadableSocketClosedErrorMessage(err, { appId, hostConfig }) {
|
|
48
|
-
const closeCode = err?.original?.code;
|
|
49
|
-
const closeMessage = closeCode ? closeCodeMessages[closeCode] || uknownCloseErrorMessage : err.message;
|
|
50
|
-
if (hostConfig?.host) {
|
|
51
|
-
return `Failed to open app ${appId} on ${hostConfig?.host}: ${closeMessage}`;
|
|
52
|
-
} else {
|
|
53
|
-
return `Failed to open app ${appId}: ${closeMessage}`;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// src/qix/session/shared-sessions.ts
|
|
58
|
-
var globalEventListeners = /* @__PURE__ */ new Set();
|
|
59
|
-
function globalOnWebSocketEvent(listener) {
|
|
60
|
-
globalEventListeners.add(listener);
|
|
61
|
-
return () => {
|
|
62
|
-
globalEventListeners.delete(listener);
|
|
16
|
+
// src/qix/app-session.ts
|
|
17
|
+
var isBrowserEnvironment = isBrowser();
|
|
18
|
+
function createAppSession(sharedSession) {
|
|
19
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
20
|
+
let alreadyClosed = false;
|
|
21
|
+
const sharedSessionClient = {
|
|
22
|
+
onWebSocketEvent(event) {
|
|
23
|
+
listeners.forEach((listener) => {
|
|
24
|
+
listener(event);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
63
27
|
};
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
28
|
+
const appSession = {
|
|
29
|
+
getDoc: () => sharedSession.getDoc(),
|
|
30
|
+
onWebSocketEvent(fn) {
|
|
31
|
+
listeners.add(fn);
|
|
32
|
+
return () => {
|
|
33
|
+
listeners.delete(fn);
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
resume: async () => {
|
|
37
|
+
return sharedSession.resume();
|
|
38
|
+
},
|
|
39
|
+
close(props) {
|
|
40
|
+
if (!alreadyClosed) {
|
|
41
|
+
alreadyClosed = true;
|
|
42
|
+
const defaultDelay = isBrowserEnvironment ? 5e3 : -1;
|
|
43
|
+
return sharedSession.removeClient(sharedSessionClient, props?.websocketCloseDelay ?? defaultDelay);
|
|
44
|
+
}
|
|
45
|
+
return Promise.resolve();
|
|
46
|
+
},
|
|
47
|
+
/* Only for test cases */
|
|
48
|
+
// @ts-expect-error ts(2353)
|
|
49
|
+
_listeners: listeners
|
|
70
50
|
};
|
|
51
|
+
sharedSession.addClient(sharedSessionClient);
|
|
52
|
+
return appSession;
|
|
71
53
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
54
|
+
|
|
55
|
+
// src/qix/external-app-session.ts
|
|
56
|
+
function createExternalSharedSession(externalApp, onWebSocketEvent2, appSessionProps) {
|
|
57
|
+
const clients = [];
|
|
58
|
+
const sharedSession = {
|
|
59
|
+
getDoc: () => externalApp,
|
|
60
|
+
addClient(client) {
|
|
61
|
+
const index = clients.indexOf(client, 0);
|
|
62
|
+
if (index === -1) {
|
|
63
|
+
clients.push(client);
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
removeClient(client) {
|
|
67
|
+
const index = clients.indexOf(client, 0);
|
|
68
|
+
if (index > -1) {
|
|
69
|
+
clients.splice(index, 1);
|
|
70
|
+
}
|
|
71
|
+
return Promise.resolve();
|
|
72
|
+
},
|
|
73
|
+
initialActionsUpdated: () => {
|
|
74
|
+
},
|
|
75
|
+
clientsCount: () => clients.length,
|
|
76
|
+
resume: async () => {
|
|
77
|
+
try {
|
|
78
|
+
await externalApp.then((doc) => doc.session?.resume());
|
|
79
|
+
} catch (err) {
|
|
80
|
+
console.warn(err);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
const triggerEventListeners = (event) => {
|
|
85
|
+
onWebSocketEvent2(event);
|
|
86
|
+
for (const client of clients) {
|
|
87
|
+
client.onWebSocketEvent(event);
|
|
78
88
|
}
|
|
89
|
+
};
|
|
90
|
+
void externalApp.then((app) => {
|
|
91
|
+
app.session.on("opened", (event) => {
|
|
92
|
+
const wsEvent = {
|
|
93
|
+
eventType: "opened",
|
|
94
|
+
...appSessionProps,
|
|
95
|
+
...event
|
|
96
|
+
};
|
|
97
|
+
triggerEventListeners(wsEvent);
|
|
98
|
+
});
|
|
99
|
+
app.session.on("closed", (event) => {
|
|
100
|
+
const wsEvent = {
|
|
101
|
+
eventType: "closed",
|
|
102
|
+
...appSessionProps,
|
|
103
|
+
...event
|
|
104
|
+
};
|
|
105
|
+
triggerEventListeners(wsEvent);
|
|
106
|
+
});
|
|
107
|
+
app.session.on("suspended", (event) => {
|
|
108
|
+
const wsEvent = {
|
|
109
|
+
eventType: "suspended",
|
|
110
|
+
...appSessionProps,
|
|
111
|
+
...event
|
|
112
|
+
};
|
|
113
|
+
triggerEventListeners(wsEvent);
|
|
114
|
+
});
|
|
115
|
+
app.session.on("resuming", (event) => {
|
|
116
|
+
const wsEvent = {
|
|
117
|
+
eventType: "resuming",
|
|
118
|
+
...appSessionProps,
|
|
119
|
+
...event
|
|
120
|
+
};
|
|
121
|
+
triggerEventListeners(wsEvent);
|
|
122
|
+
});
|
|
123
|
+
app.session.on("resumed", (event) => {
|
|
124
|
+
const wsEvent = {
|
|
125
|
+
eventType: "resumed",
|
|
126
|
+
...appSessionProps,
|
|
127
|
+
...event
|
|
128
|
+
};
|
|
129
|
+
triggerEventListeners(wsEvent);
|
|
130
|
+
});
|
|
79
131
|
});
|
|
80
|
-
|
|
81
|
-
return Promise.resolve();
|
|
132
|
+
return sharedSession;
|
|
82
133
|
}
|
|
83
|
-
|
|
84
|
-
|
|
134
|
+
|
|
135
|
+
// src/qix/internal/global-app-session.id.ts
|
|
85
136
|
function toGlobalAppSessionId({
|
|
86
137
|
appId,
|
|
87
138
|
identity,
|
|
@@ -89,7 +140,8 @@ function toGlobalAppSessionId({
|
|
|
89
140
|
withoutData,
|
|
90
141
|
useReloadEngine,
|
|
91
142
|
ttlSeconds,
|
|
92
|
-
workloadType
|
|
143
|
+
workloadType,
|
|
144
|
+
autoResume
|
|
93
145
|
}) {
|
|
94
146
|
const locationUrl = toValidWebsocketLocationUrl(hostConfig);
|
|
95
147
|
let url = `${locationUrl}/${appId}`;
|
|
@@ -108,38 +160,142 @@ function toGlobalAppSessionId({
|
|
|
108
160
|
if (workloadType) {
|
|
109
161
|
url += `?workloadType=${workloadType}`;
|
|
110
162
|
}
|
|
163
|
+
if (autoResume) {
|
|
164
|
+
url += "/auto-resume";
|
|
165
|
+
}
|
|
111
166
|
return url;
|
|
112
167
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
168
|
+
|
|
169
|
+
// src/qix/global-events.ts
|
|
170
|
+
var globalEventListeners = /* @__PURE__ */ new Set();
|
|
171
|
+
var globalStateListeners = /* @__PURE__ */ new Set();
|
|
172
|
+
function onWebSocketEvent(listener) {
|
|
173
|
+
globalEventListeners.add(listener);
|
|
174
|
+
return () => {
|
|
175
|
+
globalEventListeners.delete(listener);
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function onCombinedWebSocketStateChange(listener) {
|
|
179
|
+
globalStateListeners.add(listener);
|
|
180
|
+
return () => {
|
|
181
|
+
globalStateListeners.delete(listener);
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
var globalState = {
|
|
185
|
+
sessionStates: {},
|
|
186
|
+
state: "closed"
|
|
187
|
+
};
|
|
188
|
+
function stateListener(key, event) {
|
|
189
|
+
if (event.eventType === "closed") {
|
|
190
|
+
delete globalState.sessionStates[key];
|
|
191
|
+
} else {
|
|
192
|
+
globalState.sessionStates[key] = event.eventType;
|
|
193
|
+
}
|
|
194
|
+
const states = Object.values(globalState.sessionStates);
|
|
195
|
+
let anySuspended = false;
|
|
196
|
+
let anyResuming = false;
|
|
197
|
+
for (const state of states) {
|
|
198
|
+
if (state === "suspended") {
|
|
199
|
+
anySuspended = true;
|
|
200
|
+
} else if (state === "resuming") {
|
|
201
|
+
anyResuming = true;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
let newState;
|
|
205
|
+
if (states.length === 0) {
|
|
206
|
+
newState = "closed";
|
|
207
|
+
} else if (anySuspended) {
|
|
208
|
+
newState = "suspended";
|
|
209
|
+
} else if (anyResuming) {
|
|
210
|
+
newState = "resuming";
|
|
211
|
+
} else {
|
|
212
|
+
newState = "open";
|
|
213
|
+
}
|
|
214
|
+
if (globalState.state !== newState) {
|
|
215
|
+
globalState.state = newState;
|
|
216
|
+
for (const fn of globalStateListeners) {
|
|
217
|
+
fn({ state: newState });
|
|
118
218
|
}
|
|
119
219
|
}
|
|
120
220
|
}
|
|
121
|
-
function
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
if (!initialActionArray) {
|
|
125
|
-
initialActionArray = initialActions[key] = [];
|
|
221
|
+
function triggerGlobalWebSocketEventListeners(event) {
|
|
222
|
+
for (const fn of globalEventListeners) {
|
|
223
|
+
fn(event);
|
|
126
224
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
225
|
+
stateListener(toGlobalAppSessionId(event), event);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// src/qix/session/shared-sessions-phoenix.ts
|
|
229
|
+
function createSharedPhoenixSession(props, { onClose, onWebSocketEvent: onWebSocketEventGlobal, getInitialAppActions }) {
|
|
230
|
+
try {
|
|
231
|
+
const clients = [];
|
|
232
|
+
const onWebSocketEvent2 = (event) => {
|
|
233
|
+
onWebSocketEventGlobal(event);
|
|
234
|
+
for (const client of clients) {
|
|
235
|
+
client.onWebSocketEvent(event);
|
|
133
236
|
}
|
|
237
|
+
};
|
|
238
|
+
const phoenixConnectionPromise = import("./M64RLKVG.js").then((module) => {
|
|
239
|
+
return module.createPhoenixConnectionEntrypoint(props, {
|
|
240
|
+
onWebSocketEvent: onWebSocketEvent2,
|
|
241
|
+
getInitialAppActions
|
|
242
|
+
});
|
|
134
243
|
});
|
|
244
|
+
const docPromise = phoenixConnectionPromise.then((phoenixConnection) => phoenixConnection.doc);
|
|
245
|
+
const sharedSession = {
|
|
246
|
+
getDoc: () => docPromise,
|
|
247
|
+
addClient(client) {
|
|
248
|
+
const index = clients.indexOf(client, 0);
|
|
249
|
+
if (index === -1) {
|
|
250
|
+
clients.push(client);
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
removeClient(client, closeDelay) {
|
|
254
|
+
if (clients.length === 1) {
|
|
255
|
+
void phoenixConnectionPromise.then((phoenixConnection) => {
|
|
256
|
+
phoenixConnection.stopActivityMonitoring();
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
const actuallyRemove = () => {
|
|
260
|
+
const index = clients.indexOf(client, 0);
|
|
261
|
+
if (index > -1) {
|
|
262
|
+
clients.splice(index, 1);
|
|
263
|
+
}
|
|
264
|
+
if (clients.length === 0) {
|
|
265
|
+
onClose();
|
|
266
|
+
void phoenixConnectionPromise.then((phoenixConnection) => {
|
|
267
|
+
phoenixConnection.close();
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
if (closeDelay > 0) {
|
|
272
|
+
return new Promise((resolve) => {
|
|
273
|
+
setTimeout(() => {
|
|
274
|
+
actuallyRemove();
|
|
275
|
+
resolve();
|
|
276
|
+
}, closeDelay);
|
|
277
|
+
});
|
|
278
|
+
} else {
|
|
279
|
+
actuallyRemove();
|
|
280
|
+
return Promise.resolve();
|
|
281
|
+
}
|
|
282
|
+
},
|
|
283
|
+
resume: async () => {
|
|
284
|
+
void phoenixConnectionPromise.then((session) => session.resume());
|
|
285
|
+
},
|
|
286
|
+
initialActionsUpdated() {
|
|
287
|
+
void phoenixConnectionPromise.then((session) => session.initialAppActionsUpdated());
|
|
288
|
+
},
|
|
289
|
+
clientsCount: () => clients.length
|
|
290
|
+
};
|
|
291
|
+
return sharedSession;
|
|
292
|
+
} catch (err) {
|
|
293
|
+
console.error(err);
|
|
294
|
+
throw err;
|
|
135
295
|
}
|
|
136
|
-
return () => {
|
|
137
|
-
const index = initialActionArray.indexOf(action);
|
|
138
|
-
if (index > -1) {
|
|
139
|
-
initialActionArray.splice(index, 1);
|
|
140
|
-
}
|
|
141
|
-
};
|
|
142
296
|
}
|
|
297
|
+
|
|
298
|
+
// src/qix/session/shared-sessions.ts
|
|
143
299
|
function listenForWindowsAuthenticationInformation(session) {
|
|
144
300
|
let resolveAuthSuggestedInWebsocket;
|
|
145
301
|
const authSuggestedInWebsocket = new Promise((resolve, reject) => {
|
|
@@ -160,10 +316,10 @@ function listenForWindowsAuthenticationInformation(session) {
|
|
|
160
316
|
);
|
|
161
317
|
return authSuggestedInWebsocket;
|
|
162
318
|
}
|
|
163
|
-
async function createAndSetupEnigmaSession(props, canRetry) {
|
|
164
|
-
const {
|
|
165
|
-
const session = await
|
|
166
|
-
setupSessionListeners(session, props);
|
|
319
|
+
async function createAndSetupEnigmaSession(props, canRetry, onWebSocketEvent2) {
|
|
320
|
+
const { createEnigmaSessionEntrypoint } = await import("./M64RLKVG.js");
|
|
321
|
+
const session = await createEnigmaSessionEntrypoint(props);
|
|
322
|
+
setupSessionListeners(session, props, onWebSocketEvent2);
|
|
167
323
|
let global;
|
|
168
324
|
if (await isWindows(props.hostConfig)) {
|
|
169
325
|
const loginInfoPromise = listenForWindowsAuthenticationInformation(session);
|
|
@@ -177,7 +333,7 @@ async function createAndSetupEnigmaSession(props, canRetry) {
|
|
|
177
333
|
hostConfig: props.hostConfig
|
|
178
334
|
});
|
|
179
335
|
if (canRetry && action.retry) {
|
|
180
|
-
return createAndSetupEnigmaSession(props, false);
|
|
336
|
+
return createAndSetupEnigmaSession(props, false, onWebSocketEvent2);
|
|
181
337
|
}
|
|
182
338
|
if (action.preventDefault) {
|
|
183
339
|
return new Promise(() => {
|
|
@@ -192,100 +348,7 @@ async function createAndSetupEnigmaSession(props, canRetry) {
|
|
|
192
348
|
global
|
|
193
349
|
};
|
|
194
350
|
}
|
|
195
|
-
|
|
196
|
-
sessionStates: {},
|
|
197
|
-
state: "closed"
|
|
198
|
-
};
|
|
199
|
-
function stateListener(key, event) {
|
|
200
|
-
if (event.eventType === "closed") {
|
|
201
|
-
delete globalState.sessionStates[key];
|
|
202
|
-
} else {
|
|
203
|
-
globalState.sessionStates[key] = event.eventType;
|
|
204
|
-
}
|
|
205
|
-
const states = Object.values(globalState.sessionStates);
|
|
206
|
-
let anySuspended = false;
|
|
207
|
-
let anyResuming = false;
|
|
208
|
-
for (const state of states) {
|
|
209
|
-
if (state === "suspended") {
|
|
210
|
-
anySuspended = true;
|
|
211
|
-
} else if (state === "resuming") {
|
|
212
|
-
anyResuming = true;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
let newState;
|
|
216
|
-
if (states.length === 0) {
|
|
217
|
-
newState = "closed";
|
|
218
|
-
} else if (anySuspended) {
|
|
219
|
-
newState = "suspended";
|
|
220
|
-
} else if (anyResuming) {
|
|
221
|
-
newState = "resuming";
|
|
222
|
-
} else {
|
|
223
|
-
newState = "open";
|
|
224
|
-
}
|
|
225
|
-
if (globalState.state !== newState) {
|
|
226
|
-
globalState.state = newState;
|
|
227
|
-
for (const fn of globalStateListeners) {
|
|
228
|
-
fn({ state: newState });
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
function setupSessionListeners(session, props) {
|
|
233
|
-
const key = toGlobalAppSessionId(props);
|
|
234
|
-
const eventListener = (event) => {
|
|
235
|
-
let sharedSession = void 0;
|
|
236
|
-
let shouldHandleEvent = false;
|
|
237
|
-
if (key in sharedSessions) {
|
|
238
|
-
sharedSession = sharedSessions[key];
|
|
239
|
-
shouldHandleEvent = sharedSession.connected;
|
|
240
|
-
} else if (key in globalState.sessionStates) {
|
|
241
|
-
shouldHandleEvent = true;
|
|
242
|
-
}
|
|
243
|
-
if (!shouldHandleEvent) {
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
stateListener(key, event);
|
|
247
|
-
for (const fn of globalEventListeners) {
|
|
248
|
-
fn(event);
|
|
249
|
-
}
|
|
250
|
-
if (sharedSession) {
|
|
251
|
-
sharedSession.clients.forEach((client) => {
|
|
252
|
-
for (const fn of client._listeners) {
|
|
253
|
-
fn(event);
|
|
254
|
-
}
|
|
255
|
-
});
|
|
256
|
-
if (event.eventType === "suspended" && shouldAutoResume(event.code)) {
|
|
257
|
-
sharedSession.resume().catch((err) => {
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
};
|
|
262
|
-
const suspendListener = (event) => {
|
|
263
|
-
if (!(key in sharedSessions)) {
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
266
|
-
const sharedSession = sharedSessions[key];
|
|
267
|
-
let resumed = false;
|
|
268
|
-
let resumePromise = Promise.resolve();
|
|
269
|
-
sharedSession.resume = async () => {
|
|
270
|
-
if (!resumed) {
|
|
271
|
-
session.emit("resuming", {});
|
|
272
|
-
resumePromise = sessionResumeWithRetry(session, props.hostConfig).catch((err) => {
|
|
273
|
-
session.suspend();
|
|
274
|
-
return Promise.reject(err);
|
|
275
|
-
});
|
|
276
|
-
resumed = true;
|
|
277
|
-
}
|
|
278
|
-
return resumePromise;
|
|
279
|
-
};
|
|
280
|
-
};
|
|
281
|
-
session.on("suspended", (event) => {
|
|
282
|
-
const wsEvent = {
|
|
283
|
-
eventType: "suspended",
|
|
284
|
-
...props,
|
|
285
|
-
...event
|
|
286
|
-
};
|
|
287
|
-
suspendListener(wsEvent);
|
|
288
|
-
});
|
|
351
|
+
function setupSessionListeners(session, props, eventListener) {
|
|
289
352
|
session.on("opened", (event) => {
|
|
290
353
|
const wsEvent = {
|
|
291
354
|
eventType: "opened",
|
|
@@ -367,12 +430,51 @@ function shouldAutoResume(code) {
|
|
|
367
430
|
}
|
|
368
431
|
return false;
|
|
369
432
|
}
|
|
370
|
-
function
|
|
371
|
-
const
|
|
433
|
+
function createSharedEnigmaSession(props, { getInitialAppActions, onClose, onWebSocketEvent: onGlobalWebsocketEvent }) {
|
|
434
|
+
const clients = [];
|
|
435
|
+
const alreadyExecutedInitialActions = [];
|
|
436
|
+
async function runPendingInitialActions(initialActionsForApp, doc) {
|
|
437
|
+
for (const initialAction of initialActionsForApp) {
|
|
438
|
+
if (alreadyExecutedInitialActions.indexOf(initialAction) === -1) {
|
|
439
|
+
alreadyExecutedInitialActions.push(initialAction);
|
|
440
|
+
await initialAction(doc);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
let resumePromise;
|
|
445
|
+
function onWebSocketEvent2(event) {
|
|
446
|
+
if (event.eventType === "suspended") {
|
|
447
|
+
resumePromise = void 0;
|
|
448
|
+
if (shouldAutoResume(event.code)) {
|
|
449
|
+
resume().catch((err) => {
|
|
450
|
+
console.error("Failed to auto-resume");
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
for (const client of clients) {
|
|
455
|
+
client.onWebSocketEvent(event);
|
|
456
|
+
}
|
|
457
|
+
onGlobalWebsocketEvent(event);
|
|
458
|
+
}
|
|
459
|
+
const { sessionPromise, globalPromise } = separatePromises(
|
|
460
|
+
createAndSetupEnigmaSession(props, true, onWebSocketEvent2)
|
|
461
|
+
);
|
|
462
|
+
async function resume() {
|
|
463
|
+
if (!resumePromise) {
|
|
464
|
+
resumePromise = (async () => {
|
|
465
|
+
let session = await sessionPromise;
|
|
466
|
+
session.emit("resuming", {});
|
|
467
|
+
await sessionResumeWithRetry(session, props.hostConfig).catch((err) => {
|
|
468
|
+
session.suspend();
|
|
469
|
+
return Promise.reject(err);
|
|
470
|
+
});
|
|
471
|
+
})();
|
|
472
|
+
}
|
|
473
|
+
return resumePromise;
|
|
474
|
+
}
|
|
372
475
|
const docPromise = globalPromise.then(async (global) => {
|
|
373
476
|
if (props.useSessionApp) {
|
|
374
|
-
|
|
375
|
-
return global2.createSessionApp();
|
|
477
|
+
return global.createSessionApp();
|
|
376
478
|
} else {
|
|
377
479
|
return global.openDoc(props.appId, "", "", "", !!props.withoutData).then((doc) => {
|
|
378
480
|
if (!doc) {
|
|
@@ -382,32 +484,40 @@ function createSharedSession(props) {
|
|
|
382
484
|
return doc;
|
|
383
485
|
});
|
|
384
486
|
}
|
|
487
|
+
}).then(async (doc) => {
|
|
488
|
+
const initialActionsForApp = getInitialAppActions();
|
|
489
|
+
if (initialActionsForApp && doc) {
|
|
490
|
+
await runPendingInitialActions(initialActionsForApp, doc);
|
|
491
|
+
}
|
|
492
|
+
return doc;
|
|
493
|
+
}).catch((err) => {
|
|
494
|
+
closeEnigmaSession();
|
|
495
|
+
const errorWithReadableMessage = new Error(getHumanReadableSocketClosedErrorMessage(err.original || err, props));
|
|
496
|
+
Object.entries(err).forEach(([key, value]) => {
|
|
497
|
+
errorWithReadableMessage[key] = value;
|
|
498
|
+
});
|
|
499
|
+
return Promise.reject(errorWithReadableMessage);
|
|
385
500
|
});
|
|
386
|
-
const key = toGlobalAppSessionId(props);
|
|
387
|
-
const clients = [];
|
|
388
501
|
function closeEnigmaSession() {
|
|
389
|
-
|
|
390
|
-
return
|
|
502
|
+
onClose();
|
|
503
|
+
return sessionPromise.then((session) => session.close()).catch(() => {
|
|
391
504
|
});
|
|
392
505
|
}
|
|
393
506
|
const sharedSession = {
|
|
394
|
-
|
|
395
|
-
globalPromise,
|
|
396
|
-
docPromise,
|
|
397
|
-
clients,
|
|
507
|
+
getDoc: () => docPromise,
|
|
398
508
|
addClient(client) {
|
|
399
|
-
const index =
|
|
509
|
+
const index = clients.indexOf(client, 0);
|
|
400
510
|
if (index === -1) {
|
|
401
|
-
|
|
511
|
+
clients.push(client);
|
|
402
512
|
}
|
|
403
513
|
},
|
|
404
514
|
removeClient(client, closeDelay) {
|
|
405
515
|
const actuallyRemove = () => {
|
|
406
|
-
const index =
|
|
516
|
+
const index = clients.indexOf(client, 0);
|
|
407
517
|
if (index > -1) {
|
|
408
|
-
|
|
518
|
+
clients.splice(index, 1);
|
|
409
519
|
}
|
|
410
|
-
if (
|
|
520
|
+
if (clients.length === 0) {
|
|
411
521
|
closeEnigmaSession();
|
|
412
522
|
}
|
|
413
523
|
};
|
|
@@ -423,36 +533,15 @@ function createSharedSession(props) {
|
|
|
423
533
|
}
|
|
424
534
|
return Promise.resolve();
|
|
425
535
|
},
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
536
|
+
resume,
|
|
537
|
+
initialActionsUpdated() {
|
|
538
|
+
getInitialAppActions();
|
|
429
539
|
},
|
|
430
|
-
|
|
540
|
+
clientsCount: () => clients.length
|
|
431
541
|
};
|
|
432
|
-
sharedSession.docPromise = sharedSession.docPromise.then(async (doc) => {
|
|
433
|
-
sharedSession.connected = true;
|
|
434
|
-
const session = await sharedSession.sessionPromise;
|
|
435
|
-
session.emit("opened", {});
|
|
436
|
-
const initialActionsForApp = initialActions[key];
|
|
437
|
-
if (initialActionsForApp && doc) {
|
|
438
|
-
await runPendingInitialActions(initialActionsForApp, sharedSession, doc);
|
|
439
|
-
}
|
|
440
|
-
return doc;
|
|
441
|
-
});
|
|
442
|
-
sharedSession.docPromise = sharedSession.docPromise.catch((err) => {
|
|
443
|
-
closeEnigmaSession();
|
|
444
|
-
const errorWithReadableMessage = new Error(getHumanReadableSocketClosedErrorMessage(err, props));
|
|
445
|
-
Object.entries(err).forEach(([key2, value]) => {
|
|
446
|
-
errorWithReadableMessage[key2] = value;
|
|
447
|
-
});
|
|
448
|
-
return Promise.reject(errorWithReadableMessage);
|
|
449
|
-
});
|
|
450
542
|
return sharedSession;
|
|
451
543
|
}
|
|
452
544
|
var onlyOnReattach = false;
|
|
453
|
-
function resumeShouldRejectPromiseIfNotReattached(bool) {
|
|
454
|
-
onlyOnReattach = bool;
|
|
455
|
-
}
|
|
456
545
|
async function checkConnectivity(hostConfig) {
|
|
457
546
|
let status = "online";
|
|
458
547
|
const method = "get";
|
|
@@ -511,76 +600,80 @@ async function sessionResumeWithRetry(session, hostConfig) {
|
|
|
511
600
|
}
|
|
512
601
|
return Promise.resolve();
|
|
513
602
|
}
|
|
603
|
+
|
|
604
|
+
// src/qix/shared-sessions-manager.ts
|
|
605
|
+
var initialActions = {};
|
|
606
|
+
var sharedSessions = {};
|
|
607
|
+
var externalApps = {};
|
|
514
608
|
function getOrCreateSharedSession(props) {
|
|
609
|
+
const appSessionId = toGlobalAppSessionId(props);
|
|
610
|
+
const externalAppSession = externalApps[appSessionId];
|
|
611
|
+
if (externalAppSession) {
|
|
612
|
+
return externalAppSession;
|
|
613
|
+
}
|
|
515
614
|
const key = toGlobalAppSessionId(props);
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
_listeners: listeners,
|
|
523
|
-
getDoc: () => externalApp,
|
|
524
|
-
onWebSocketEvent: (fn) => () => {
|
|
525
|
-
appSession._listeners.add(fn);
|
|
526
|
-
return () => {
|
|
527
|
-
appSession._listeners.delete(fn);
|
|
528
|
-
};
|
|
615
|
+
if (sharedSessions[key]) {
|
|
616
|
+
return sharedSessions[key];
|
|
617
|
+
}
|
|
618
|
+
const extraProps = {
|
|
619
|
+
onClose: () => {
|
|
620
|
+
delete sharedSessions[key];
|
|
529
621
|
},
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
const triggerEventListeners = (event) => {
|
|
534
|
-
for (const fn of globalEventListeners) {
|
|
535
|
-
fn(event);
|
|
622
|
+
onWebSocketEvent: triggerGlobalWebSocketEventListeners,
|
|
623
|
+
getInitialAppActions: () => {
|
|
624
|
+
return initialActions[key] || [];
|
|
536
625
|
}
|
|
537
|
-
|
|
538
|
-
|
|
626
|
+
};
|
|
627
|
+
let session;
|
|
628
|
+
if (props.autoResume) {
|
|
629
|
+
session = createSharedPhoenixSession(props, extraProps);
|
|
630
|
+
} else {
|
|
631
|
+
session = createSharedEnigmaSession(props, extraProps);
|
|
632
|
+
}
|
|
633
|
+
sharedSessions[key] = session;
|
|
634
|
+
return sharedSessions[key];
|
|
635
|
+
}
|
|
636
|
+
async function resumeSuspendedSessions() {
|
|
637
|
+
await Promise.all(
|
|
638
|
+
Object.values(sharedSessions).map((sharedSession) => {
|
|
639
|
+
return sharedSession.resume();
|
|
640
|
+
})
|
|
641
|
+
);
|
|
642
|
+
}
|
|
643
|
+
async function resumeOnlyOnReattach() {
|
|
644
|
+
await Promise.all(
|
|
645
|
+
Object.values(sharedSessions).map((sharedSession) => {
|
|
646
|
+
return sharedSession.resume();
|
|
647
|
+
})
|
|
648
|
+
);
|
|
649
|
+
}
|
|
650
|
+
function addInitialAppAction(openAppSessionProps, action) {
|
|
651
|
+
const key = toGlobalAppSessionId(openAppSessionProps);
|
|
652
|
+
let initialActionArray = initialActions[key];
|
|
653
|
+
if (!initialActionArray) {
|
|
654
|
+
initialActionArray = [];
|
|
655
|
+
initialActions[key] = initialActionArray;
|
|
656
|
+
}
|
|
657
|
+
initialActionArray.push(action);
|
|
658
|
+
const existingSharedSession = sharedSessions[key];
|
|
659
|
+
if (existingSharedSession) {
|
|
660
|
+
existingSharedSession.initialActionsUpdated();
|
|
661
|
+
}
|
|
662
|
+
return () => {
|
|
663
|
+
const index = initialActionArray.indexOf(action);
|
|
664
|
+
if (index > -1) {
|
|
665
|
+
initialActionArray.splice(index, 1);
|
|
539
666
|
}
|
|
540
667
|
};
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
});
|
|
550
|
-
app.session.on("closed", (event) => {
|
|
551
|
-
const wsEvent = {
|
|
552
|
-
eventType: "closed",
|
|
553
|
-
...appSessionProps,
|
|
554
|
-
...event
|
|
555
|
-
};
|
|
556
|
-
triggerEventListeners(wsEvent);
|
|
557
|
-
});
|
|
558
|
-
app.session.on("suspended", (event) => {
|
|
559
|
-
const wsEvent = {
|
|
560
|
-
eventType: "suspended",
|
|
561
|
-
...appSessionProps,
|
|
562
|
-
...event
|
|
563
|
-
};
|
|
564
|
-
triggerEventListeners(wsEvent);
|
|
565
|
-
});
|
|
566
|
-
app.session.on("resuming", (event) => {
|
|
567
|
-
const wsEvent = {
|
|
568
|
-
eventType: "resuming",
|
|
569
|
-
...appSessionProps,
|
|
570
|
-
...event
|
|
571
|
-
};
|
|
572
|
-
triggerEventListeners(wsEvent);
|
|
573
|
-
});
|
|
574
|
-
app.session.on("resumed", (event) => {
|
|
575
|
-
const wsEvent = {
|
|
576
|
-
eventType: "resumed",
|
|
577
|
-
...appSessionProps,
|
|
578
|
-
...event
|
|
579
|
-
};
|
|
580
|
-
triggerEventListeners(wsEvent);
|
|
581
|
-
});
|
|
668
|
+
}
|
|
669
|
+
function registerExternalAppSession(appId, enigmaDocObject) {
|
|
670
|
+
const appSessionId = toGlobalAppSessionId({ appId });
|
|
671
|
+
function onWebSocketEvent2(event) {
|
|
672
|
+
triggerGlobalWebSocketEventListeners(event);
|
|
673
|
+
}
|
|
674
|
+
externalApps[appSessionId] = createExternalSharedSession(Promise.resolve(enigmaDocObject), onWebSocketEvent2, {
|
|
675
|
+
appId
|
|
582
676
|
});
|
|
583
|
-
return appSession;
|
|
584
677
|
}
|
|
585
678
|
|
|
586
679
|
// src/qix/qix-functions.ts
|
|
@@ -596,103 +689,30 @@ async function createSessionApp(ttlSeconds, workloadType) {
|
|
|
596
689
|
workloadType
|
|
597
690
|
});
|
|
598
691
|
}
|
|
599
|
-
|
|
600
|
-
const listeners = /* @__PURE__ */ new Set();
|
|
601
|
-
const qixSessionAppSession = {
|
|
602
|
-
getDoc: () => sharedSession.docPromise,
|
|
603
|
-
onWebSocketEvent(fn) {
|
|
604
|
-
qixSessionAppSession._listeners.add(fn);
|
|
605
|
-
return () => {
|
|
606
|
-
qixSessionAppSession._listeners.delete(fn);
|
|
607
|
-
};
|
|
608
|
-
},
|
|
609
|
-
_listeners: listeners,
|
|
610
|
-
resume: async () => {
|
|
611
|
-
return await sharedSession.resume();
|
|
612
|
-
},
|
|
613
|
-
close(props) {
|
|
614
|
-
if (!alreadyClosed) {
|
|
615
|
-
alreadyClosed = true;
|
|
616
|
-
const defaultDelay = isBrowserEnvironment ? 5e3 : -1;
|
|
617
|
-
return sharedSession.removeClient(qixSessionAppSession, props?.websocketCloseDelay ?? defaultDelay);
|
|
618
|
-
}
|
|
619
|
-
return Promise.resolve();
|
|
620
|
-
}
|
|
621
|
-
};
|
|
622
|
-
return qixSessionAppSession;
|
|
692
|
+
return createAppSession(sharedSession);
|
|
623
693
|
}
|
|
624
694
|
function openAppSession(appIdOrProps) {
|
|
625
|
-
const appSessionProps = typeof appIdOrProps === "string" ? { appId: appIdOrProps
|
|
626
|
-
const appSessionId = toGlobalAppSessionId(appSessionProps);
|
|
627
|
-
const externalApp = externalApps[appSessionId];
|
|
628
|
-
if (externalApp) {
|
|
629
|
-
return getExternalSession(externalApp, appSessionProps);
|
|
630
|
-
}
|
|
695
|
+
const appSessionProps = typeof appIdOrProps === "string" ? { appId: appIdOrProps } : appIdOrProps;
|
|
631
696
|
const sharedSession = getOrCreateSharedSession(appSessionProps);
|
|
632
|
-
|
|
633
|
-
let alreadyClosed = false;
|
|
634
|
-
const qixAppSession = {
|
|
635
|
-
getDoc: () => sharedSession.docPromise,
|
|
636
|
-
onWebSocketEvent(fn) {
|
|
637
|
-
qixAppSession._listeners.add(fn);
|
|
638
|
-
return () => {
|
|
639
|
-
qixAppSession._listeners.delete(fn);
|
|
640
|
-
};
|
|
641
|
-
},
|
|
642
|
-
_listeners: listeners,
|
|
643
|
-
resume: async () => {
|
|
644
|
-
return await sharedSession.resume();
|
|
645
|
-
},
|
|
646
|
-
close(props) {
|
|
647
|
-
if (!alreadyClosed) {
|
|
648
|
-
alreadyClosed = true;
|
|
649
|
-
const defaultDelay = isBrowserEnvironment ? 5e3 : -1;
|
|
650
|
-
return sharedSession.removeClient(qixAppSession, props?.websocketCloseDelay ?? defaultDelay);
|
|
651
|
-
}
|
|
652
|
-
return Promise.resolve();
|
|
653
|
-
}
|
|
654
|
-
};
|
|
655
|
-
sharedSession.addClient(qixAppSession);
|
|
656
|
-
return qixAppSession;
|
|
657
|
-
}
|
|
658
|
-
function registerExternalAppSession(appId, enigmaDocObject) {
|
|
659
|
-
const appSessionId = toGlobalAppSessionId({ appId });
|
|
660
|
-
externalApps[appSessionId] = Promise.resolve(enigmaDocObject);
|
|
697
|
+
return createAppSession(sharedSession);
|
|
661
698
|
}
|
|
662
699
|
function useAppHook(react) {
|
|
663
700
|
return (appId) => {
|
|
664
701
|
const [app, setApp] = react.useState(void 0);
|
|
665
702
|
react.useEffect(() => {
|
|
666
703
|
const appSession = openAppSession(appId);
|
|
667
|
-
appSession.getDoc().then((x) => {
|
|
704
|
+
void appSession.getDoc().then((x) => {
|
|
668
705
|
setApp(x);
|
|
669
706
|
});
|
|
670
707
|
return () => {
|
|
671
708
|
if (appSession) {
|
|
672
|
-
appSession.close();
|
|
709
|
+
void appSession.close();
|
|
673
710
|
}
|
|
674
711
|
};
|
|
675
712
|
}, [appId]);
|
|
676
713
|
return app;
|
|
677
714
|
};
|
|
678
715
|
}
|
|
679
|
-
function addInitialAppAction(openAppSessionProps, action) {
|
|
680
|
-
return addInitialSharedSessionCreationAction(openAppSessionProps, action);
|
|
681
|
-
}
|
|
682
|
-
function onWebSocketEvent(fn) {
|
|
683
|
-
return globalOnWebSocketEvent(fn);
|
|
684
|
-
}
|
|
685
|
-
function onCombinedWebSocketStateChange(fn) {
|
|
686
|
-
return globalOnStateChange(fn);
|
|
687
|
-
}
|
|
688
|
-
async function resumeSuspendedSessions() {
|
|
689
|
-
return resumeAll();
|
|
690
|
-
}
|
|
691
|
-
function resumeOnlyOnReattach(bool) {
|
|
692
|
-
resumeShouldRejectPromiseIfNotReattached(bool);
|
|
693
|
-
}
|
|
694
|
-
var externalApps = {};
|
|
695
|
-
var isBrowserEnvironment = isBrowser();
|
|
696
716
|
|
|
697
717
|
// src/qix/qix.ts
|
|
698
718
|
var qix = {
|