@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.
Files changed (86) hide show
  1. package/api-keys.d.ts +2 -2
  2. package/api-keys.js +2 -2
  3. package/apps.d.ts +4 -2
  4. package/apps.js +2 -2
  5. package/audits.d.ts +2 -2
  6. package/audits.js +2 -2
  7. package/{auth-types-PkN9CAF_.d.ts → auth-types-DqfMuSRX.d.ts} +1 -0
  8. package/auth.d.ts +27 -3
  9. package/auth.js +8 -4
  10. package/automations.d.ts +2 -2
  11. package/automations.js +2 -2
  12. package/brands.d.ts +2 -2
  13. package/brands.js +2 -2
  14. package/chunks/{JIX6RMFP.js → 6ZONDHRN.js} +1 -1
  15. package/chunks/{TXC5XORK.js → DLKLPD7T.js} +3 -3
  16. package/chunks/ETNHFALU.js +61 -0
  17. package/chunks/{G6QUM5WQ.js → FKDGGR2O.js} +137 -45
  18. package/chunks/{QK4TMJ64.js → GUU3KZGK.js} +11 -1
  19. package/chunks/{IQBP2PKS.js → KBSD75QL.js} +1 -1
  20. package/chunks/{OTTC4QSX.js → LY7RP2HA.js} +7 -3
  21. package/chunks/{FKCZFVJL.js → M64RLKVG.js} +2074 -12
  22. package/chunks/{F5UDCCRD.js → PLVPW5IR.js} +1 -1
  23. package/chunks/{QWQLGDMI.js → UZTIZ4H5.js} +392 -372
  24. package/chunks/{PTDXR7AY.js → YKZ2QYHN.js} +2 -2
  25. package/collections.d.ts +3 -3
  26. package/collections.js +2 -2
  27. package/csp-origins.d.ts +2 -2
  28. package/csp-origins.js +2 -2
  29. package/data-assets.d.ts +2 -2
  30. package/data-assets.js +2 -2
  31. package/data-connections.d.ts +7 -7
  32. package/data-connections.js +2 -2
  33. package/data-credentials.d.ts +2 -2
  34. package/data-credentials.js +2 -2
  35. package/data-files.d.ts +2 -2
  36. package/data-files.js +2 -2
  37. package/docs/authentication.md +47 -0
  38. package/extensions.d.ts +2 -2
  39. package/extensions.js +2 -2
  40. package/glossaries.d.ts +2 -2
  41. package/glossaries.js +2 -2
  42. package/groups.d.ts +5 -4
  43. package/groups.js +2 -2
  44. package/identity-providers.d.ts +2 -2
  45. package/identity-providers.js +2 -2
  46. package/index.d.ts +5 -3
  47. package/index.js +4 -4
  48. package/interceptors.d.ts +2 -2
  49. package/{invoke-fetch-types-BXn-uSF5.d.ts → invoke-fetch-types-Cq7bjkqn.d.ts} +10 -2
  50. package/items.d.ts +3 -3
  51. package/items.js +2 -2
  52. package/licenses.d.ts +5 -2
  53. package/licenses.js +2 -2
  54. package/oauth-clients.d.ts +7 -2
  55. package/oauth-clients.js +2 -2
  56. package/package.json +3 -2
  57. package/qix.d.ts +421 -26
  58. package/qix.js +2 -2
  59. package/quotas.d.ts +2 -2
  60. package/quotas.js +2 -2
  61. package/reload-tasks.d.ts +4 -2
  62. package/reload-tasks.js +2 -2
  63. package/reloads.d.ts +4 -2
  64. package/reloads.js +2 -2
  65. package/reports.d.ts +2 -2
  66. package/reports.js +2 -2
  67. package/roles.d.ts +2 -2
  68. package/roles.js +2 -2
  69. package/spaces.d.ts +3 -7
  70. package/spaces.js +2 -2
  71. package/temp-contents.d.ts +2 -2
  72. package/temp-contents.js +2 -2
  73. package/tenants.d.ts +2 -2
  74. package/tenants.js +2 -2
  75. package/themes.d.ts +2 -2
  76. package/themes.js +2 -2
  77. package/transports.d.ts +2 -2
  78. package/transports.js +2 -2
  79. package/users.d.ts +2 -2
  80. package/users.js +2 -2
  81. package/web-integrations.d.ts +2 -2
  82. package/web-integrations.js +2 -2
  83. package/web-notifications.d.ts +2 -2
  84. package/web-notifications.js +2 -2
  85. package/webhooks.d.ts +2 -2
  86. package/webhooks.js +2 -2
@@ -1,17 +1,20 @@
1
1
  import {
2
+ getHumanReadableSocketClosedErrorMessage
3
+ } from "./ETNHFALU.js";
4
+ import {
5
+ exposeInternalApiOnWindow,
2
6
  generateRandomString,
3
7
  getRestCallAuthParams,
4
8
  getWebSocketAuthParams,
9
+ handleAuthenticationError,
10
+ isWindows,
5
11
  toValidWebsocketLocationUrl
6
- } from "./G6QUM5WQ.js";
12
+ } from "./FKDGGR2O.js";
7
13
  import "./3RGGGGAR.js";
8
14
  import {
9
15
  isNode
10
16
  } from "./2ZQ3ZX7F.js";
11
17
 
12
- // src/qix/session/enigma-session.ts
13
- import enigma from "enigma.js";
14
-
15
18
  // src/qix/session/schema/engine-api.js
16
19
  var engine_api_default = {
17
20
  structs: {
@@ -8575,6 +8578,9 @@ var base_default = {
8575
8578
  types: ["Doc", "GenericObject", "GenericDimension", "GenericMeasure", "GenericBookmark", "GenericVariable", "Field"],
8576
8579
  init(args) {
8577
8580
  const { api } = args;
8581
+ if (api.Promise) {
8582
+ return;
8583
+ }
8578
8584
  if (api.getAppLayout) {
8579
8585
  api.session.app = api;
8580
8586
  }
@@ -8602,9 +8608,13 @@ function createGetMethod(cacheKey) {
8602
8608
  return api.migrate.object(api).then(() => api);
8603
8609
  }
8604
8610
  return api;
8605
- }).catch(() => {
8611
+ }).catch((err) => {
8606
8612
  delete apiCache[id];
8607
- return Promise.reject({ error: { code: engine_enums_default.NxLocalizedErrorCode.LOCERR_GENERIC_NOT_FOUND } });
8613
+ return Promise.reject({
8614
+ code: engine_enums_default.NxLocalizedErrorCode.LOCERR_GENERIC_NOT_FOUND,
8615
+ message: "Object not found",
8616
+ error: { code: engine_enums_default.NxLocalizedErrorCode.LOCERR_GENERIC_NOT_FOUND }
8617
+ });
8608
8618
  });
8609
8619
  apiCache[id] = promise;
8610
8620
  return promise;
@@ -9209,16 +9219,16 @@ var state_default = {
9209
9219
  self.setState(RPCStates.VALIDATING);
9210
9220
  }
9211
9221
  if (self.ongoingRequests[CACHE_KEY]) {
9212
- const ongoingRequests = self.ongoingRequests[CACHE_KEY];
9222
+ const ongoingRequests2 = self.ongoingRequests[CACHE_KEY];
9213
9223
  if (pure) {
9214
- return ongoingRequests.then(() => {
9224
+ return ongoingRequests2.then(() => {
9215
9225
  if (!self.pureLayout.permissions) {
9216
9226
  self.pureLayout.permissions = self.layout.permissions;
9217
9227
  }
9218
9228
  return self.pureLayout;
9219
9229
  });
9220
9230
  }
9221
- return ongoingRequests;
9231
+ return ongoingRequests2;
9222
9232
  }
9223
9233
  const request = _getLayout().then((layout) => {
9224
9234
  if (!self.isValid) {
@@ -10380,8 +10390,9 @@ async function createEnigmaSession({
10380
10390
  /^http/,
10381
10391
  "ws"
10382
10392
  );
10393
+ const unitTestCreateWebSocket = hostConfig?.createWebSocket;
10383
10394
  let createSocketBuilder;
10384
- if (isNodeEnvironment) {
10395
+ if (isNodeEnvironment && !unitTestCreateWebSocket) {
10385
10396
  const WS = (await import("ws")).default;
10386
10397
  createSocketBuilder = async () => {
10387
10398
  let url = baseUrl;
@@ -10400,9 +10411,17 @@ async function createEnigmaSession({
10400
10411
  Object.entries(queryParams).forEach(([key, value]) => {
10401
10412
  url = `${url}&${key}=${value}`;
10402
10413
  });
10403
- return (socketUrl) => new WebSocket(url);
10414
+ return (socketUrl) => {
10415
+ const socket = unitTestCreateWebSocket ? unitTestCreateWebSocket(url) : new WebSocket(url);
10416
+ exposeInternalApiOnWindow("closeLastWebSocket", (code) => {
10417
+ console.log("Closing websocket with code", code, socket);
10418
+ socket.close(code);
10419
+ });
10420
+ return socket;
10421
+ };
10404
10422
  };
10405
10423
  }
10424
+ const { default: enigma } = await import("enigma.js");
10406
10425
  const session = enigma.create({
10407
10426
  schema: engine_api_default,
10408
10427
  mixins: mixins5,
@@ -10424,6 +10443,2049 @@ async function createEnigmaSession({
10424
10443
  session.resume = resume;
10425
10444
  return session;
10426
10445
  }
10446
+
10447
+ // src/qix/session/phoenix/logger.ts
10448
+ var ongoingRequests = /* @__PURE__ */ new Set();
10449
+ var requestDepths = /* @__PURE__ */ new Map();
10450
+ var startIntent = 0;
10451
+ var baseIndent = " ";
10452
+ var logEnabled = false;
10453
+ try {
10454
+ logEnabled = globalThis.qlikQixWebSocketLogEnabled || localStorage?.getItem("qlik-qix-websocket-log") === "true";
10455
+ } catch {
10456
+ }
10457
+ function logRequest(handleOrObject, websocketRequest, request) {
10458
+ if (logEnabled) {
10459
+ const indent = startIndent(websocketRequest);
10460
+ const preThing = `${indent} ===> ${websocketRequest.id} call `;
10461
+ console.log(`${preThing}${toLogName(handleOrObject)}.${request.method}`, ...formatParams(request.params));
10462
+ }
10463
+ }
10464
+ function logResponse(handleOrObject, websocketRequest, sendResponse) {
10465
+ if (logEnabled) {
10466
+ const indent = endIndent(websocketRequest);
10467
+ if (sendResponse?.change) {
10468
+ console.log(`${indent} <--- ${websocketRequest.id} Changed: ${sendResponse.change.join(", ")}`);
10469
+ }
10470
+ if (sendResponse?.close) {
10471
+ console.log(`${indent} <--- ${websocketRequest.id} Closed: ${sendResponse.close.join(", ")}`);
10472
+ }
10473
+ const preThing = `${indent} <=== ${websocketRequest.id} return`;
10474
+ if (sendResponse.error) {
10475
+ console.log(preThing, JSON.stringify(sendResponse.error));
10476
+ } else {
10477
+ console.log(preThing, sendResponse.result);
10478
+ }
10479
+ }
10480
+ }
10481
+ function logJsonRpcChannelError(handleOrObject, websocketRequest, error) {
10482
+ if (logEnabled) {
10483
+ const indent = endIndent(websocketRequest);
10484
+ const preThing = `${indent} <=== ${websocketRequest.id} throw`;
10485
+ console.log(preThing, JSON.stringify(error));
10486
+ }
10487
+ }
10488
+ function logEvent(message, ...optionalParams) {
10489
+ if (logEnabled) {
10490
+ console.log("QIX", message, ...optionalParams);
10491
+ }
10492
+ }
10493
+ function startIndent(websocketRequest) {
10494
+ ongoingRequests.add(websocketRequest.id);
10495
+ requestDepths.set(websocketRequest.id, ongoingRequests.size);
10496
+ const indent = baseIndent.repeat(startIntent + ongoingRequests.size);
10497
+ return indent;
10498
+ }
10499
+ function endIndent(websocketRequest) {
10500
+ const indent = baseIndent.repeat(startIntent + (requestDepths.get(websocketRequest.id) || 0));
10501
+ ongoingRequests.delete(websocketRequest.id);
10502
+ requestDepths.delete(websocketRequest.id);
10503
+ return indent;
10504
+ }
10505
+ function toLogName(handleOrObject) {
10506
+ if (handleOrObject === 1) {
10507
+ return "Doc";
10508
+ } else if (handleOrObject === -1) {
10509
+ return "Global";
10510
+ } else if (typeof handleOrObject === "undefined") {
10511
+ return "(undefined handle)";
10512
+ } else if (typeof handleOrObject === "object") {
10513
+ const obj = handleOrObject;
10514
+ if (!obj.id) {
10515
+ const params = obj.respawnInfo.creatingRequest?.params;
10516
+ if (Array.isArray(params)) {
10517
+ return params?.filter((arg) => typeof arg === "string").join("/");
10518
+ }
10519
+ }
10520
+ return `${obj.id}/${obj.getHandle()}`;
10521
+ } else {
10522
+ return handleOrObject;
10523
+ }
10524
+ }
10525
+ function formatParams(params) {
10526
+ if (Array.isArray(params)) {
10527
+ const result = ["("];
10528
+ for (let i = 0; i < params.length; i++) {
10529
+ result.push(params[i]);
10530
+ if (i < params.length - 1) {
10531
+ result.push(",");
10532
+ }
10533
+ }
10534
+ result.push(")");
10535
+ return result;
10536
+ } else {
10537
+ return [params];
10538
+ }
10539
+ }
10540
+
10541
+ // src/qix/session/phoenix/interest-monitor.ts
10542
+ function createInterestMonitor() {
10543
+ let activity = createPromiseAndResolveFunc();
10544
+ let listening = false;
10545
+ let onUserActivityDetectedCallback;
10546
+ function signalInterest() {
10547
+ stopListeningForActivity();
10548
+ logEvent("Someone is interested in this");
10549
+ onUserActivityDetectedCallback?.();
10550
+ activity.resolve();
10551
+ }
10552
+ function waitUntilSomeoneIsInterestedInThis() {
10553
+ logEvent("Waiting for someone to be interested in this");
10554
+ startListeningForActivity();
10555
+ const result = activity.promise;
10556
+ activity = createPromiseAndResolveFunc();
10557
+ return result;
10558
+ }
10559
+ function resetAnyInterestSignalledBeforeNow() {
10560
+ logEvent("stop waiting for someone to be interested in this");
10561
+ stopListeningForActivity();
10562
+ activity = createPromiseAndResolveFunc();
10563
+ }
10564
+ function onUserActivityDetected(activityCallback) {
10565
+ onUserActivityDetectedCallback = activityCallback;
10566
+ }
10567
+ function mouseListener() {
10568
+ signalInterest();
10569
+ }
10570
+ function visibilityChangeListener() {
10571
+ if (globalThis.document?.visibilityState === "visible") {
10572
+ logEvent("Document is visible");
10573
+ signalInterest();
10574
+ }
10575
+ }
10576
+ function focusListener() {
10577
+ logEvent("Document has focus");
10578
+ signalInterest();
10579
+ }
10580
+ function startListeningForActivity() {
10581
+ if (!listening) {
10582
+ listening = true;
10583
+ globalThis.window?.document.addEventListener("visibilitychange", visibilityChangeListener);
10584
+ globalThis.window?.addEventListener("focus", focusListener);
10585
+ globalThis.window?.addEventListener("mousemove", mouseListener);
10586
+ }
10587
+ }
10588
+ function stopListeningForActivity() {
10589
+ if (listening) {
10590
+ listening = false;
10591
+ globalThis.window?.document.removeEventListener("visibilitychange", visibilityChangeListener);
10592
+ globalThis.window?.removeEventListener("focus", focusListener);
10593
+ globalThis.window?.removeEventListener("mousemove", mouseListener);
10594
+ }
10595
+ }
10596
+ const api = {
10597
+ startListeningForActivity,
10598
+ stopListeningForActivity,
10599
+ waitUntilSomeoneIsInterestedInThis,
10600
+ resetAnyInterestSignalledBeforeNow,
10601
+ onUserActivityDetected,
10602
+ signalInterest
10603
+ };
10604
+ return api;
10605
+ }
10606
+ function createPromiseAndResolveFunc() {
10607
+ let resolve = () => {
10608
+ };
10609
+ const promise = new Promise((res) => {
10610
+ resolve = res;
10611
+ });
10612
+ return { promise, resolve };
10613
+ }
10614
+
10615
+ // src/qix/session/phoenix/rpc-object-ref.ts
10616
+ function normalizeObjectRef(response) {
10617
+ if (response.qHandle) {
10618
+ return {
10619
+ handle: response.qHandle,
10620
+ type: response.qType,
10621
+ id: response.qGenericId,
10622
+ genericType: response.qGenericType
10623
+ };
10624
+ } else {
10625
+ return {
10626
+ handle: response.handle,
10627
+ type: response.type,
10628
+ id: response.id,
10629
+ genericType: response.genericType
10630
+ };
10631
+ }
10632
+ }
10633
+ function isQixObjectRef(ref) {
10634
+ return typeof ref === "object" && ref.qHandle && ref.qType;
10635
+ }
10636
+ function getHandleOfRef(response) {
10637
+ return response.qHandle ?? response.handle;
10638
+ }
10639
+
10640
+ // src/qix/session/phoenix/phoenix-session-state.ts
10641
+ function createPhoenixSessionState({
10642
+ doc,
10643
+ global,
10644
+ executedAppActions
10645
+ }) {
10646
+ const objects = {};
10647
+ return {
10648
+ getObjects() {
10649
+ return objects;
10650
+ },
10651
+ getObject(ref) {
10652
+ if (typeof ref === "object") {
10653
+ const handle = getHandleOfRef(ref);
10654
+ if (handle === global.getHandle()) {
10655
+ return global;
10656
+ }
10657
+ if (handle === doc.getHandle()) {
10658
+ return doc;
10659
+ }
10660
+ if (handle) {
10661
+ return objects[handle];
10662
+ }
10663
+ return void 0;
10664
+ }
10665
+ return objects[ref];
10666
+ },
10667
+ removeObject(handle) {
10668
+ delete objects[handle];
10669
+ },
10670
+ setObject(handle, object) {
10671
+ objects[handle] = object;
10672
+ },
10673
+ getDoc() {
10674
+ return doc;
10675
+ },
10676
+ getGlobal() {
10677
+ return global;
10678
+ },
10679
+ addExecutedInitialAppAction(initialAppAction) {
10680
+ executedAppActions.push(initialAppAction);
10681
+ },
10682
+ isAppActionExecuted(initialAppAction) {
10683
+ return executedAppActions.indexOf(initialAppAction) >= 0;
10684
+ },
10685
+ getExecutedAppActions() {
10686
+ return executedAppActions;
10687
+ }
10688
+ };
10689
+ }
10690
+
10691
+ // src/qix/session/phoenix/json-patch.js
10692
+ import originalExtend from "extend";
10693
+ var extend2 = originalExtend.bind(null, true);
10694
+ var JSONPatch2 = {};
10695
+ var { isArray: isArray2 } = Array;
10696
+ function isObject2(v) {
10697
+ return v != null && !Array.isArray(v) && typeof v === "object";
10698
+ }
10699
+ function isUndef2(v) {
10700
+ return typeof v === "undefined";
10701
+ }
10702
+ function isFunction2(v) {
10703
+ return typeof v === "function";
10704
+ }
10705
+ function generateValue2(val) {
10706
+ if (val) {
10707
+ return extend2({}, { val }).val;
10708
+ }
10709
+ return val;
10710
+ }
10711
+ function isSpecialProperty2(obj, key) {
10712
+ return isFunction2(obj[key]) || key.substring(0, 2) === "$$" || key.substring(0, 1) === "_";
10713
+ }
10714
+ function getParent2(data, str) {
10715
+ const seperator = "/";
10716
+ const parts = str.substring(1).split(seperator).slice(0, -1);
10717
+ let numPart;
10718
+ parts.forEach((part, i) => {
10719
+ if (i === parts.length) {
10720
+ return;
10721
+ }
10722
+ numPart = +part;
10723
+ const newPart = !isNaN(numPart) ? [] : {};
10724
+ data[numPart || part] = isUndef2(data[numPart || part]) ? newPart : data[part];
10725
+ data = data[numPart || part];
10726
+ });
10727
+ return data;
10728
+ }
10729
+ function emptyObject2(obj) {
10730
+ Object.keys(obj).forEach((key) => {
10731
+ const config = Object.getOwnPropertyDescriptor(obj, key);
10732
+ if (config.configurable && !isSpecialProperty2(obj, key)) {
10733
+ delete obj[key];
10734
+ }
10735
+ });
10736
+ }
10737
+ function compare2(a, b) {
10738
+ let isIdentical = true;
10739
+ if (isObject2(a) && isObject2(b)) {
10740
+ if (Object.keys(a).length !== Object.keys(b).length) {
10741
+ return false;
10742
+ }
10743
+ Object.keys(a).forEach((key) => {
10744
+ if (!compare2(a[key], b[key])) {
10745
+ isIdentical = false;
10746
+ }
10747
+ });
10748
+ return isIdentical;
10749
+ }
10750
+ if (isArray2(a) && isArray2(b)) {
10751
+ if (a.length !== b.length) {
10752
+ return false;
10753
+ }
10754
+ for (let i = 0, l = a.length; i < l; i += 1) {
10755
+ if (!compare2(a[i], b[i])) {
10756
+ return false;
10757
+ }
10758
+ }
10759
+ return true;
10760
+ }
10761
+ return a === b;
10762
+ }
10763
+ function patchArray2(original, newA, basePath) {
10764
+ let patches = [];
10765
+ const oldA = original.slice();
10766
+ let tmpIdx = -1;
10767
+ function findIndex(a, id, idx) {
10768
+ if (a[idx] && isUndef2(a[idx].qInfo)) {
10769
+ return null;
10770
+ }
10771
+ if (a[idx] && a[idx].qInfo.qId === id) {
10772
+ return idx;
10773
+ }
10774
+ for (let ii = 0, ll = a.length; ii < ll; ii += 1) {
10775
+ if (a[ii] && a[ii].qInfo.qId === id) {
10776
+ return ii;
10777
+ }
10778
+ }
10779
+ return -1;
10780
+ }
10781
+ if (compare2(newA, oldA)) {
10782
+ return patches;
10783
+ }
10784
+ if (!isUndef2(newA[0]) && isUndef2(newA[0].qInfo)) {
10785
+ patches.push({
10786
+ op: "replace",
10787
+ path: basePath,
10788
+ value: newA
10789
+ });
10790
+ return patches;
10791
+ }
10792
+ for (let i = oldA.length - 1; i >= 0; i -= 1) {
10793
+ tmpIdx = findIndex(newA, oldA[i].qInfo && oldA[i].qInfo.qId, i);
10794
+ if (tmpIdx === -1) {
10795
+ patches.push({
10796
+ op: "remove",
10797
+ path: `${basePath}/${i}`
10798
+ });
10799
+ oldA.splice(i, 1);
10800
+ } else {
10801
+ patches = patches.concat(JSONPatch2.generate(oldA[i], newA[tmpIdx], `${basePath}/${i}`));
10802
+ }
10803
+ }
10804
+ for (let i = 0, l = newA.length; i < l; i += 1) {
10805
+ tmpIdx = findIndex(oldA, newA[i].qInfo && newA[i].qInfo.qId);
10806
+ if (tmpIdx === -1) {
10807
+ patches.push({
10808
+ op: "add",
10809
+ path: `${basePath}/${i}`,
10810
+ value: newA[i]
10811
+ });
10812
+ oldA.splice(i, 0, newA[i]);
10813
+ } else if (tmpIdx !== i) {
10814
+ patches.push({
10815
+ op: "move",
10816
+ path: `${basePath}/${i}`,
10817
+ from: `${basePath}/${tmpIdx}`
10818
+ });
10819
+ oldA.splice(i, 0, oldA.splice(tmpIdx, 1)[0]);
10820
+ }
10821
+ }
10822
+ return patches;
10823
+ }
10824
+ JSONPatch2.generate = function generate(original, newData, basePath) {
10825
+ basePath = basePath || "";
10826
+ let patches = [];
10827
+ Object.keys(newData).forEach((key) => {
10828
+ const val = generateValue2(newData[key]);
10829
+ const oldVal = original[key];
10830
+ const tmpPath = `${basePath}/${key}`;
10831
+ if (compare2(val, oldVal) || isSpecialProperty2(newData, key)) {
10832
+ return;
10833
+ }
10834
+ if (isUndef2(oldVal)) {
10835
+ patches.push({
10836
+ op: "add",
10837
+ path: tmpPath,
10838
+ value: val
10839
+ });
10840
+ } else if (isObject2(val) && isObject2(oldVal)) {
10841
+ patches = patches.concat(JSONPatch2.generate(oldVal, val, tmpPath));
10842
+ } else if (isArray2(val) && isArray2(oldVal)) {
10843
+ patches = patches.concat(patchArray2(oldVal, val, tmpPath));
10844
+ } else {
10845
+ patches.push({
10846
+ op: "replace",
10847
+ path: `${basePath}/${key}`,
10848
+ value: val
10849
+ });
10850
+ }
10851
+ });
10852
+ Object.keys(original).forEach((key) => {
10853
+ if (isUndef2(newData[key]) && !isSpecialProperty2(original, key)) {
10854
+ patches.push({
10855
+ op: "remove",
10856
+ path: `${basePath}/${key}`
10857
+ });
10858
+ }
10859
+ });
10860
+ return patches;
10861
+ };
10862
+ JSONPatch2.apply = function apply(original, patches) {
10863
+ patches.forEach((patch) => {
10864
+ let parent = getParent2(original, patch.path);
10865
+ let key = patch.path.split("/").splice(-1)[0];
10866
+ let target = key && isNaN(+key) ? parent[key] : parent[+key] || parent;
10867
+ const from = patch.from ? patch.from.split("/").splice(-1)[0] : null;
10868
+ if (patch.path === "/") {
10869
+ parent = null;
10870
+ target = original;
10871
+ }
10872
+ if (patch.op === "add" || patch.op === "replace") {
10873
+ if (isArray2(parent)) {
10874
+ if (key === "-") {
10875
+ key = parent.length;
10876
+ }
10877
+ parent.splice(+key, patch.op === "add" ? 0 : 1, patch.value);
10878
+ } else if (isArray2(target) && isArray2(patch.value)) {
10879
+ target.length = 0;
10880
+ const chunkSize = 1e3;
10881
+ for (let i = 0; i < patch.value.length; i += chunkSize) {
10882
+ const chunk = patch.value.slice(i, i + chunkSize);
10883
+ target.push(...chunk);
10884
+ }
10885
+ } else if (isObject2(target) && isObject2(patch.value)) {
10886
+ emptyObject2(target);
10887
+ extend2(target, patch.value);
10888
+ } else if (!parent) {
10889
+ throw new Error("Patchee is not an object we can patch");
10890
+ } else {
10891
+ parent[key] = patch.value;
10892
+ }
10893
+ } else if (patch.op === "move") {
10894
+ const oldParent = getParent2(original, patch.from);
10895
+ if (isArray2(parent)) {
10896
+ parent.splice(+key, 0, oldParent.splice(+from, 1)[0]);
10897
+ } else {
10898
+ parent[key] = oldParent[from];
10899
+ delete oldParent[from];
10900
+ }
10901
+ } else if (patch.op === "remove") {
10902
+ if (isArray2(parent)) {
10903
+ parent.splice(+key, 1);
10904
+ } else {
10905
+ delete parent[key];
10906
+ }
10907
+ }
10908
+ });
10909
+ };
10910
+ JSONPatch2.clone = function clone(obj) {
10911
+ return extend2({}, obj);
10912
+ };
10913
+ JSONPatch2.createPatch = function createPatch(op, val, path) {
10914
+ const patch = {
10915
+ op: op.toLowerCase(),
10916
+ path
10917
+ };
10918
+ if (patch.op === "move") {
10919
+ patch.from = val;
10920
+ } else if (typeof val !== "undefined") {
10921
+ patch.value = val;
10922
+ }
10923
+ return patch;
10924
+ };
10925
+ JSONPatch2.updateObject = function updateObject(original, newData) {
10926
+ if (!Object.keys(original).length) {
10927
+ extend2(original, newData);
10928
+ return;
10929
+ }
10930
+ JSONPatch2.apply(original, JSONPatch2.generate(original, newData));
10931
+ };
10932
+ var json_patch_default2 = JSONPatch2;
10933
+
10934
+ // src/qix/session/phoenix/delta-compression.ts
10935
+ function unwrapDeltas(result, state, handle, method) {
10936
+ const newResult = {};
10937
+ Object.entries(result).forEach(([outKey, patches]) => {
10938
+ if (!Array.isArray(patches)) {
10939
+ throw new Error("Unexpected RPC response, expected array of patches");
10940
+ }
10941
+ let entry = state[handle]?.[method]?.[outKey];
10942
+ if (typeof entry === "undefined") {
10943
+ entry = patches[0] && Array.isArray(patches[0].value) ? [] : {};
10944
+ }
10945
+ if (patches.length) {
10946
+ if (patches[0].path === "/" && typeof patches[0].value !== "object") {
10947
+ entry = patches[0].value;
10948
+ } else {
10949
+ json_patch_default2.apply(entry, patches);
10950
+ }
10951
+ if (!state[handle]) {
10952
+ state[handle] = {};
10953
+ }
10954
+ if (!state[handle][method]) {
10955
+ state[handle][method] = {};
10956
+ }
10957
+ state[handle][method][outKey] = entry;
10958
+ }
10959
+ newResult[outKey] = entry;
10960
+ });
10961
+ return JSON.parse(JSON.stringify(newResult));
10962
+ }
10963
+
10964
+ // src/qix/session/phoenix/protocol-helpers.ts
10965
+ function getDeltaAndReturnEmptyProps(request) {
10966
+ if (request.method === "GetProperties" || request.method === "GetFullPropertyTree") {
10967
+ return {
10968
+ return_empty: true,
10969
+ delta: false
10970
+ // return_empty require delta to be false to work
10971
+ };
10972
+ } else {
10973
+ return {
10974
+ delta: request.outKey !== -1 && request.outKey !== "qSuccess"
10975
+ };
10976
+ }
10977
+ }
10978
+ function extractResult(request, resultObject) {
10979
+ if (typeof resultObject !== "object") {
10980
+ return resultObject;
10981
+ }
10982
+ if (request.method === "CreateSessionApp" || request.method === "CreateSessionAppFromApp") {
10983
+ resultObject.qReturn.qGenericId = resultObject.qSessionAppId || resultObject.qReturn.qGenericId;
10984
+ } else if (request.method === "GetInteract" || request.method === "StoreTempSelectionState" || request.method === "CreateTemporaryBookmark") {
10985
+ delete resultObject.qReturn;
10986
+ }
10987
+ if (typeof resultObject.qReturn !== "undefined") {
10988
+ return resultObject.qReturn;
10989
+ }
10990
+ if (request.outKey !== -1) {
10991
+ return resultObject[request.outKey || "qReturn"];
10992
+ }
10993
+ return resultObject;
10994
+ }
10995
+ function createResolvablePromise() {
10996
+ let resolve;
10997
+ let reject;
10998
+ const promise = new Promise((res, rej) => {
10999
+ resolve = res;
11000
+ reject = rej;
11001
+ });
11002
+ return [promise, resolve, reject];
11003
+ }
11004
+
11005
+ // src/qix/session/phoenix/websocket.ts
11006
+ var forceUniqueSessionForTestPurposes = false;
11007
+ exposeInternalApiOnWindow("makeNextWebsocketGetNewEngineSession", () => {
11008
+ forceUniqueSessionForTestPurposes = true;
11009
+ });
11010
+ var WebSocketError = class extends Error {
11011
+ code;
11012
+ reason;
11013
+ constructor({ code = 0, reason = "" }, { appId, hostConfig }) {
11014
+ super(getHumanReadableSocketClosedErrorMessage({ code, reason }, { appId, hostConfig }));
11015
+ this.code = code;
11016
+ this.reason = reason;
11017
+ }
11018
+ };
11019
+ async function createWebSocket(props, listeners) {
11020
+ try {
11021
+ return await createWebsocketSingleAttempt(props, listeners);
11022
+ } catch (err) {
11023
+ logEvent("Retrying to create websocket", err);
11024
+ const action = await handleAuthenticationError({
11025
+ headers: new Headers(),
11026
+ status: 101,
11027
+ canRetry: true,
11028
+ hostConfig: props.hostConfig
11029
+ });
11030
+ if (action.retry) {
11031
+ return createWebsocketSingleAttempt(props, listeners);
11032
+ }
11033
+ if (action.preventDefault) {
11034
+ return new Promise(() => {
11035
+ });
11036
+ }
11037
+ throw err;
11038
+ }
11039
+ }
11040
+ async function createWebsocketSingleAttempt({ appId, identity, hostConfig, useReloadEngine = false, workloadType, ttlSeconds }, listeners) {
11041
+ const locationUrl = toValidWebsocketLocationUrl(hostConfig);
11042
+ const reloadUri = encodeURIComponent(`${locationUrl}/sense/app/${appId}`);
11043
+ const ttlPart = ttlSeconds !== void 0 && ttlSeconds >= 0 ? `/ttl/${ttlSeconds}` : "";
11044
+ const identityToUse = forceUniqueSessionForTestPurposes ? generateRandomString(16) : identity;
11045
+ if (forceUniqueSessionForTestPurposes) {
11046
+ logEvent("Forcing a new session for testing purposes");
11047
+ forceUniqueSessionForTestPurposes = false;
11048
+ }
11049
+ const identityPart = identityToUse ? `/identity/${identityToUse}` : "";
11050
+ const workloadTypePart = useReloadEngine ? "&workloadType=interactive-reload" : workloadType ? `&workloadType=${workloadType}` : "";
11051
+ let url = `${locationUrl}/app/${appId}${identityPart}${ttlPart}?reloadUri=${reloadUri}${workloadTypePart}`.replace(
11052
+ /^http/,
11053
+ "ws"
11054
+ );
11055
+ const isNodeEnvironment = isNode();
11056
+ const unitTestCreateWebSocket = hostConfig?.createWebSocket;
11057
+ logEvent("Creating websocket", url);
11058
+ let socket;
11059
+ if (isNodeEnvironment && !unitTestCreateWebSocket) {
11060
+ const { headers, queryParams } = await getRestCallAuthParams({ hostConfig, method: "POST" });
11061
+ const WS = (await import("ws")).default;
11062
+ Object.entries(queryParams).forEach(([key, value]) => {
11063
+ url = `${url}&${key}=${value}`;
11064
+ });
11065
+ socket = new WS(url, void 0, {
11066
+ headers
11067
+ });
11068
+ } else {
11069
+ const { queryParams } = await getWebSocketAuthParams({ hostConfig });
11070
+ Object.entries(queryParams).forEach(([key, value]) => {
11071
+ url = `${url}&${key}=${value}`;
11072
+ });
11073
+ socket = unitTestCreateWebSocket ? unitTestCreateWebSocket(url) : new WebSocket(url);
11074
+ exposeInternalApiOnWindow("closeLastWebSocket", (code) => {
11075
+ console.log("Closing websocket with code", code, socket);
11076
+ socket.close(code);
11077
+ });
11078
+ }
11079
+ logEvent("Created websocket", url);
11080
+ const [socketOpenPromise, resolveSocketOpenPromise, rejectSocketOpenPromise] = createResolvablePromise();
11081
+ let opened = false;
11082
+ socket.onopen = () => {
11083
+ socket.onopen = null;
11084
+ socket.onerror = null;
11085
+ logEvent("Websocket opened");
11086
+ opened = true;
11087
+ resolveSocketOpenPromise(socket);
11088
+ };
11089
+ socket.onerror = () => {
11090
+ socket.onopen = null;
11091
+ socket.onerror = null;
11092
+ };
11093
+ socket.onmessage = (message) => {
11094
+ listeners.onMessage(message);
11095
+ };
11096
+ socket.onclose = ({ code, reason }) => {
11097
+ if (!opened) {
11098
+ rejectSocketOpenPromise(new WebSocketError({ code, reason }, { appId, hostConfig }));
11099
+ } else {
11100
+ listeners.onClose({ code, reason });
11101
+ }
11102
+ };
11103
+ return socketOpenPromise;
11104
+ }
11105
+
11106
+ // src/qix/session/phoenix/json-rpc-channel.ts
11107
+ var RPC_CLOSE_NORMAL = 1e3;
11108
+ var RPC_CLOSE_MANUAL_SUSPEND = 4e3;
11109
+ var WebsocketClosedError = class extends Error {
11110
+ };
11111
+ async function createJsonRpcChannel(props, listener) {
11112
+ const { hostConfig } = props;
11113
+ const [connectionInfoPromise, resolveConnectionInfo] = createResolvablePromise();
11114
+ const [authenticationInfoPromise, resolveAuthenticationInfo] = createResolvablePromise();
11115
+ let pendingInvocations = {};
11116
+ let initiator = "network";
11117
+ let closed = false;
11118
+ const socket = await createWebSocket(props, {
11119
+ onMessage: (event) => {
11120
+ const data = JSON.parse(event.data);
11121
+ if (isInvocationResponse(data)) {
11122
+ const pendingInvocation = pendingInvocations[data.id];
11123
+ listener.onMessage(data, pendingInvocation?.handle);
11124
+ pendingInvocation?.resolve(data);
11125
+ } else {
11126
+ listener.onMessage(data, void 0);
11127
+ if (data.method === "OnConnected") {
11128
+ resolveConnectionInfo(data.params?.qSessionState);
11129
+ } else if (data.method === "OnAuthenticationInformation") {
11130
+ if (data.mustAuthenticate) {
11131
+ void handleAuthenticationError({
11132
+ headers: new Headers(),
11133
+ status: 101,
11134
+ canRetry: true,
11135
+ hostConfig
11136
+ }).then(() => {
11137
+ socket.close();
11138
+ });
11139
+ } else {
11140
+ resolveAuthenticationInfo(data);
11141
+ }
11142
+ }
11143
+ }
11144
+ },
11145
+ onClose: ({ code, reason }) => {
11146
+ logEvent("Websocket closed", code, reason);
11147
+ closed = true;
11148
+ listener.onConnectionClosed({ code, reason, initiator });
11149
+ const pendingInvocationsAtCloseTime = Object.values(pendingInvocations);
11150
+ pendingInvocations = {};
11151
+ pendingInvocationsAtCloseTime.forEach(
11152
+ (pendingInvocation) => pendingInvocation.reject(new WebsocketClosedError())
11153
+ );
11154
+ }
11155
+ });
11156
+ const sessionState = await connectionInfoPromise;
11157
+ const reattached = sessionState === "SESSION_ATTACHED";
11158
+ if (await isWindows(hostConfig)) {
11159
+ const authInfo = await authenticationInfoPromise;
11160
+ if (authInfo.mustAuthenticate) {
11161
+ throw new Error("Windows authentication needed");
11162
+ }
11163
+ }
11164
+ function send(request) {
11165
+ if (closed) {
11166
+ throw new WebsocketClosedError();
11167
+ }
11168
+ const promise = new Promise((resolve, reject) => {
11169
+ pendingInvocations[request.id] = {
11170
+ handle: request.handle,
11171
+ resolve,
11172
+ reject
11173
+ };
11174
+ socket.send(JSON.stringify(request));
11175
+ });
11176
+ return promise;
11177
+ }
11178
+ return {
11179
+ send,
11180
+ isClosed: () => !!closed,
11181
+ isReattached: () => !!reattached,
11182
+ getSessionState: () => sessionState,
11183
+ closeNormal: () => {
11184
+ logEvent("Closing websocket!");
11185
+ initiator = "manual";
11186
+ closed = true;
11187
+ socket.close(RPC_CLOSE_NORMAL, "Websocket closed from client side");
11188
+ },
11189
+ closeSuspend: () => {
11190
+ logEvent("Suspending websocket!");
11191
+ initiator = "manual";
11192
+ closed = true;
11193
+ socket.close(RPC_CLOSE_MANUAL_SUSPEND, "Websocket suspended from client side");
11194
+ }
11195
+ };
11196
+ }
11197
+ function isInvocationResponse(data) {
11198
+ return data.id;
11199
+ }
11200
+
11201
+ // src/qix/session/phoenix/qix-connection.ts
11202
+ var QixError = class extends Error {
11203
+ code;
11204
+ parameter;
11205
+ enigmaError = true;
11206
+ isCancelled;
11207
+ constructor({
11208
+ message,
11209
+ code,
11210
+ parameter
11211
+ }, isCancelled) {
11212
+ super(message);
11213
+ this.code = code;
11214
+ this.parameter = parameter;
11215
+ this.isCancelled = isCancelled || false;
11216
+ }
11217
+ };
11218
+ function isCancelRequest(handleOrObject, method) {
11219
+ const handle = typeof handleOrObject === "object" ? handleOrObject.getHandle() : handleOrObject;
11220
+ return handle === 1 && method === "CancelRequest";
11221
+ }
11222
+ async function createQixConnection(props, listener) {
11223
+ let requestCounter = 1;
11224
+ const canceledRequests = {};
11225
+ function storeCanceledRequestId(request) {
11226
+ if (Array.isArray(request.params) && request.params.length > 0) {
11227
+ const cancelledRequestId = request.params[0];
11228
+ canceledRequests[cancelledRequestId] = true;
11229
+ }
11230
+ }
11231
+ function requestWasCanceled(requestId) {
11232
+ if (canceledRequests[requestId]) {
11233
+ delete canceledRequests[requestId];
11234
+ return true;
11235
+ }
11236
+ return false;
11237
+ }
11238
+ function onMessage(message, handle) {
11239
+ listener.onMessageReceived(message, handle);
11240
+ if (message.change) {
11241
+ message.change.forEach((changedHandle) => listener.onObjectChanged(changedHandle));
11242
+ }
11243
+ if (message.close) {
11244
+ message.close.forEach((closedHandle) => listener.onObjectClosed(closedHandle));
11245
+ }
11246
+ if (message.params) {
11247
+ listener.onNotification(message);
11248
+ }
11249
+ }
11250
+ function onConnectionClosed(closeEvent) {
11251
+ listener.onConnectionClosed(closeEvent);
11252
+ }
11253
+ const lowLevelConnection = await createJsonRpcChannel(props, { onMessage, onConnectionClosed });
11254
+ const deltaState = {};
11255
+ async function invoke(handleOrObject, request, reportRequestId) {
11256
+ const { outKey, ...requestWithoutOutKey } = request;
11257
+ const handle = typeof handleOrObject === "object" ? handleOrObject.getHandle() : handleOrObject;
11258
+ const websocketRequest = {
11259
+ jsonrpc: "2.0",
11260
+ handle,
11261
+ id: requestCounter++,
11262
+ ...getDeltaAndReturnEmptyProps({ method: request.method, outKey: outKey || -1 }),
11263
+ ...requestWithoutOutKey
11264
+ };
11265
+ reportRequestId?.(websocketRequest.id);
11266
+ if (isCancelRequest(handleOrObject, request.method)) {
11267
+ storeCanceledRequestId(request);
11268
+ }
11269
+ logRequest(handleOrObject, websocketRequest, request);
11270
+ listener.onMessageSent(websocketRequest, websocketRequest.handle);
11271
+ let response;
11272
+ try {
11273
+ response = await lowLevelConnection.send(websocketRequest);
11274
+ } catch (error) {
11275
+ logJsonRpcChannelError(handleOrObject, websocketRequest, error);
11276
+ throw error;
11277
+ }
11278
+ if (response.error) {
11279
+ const isCancelled = requestWasCanceled(websocketRequest.id);
11280
+ const { jsonrpc: jsonrpc2, delta: delta2, id: id2, ...errorResponse } = response;
11281
+ logResponse(handleOrObject, websocketRequest, errorResponse);
11282
+ throw new QixError(response.error, isCancelled);
11283
+ }
11284
+ let resultObject = response.result || {};
11285
+ if (response.delta) {
11286
+ resultObject = unwrapDeltas(resultObject, deltaState, handle, request.method);
11287
+ }
11288
+ const result = extractResult({ method: request.method, outKey: outKey || -1 }, resultObject);
11289
+ const { jsonrpc, delta, id, ...sendResponse } = { ...response, result };
11290
+ logResponse(handleOrObject, websocketRequest, sendResponse);
11291
+ return result;
11292
+ }
11293
+ return {
11294
+ invoke,
11295
+ isReattached: lowLevelConnection.isReattached,
11296
+ getSessionState: lowLevelConnection.getSessionState,
11297
+ isClosed: lowLevelConnection.isClosed,
11298
+ closeNormal: lowLevelConnection.closeNormal,
11299
+ closeSuspend: lowLevelConnection.closeSuspend
11300
+ };
11301
+ }
11302
+
11303
+ // src/qix/session/phoenix/retry-logic.ts
11304
+ var retryRegexpFilter2 = /(?!^GetHyperCube|^GetListObject)(^Get|^Create|^OpenDoc$)/i;
11305
+ function shouldRetryRequest(request, error) {
11306
+ if (error instanceof QixError) {
11307
+ if (error.isCancelled) {
11308
+ return { retry: false };
11309
+ }
11310
+ if (!retryRegexpFilter2.test(request.method)) {
11311
+ return { retry: false };
11312
+ }
11313
+ if (error.code === engine_api_default.enums.LocalizedErrorCode.LOCERR_GENERIC_ABORTED) {
11314
+ return {
11315
+ retry: true
11316
+ };
11317
+ }
11318
+ if (error.code === engine_api_default.enums.LocalizedErrorCode.LOCERR_HC_MODAL_OBJECT_ERROR) {
11319
+ return {
11320
+ retry: true,
11321
+ retryPrepAction: async ({ connection, appHandle }) => {
11322
+ return connection.invoke(appHandle, { method: "abortModalSelection", params: [] });
11323
+ }
11324
+ };
11325
+ }
11326
+ return { retry: false };
11327
+ }
11328
+ return { retry: true };
11329
+ }
11330
+
11331
+ // src/qix/session/phoenix/event-emitter.js
11332
+ var util = {};
11333
+ util.isObject = function isObject3(arg) {
11334
+ return typeof arg === "object" && arg !== null;
11335
+ };
11336
+ util.isNumber = function isNumber(arg) {
11337
+ return typeof arg === "number";
11338
+ };
11339
+ util.isUndefined = function isUndefined(arg) {
11340
+ return arg === void 0;
11341
+ };
11342
+ util.isFunction = function isFunction3(arg) {
11343
+ return typeof arg === "function";
11344
+ };
11345
+ function EventEmitter() {
11346
+ EventEmitter.init.call(this);
11347
+ }
11348
+ EventEmitter.EventEmitter = EventEmitter;
11349
+ EventEmitter.prototype._events = void 0;
11350
+ EventEmitter.prototype._maxListeners = void 0;
11351
+ EventEmitter.defaultMaxListeners = 10;
11352
+ EventEmitter.init = function() {
11353
+ this._events = this._events || {};
11354
+ this._maxListeners = this._maxListeners || void 0;
11355
+ };
11356
+ EventEmitter.prototype.setMaxListeners = function(n) {
11357
+ if (!util.isNumber(n) || n < 0 || isNaN(n)) throw TypeError("n must be a positive number");
11358
+ this._maxListeners = n;
11359
+ return this;
11360
+ };
11361
+ EventEmitter.prototype.emit = function(type) {
11362
+ var er, handler, len, args, i, listeners;
11363
+ if (!this._events) this._events = {};
11364
+ if (type === "error" && !this._events.error) {
11365
+ er = arguments[1];
11366
+ if (er instanceof Error) {
11367
+ throw er;
11368
+ } else {
11369
+ throw Error('Uncaught, unspecified "error" event.');
11370
+ }
11371
+ return false;
11372
+ }
11373
+ handler = this._events[type];
11374
+ if (util.isUndefined(handler)) return false;
11375
+ if (util.isFunction(handler)) {
11376
+ switch (arguments.length) {
11377
+ // fast cases
11378
+ case 1:
11379
+ handler.call(this);
11380
+ break;
11381
+ case 2:
11382
+ handler.call(this, arguments[1]);
11383
+ break;
11384
+ case 3:
11385
+ handler.call(this, arguments[1], arguments[2]);
11386
+ break;
11387
+ // slower
11388
+ default:
11389
+ len = arguments.length;
11390
+ args = new Array(len - 1);
11391
+ for (i = 1; i < len; i++) args[i - 1] = arguments[i];
11392
+ handler.apply(this, args);
11393
+ }
11394
+ } else if (util.isObject(handler)) {
11395
+ len = arguments.length;
11396
+ args = new Array(len - 1);
11397
+ for (i = 1; i < len; i++) args[i - 1] = arguments[i];
11398
+ listeners = handler.slice();
11399
+ len = listeners.length;
11400
+ for (i = 0; i < len; i++) listeners[i].apply(this, args);
11401
+ }
11402
+ return true;
11403
+ };
11404
+ EventEmitter.prototype.addListener = function(type, listener) {
11405
+ var m;
11406
+ if (!util.isFunction(listener)) throw TypeError("listener must be a function");
11407
+ if (!this._events) this._events = {};
11408
+ if (this._events.newListener)
11409
+ this.emit("newListener", type, util.isFunction(listener.listener) ? listener.listener : listener);
11410
+ if (!this._events[type])
11411
+ this._events[type] = listener;
11412
+ else if (util.isObject(this._events[type]))
11413
+ this._events[type].push(listener);
11414
+ else this._events[type] = [this._events[type], listener];
11415
+ if (util.isObject(this._events[type]) && !this._events[type].warned) {
11416
+ var m;
11417
+ if (!util.isUndefined(this._maxListeners)) {
11418
+ m = this._maxListeners;
11419
+ } else {
11420
+ m = EventEmitter.defaultMaxListeners;
11421
+ }
11422
+ if (m && m > 0 && this._events[type].length > m) {
11423
+ this._events[type].warned = true;
11424
+ if (util.isFunction(console.error)) {
11425
+ console.error(
11426
+ "(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",
11427
+ this._events[type].length
11428
+ );
11429
+ }
11430
+ if (util.isFunction(console.trace)) console.trace();
11431
+ }
11432
+ }
11433
+ return this;
11434
+ };
11435
+ EventEmitter.prototype.on = EventEmitter.prototype.addListener;
11436
+ EventEmitter.prototype.once = function(type, listener) {
11437
+ if (!util.isFunction(listener)) throw TypeError("listener must be a function");
11438
+ var fired = false;
11439
+ function g() {
11440
+ this.removeListener(type, g);
11441
+ if (!fired) {
11442
+ fired = true;
11443
+ listener.apply(this, arguments);
11444
+ }
11445
+ }
11446
+ g.listener = listener;
11447
+ this.on(type, g);
11448
+ return this;
11449
+ };
11450
+ EventEmitter.prototype.removeListener = function(type, listener) {
11451
+ var list, position, length, i;
11452
+ if (!util.isFunction(listener)) throw TypeError("listener must be a function");
11453
+ if (!this._events || !this._events[type]) return this;
11454
+ list = this._events[type];
11455
+ length = list.length;
11456
+ position = -1;
11457
+ if (list === listener || util.isFunction(list.listener) && list.listener === listener) {
11458
+ delete this._events[type];
11459
+ if (this._events.removeListener) this.emit("removeListener", type, listener);
11460
+ } else if (util.isObject(list)) {
11461
+ for (i = length; i-- > 0; ) {
11462
+ if (list[i] === listener || list[i].listener && list[i].listener === listener) {
11463
+ position = i;
11464
+ break;
11465
+ }
11466
+ }
11467
+ if (position < 0) return this;
11468
+ if (list.length === 1) {
11469
+ list.length = 0;
11470
+ delete this._events[type];
11471
+ } else {
11472
+ list.splice(position, 1);
11473
+ }
11474
+ if (this._events.removeListener) this.emit("removeListener", type, listener);
11475
+ }
11476
+ return this;
11477
+ };
11478
+ EventEmitter.prototype.removeAllListeners = function(type) {
11479
+ var key, listeners;
11480
+ if (!this._events) return this;
11481
+ if (!this._events.removeListener) {
11482
+ if (arguments.length === 0) this._events = {};
11483
+ else if (this._events[type]) delete this._events[type];
11484
+ return this;
11485
+ }
11486
+ if (arguments.length === 0) {
11487
+ for (key in this._events) {
11488
+ if (key === "removeListener") continue;
11489
+ this.removeAllListeners(key);
11490
+ }
11491
+ this.removeAllListeners("removeListener");
11492
+ this._events = {};
11493
+ return this;
11494
+ }
11495
+ listeners = this._events[type];
11496
+ if (util.isFunction(listeners)) {
11497
+ this.removeListener(type, listeners);
11498
+ } else if (Array.isArray(listeners)) {
11499
+ while (listeners.length) this.removeListener(type, listeners[listeners.length - 1]);
11500
+ }
11501
+ delete this._events[type];
11502
+ return this;
11503
+ };
11504
+ EventEmitter.prototype.listeners = function(type) {
11505
+ var ret;
11506
+ if (!this._events || !this._events[type]) ret = [];
11507
+ else if (util.isFunction(this._events[type])) ret = [this._events[type]];
11508
+ else ret = this._events[type].slice();
11509
+ return ret;
11510
+ };
11511
+ EventEmitter.listenerCount = function(emitter, type) {
11512
+ var ret;
11513
+ if (!emitter._events || !emitter._events[type]) ret = 0;
11514
+ else if (util.isFunction(emitter._events[type])) ret = 1;
11515
+ else ret = emitter._events[type].length;
11516
+ return ret;
11517
+ };
11518
+
11519
+ // src/qix/session/phoenix/rpc-object-session.ts
11520
+ var counter = 0;
11521
+ var SuspendResumeImpl = class {
11522
+ Promise;
11523
+ #connection;
11524
+ constructor(connection) {
11525
+ this.Promise = Promise;
11526
+ this.#connection = connection;
11527
+ }
11528
+ resume() {
11529
+ return this.#connection.resume();
11530
+ }
11531
+ suspend() {
11532
+ return this.#connection.suspend();
11533
+ }
11534
+ get isSuspended() {
11535
+ return this.#connection.isSuspended;
11536
+ }
11537
+ };
11538
+ var ConfigImpl = class {
11539
+ Promise;
11540
+ constructor() {
11541
+ this.Promise = Promise;
11542
+ }
11543
+ };
11544
+ var RpcImpl = class extends EventEmitter {
11545
+ Promise;
11546
+ #connection;
11547
+ constructor(connection) {
11548
+ super();
11549
+ this.#connection = connection;
11550
+ this.Promise = Promise;
11551
+ }
11552
+ /**
11553
+ * @deprecated
11554
+ * For backwards compatibility, this function is deprecated.
11555
+ */
11556
+ send(requestWithHandle) {
11557
+ const object = { getHandle: () => requestWithHandle.handle };
11558
+ const { handle, ...request } = requestWithHandle;
11559
+ return this.#connection.invoke(object, request, () => {
11560
+ });
11561
+ }
11562
+ // Backwards compatibility placeholder functions that does nothing
11563
+ close() {
11564
+ }
11565
+ };
11566
+ var RpcObjectSessionImpl = class extends EventEmitter {
11567
+ rpc;
11568
+ suspendResume;
11569
+ config;
11570
+ id = counter++;
11571
+ #connection;
11572
+ /**
11573
+ *
11574
+ * @internal
11575
+ */
11576
+ constructor(connection) {
11577
+ super();
11578
+ this.#connection = connection;
11579
+ this.rpc = new RpcImpl(connection);
11580
+ this.suspendResume = new SuspendResumeImpl(connection);
11581
+ this.config = new ConfigImpl();
11582
+ }
11583
+ /**
11584
+ * @deprecated
11585
+ * For backwards compatibility, this function is deprecated.
11586
+ */
11587
+ send(requestWithHandle) {
11588
+ return this.rpc.send(requestWithHandle);
11589
+ }
11590
+ getObjectApi(ref) {
11591
+ return this.#connection.getObjectApi(ref);
11592
+ }
11593
+ /**
11594
+ * Returns the app object for the session.
11595
+ */
11596
+ get global() {
11597
+ return this.#connection.global;
11598
+ }
11599
+ /**
11600
+ * Returns the app object for the session.
11601
+ */
11602
+ get app() {
11603
+ return this.#connection.doc;
11604
+ }
11605
+ get sessionState() {
11606
+ return this.#connection.sessionState;
11607
+ }
11608
+ get Promise() {
11609
+ return Promise;
11610
+ }
11611
+ resume() {
11612
+ return this.#connection.resume();
11613
+ }
11614
+ suspend() {
11615
+ return this.#connection.suspend();
11616
+ }
11617
+ get createdAt() {
11618
+ return this.#connection.createdAt;
11619
+ }
11620
+ get lastTrafficAt() {
11621
+ return this.#connection.lastTrafficAt;
11622
+ }
11623
+ get globalPromise() {
11624
+ return Promise.resolve(this.#connection.global);
11625
+ }
11626
+ get openDocPromise() {
11627
+ return Promise.resolve(this.#connection.doc);
11628
+ }
11629
+ // TODO IMPLEMENT FOR BACKWARDS COMPATIBLIITY
11630
+ open() {
11631
+ return this.globalPromise;
11632
+ }
11633
+ close() {
11634
+ return Promise.resolve();
11635
+ }
11636
+ };
11637
+
11638
+ // src/qix/session/phoenix/phoenix-connection.ts
11639
+ async function createPhoenixConnection(openProps, objectFactory2, { onWebSocketEvent, getInitialAppActions }) {
11640
+ const phoenixConnection = new PhoenixConnectionImpl(openProps, objectFactory2, {
11641
+ onWebSocketEvent,
11642
+ getInitialAppActions
11643
+ });
11644
+ await phoenixConnection.waitForConnection();
11645
+ return phoenixConnection;
11646
+ }
11647
+ var PhoenixConnectionImpl = class {
11648
+ #interestMonitor = createInterestMonitor();
11649
+ #sessionIsNotInUseAnymore = false;
11650
+ #openProps;
11651
+ #objectFactory;
11652
+ #rpcObjectSession;
11653
+ #owner;
11654
+ #globalRpcObject;
11655
+ #docRpcObject;
11656
+ #state = "opening";
11657
+ #currentReincarnationPromise = Promise.resolve(void 0);
11658
+ #currentReincarnation;
11659
+ #lastTrafficAt = Date.now();
11660
+ #createdAt = Date.now();
11661
+ /** @internal */
11662
+ constructor(openProps, objectFactory2, owner) {
11663
+ this.#openProps = openProps;
11664
+ this.#objectFactory = objectFactory2;
11665
+ this.#owner = owner;
11666
+ this.#rpcObjectSession = new RpcObjectSessionImpl(this);
11667
+ logEvent("Creating phoenix session", openProps);
11668
+ this.#globalRpcObject = objectFactory2.createObject(
11669
+ { qHandle: -1, qType: "Global", qGenericId: "Global" },
11670
+ this,
11671
+ void 0
11672
+ );
11673
+ this.#docRpcObject = objectFactory2.createObject(
11674
+ { qHandle: 1, qGenericId: openProps.appId, qType: "Doc" },
11675
+ this,
11676
+ void 0
11677
+ );
11678
+ this.#interestMonitor.onUserActivityDetected(() => {
11679
+ void this.#getCurrentOrAcquireNewReincarnation();
11680
+ });
11681
+ }
11682
+ get classicEnigmaSessionApi() {
11683
+ return this.#rpcObjectSession;
11684
+ }
11685
+ get createdAt() {
11686
+ return this.#createdAt;
11687
+ }
11688
+ get lastTrafficAt() {
11689
+ return this.#lastTrafficAt;
11690
+ }
11691
+ async waitForConnection() {
11692
+ await this.#getCurrentOrAcquireNewReincarnation();
11693
+ }
11694
+ /**
11695
+ * Invokes a method on the engine and returns the result.
11696
+ * If the result is an object reference, it will be resolved to a PhoenixRpcObject.
11697
+ * If the request fails, it will be retried if the error is retryable.
11698
+ * If the websocket is down or goes down during the request a new connection will be opened and reestablished and the request retried.
11699
+ *
11700
+ *
11701
+ * @param object An rpc object (or at least something that can provide a handle)
11702
+ * @param request a high level qix request (method, params and outKey)
11703
+ * @param reportRequestId
11704
+ * @returns Either the Json response or a PhoenixRpcObject
11705
+ * @throws QixError if the request fails and is not retryable
11706
+ */
11707
+ async invoke(object, request, reportRequestId) {
11708
+ try {
11709
+ return await this.#sendAndResolveRpcObjects(object, request, reportRequestId);
11710
+ } catch (err) {
11711
+ const { retry, retryPrepAction } = shouldRetryRequest(request, err);
11712
+ if (retry) {
11713
+ if (retryPrepAction) {
11714
+ await retryPrepAction({
11715
+ connection: this.#currentReincarnation.connection,
11716
+ appHandle: this.#currentReincarnation.state.getDoc().getHandle()
11717
+ });
11718
+ }
11719
+ return this.#sendAndResolveRpcObjects(object, request, reportRequestId);
11720
+ }
11721
+ throw err;
11722
+ }
11723
+ }
11724
+ /**
11725
+ * Returns an RPC object for the given reference. If the object already exists, it will be returned.
11726
+ */
11727
+ getObjectApi(ref) {
11728
+ if (!this.#currentReincarnation) {
11729
+ throw new Error("Not yet connected!");
11730
+ }
11731
+ const existingObject = this.#currentReincarnation.state.getObject(ref);
11732
+ if (existingObject) {
11733
+ return existingObject;
11734
+ }
11735
+ const newObject = this.#objectFactory.createObject(ref, this, void 0);
11736
+ this.#currentReincarnation.state.setObject(newObject.getHandle(), newObject);
11737
+ return newObject;
11738
+ }
11739
+ /**
11740
+ * The main Doc/App rpc object
11741
+ */
11742
+ get doc() {
11743
+ return this.#docRpcObject;
11744
+ }
11745
+ /**
11746
+ * The Global rpc object
11747
+ */
11748
+ get global() {
11749
+ return this.#globalRpcObject;
11750
+ }
11751
+ /**
11752
+ * A string representing if the session was newly established or reonnected
11753
+ */
11754
+ get sessionState() {
11755
+ return this.#currentReincarnation?.connection.getSessionState() ?? "";
11756
+ }
11757
+ /**
11758
+ * Signals from outside that the session is not in use (maybe will be in a few seconds!)
11759
+ */
11760
+ stopActivityMonitoring() {
11761
+ this.#interestMonitor.stopListeningForActivity();
11762
+ }
11763
+ close() {
11764
+ this.#interestMonitor.stopListeningForActivity();
11765
+ this.#sessionIsNotInUseAnymore = true;
11766
+ if (this.#currentReincarnation && !this.#currentReincarnation.connection.isClosed()) {
11767
+ this.#currentReincarnation.connection.closeNormal();
11768
+ }
11769
+ }
11770
+ async resume() {
11771
+ this.#interestMonitor.signalInterest();
11772
+ await this.#getCurrentOrAcquireNewReincarnation();
11773
+ }
11774
+ async suspend() {
11775
+ if (this.#currentReincarnation && !this.#currentReincarnation.connection.isClosed()) {
11776
+ this.#currentReincarnation.connection.closeSuspend();
11777
+ }
11778
+ }
11779
+ get isSuspended() {
11780
+ return this.#currentReincarnation && this.#currentReincarnation.connection.isClosed() || false;
11781
+ }
11782
+ initialAppActionsUpdated() {
11783
+ void (async () => {
11784
+ await this.#runPendingInitialAppActions(await this.#getCurrentOrAcquireNewReincarnation());
11785
+ })();
11786
+ }
11787
+ /**
11788
+ * Makes a single attempt at calling the backend
11789
+ * * Acquires a working connection
11790
+ * * Invokes the backend using thta connection
11791
+ * * If the result is an object reference, it will be resolved to a PhoenixRpcObject
11792
+ */
11793
+ async #sendAndResolveRpcObjects(object, request, reportRequestId) {
11794
+ const { connection, state } = await this.#getCurrentOrAcquireNewReincarnation();
11795
+ const result = await connection.invoke(object, request, reportRequestId);
11796
+ if (isQixObjectRef(result)) {
11797
+ const objectRef = result;
11798
+ let objectResult = state.getObject(objectRef.qHandle);
11799
+ if (!objectResult) {
11800
+ objectResult = this.#objectFactory.createObject(objectRef, this, request);
11801
+ state.setObject(objectRef.qHandle, objectResult);
11802
+ }
11803
+ return objectResult;
11804
+ }
11805
+ return result;
11806
+ }
11807
+ /**
11808
+ * This function will acquire a new reincarnation (connection + session state) if the current one is closed
11809
+ * It will also update the traffic timestamp
11810
+ */
11811
+ async #getCurrentOrAcquireNewReincarnation() {
11812
+ this.#lastTrafficAt = Date.now();
11813
+ const result = this.#currentReincarnationPromise.then(async (lastReincarnation) => {
11814
+ while (lastReincarnation?.next !== void 0) {
11815
+ lastReincarnation = await lastReincarnation.next;
11816
+ }
11817
+ if (lastReincarnation && !lastReincarnation.connection.isClosed()) {
11818
+ return lastReincarnation;
11819
+ }
11820
+ const isResume = !!lastReincarnation;
11821
+ if (isResume) {
11822
+ this.#state = "resuming";
11823
+ this.#onResuming();
11824
+ }
11825
+ const newReincarnation = await this.#openNewQixConnectionAndPrepareSessionStateWithRetry(
11826
+ lastReincarnation,
11827
+ isResume
11828
+ );
11829
+ this.#state = "open";
11830
+ if (isResume) {
11831
+ this.#onResume();
11832
+ } else {
11833
+ this.#onOpen();
11834
+ }
11835
+ this.#currentReincarnation = newReincarnation;
11836
+ await this.#runPendingInitialAppActions(newReincarnation);
11837
+ return newReincarnation;
11838
+ });
11839
+ this.#currentReincarnationPromise = result;
11840
+ return result;
11841
+ }
11842
+ /**
11843
+ * Really tries and retries to successfully open a new Qix connection and prepares the session state for the new connection.
11844
+ * If a few attempts of reopening fails, it will wait for activity on the session before trying again.
11845
+ * This means that this function will not return until a new reincarnation is acquired.
11846
+ *
11847
+ */
11848
+ async #openNewQixConnectionAndPrepareSessionStateWithRetry(lastReincarnation, isResume) {
11849
+ return new Promise((resolve, reject) => {
11850
+ let retryCount = 0;
11851
+ const INITIAL_RETRY_TIME = 2e3;
11852
+ let retryWaitTime = INITIAL_RETRY_TIME;
11853
+ const oneTry = async () => {
11854
+ logEvent("Trying to acquire new reincarnation", this.#openProps);
11855
+ try {
11856
+ resolve(await this.#openNewQixConnectionAndPrepareSessionState(lastReincarnation?.state));
11857
+ } catch (err) {
11858
+ if (isResume) {
11859
+ this.#interestMonitor.resetAnyInterestSignalledBeforeNow();
11860
+ if (retryCount < 5) {
11861
+ retryCount++;
11862
+ retryWaitTime *= 1.5;
11863
+ logEvent("Failed to acquire new reincarnation, retrying in ", retryWaitTime, err);
11864
+ setTimeout(() => {
11865
+ void oneTry();
11866
+ }, retryWaitTime);
11867
+ } else {
11868
+ await this.#interestMonitor.waitUntilSomeoneIsInterestedInThis();
11869
+ logEvent("Activity detected, retrying to acquire new reincarnation", this.#openProps);
11870
+ retryCount = 0;
11871
+ retryWaitTime = INITIAL_RETRY_TIME;
11872
+ setTimeout(() => {
11873
+ void oneTry();
11874
+ }, retryWaitTime);
11875
+ }
11876
+ } else {
11877
+ logEvent("Failed to open app", err);
11878
+ reject(err);
11879
+ }
11880
+ }
11881
+ };
11882
+ void oneTry();
11883
+ });
11884
+ }
11885
+ async #openNewQixConnectionAndPrepareSessionState(lastState) {
11886
+ let stateForNewConnection;
11887
+ stateForNewConnection = void 0;
11888
+ logEvent("-------- Opening new Qix Connection ---------");
11889
+ const newConnection = await createQixConnection(this.#openProps, {
11890
+ onMessageSent: (message, handle) => {
11891
+ this.#onMessageSent(message, stateForNewConnection?.getObject(handle));
11892
+ },
11893
+ onMessageReceived: (message, handle) => {
11894
+ const object = handle ? stateForNewConnection?.getObject(handle) : void 0;
11895
+ this.#onMessageReceived(message, object);
11896
+ },
11897
+ onNotification: (message) => {
11898
+ this.#onNotification(message);
11899
+ },
11900
+ onObjectChanged: (handle) => {
11901
+ stateForNewConnection?.getObject(handle)?.emit("changed");
11902
+ },
11903
+ onObjectClosed: (handle) => {
11904
+ stateForNewConnection?.getObject(handle)?.emit("closed");
11905
+ stateForNewConnection?.removeObject(handle);
11906
+ },
11907
+ onConnectionClosed: (error) => {
11908
+ this.#onConnectionClosed(error);
11909
+ }
11910
+ });
11911
+ const appRef = await newConnection.invoke(-1, {
11912
+ method: "OpenDoc",
11913
+ params: [this.#openProps.appId, "", "", "", !!this.#openProps.withoutData],
11914
+ outKey: -1
11915
+ });
11916
+ this.#docRpcObject.setHandle(appRef.qHandle);
11917
+ const newState = createPhoenixSessionState({
11918
+ global: this.#globalRpcObject,
11919
+ doc: this.#docRpcObject,
11920
+ executedAppActions: lastState?.getExecutedAppActions() ?? []
11921
+ });
11922
+ if (lastState) {
11923
+ await Promise.all(
11924
+ Object.values(lastState.getObjects()).map(async (object) => {
11925
+ await object.respawn(newConnection);
11926
+ newState.setObject(object.getHandle(), object);
11927
+ })
11928
+ );
11929
+ logEvent("-------- Respawned objects ---------");
11930
+ logEvent(
11931
+ Object.entries(lastState.getObjects()).map(([key, value]) => `${value.id}: ${key} => ${value.getHandle()}`)
11932
+ );
11933
+ }
11934
+ stateForNewConnection = newState;
11935
+ if (lastState) {
11936
+ Object.values(lastState.getObjects()).forEach((object) => {
11937
+ object.emit("changed");
11938
+ });
11939
+ }
11940
+ logEvent("-------- Opening done ---------");
11941
+ return { connection: newConnection, state: newState };
11942
+ }
11943
+ /* -------------------------------------------------------------------------- */
11944
+ /* Event handlers for various Qix Connection events */
11945
+ /* -------------------------------------------------------------------------- */
11946
+ #onOpen() {
11947
+ this.#owner.onWebSocketEvent({ eventType: "opened", ...this.#openProps });
11948
+ this.#rpcObjectSession.emit("opened");
11949
+ }
11950
+ #onResuming() {
11951
+ this.#owner.onWebSocketEvent({ eventType: "resuming", ...this.#openProps });
11952
+ this.#rpcObjectSession.emit("resuming");
11953
+ }
11954
+ #onResume() {
11955
+ this.#createdAt = Date.now();
11956
+ this.#owner.onWebSocketEvent({ eventType: "resumed", ...this.#openProps });
11957
+ this.#rpcObjectSession.emit("resumed");
11958
+ }
11959
+ #onMessageSent(message, object) {
11960
+ this.#rpcObjectSession.rpc.emit("traffic", "sent", message, object?.handle);
11961
+ this.#rpcObjectSession.emit("traffic:*", "sent", message);
11962
+ this.#rpcObjectSession.emit(`traffic:sent`, message);
11963
+ object?.emit("traffic:*", "sent", message);
11964
+ object?.emit("traffic:sent", message);
11965
+ }
11966
+ #onMessageReceived(message, object) {
11967
+ this.#rpcObjectSession.rpc.emit("traffic", "received", message, object?.handle);
11968
+ this.#rpcObjectSession.emit("traffic:*", message);
11969
+ this.#rpcObjectSession.emit(`traffic:received`, message);
11970
+ object?.emit("traffic:*", "received", message);
11971
+ object?.emit("traffic:received", message);
11972
+ }
11973
+ #onNotification(message) {
11974
+ this.#rpcObjectSession.emit("notification:*", message.method, message.params);
11975
+ this.#rpcObjectSession.emit(`notification:${message.method}`, message.params);
11976
+ this.#rpcObjectSession.rpc.emit("notification", message);
11977
+ }
11978
+ #onConnectionClosed(closeEvent) {
11979
+ const { code, reason, initiator } = closeEvent || { code: 0, reason: "unknown", initiator: "network" };
11980
+ if (this.#sessionIsNotInUseAnymore) {
11981
+ logEvent("Connection closed, session is not in use anymore", this.#openProps);
11982
+ this.#owner.onWebSocketEvent({ eventType: "closed", code, reason, ...this.#openProps });
11983
+ this.#rpcObjectSession.emit("closed", { code, reason, initiator });
11984
+ } else if (this.#state === "open") {
11985
+ logEvent("Connection closed, session is still in use", this.#openProps, code, reason);
11986
+ this.#owner.onWebSocketEvent({ eventType: "suspended", code, reason, initiator, ...this.#openProps });
11987
+ this.#rpcObjectSession.emit("suspended", { code, reason, initiator });
11988
+ if (shouldResumeImmediately(code)) {
11989
+ void this.#getCurrentOrAcquireNewReincarnation();
11990
+ } else {
11991
+ this.#interestMonitor.startListeningForActivity();
11992
+ }
11993
+ }
11994
+ }
11995
+ async #runPendingInitialAppActions(newReincarnation) {
11996
+ for (const action of this.#owner.getInitialAppActions()) {
11997
+ if (!newReincarnation.state.isAppActionExecuted(action)) {
11998
+ await action(newReincarnation.state.getDoc());
11999
+ newReincarnation.state.addExecutedInitialAppAction(action);
12000
+ }
12001
+ }
12002
+ }
12003
+ };
12004
+ function shouldResumeImmediately(code) {
12005
+ const IMMEDIATE_RESUME_CDDES = {
12006
+ /** The engine hosting the session is shutting down,
12007
+ * auto-resume to get another session from another engine. */
12008
+ ENGINE_TERMINATING: 4003,
12009
+ /** App deleted from an engine, auto-resume to open it on another engine. */
12010
+ APP_DELETED: 4004,
12011
+ /** App-mode changed to Direct Query mode, let's auto-resume */
12012
+ APP_MODE_CHANGED: 4007
12013
+ };
12014
+ switch (code) {
12015
+ case IMMEDIATE_RESUME_CDDES.ENGINE_TERMINATING:
12016
+ case IMMEDIATE_RESUME_CDDES.APP_DELETED:
12017
+ case IMMEDIATE_RESUME_CDDES.APP_MODE_CHANGED:
12018
+ return true;
12019
+ default:
12020
+ return false;
12021
+ }
12022
+ }
12023
+
12024
+ // src/qix/session/phoenix/remote-object.ts
12025
+ var RemoteObjectImpl = class {
12026
+ #connection;
12027
+ #handle;
12028
+ #id;
12029
+ #type;
12030
+ #genericType;
12031
+ #respawnInfo;
12032
+ constructor({ connection, handle, id, type, genericType, respawnInfo }) {
12033
+ this.#connection = connection;
12034
+ this.#handle = handle;
12035
+ this.#id = id;
12036
+ this.#type = type;
12037
+ this.#genericType = genericType;
12038
+ this.#respawnInfo = respawnInfo;
12039
+ }
12040
+ invoke(req) {
12041
+ let lastRequestId = 0;
12042
+ const promise = this.#connection.invoke(this, req, (requestId) => {
12043
+ lastRequestId = requestId;
12044
+ });
12045
+ addToPromiseChain(promise, "requestId", () => lastRequestId);
12046
+ return promise;
12047
+ }
12048
+ getHandle() {
12049
+ return this.#handle;
12050
+ }
12051
+ get handle() {
12052
+ return this.#handle;
12053
+ }
12054
+ set handle(newHandle) {
12055
+ this.#handle = newHandle;
12056
+ }
12057
+ get id() {
12058
+ return this.#id;
12059
+ }
12060
+ get type() {
12061
+ return this.#type;
12062
+ }
12063
+ get genericType() {
12064
+ return this.#genericType;
12065
+ }
12066
+ get session() {
12067
+ return this.#connection.classicEnigmaSessionApi;
12068
+ }
12069
+ get respawnInfo() {
12070
+ return this.#respawnInfo;
12071
+ }
12072
+ };
12073
+ function addToPromiseChain(promise, name, getValue) {
12074
+ Object.defineProperty(promise, name, {
12075
+ get() {
12076
+ return getValue();
12077
+ },
12078
+ enumerable: true,
12079
+ configurable: true
12080
+ });
12081
+ const { then } = promise;
12082
+ promise.then = function patchedThen(...params) {
12083
+ const chain = then.apply(this, params);
12084
+ addToPromiseChain(chain, name, getValue);
12085
+ return chain;
12086
+ };
12087
+ }
12088
+
12089
+ // src/qix/session/phoenix/rpc-object.ts
12090
+ var PhoenixRpcObjectImpl = class extends EventEmitter {
12091
+ /** @internal */
12092
+ #remoteObject;
12093
+ /** @deprecated */
12094
+ Promise;
12095
+ /**
12096
+ * @internal
12097
+ */
12098
+ constructor(rpcObjectCore) {
12099
+ super();
12100
+ this.#remoteObject = rpcObjectCore;
12101
+ this.Promise = Promise;
12102
+ }
12103
+ get __remote__() {
12104
+ return this.#remoteObject;
12105
+ }
12106
+ get handle() {
12107
+ return this.#remoteObject.handle;
12108
+ }
12109
+ set handle(handle) {
12110
+ this.#remoteObject.handle = handle;
12111
+ }
12112
+ get app() {
12113
+ return this.#remoteObject.session.app;
12114
+ }
12115
+ get global() {
12116
+ return this.#remoteObject.session.global;
12117
+ }
12118
+ set global(newGlobal) {
12119
+ if (newGlobal !== this.#remoteObject.session.global) {
12120
+ console.warn("Changing the global object on a qix object is not allowed");
12121
+ }
12122
+ }
12123
+ get id() {
12124
+ return this.#remoteObject.id;
12125
+ }
12126
+ get type() {
12127
+ return this.#remoteObject.type;
12128
+ }
12129
+ get genericType() {
12130
+ return this.#remoteObject.genericType;
12131
+ }
12132
+ get session() {
12133
+ return this.#remoteObject.session;
12134
+ }
12135
+ getHandle() {
12136
+ return this.#remoteObject.handle;
12137
+ }
12138
+ setHandle(handle) {
12139
+ const oldHandle = this.#remoteObject.handle;
12140
+ this.#remoteObject.handle = handle;
12141
+ if (oldHandle !== handle) {
12142
+ logEvent("Change handle for ", this.#remoteObject.id, "from", oldHandle, "to", handle);
12143
+ }
12144
+ }
12145
+ /** @deprecated */
12146
+ get enigmaModel() {
12147
+ return this;
12148
+ }
12149
+ /**
12150
+ * @internal
12151
+ */
12152
+ // This is overriden in mixins but the signature needs to have a QixConnection as parameter
12153
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
12154
+ async respawn(newConnection) {
12155
+ if (this.#remoteObject.type !== "Doc" && this.#remoteObject.type !== "Global") {
12156
+ console.error("No respawn mixin found for object ", this.#remoteObject.type, this.#remoteObject.genericType);
12157
+ }
12158
+ }
12159
+ };
12160
+
12161
+ // src/qix/session/phoenix/rpc-object-respawn-mixins.ts
12162
+ var refetch1 = {
12163
+ types: ["GenericObject"],
12164
+ override: {
12165
+ async respawn(original, connection) {
12166
+ if (this.__remote__.respawnInfo.isSessionObject) {
12167
+ let objectFoundInEngine = false;
12168
+ if (connection.isReattached()) {
12169
+ try {
12170
+ this.setHandle(
12171
+ await connection.invoke(this.app.handle, { method: "GetObject", params: [this.id], outKey: -1 }).then((res) => res.qHandle)
12172
+ );
12173
+ objectFoundInEngine = true;
12174
+ } catch (err) {
12175
+ console.warn("Session object not found in reattached session", err);
12176
+ objectFoundInEngine = false;
12177
+ }
12178
+ }
12179
+ if (!objectFoundInEngine) {
12180
+ const props = JSON.parse(JSON.stringify(this.__remote__.respawnInfo.properties));
12181
+ props.qInfo = props.qInfo || {};
12182
+ props.qInfo.qId = this.id;
12183
+ logEvent("Respawning session object using", this.__remote__.respawnInfo.properties);
12184
+ this.setHandle(
12185
+ await connection.invoke(this.app.handle, {
12186
+ method: "CreateSessionObject",
12187
+ params: [props],
12188
+ outKey: -1
12189
+ }).then((res) => res.qHandle)
12190
+ );
12191
+ }
12192
+ } else {
12193
+ this.setHandle(
12194
+ await connection.invoke(this.app.handle, { method: "GetObject", params: [this.id], outKey: -1 }).then((res) => res.qHandle)
12195
+ );
12196
+ }
12197
+ if (this.__remote__.respawnInfo.activeModalSelectionPaths && !connection.isReattached()) {
12198
+ try {
12199
+ logEvent(
12200
+ "########### BeginSelections ###################################",
12201
+ this.__remote__.respawnInfo.activeModalSelectionPaths
12202
+ );
12203
+ await connection.invoke(this.handle, {
12204
+ method: "BeginSelections",
12205
+ params: [this.__remote__.respawnInfo.activeModalSelectionPaths],
12206
+ outKey: -1
12207
+ });
12208
+ } catch (err) {
12209
+ console.warn("Could not reapply modal selection state", err);
12210
+ }
12211
+ }
12212
+ },
12213
+ async beginSelections(original, paths) {
12214
+ logEvent("Storing modal selections", this.handle, this.__remote__.respawnInfo.activeModalSelectionPaths);
12215
+ this.__remote__.respawnInfo.activeModalSelectionPaths = paths;
12216
+ return original(paths);
12217
+ },
12218
+ async endSelections(original, accept) {
12219
+ this.__remote__.respawnInfo.activeModalSelectionPaths = void 0;
12220
+ logEvent("Removing modal selections", this.handle, this.__remote__.respawnInfo.activeModalSelectionPaths);
12221
+ return original(accept);
12222
+ },
12223
+ /**
12224
+ * TODO SUPPORT THESE ASWELL
12225
+ applyPatches: (patches: NxPatch[], softPatch?: boolean) => Promise<void>;
12226
+ clearSoftPatches: () => Promise<void>;
12227
+ copyFrom: (fromId: string) => Promise<void>;
12228
+ destroyAllChildren: (propForThis?: CustomProperties) => Promise<void>;
12229
+ destroyChild: (id: string, propForThis?: CustomProperties) => Promise<boolean>;
12230
+ lock: (path: string, colIndices?: number[]) => Promise<void>;
12231
+ resetMadeSelections: () => Promise<void>;
12232
+ setChildArrayOrder: (ids: string[]) => Promise<void>;
12233
+ setFullPropertyTree: (propEntry: GenericObjectEntry) => Promise<void>;
12234
+ setProperties: (prop: CustomProperties) => Promise<void>;
12235
+ unlock: (path: string, colIndices?: number[]) => Promise<void>;
12236
+ */
12237
+ async setProperties(original, props) {
12238
+ this.__remote__.respawnInfo.properties = props;
12239
+ return original(props);
12240
+ }
12241
+ }
12242
+ };
12243
+ var variableRespawnMixin = {
12244
+ types: ["GenericVariable"],
12245
+ override: {
12246
+ async respawn(original, connection) {
12247
+ logEvent("Respawning variable ", this.id);
12248
+ if (this.__remote__.respawnInfo.isSessionObject) {
12249
+ let objectFoundInEngine = false;
12250
+ if (connection.isReattached()) {
12251
+ try {
12252
+ this.setHandle(
12253
+ await connection.invoke(this.app.handle, { method: "GetObject", params: [this.id], outKey: -1 }).then((res) => res.qHandle)
12254
+ );
12255
+ objectFoundInEngine = true;
12256
+ } catch (err) {
12257
+ console.warn("Session variable not found in reattached session", err);
12258
+ objectFoundInEngine = false;
12259
+ }
12260
+ }
12261
+ if (!objectFoundInEngine) {
12262
+ this.setHandle(
12263
+ await connection.invoke(this.app.handle, {
12264
+ method: "CreateSessionVariable",
12265
+ params: [this.__remote__.respawnInfo.properties],
12266
+ outKey: -1
12267
+ }).then((res) => res.qHandle)
12268
+ );
12269
+ }
12270
+ } else {
12271
+ this.setHandle(
12272
+ await connection.invoke(this.app.handle, { method: "GetObject", params: [this.id], outKey: -1 }).then((res) => res.qHandle)
12273
+ );
12274
+ }
12275
+ },
12276
+ // TODO suppor these functions as well
12277
+ //applyPatches: (patches: NxPatch[]) => Promise<void>;
12278
+ //setDualValue: (text: string, num: number) => Promise<void>;
12279
+ //setNumValue: (val: number) => Promise<void>;
12280
+ //setStringValue: (val: string) => Promise<void>;
12281
+ async setProperties(original, props) {
12282
+ this.__remote__.respawnInfo.properties = props;
12283
+ return original(props);
12284
+ }
12285
+ }
12286
+ };
12287
+ var variarbleMeasureAndBookmarkRespawnMixin = {
12288
+ types: ["GenericDimension", "GenericMeasure", "GenericBookmark"],
12289
+ override: {
12290
+ async respawn(original, connection) {
12291
+ logEvent("Respawning field dimension, measure or bookmark", this.id);
12292
+ this.setHandle(
12293
+ await connection.invoke(this.app.handle, { method: "GetObject", params: [this.id], outKey: -1 }).then((res) => res.qHandle)
12294
+ );
12295
+ }
12296
+ }
12297
+ };
12298
+ var fieldRespawningMixin = {
12299
+ types: ["Field"],
12300
+ override: {
12301
+ async respawn(original, connection) {
12302
+ logEvent("Respawning field object ", this.id);
12303
+ if (this.__remote__.respawnInfo.creatingRequest && this.__remote__.respawnInfo.creatingRequest.method.startsWith("Get")) {
12304
+ this.setHandle(
12305
+ await connection.invoke(1, this.__remote__.respawnInfo.creatingRequest).then((res) => res.qHandle)
12306
+ );
12307
+ logEvent("Respawned field object using creating request ", this.id, this.handle);
12308
+ } else {
12309
+ this.setHandle(0);
12310
+ logEvent("No idea how to respawn", this.id);
12311
+ }
12312
+ }
12313
+ }
12314
+ };
12315
+ var rememberCreatePropsMixin = {
12316
+ types: ["Doc"],
12317
+ override: {
12318
+ async createSessionObject(original, properties) {
12319
+ const object = await original(properties);
12320
+ const phoenixObject = object;
12321
+ phoenixObject.__remote__.respawnInfo.isSessionObject = true;
12322
+ phoenixObject.__remote__.respawnInfo.properties = properties;
12323
+ return phoenixObject;
12324
+ },
12325
+ async createSessionVariable(original, properties) {
12326
+ const object = await original(properties);
12327
+ const phoenixObject = object;
12328
+ phoenixObject.__remote__.respawnInfo.isSessionObject = true;
12329
+ phoenixObject.__remote__.respawnInfo.properties = properties;
12330
+ return object;
12331
+ }
12332
+ }
12333
+ };
12334
+ var rpc_object_respawn_mixins_default = [
12335
+ refetch1,
12336
+ variableRespawnMixin,
12337
+ variarbleMeasureAndBookmarkRespawnMixin,
12338
+ fieldRespawningMixin,
12339
+ rememberCreatePropsMixin
12340
+ ];
12341
+
12342
+ // src/qix/session/phoenix/rpc-object-mixins.ts
12343
+ function toMixinMap(mixinsArray) {
12344
+ const mixins6 = {};
12345
+ rpc_object_respawn_mixins_default.concat(mixinsArray).forEach((mixin22) => {
12346
+ (Array.isArray(mixin22.types) ? mixin22.types : [mixin22.types]).forEach((type) => {
12347
+ mixins6[type] = mixins6[type] || [];
12348
+ mixins6[type].push(mixin22);
12349
+ });
12350
+ });
12351
+ return mixins6;
12352
+ }
12353
+ function applyMixins(classPrototype, mixinList) {
12354
+ mixinList.forEach(({ extend: extend3 = {}, override = {} }) => {
12355
+ Object.keys(override).forEach((key) => {
12356
+ if (typeof classPrototype[key] === "function" && typeof override[key] === "function") {
12357
+ const baseFn = classPrototype[key];
12358
+ classPrototype[key] = function wrappedFn(...args) {
12359
+ return override[key].apply(this, [baseFn.bind(this), ...args]);
12360
+ };
12361
+ } else {
12362
+ throw new Error(
12363
+ `Tring to override non-existing function in ${classPrototype.type}/${classPrototype.genericType}: ${key}`
12364
+ );
12365
+ }
12366
+ });
12367
+ Object.keys(extend3).forEach((key) => {
12368
+ if (typeof classPrototype[key] === "function" && typeof extend3[key] === "function") {
12369
+ throw new Error(
12370
+ `Extend is not allowed. Function already exists in ${classPrototype.type}/${classPrototype.genericType}: ${key}`
12371
+ );
12372
+ } else {
12373
+ classPrototype[key] = extend3[key];
12374
+ }
12375
+ });
12376
+ });
12377
+ }
12378
+ function initMixins(rpcObject, mixinList) {
12379
+ mixinList.forEach(({ init }) => {
12380
+ if (init) {
12381
+ init.bind(rpcObject)({ api: rpcObject, config: { Promise } });
12382
+ }
12383
+ });
12384
+ }
12385
+
12386
+ // src/qix/session/phoenix/rpc-object-schema.ts
12387
+ function schemaToStructureOfUnboundFunctions(schema) {
12388
+ const result = {};
12389
+ Object.entries(schema.structs).forEach(([type, objectSchema]) => {
12390
+ result[type] = schemaToFunctionsEntries(objectSchema);
12391
+ });
12392
+ function schemaToFunctionsEntries(objectSchema) {
12393
+ return Object.entries(objectSchema).map(([pascalName, methodSchema]) => {
12394
+ return { methodName: toCamelCase(pascalName), fn: generateUnboundMethod(pascalName, methodSchema) };
12395
+ });
12396
+ }
12397
+ return result;
12398
+ }
12399
+ function generateUnboundMethod(pascalMethodName, methodSchema) {
12400
+ const out = methodSchema.Out;
12401
+ const outKey = out.length === 1 ? out[0].Name : -1;
12402
+ return function generatedMethod(...params) {
12403
+ return this.__remote__.invoke({ method: pascalMethodName, params, outKey });
12404
+ };
12405
+ }
12406
+ function toCamelCase(symbol) {
12407
+ return symbol.substring(0, 1).toLowerCase() + symbol.substring(1);
12408
+ }
12409
+
12410
+ // src/qix/session/phoenix/rpc-object-factory.ts
12411
+ function createRpcObjectFactory(schema, mixinsArray) {
12412
+ return new RpcObjectFactoryImpl(schema, mixinsArray);
12413
+ }
12414
+ var RpcObjectFactoryImpl = class {
12415
+ /**
12416
+ * Map from type to mixin
12417
+ */
12418
+ #mixinsByType;
12419
+ /**
12420
+ * Map from type to array of native qix functions
12421
+ */
12422
+ #nativeFunctionsByType;
12423
+ /**
12424
+ * All generated rpc object classes with mixins and native functions
12425
+ */
12426
+ #generatedClasses = {};
12427
+ constructor(schema, mixinsArray) {
12428
+ this.#mixinsByType = toMixinMap(mixinsArray);
12429
+ this.#nativeFunctionsByType = schemaToStructureOfUnboundFunctions(schema);
12430
+ }
12431
+ /**
12432
+ * Creates a new RPC Object with mixins et'al
12433
+ */
12434
+ createObject(refMultipleFormats, connection, creatingRequest) {
12435
+ const { handle, id, type, genericType } = normalizeObjectRef(refMultipleFormats);
12436
+ if (!type) {
12437
+ throw new Error(`Trying to create object without type: ${type}`);
12438
+ }
12439
+ const coreRpcObject = new RemoteObjectImpl({
12440
+ connection,
12441
+ handle,
12442
+ respawnInfo: {
12443
+ creatingRequest
12444
+ },
12445
+ id,
12446
+ type,
12447
+ genericType
12448
+ });
12449
+ const TypeSpecificPhoenixRpcClass = this.#getClass(type, genericType);
12450
+ return new TypeSpecificPhoenixRpcClass(coreRpcObject);
12451
+ }
12452
+ #getClass(type, genericType) {
12453
+ const key = `${type}:${genericType}`;
12454
+ if (!this.#generatedClasses[key]) {
12455
+ const rpcFunctions = this.#getRpcFunctionsForType(type);
12456
+ const mixins6 = this.#getMixinsForType(type).concat(this.#getMixinsForType(genericType));
12457
+ this.#generatedClasses[type] = class GeneratedBaseQixRpxObject extends PhoenixRpcObjectImpl {
12458
+ constructor(createProps) {
12459
+ super(createProps);
12460
+ initMixins(this, mixins6);
12461
+ }
12462
+ };
12463
+ const classPrototype = this.#generatedClasses[type].prototype;
12464
+ rpcFunctions.forEach(({ methodName, fn }) => {
12465
+ classPrototype[methodName] = fn;
12466
+ });
12467
+ applyMixins(classPrototype, mixins6);
12468
+ }
12469
+ return this.#generatedClasses[type];
12470
+ }
12471
+ #getMixinsForType(type) {
12472
+ return (type ? this.#mixinsByType[type] : []) || [];
12473
+ }
12474
+ #getRpcFunctionsForType(type) {
12475
+ return this.#nativeFunctionsByType[type];
12476
+ }
12477
+ };
12478
+
12479
+ // src/qix/session/qix-chunk-entrypoint.ts
12480
+ var objectFactory;
12481
+ async function createPhoenixConnectionEntrypoint(openProps, connectionwOwner) {
12482
+ objectFactory = objectFactory || createRpcObjectFactory(engine_api_default, mixins5);
12483
+ return createPhoenixConnection(openProps, objectFactory, connectionwOwner);
12484
+ }
12485
+ async function createEnigmaSessionEntrypoint(openProps) {
12486
+ return createEnigmaSession(openProps);
12487
+ }
10427
12488
  export {
10428
- createEnigmaSession
12489
+ createEnigmaSessionEntrypoint,
12490
+ createPhoenixConnectionEntrypoint
10429
12491
  };