@qlik/api 2.2.0 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (232) hide show
  1. package/analytics/change-stores.d.ts +386 -0
  2. package/analytics/change-stores.js +123 -0
  3. package/analytics.d.ts +14 -0
  4. package/analytics.js +13 -0
  5. package/api-keys.d.ts +362 -3
  6. package/api-keys.js +2 -3
  7. package/apps.d.ts +2673 -3
  8. package/apps.js +2 -3
  9. package/assistants.d.ts +1370 -3
  10. package/assistants.js +2 -3
  11. package/audits.d.ts +318 -3
  12. package/audits.js +4 -4
  13. package/auth-types.d.ts +1 -1
  14. package/auth-types.js +1 -2
  15. package/auth.d.ts +94 -2
  16. package/auth.js +63 -3
  17. package/automation-connections.d.ts +366 -3
  18. package/automation-connections.js +2 -3
  19. package/automation-connectors.d.ts +84 -3
  20. package/automation-connectors.js +2 -3
  21. package/automations.d.ts +805 -3
  22. package/automations.js +2 -3
  23. package/automl-deployments.d.ts +101 -3
  24. package/automl-deployments.js +2 -3
  25. package/automl-predictions.d.ts +238 -3
  26. package/automl-predictions.js +2 -3
  27. package/banners.d.ts +184 -3
  28. package/banners.js +2 -3
  29. package/brands.d.ts +670 -3
  30. package/brands.js +2 -3
  31. package/chunks/auth-XusKk8IA.js +32 -0
  32. package/chunks/{chunk-EtTptKIv.js → chunk-D3vHIbds.js} +2 -2
  33. package/chunks/{dist-gXLIqDJW.js → dist-n3iOVn1W.js} +4 -4
  34. package/chunks/{auth-functions-BmZgZYSs.js → interceptors-2VSXImC9.js} +498 -146
  35. package/chunks/{invoke-fetch-PcVIxLW4.js → invoke-fetch-CckTK7bh.js} +3 -3
  36. package/chunks/{invoke-fetch-CucBpA1C.js → invoke-fetch-D9lpiAb-.js} +1 -5
  37. package/chunks/{public-runtime-modules-Dwjzb3l8.js → public-runtime-modules-BqxAMJ9M.js} +7 -7
  38. package/chunks/{qix-DI5o5XF4.d.ts → qix-CrqXv44x.d.ts} +6 -2
  39. package/chunks/{qix-DjxuPCX0.js → qix-DpvHvpx7.js} +11 -10
  40. package/chunks/{qix-chunk-entrypoint-tmTo-kpa.js → qix-chunk-entrypoint-BXZPnE6J.js} +48 -50
  41. package/collections.d.ts +582 -3
  42. package/collections.js +2 -3
  43. package/conditions.d.ts +662 -3
  44. package/conditions.js +2 -3
  45. package/consumption.d.ts +182 -3
  46. package/consumption.js +2 -3
  47. package/core/ip-policies.d.ts +328 -4
  48. package/core/ip-policies.js +108 -5
  49. package/core.d.ts +13 -4
  50. package/core.js +3 -4
  51. package/csp-origins.d.ts +273 -3
  52. package/csp-origins.js +2 -3
  53. package/csrf-token.d.ts +62 -3
  54. package/csrf-token.js +2 -3
  55. package/data-alerts.d.ts +1004 -3
  56. package/data-alerts.js +2 -3
  57. package/data-assets.d.ts +207 -3
  58. package/data-assets.js +2 -3
  59. package/data-connections.d.ts +678 -3
  60. package/data-connections.js +2 -3
  61. package/data-credentials.d.ts +292 -3
  62. package/data-credentials.js +2 -3
  63. package/data-files.d.ts +860 -3
  64. package/data-files.js +2 -3
  65. package/data-qualities.d.ts +175 -3
  66. package/data-qualities.js +2 -3
  67. package/data-sets.d.ts +424 -3
  68. package/data-sets.js +2 -3
  69. package/data-sources.d.ts +348 -3
  70. package/data-sources.js +2 -3
  71. package/data-stores.d.ts +537 -3
  72. package/data-stores.js +2 -3
  73. package/dcaas.d.ts +192 -3
  74. package/dcaas.js +2 -3
  75. package/di-projects.d.ts +812 -4
  76. package/di-projects.js +25 -4
  77. package/direct-access-agents.d.ts +710 -4
  78. package/direct-access-agents.js +37 -5
  79. package/docs/authentication.md +1 -1
  80. package/encryption.d.ts +372 -3
  81. package/encryption.js +2 -3
  82. package/extensions.d.ts +295 -3
  83. package/extensions.js +2 -3
  84. package/global-types.d.ts +1 -1
  85. package/global-types.js +0 -2
  86. package/glossaries.d.ts +1223 -3
  87. package/glossaries.js +2 -3
  88. package/groups.d.ts +510 -3
  89. package/groups.js +2 -3
  90. package/identity-providers.d.ts +711 -3
  91. package/identity-providers.js +2 -3
  92. package/index.d.ts +78 -69
  93. package/index.js +28 -10
  94. package/interceptors.d.ts +52 -3
  95. package/interceptors.js +1 -2
  96. package/invoke-fetch-types.d.ts +1 -1
  97. package/items.d.ts +536 -3
  98. package/items.js +2 -3
  99. package/knowledgebases.d.ts +976 -3
  100. package/knowledgebases.js +2 -3
  101. package/licenses.d.ts +663 -3
  102. package/licenses.js +2 -3
  103. package/lineage-graphs.d.ts +704 -3
  104. package/lineage-graphs.js +2 -3
  105. package/ml.d.ts +2808 -3
  106. package/ml.js +2 -3
  107. package/notes.d.ts +110 -3
  108. package/notes.js +2 -3
  109. package/notifications.d.ts +98 -3
  110. package/notifications.js +2 -3
  111. package/oauth-callback.iife.js +1151 -0
  112. package/oauth-clients.d.ts +562 -3
  113. package/oauth-clients.js +2 -3
  114. package/oauth-tokens.d.ts +126 -3
  115. package/oauth-tokens.js +2 -3
  116. package/package.json +5 -4
  117. package/qix.d.ts +3 -3
  118. package/qix.js +38 -3
  119. package/questions.d.ts +364 -3
  120. package/questions.js +2 -3
  121. package/quotas.d.ts +112 -3
  122. package/quotas.js +2 -3
  123. package/reload-tasks.d.ts +249 -3
  124. package/reload-tasks.js +2 -3
  125. package/reloads.d.ts +260 -3
  126. package/reloads.js +2 -3
  127. package/report-templates.d.ts +287 -3
  128. package/report-templates.js +2 -3
  129. package/reports.d.ts +863 -3
  130. package/reports.js +2 -3
  131. package/roles.d.ts +312 -3
  132. package/roles.js +2 -3
  133. package/sharing-tasks.d.ts +1164 -3
  134. package/sharing-tasks.js +2 -3
  135. package/spaces.d.ts +779 -3
  136. package/spaces.js +2 -3
  137. package/tasks.d.ts +564 -3
  138. package/tasks.js +2 -3
  139. package/temp-contents.d.ts +167 -3
  140. package/temp-contents.js +2 -3
  141. package/tenants.d.ts +360 -3
  142. package/tenants.js +2 -3
  143. package/themes.d.ts +270 -3
  144. package/themes.js +2 -3
  145. package/transports.d.ts +435 -4
  146. package/transports.js +20 -5
  147. package/ui-config.d.ts +274 -3
  148. package/ui-config.js +2 -3
  149. package/users.d.ts +674 -3
  150. package/users.js +2 -3
  151. package/web-integrations.d.ts +294 -3
  152. package/web-integrations.js +2 -3
  153. package/web-notifications.d.ts +273 -3
  154. package/web-notifications.js +2 -3
  155. package/webhooks.d.ts +505 -3
  156. package/webhooks.js +2 -3
  157. package/chunks/api-keys-D6Rqaov4.d.ts +0 -365
  158. package/chunks/apps-BwpXUGDb.d.ts +0 -2673
  159. package/chunks/assistants-wh6Qe7l6.d.ts +0 -1366
  160. package/chunks/audits-DakwzT97.d.ts +0 -316
  161. package/chunks/auth-6mptVm5Q.d.ts +0 -95
  162. package/chunks/auth-Cle0_tmz.js +0 -32
  163. package/chunks/auth-D11iO7ZV.js +0 -65
  164. package/chunks/automation-connections-k2G_n9rj.d.ts +0 -366
  165. package/chunks/automation-connectors-J5OE-1P0.d.ts +0 -84
  166. package/chunks/automations-BGy83EBO.d.ts +0 -797
  167. package/chunks/automl-deployments-CWEpX2pk.d.ts +0 -101
  168. package/chunks/automl-predictions-BNIjRhBm.d.ts +0 -238
  169. package/chunks/banners-CgBRnZGv.d.ts +0 -184
  170. package/chunks/brands-DCgk6Gqx.d.ts +0 -671
  171. package/chunks/collections-BpYjcpIY.d.ts +0 -582
  172. package/chunks/conditions-CJJG7Uph.d.ts +0 -662
  173. package/chunks/consumption-DerFk437.d.ts +0 -182
  174. package/chunks/core-DQXNZdnf.d.ts +0 -12
  175. package/chunks/csp-origins-3NJlh_n9.d.ts +0 -273
  176. package/chunks/csrf-token-DoaoOQzH.d.ts +0 -63
  177. package/chunks/data-alerts-CILSEFbQ.d.ts +0 -1004
  178. package/chunks/data-assets-CJDcssoX.d.ts +0 -207
  179. package/chunks/data-connections-VSB13K6g.d.ts +0 -678
  180. package/chunks/data-credentials-ChEp_hyU.d.ts +0 -292
  181. package/chunks/data-files-CVzn9M6V.d.ts +0 -860
  182. package/chunks/data-qualities-DBrot957.d.ts +0 -176
  183. package/chunks/data-sets-CFzxgWnO.d.ts +0 -424
  184. package/chunks/data-sources-IsAaof_C.d.ts +0 -346
  185. package/chunks/data-stores-DFOPdgfz.d.ts +0 -537
  186. package/chunks/dcaas-qyv7YlrN.d.ts +0 -192
  187. package/chunks/di-projects-DVQTxASr.d.ts +0 -777
  188. package/chunks/direct-access-agents-B77OhzZi.d.ts +0 -580
  189. package/chunks/encryption-BjA6xbCO.d.ts +0 -372
  190. package/chunks/extensions-OO0WtInj.d.ts +0 -294
  191. package/chunks/glossaries-CIX7-KT_.d.ts +0 -1213
  192. package/chunks/groups-C86-UG7S.d.ts +0 -511
  193. package/chunks/identity-providers-h0dKNxGZ.d.ts +0 -711
  194. package/chunks/interceptors-Csx2tEi5.d.ts +0 -52
  195. package/chunks/interceptors-DTYm37AU.js +0 -104
  196. package/chunks/ip-policies-CKRIlbP7.d.ts +0 -327
  197. package/chunks/ip-policies-DXlf172B.js +0 -108
  198. package/chunks/items-C-jzqvFW.d.ts +0 -536
  199. package/chunks/knowledgebases-CyQtVcZN.d.ts +0 -977
  200. package/chunks/licenses-xzjnkitW.d.ts +0 -663
  201. package/chunks/lineage-graphs-CViCCzKy.d.ts +0 -697
  202. package/chunks/ml-Abt2MUva.d.ts +0 -2809
  203. package/chunks/notes-BZxuyDgt.d.ts +0 -111
  204. package/chunks/notifications-Bd_gp4jU.d.ts +0 -99
  205. package/chunks/oauth-clients-B5QPr4IM.d.ts +0 -563
  206. package/chunks/oauth-tokens-1b7V8182.d.ts +0 -127
  207. package/chunks/qix-CYQsLyGQ.js +0 -40
  208. package/chunks/questions-BVp0tvNs.d.ts +0 -364
  209. package/chunks/quotas-CfAebRJd.d.ts +0 -113
  210. package/chunks/reload-tasks-DfwUTetn.d.ts +0 -249
  211. package/chunks/reloads-CwmagnFx.d.ts +0 -260
  212. package/chunks/report-templates-DjQYj5dn.d.ts +0 -287
  213. package/chunks/reports-DzNC6Uq3.d.ts +0 -861
  214. package/chunks/roles-BYFIY6E7.d.ts +0 -312
  215. package/chunks/sharing-tasks-BMGIQ-FO.d.ts +0 -1164
  216. package/chunks/spaces-BK823t-b.d.ts +0 -780
  217. package/chunks/tasks-COKDfShO.d.ts +0 -564
  218. package/chunks/temp-contents-zDomB-g6.d.ts +0 -168
  219. package/chunks/tenants-Bhn86519.d.ts +0 -361
  220. package/chunks/themes-v9NbhiBo.d.ts +0 -269
  221. package/chunks/transports-CqEiFxD3.d.ts +0 -362
  222. package/chunks/ui-config-Crs0mVMp.d.ts +0 -274
  223. package/chunks/users-BSOBU_fg.d.ts +0 -675
  224. package/chunks/web-integrations-MisPAHod.d.ts +0 -295
  225. package/chunks/web-notifications-DVy6FHYh.d.ts +0 -274
  226. package/chunks/webhooks-Dr4EiXqy.d.ts +0 -505
  227. /package/chunks/{auth-types-E99tzdN0.d.ts → auth-types-YrlH_R9f.d.ts} +0 -0
  228. /package/chunks/{auth-types-JehqruDP.js → auth-types-h43TVDpB.js} +0 -0
  229. /package/chunks/{global-types-CrOvI33z.js → global-types-CEVAJebk.js} +0 -0
  230. /package/chunks/{invoke-fetch-CbU2Dgqr.d.ts → invoke-fetch-C1Z0RJYU.d.ts} +0 -0
  231. /package/chunks/{utils-BnC4lrlq.js → utils-vv-xFm06.js} +0 -0
  232. /package/chunks/{websocket-errors-DSbO6kDZ.js → websocket-errors-CRTDTtBL.js} +0 -0
@@ -1,11 +1,9 @@
1
- import { a as sortKeys, i as isNode, r as isBrowser, t as cleanFalsyValues } from "./utils-BnC4lrlq.js";
2
- import { i as getInterceptors } from "./interceptors-DTYm37AU.js";
3
- import { n as hostConfigCommonProperties, t as authTypesThatCanBeOmitted } from "./auth-types-JehqruDP.js";
4
- import { customAlphabet, nanoid } from "nanoid";
1
+ import { a as sortKeys, i as isNode, r as isBrowser, t as cleanFalsyValues } from "./utils-vv-xFm06.js";
2
+ import { n as hostConfigCommonProperties, t as authTypesThatCanBeOmitted } from "./auth-types-h43TVDpB.js";
5
3
 
6
4
  //#region src/platform/platform-functions.ts
7
5
  const getPlatform = async (options = {}) => {
8
- const hc = withResolvedHostConfig(options.hostConfig);
6
+ const hc = resolveHostConfig(options.hostConfig);
9
7
  if (hc.authType === "mock-backend-rest-recorder") return hc.recordGetPlatform();
10
8
  if (hc?.authType === "mock-backend") return hc.mockGetPlatform();
11
9
  if (hc?.authType === "noauth") return result({ isUnknown: true });
@@ -130,28 +128,190 @@ const result = (data) => ({
130
128
 
131
129
  //#endregion
132
130
  //#region src/utils/random.ts
131
+ const NANOID_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
132
+ const HEX_ALPHABET = "0123456789abcdef";
133
+ /**
134
+ * Generates a random string from the given alphabet using crypto.getRandomValues
135
+ * Works in both browser and Node.js environments
136
+ */
137
+ function generateRandomFromAlphabet(alphabet, length) {
138
+ const bytes = new Uint8Array(length);
139
+ globalThis.crypto.getRandomValues(bytes);
140
+ let result$1 = "";
141
+ for (let i = 0; i < length; i++) result$1 += alphabet[bytes[i] % alphabet.length];
142
+ return result$1;
143
+ }
133
144
  /**
134
145
  * Method helper for generating a random string [a-zA-Z0-9\-_]{length}
135
146
  * @param length - the length of the string
136
147
  */
137
148
  function generateRandomString(targetLength) {
138
- return nanoid(targetLength);
149
+ return generateRandomFromAlphabet(NANOID_ALPHABET, targetLength);
139
150
  }
140
151
  /**
141
152
  * Method helper for generating a random hexadecimal-string [0-9a-f]{length}
142
153
  * @param length - the length of the string
143
154
  */
144
155
  function generateRandomHexString(targetLength) {
145
- return customAlphabet("1234567890abcdef", targetLength)();
156
+ return generateRandomFromAlphabet(HEX_ALPHABET, targetLength);
157
+ }
158
+
159
+ //#endregion
160
+ //#region src/auth/internal/host-config-functions.ts
161
+ const emptyHostConfig = {};
162
+ const normalizedHostConfigs = /* @__PURE__ */ new Map();
163
+ /**
164
+ * Returns a new host config with all default and falsy values removed.
165
+ * @param hostConfig - The host config to fill with defaults
166
+ * @returns
167
+ */
168
+ function removeDefaults(hostConfig) {
169
+ const cleanedHostConfig = cleanFalsyValues(hostConfig) || {};
170
+ if (cleanedHostConfig.host) cleanedHostConfig.host = toValidLocationUrl(cleanedHostConfig);
171
+ if (isBrowser()) {
172
+ if (toValidLocationUrl(cleanedHostConfig) === window.location.origin) delete cleanedHostConfig.host;
173
+ }
174
+ if (cleanedHostConfig.authType && authTypesThatCanBeOmitted.includes(cleanedHostConfig.authType)) delete cleanedHostConfig.authType;
175
+ return cleanedHostConfig;
176
+ }
177
+ function globalReplacer(key, value) {
178
+ if (typeof value === "function") return;
179
+ return value;
180
+ }
181
+ /**
182
+ * Serializes the provided hostConfig, if present, otherwise the default one.
183
+ */
184
+ function serializeHostConfig$1(hostConfig) {
185
+ const sorted = sortKeys(removeDefaults(resolveHostConfig(hostConfig)));
186
+ return JSON.stringify(sorted, globalReplacer);
187
+ }
188
+ const registeredHostConfigs = /* @__PURE__ */ new Map();
189
+ /**
190
+ * Registers a host config with the given name.
191
+ * @param name The name of the host config to be used to reference the host config later.
192
+ * @param hostConfig The host config to register.
193
+ */
194
+ function registerHostConfig$1(name, hostConfig) {
195
+ const reference = hostConfig?.reference || null;
196
+ if (reference && !registeredHostConfigs.has(reference)) throw new InvalidHostConfigError(`Host config with reference "${reference}" is not registered. Please register it before using it.`);
197
+ if (registeredHostConfigs.has(name)) console.warn(`registerHostConfig: Host config with name "${name}" is already registered. Overwriting.`);
198
+ registeredHostConfigs.set(name, hostConfig);
199
+ }
200
+ /**
201
+ * Unregisters a host config with the given name.
202
+ * @param name The name of the host config to unregister.
203
+ */
204
+ function unregisterHostConfig$1(name) {
205
+ if (registeredHostConfigs.has(name)) registeredHostConfigs.delete(name);
206
+ else console.warn(`unregisterHostConfig: Host config with name "${name}" not found.`);
207
+ }
208
+ /**
209
+ * Gets the host config with the given name.
210
+ * @private
211
+ * @param name The name of the host config to get.
212
+ * @returns The host config, or undefined if not found.
213
+ */
214
+ function getRegisteredHostConfig(name) {
215
+ return registeredHostConfigs.get(name);
216
+ }
217
+ /**
218
+ * Sets the default host config that will be used for all api calls that do not include a HostConfig
219
+ * @private
220
+ * @param hostConfig the default HostConfig to use
221
+ */
222
+ function setDefaultHostConfig$1(hostConfig) {
223
+ registerHostConfig$1("default", hostConfig || {});
224
+ }
225
+ /**
226
+ * Gets the default host config that will be used for all qmfe api calls that do not include a HostConfig.
227
+ * @private
228
+ * @returns The default host config that will be used for all qmfe api calls that do not include a HostConfig
229
+ */
230
+ function getDefaultHostConfig$1() {
231
+ return getRegisteredHostConfig("default") || {};
232
+ }
233
+ function normalizeHostConfig$1(hostConfig) {
234
+ const suppliedHostConfigOrEmpty = hostConfig || emptyHostConfig;
235
+ const serializedHostConfigKey = serializeHostConfig$1(suppliedHostConfigOrEmpty);
236
+ let normalizedHostConfig = normalizedHostConfigs.get(serializedHostConfigKey);
237
+ if (!normalizedHostConfig) {
238
+ normalizedHostConfig = removeDefaults(resolveHostConfig(suppliedHostConfigOrEmpty));
239
+ normalizedHostConfigs.set(serializedHostConfigKey, normalizedHostConfig);
240
+ }
241
+ return normalizedHostConfig;
242
+ }
243
+
244
+ //#endregion
245
+ //#region src/auth/internal/page-redirect-request-listeners.ts
246
+ /**
247
+ * A store containing all listener registries for different host configurations.
248
+ */
249
+ const listenerRegistries$1 = /* @__PURE__ */ new Map();
250
+ /**
251
+ * Retrieves the listener registry for a given host configuration, creating one if it doesn't exist.
252
+ */
253
+ function getRegistryForHostConfig(hostConfig) {
254
+ const key = serializeHostConfig$1(hostConfig);
255
+ let registry = listenerRegistries$1.get(key);
256
+ if (!registry) {
257
+ registry = {
258
+ redirectRequestedListeners: /* @__PURE__ */ new Set(),
259
+ redirectStartedListeners: /* @__PURE__ */ new Set()
260
+ };
261
+ listenerRegistries$1.set(key, registry);
262
+ }
263
+ return registry;
264
+ }
265
+ /**
266
+ * Registers a listener for page redirects requested by auth modules.
267
+ * @param hostConfig
268
+ * @param listener
269
+ * @returns
270
+ */
271
+ function onPageRedirectRequested$1(hostConfig, listener) {
272
+ const registry = getRegistryForHostConfig(hostConfig);
273
+ registry.redirectRequestedListeners.add(listener);
274
+ return () => {
275
+ registry.redirectRequestedListeners.delete(listener);
276
+ };
277
+ }
278
+ function onPageRedirectStarted$1(hostConfig, listener) {
279
+ const registry = getRegistryForHostConfig(hostConfig);
280
+ registry.redirectStartedListeners.add(listener);
281
+ return () => {
282
+ registry.redirectStartedListeners.delete(listener);
283
+ };
284
+ }
285
+ function requestRedirect(hostConfig) {
286
+ const registry = getRegistryForHostConfig(hostConfig);
287
+ const hasRedirectListener = registry.redirectRequestedListeners.size > 0 || hostConfig.authRedirectUserConfirmation;
288
+ if (hostConfig.autoRedirect || !hasRedirectListener) return Promise.resolve();
289
+ if (typeof hostConfig.authRedirectUserConfirmation === "function") return hostConfig.authRedirectUserConfirmation().catch(() => {});
290
+ return new Promise((resolve) => {
291
+ const proceed = () => {
292
+ for (const startedListener of registry.redirectStartedListeners) try {
293
+ startedListener();
294
+ } catch (error) {
295
+ console.warn(error);
296
+ }
297
+ resolve();
298
+ };
299
+ for (const requestListener of registry.redirectRequestedListeners) try {
300
+ requestListener({ proceed });
301
+ } catch (error) {
302
+ console.warn(error);
303
+ }
304
+ });
146
305
  }
147
306
 
148
307
  //#endregion
149
308
  //#region src/utils/expose-internal-test-apis.ts
150
- const internalApisName = "__QLIK_INTERNAL__DO_NOT_USE_OR_YOU_WILL_BE_FIRED";
151
309
  function exposeInternalApiOnWindow(name, fn) {
152
310
  if (globalThis.location?.origin.startsWith("https://localhost:") || globalThis.location?.origin?.endsWith("qlik-stage.com")) {
153
- if (globalThis[internalApisName] === void 0) globalThis[internalApisName] = {};
154
- globalThis[internalApisName][name] = fn;
311
+ if (globalThis.QlikMain) {
312
+ if (globalThis.QlikMain.INTERNAL__DO_NOT_USE.qix === void 0) globalThis.QlikMain.INTERNAL__DO_NOT_USE.qix = {};
313
+ globalThis.QlikMain.INTERNAL__DO_NOT_USE.qix[name] = fn;
314
+ }
155
315
  }
156
316
  }
157
317
 
@@ -523,7 +683,7 @@ async function getOAuthTokensForBrowser(hostConfig) {
523
683
  });
524
684
  if (oauthTokens) return oauthTokens;
525
685
  if (hostConfig.performInteractiveLogin) return new Promise(() => {});
526
- if (hostConfig.authRedirectUserConfirmation) await hostConfig.authRedirectUserConfirmation();
686
+ await requestRedirect(hostConfig);
527
687
  startFullPageLoginFlow(hostConfig);
528
688
  return new Promise(() => {});
529
689
  }
@@ -969,12 +1129,12 @@ function shouldUseCachedResult(options, cacheEntry, defaultMaxCacheTime) {
969
1129
  */
970
1130
  function toCacheKey({ url, query, headers, serializedHostConfig }) {
971
1131
  let cacheKey = url;
972
- if (query) {
1132
+ if (query && Object.keys(query).length > 0) {
973
1133
  const queryString = encodeQueryParams(query);
974
1134
  if (url.includes("?")) cacheKey = cacheKey.concat(`&${queryString}`);
975
1135
  else cacheKey = cacheKey.concat(`?${queryString}`);
976
1136
  }
977
- if (headers) cacheKey = cacheKey.concat(`+headers=${JSON.stringify(headers)}`);
1137
+ if (headers && Object.keys(headers).length > 0) cacheKey = cacheKey.concat(`+headers=${JSON.stringify(headers)}`);
978
1138
  if (serializedHostConfig && serializedHostConfig !== "{}") cacheKey = cacheKey.concat(`+host-config=${serializedHostConfig}`);
979
1139
  return cacheKey;
980
1140
  }
@@ -1194,7 +1354,7 @@ async function getInvokeFetchUrlParams({ method, pathTemplate, pathVariables, qu
1194
1354
  ...query,
1195
1355
  ...authQueryParams
1196
1356
  }));
1197
- const serializedHostConfig = serializeHostConfig$1(options?.hostConfig);
1357
+ const serializedHostConfig = serializeHostConfig(options?.hostConfig);
1198
1358
  return {
1199
1359
  completeUrl,
1200
1360
  authHeaders,
@@ -1245,7 +1405,7 @@ function addPagingFunctions(api, { method, body, options, authHeaders, credentia
1245
1405
  return value.then((resp) => {
1246
1406
  const dataWithPotentialLinks = resp.data;
1247
1407
  if (!dataWithPotentialLinks) return resp;
1248
- const serializedHostConfig = serializeHostConfig$1(options?.hostConfig);
1408
+ const serializedHostConfig = serializeHostConfig(options?.hostConfig);
1249
1409
  const prevUrl = dataWithPotentialLinks.links?.prev?.href;
1250
1410
  const nextUrl = dataWithPotentialLinks.links?.next?.href;
1251
1411
  if (prevUrl) resp.prev = (prevOptions) => invokeFetchWithUrl(api, {
@@ -1340,8 +1500,8 @@ const defaultUserAgent = "qmfe-api/latest";
1340
1500
  * @param api Name of api to call. Will be used for caching responses.
1341
1501
  * @param invokeFetchProps InvokeFetchProperties
1342
1502
  */
1343
- async function invokeFetch(api, props, interceptors) {
1344
- const effectiveInterceptors = interceptors || getInterceptors();
1503
+ async function invokeFetch(api, props, interceptors$1) {
1504
+ const effectiveInterceptors = interceptors$1 || getInterceptors();
1345
1505
  const invokeFetchFinal = (reqeust) => invokeFetchIntercepted(api, reqeust);
1346
1506
  return (effectiveInterceptors || []).reduce((proceed, interceptor) => (request) => interceptor(request, proceed), invokeFetchFinal)(props);
1347
1507
  }
@@ -1451,6 +1611,7 @@ const QLIK_CSRF_TOKEN = "qlik-csrf-token";
1451
1611
  function clearCsrfToken(hostConfig) {
1452
1612
  const locationUrl = toValidLocationUrl(hostConfig);
1453
1613
  delete csrfTokens[locationUrl];
1614
+ clearApiCache("csrf-token");
1454
1615
  }
1455
1616
  /**
1456
1617
  * Fetches the CSRF token from the server. The token is cached and will be reused for subsequent calls.
@@ -1470,7 +1631,8 @@ async function getCsrfToken(hostConfig, noCache) {
1470
1631
  pathTemplate,
1471
1632
  options: {
1472
1633
  hostConfig,
1473
- noCache: true
1634
+ maxCacheAge: 5e3,
1635
+ noCache
1474
1636
  }
1475
1637
  })).headers.get(QLIK_CSRF_TOKEN);
1476
1638
  if (!csrfToken) return "";
@@ -1551,7 +1713,7 @@ async function handleAuthenticationError$7({ hostConfig, status }) {
1551
1713
  };
1552
1714
  const webIntegrationParam = hostConfig.webIntegrationId ? `qlik-web-integration-id=${hostConfig?.webIntegrationId}&` : "";
1553
1715
  const locationUrl = toValidLocationUrl(hostConfig);
1554
- if (hostConfig.authRedirectUserConfirmation) await hostConfig.authRedirectUserConfirmation();
1716
+ await requestRedirect(hostConfig);
1555
1717
  globalThis.location.replace(`${locationUrl}/login?${webIntegrationParam}returnto=${encodeURIComponent(globalThis.location.href)}`);
1556
1718
  return { preventDefault: true };
1557
1719
  }
@@ -1698,7 +1860,7 @@ async function handleAuthenticationError$4({ hostConfig }) {
1698
1860
  clearStoredOauthTokens(hostConfig);
1699
1861
  return { retry: true };
1700
1862
  }
1701
- if (hostConfig.authRedirectUserConfirmation) await hostConfig.authRedirectUserConfirmation();
1863
+ await requestRedirect(hostConfig);
1702
1864
  startFullPageLoginFlow(hostConfig);
1703
1865
  return { preventDefault: true };
1704
1866
  }
@@ -1788,7 +1950,7 @@ async function getWebSocketAuthParams$2({ hostConfig }) {
1788
1950
  }
1789
1951
  async function handleAuthenticationError$2({ hostConfig }) {
1790
1952
  if (hostConfig.loginUri) {
1791
- if (hostConfig.authRedirectUserConfirmation) await hostConfig.authRedirectUserConfirmation();
1953
+ await requestRedirect(hostConfig);
1792
1954
  globalThis.location.replace(hostConfig.loginUri.replace("{location}", encodeURIComponent(globalThis.location.href)));
1793
1955
  return { preventDefault: true };
1794
1956
  }
@@ -1826,15 +1988,15 @@ var windows_cookie_default = {
1826
1988
  //#region src/auth/internal/default-auth-modules/windows-cookie-node.ts
1827
1989
  const nodeCookieStore = /* @__PURE__ */ new Map();
1828
1990
  function clearCookieInStore(hostConfig) {
1829
- const key = serializeHostConfig$1(hostConfig);
1991
+ const key = serializeHostConfig(hostConfig);
1830
1992
  nodeCookieStore.delete(key);
1831
1993
  }
1832
1994
  function setCookieInStore(hostConfig, cookie) {
1833
- const key = serializeHostConfig$1(hostConfig);
1995
+ const key = serializeHostConfig(hostConfig);
1834
1996
  nodeCookieStore.set(key, cookie);
1835
1997
  }
1836
1998
  function getCookieInStore(hostConfig) {
1837
- const key = serializeHostConfig$1(hostConfig);
1999
+ const key = serializeHostConfig(hostConfig);
1838
2000
  return nodeCookieStore.get(key);
1839
2001
  }
1840
2002
  async function getCookie(hostConfig) {
@@ -1910,15 +2072,15 @@ let ongoingAuthModuleLoading = Promise.resolve();
1910
2072
  let authModulesRegistered = false;
1911
2073
  (function registerDefaultAuthModules() {
1912
2074
  if (!authModulesRegistered) {
1913
- registerAuthModule("apikey", apikey_default);
1914
- registerAuthModule("cookie", cookie_default);
1915
- registerAuthModule("none", none_default);
1916
- registerAuthModule("noauth", noauth_default);
1917
- registerAuthModule("oauth2", oauth_default);
1918
- registerAuthModule("anonymous", anonymous_default);
1919
- if (isBrowser()) registerAuthModule("windowscookie", windows_cookie_default);
1920
- else registerAuthModule("windowscookie", windows_cookie_node_default);
1921
- registerAuthModule("reference", reference_default);
2075
+ registerAuthModule$1("apikey", apikey_default);
2076
+ registerAuthModule$1("cookie", cookie_default);
2077
+ registerAuthModule$1("none", none_default);
2078
+ registerAuthModule$1("noauth", noauth_default);
2079
+ registerAuthModule$1("oauth2", oauth_default);
2080
+ registerAuthModule$1("anonymous", anonymous_default);
2081
+ if (isBrowser()) registerAuthModule$1("windowscookie", windows_cookie_default);
2082
+ else registerAuthModule$1("windowscookie", windows_cookie_node_default);
2083
+ registerAuthModule$1("reference", reference_default);
1922
2084
  authModulesRegistered = true;
1923
2085
  }
1924
2086
  })();
@@ -1927,7 +2089,7 @@ let authModulesRegistered = false;
1927
2089
  * @param name the name of the module
1928
2090
  * @param authModule the implementation of the AuthModule interface
1929
2091
  */
1930
- function registerAuthModule(name, authModule) {
2092
+ function registerAuthModule$1(name, authModule) {
1931
2093
  authModules[name.toLowerCase()] = authModule;
1932
2094
  }
1933
2095
  /**
@@ -1954,8 +2116,8 @@ function getRegisteredAuthModule(authType) {
1954
2116
  * @param hostConfig
1955
2117
  */
1956
2118
  async function getAuthModule(hostConfig) {
1957
- const hostConfigToUse = withResolvedHostConfig(hostConfig);
1958
- const authType = await determineAuthType(hostConfigToUse);
2119
+ const hostConfigToUse = resolveHostConfig(hostConfig);
2120
+ const authType = await determineAuthType$1(hostConfigToUse);
1959
2121
  if (ongoingAuthModuleLoading) await ongoingAuthModuleLoading;
1960
2122
  let authModule = getRegisteredAuthModule(authType);
1961
2123
  if (!authModule) {
@@ -1965,7 +2127,7 @@ async function getAuthModule(hostConfig) {
1965
2127
  */
1966
2128
  ongoingAuthModuleLoading = (async () => {
1967
2129
  authModule = await resolveGloballyDefinedAuthModule(authType);
1968
- if (authModule) registerAuthModule(authType, authModule);
2130
+ if (authModule) registerAuthModule$1(authType, authModule);
1969
2131
  })();
1970
2132
  await ongoingAuthModuleLoading;
1971
2133
  }
@@ -2025,7 +2187,7 @@ function internalValidateHostConfig(hostConfig, { requiredProps, optionalProps }
2025
2187
  * Determines the authType associated with a HostConfig even if it's
2026
2188
  * not explicitly set.
2027
2189
  */
2028
- async function determineAuthType(hostConfig) {
2190
+ async function determineAuthType$1(hostConfig) {
2029
2191
  if (hostConfig.authType) return hostConfig.authType;
2030
2192
  if (hostConfig.apiKey) return "apikey";
2031
2193
  if (hostConfig.accessCode) return "anonymous";
@@ -2079,76 +2241,55 @@ var AuthorizationError = class extends Error {
2079
2241
  };
2080
2242
 
2081
2243
  //#endregion
2082
- //#region src/auth/internal/host-config-functions.ts
2244
+ //#region src/auth/internal/fatal-auth-error-listeners.ts
2245
+ const listenerRegistries = /* @__PURE__ */ new Map();
2246
+ let lastErrorMessage = "";
2247
+ let lastHostConfig;
2083
2248
  /**
2084
- * Returns a new host config with all default and falsy values removed.
2085
- * @param hostConfig - The host config to fill with defaults
2086
- * @returns
2249
+ * Retrieves the listener registry for a given host configuration, creating one if it doesn't exist.
2087
2250
  */
2088
- function removeDefaults(hostConfig) {
2089
- const cleanedHostConfig = cleanFalsyValues(hostConfig) || {};
2090
- if (cleanedHostConfig.host) cleanedHostConfig.host = toValidLocationUrl(cleanedHostConfig);
2091
- if (isBrowser()) {
2092
- if (toValidLocationUrl(cleanedHostConfig) === window.location.origin) delete cleanedHostConfig.host;
2251
+ function getAuthErrorListenerRegistryForHostConfig(hostConfig) {
2252
+ const key = serializeHostConfig$1(hostConfig);
2253
+ let registry = listenerRegistries.get(key);
2254
+ if (!registry) {
2255
+ registry = { listeners: /* @__PURE__ */ new Set() };
2256
+ listenerRegistries.set(key, registry);
2093
2257
  }
2094
- if (cleanedHostConfig.authType && authTypesThatCanBeOmitted.includes(cleanedHostConfig.authType)) delete cleanedHostConfig.authType;
2095
- return cleanedHostConfig;
2096
- }
2097
- function globalReplacer(key, value) {
2098
- if (typeof value === "function") return;
2099
- return value;
2100
- }
2101
- /**
2102
- * Serializes the provided hostConfig, if present, otherwise the default one.
2103
- */
2104
- function serializeHostConfig(hostConfig) {
2105
- const sorted = sortKeys(removeDefaults(withResolvedHostConfig(hostConfig)));
2106
- return JSON.stringify(sorted, globalReplacer);
2107
- }
2108
- const registeredHostConfigs = /* @__PURE__ */ new Map();
2109
- /**
2110
- * Registers a host config with the given name.
2111
- * @param name The name of the host config to be used to reference the host config later.
2112
- * @param hostConfig The host config to register.
2113
- */
2114
- function registerHostConfig(name, hostConfig) {
2115
- const reference = hostConfig?.reference || null;
2116
- if (reference && !registeredHostConfigs.has(reference)) throw new InvalidHostConfigError(`Host config with reference "${reference}" is not registered. Please register it before using it.`);
2117
- if (registeredHostConfigs.has(name)) console.warn(`registerHostConfig: Host config with name "${name}" is already registered. Overwriting.`);
2118
- registeredHostConfigs.set(name, hostConfig);
2119
- }
2120
- /**
2121
- * Unregisters a host config with the given name.
2122
- * @param name The name of the host config to unregister.
2123
- */
2124
- function unregisterHostConfig(name) {
2125
- if (registeredHostConfigs.has(name)) registeredHostConfigs.delete(name);
2126
- else console.warn(`unregisterHostConfig: Host config with name "${name}" not found.`);
2127
- }
2128
- /**
2129
- * Gets the host config with the given name.
2130
- * @private
2131
- * @param name The name of the host config to get.
2132
- * @returns The host config, or undefined if not found.
2133
- */
2134
- function getRegisteredHostConfig(name) {
2135
- return registeredHostConfigs.get(name);
2136
- }
2137
- /**
2138
- * Sets the default host config that will be used for all api calls that do not include a HostConfig
2139
- * @private
2140
- * @param hostConfig the default HostConfig to use
2141
- */
2142
- function setDefaultHostConfig(hostConfig) {
2143
- registerHostConfig("default", hostConfig || {});
2258
+ return registry;
2259
+ }
2260
+ /**
2261
+ * Emits a fatal authentication error to all registered listeners plus to the onAuthFailed property in the hostConfig.
2262
+ * If there are no listeners or onAuthFailed callback, the error message is logged to the console.
2263
+ */
2264
+ function emitFatalAuthError(hostConfig, normalizedError) {
2265
+ if (hostConfig === lastHostConfig && normalizedError.message === lastErrorMessage) return;
2266
+ lastHostConfig = hostConfig;
2267
+ lastErrorMessage = normalizedError.message;
2268
+ let someOneIsListening = false;
2269
+ const registry = getAuthErrorListenerRegistryForHostConfig(hostConfig);
2270
+ for (const listener of registry.listeners) try {
2271
+ someOneIsListening = true;
2272
+ listener(normalizedError);
2273
+ } catch (listenerError) {
2274
+ console.warn("Error in auth error listener", listenerError);
2275
+ }
2276
+ if (hostConfig.onAuthFailed) try {
2277
+ someOneIsListening = true;
2278
+ hostConfig.onAuthFailed(normalizedError);
2279
+ } catch (callbackError) {
2280
+ console.warn("Error in onAuthFailed callback", callbackError);
2281
+ }
2282
+ if (!someOneIsListening) console.error(normalizedError.message);
2144
2283
  }
2145
2284
  /**
2146
- * Gets the default host config that will be used for all qmfe api calls that do not include a HostConfig.
2147
- * @private
2148
- * @returns The default host config that will be used for all qmfe api calls that do not include a HostConfig
2285
+ * Registers a listener for fatal auth errors. This means errors in the actual auth mechanism, i.e. misconfigurations etc.
2149
2286
  */
2150
- function getDefaultHostConfig() {
2151
- return getRegisteredHostConfig("default") || {};
2287
+ function onFatalAuthError$1(hostConfig, callback) {
2288
+ const registry = getAuthErrorListenerRegistryForHostConfig(hostConfig);
2289
+ registry.listeners.add(callback);
2290
+ return () => {
2291
+ registry.listeners.delete(callback);
2292
+ };
2152
2293
  }
2153
2294
 
2154
2295
  //#endregion
@@ -2157,22 +2298,14 @@ function getDefaultHostConfig() {
2157
2298
  * Set initial loggingOut value to false to make sure it has a value before any auth module is loaded
2158
2299
  */
2159
2300
  globalThis.loggingOut = false;
2160
- let lastErrorMessage = "";
2161
- /** Default error logger that simply prints the error unless it is identical to the last one (to prevent bloating of the console) */
2162
- function logToConsole({ message }) {
2163
- if (message !== lastErrorMessage) {
2164
- lastErrorMessage = message;
2165
- console.error(message);
2166
- }
2167
- }
2168
2301
  /**
2169
2302
  * Determines the authType associated with a HostConfig even if it's
2170
2303
  * not explicitly set.
2171
2304
  * @param hostConfig the HostConfig containing authentication details
2172
2305
  * @returns promise that resolvs with the determined authentication type
2173
2306
  */
2174
- function determineAuthType$1(hostConfig) {
2175
- return determineAuthType(hostConfig);
2307
+ function determineAuthType(hostConfig) {
2308
+ return determineAuthType$1(hostConfig);
2176
2309
  }
2177
2310
  /**
2178
2311
  * Determines if a host is cross origin or not
@@ -2181,7 +2314,7 @@ function determineAuthType$1(hostConfig) {
2181
2314
  */
2182
2315
  function isHostCrossOrigin(hostConfig) {
2183
2316
  if (!globalThis.location?.origin) return true;
2184
- const hostConfigToUse = withResolvedHostConfig(hostConfig);
2317
+ const hostConfigToUse = resolveHostConfig(hostConfig);
2185
2318
  if (Object.keys(hostConfigToUse).length === 0) return false;
2186
2319
  try {
2187
2320
  return new URL(toValidLocationUrl(hostConfigToUse)).origin !== globalThis.location.origin;
@@ -2193,7 +2326,7 @@ function isHostCrossOrigin(hostConfig) {
2193
2326
  * @param hostConfig the HostConfig containing authentication details
2194
2327
  */
2195
2328
  async function isWindows(hostConfig) {
2196
- const hostConfigToUse = withResolvedHostConfig(hostConfig);
2329
+ const hostConfigToUse = resolveHostConfig(hostConfig);
2197
2330
  if (typeof hostConfigToUse.forceIsWindows === "boolean") return hostConfigToUse.forceIsWindows;
2198
2331
  if (hostConfigToUse.host?.endsWith(".qlik-stage.com") || hostConfigToUse.host?.endsWith(".qlikcloud.com") || hostConfigToUse.host?.endsWith(".qlikcloudgov.com")) return false;
2199
2332
  if (hostConfigToUse.authType === "cookie") return false;
@@ -2205,7 +2338,7 @@ async function isWindows(hostConfig) {
2205
2338
  * @param hostConfig the HostConfig containing authentication details
2206
2339
  */
2207
2340
  function toValidLocationUrl(hostConfig) {
2208
- const url = withResolvedHostConfig(hostConfig)?.host?.trim();
2341
+ const url = resolveHostConfig(hostConfig)?.host?.trim();
2209
2342
  let locationUrl;
2210
2343
  if (!url) locationUrl = "";
2211
2344
  else if (url.toLowerCase().startsWith("https://") || url.toLowerCase().startsWith("http://")) locationUrl = url;
@@ -2218,7 +2351,7 @@ function toValidLocationUrl(hostConfig) {
2218
2351
  * @param hostConfig the HostConfig containing authentication details
2219
2352
  */
2220
2353
  function toValidWebsocketLocationUrl(hostConfig) {
2221
- const url = withResolvedHostConfig(hostConfig)?.host;
2354
+ const url = resolveHostConfig(hostConfig)?.host;
2222
2355
  let locationUrl;
2223
2356
  if (!url) locationUrl = globalThis.location.origin;
2224
2357
  else if (url.toLowerCase().startsWith("https://") || url.toLowerCase().startsWith("http://")) locationUrl = url;
@@ -2231,14 +2364,14 @@ function toValidWebsocketLocationUrl(hostConfig) {
2231
2364
  * @param hostConfig the HostConfig containing authentication details
2232
2365
  */
2233
2366
  async function getWebSocketAuthParams(props) {
2234
- const hostConfigToUse = withResolvedHostConfig(props.hostConfig);
2367
+ const hostConfigToUse = resolveHostConfig(props.hostConfig);
2235
2368
  try {
2236
2369
  return await (await getAuthModule(hostConfigToUse)).getWebSocketAuthParams({
2237
2370
  ...props,
2238
2371
  hostConfig: hostConfigToUse
2239
2372
  });
2240
2373
  } catch (err) {
2241
- (hostConfigToUse.onAuthFailed || logToConsole)(normalizeAuthModuleError(err));
2374
+ emitFatalAuthError(hostConfigToUse, normalizeAuthModuleError(err));
2242
2375
  throw err;
2243
2376
  }
2244
2377
  }
@@ -2248,14 +2381,14 @@ async function getWebSocketAuthParams(props) {
2248
2381
  * @param hostConfig the HostConfig containing authentication details
2249
2382
  */
2250
2383
  async function getWebResourceAuthParams(props) {
2251
- const hostConfigToUse = withResolvedHostConfig(props.hostConfig);
2384
+ const hostConfigToUse = resolveHostConfig(props.hostConfig);
2252
2385
  try {
2253
2386
  return await (await getAuthModule(hostConfigToUse)).getWebResourceAuthParams?.({
2254
2387
  ...props,
2255
2388
  hostConfig: hostConfigToUse
2256
2389
  }) || { queryParams: {} };
2257
2390
  } catch (err) {
2258
- (hostConfigToUse.onAuthFailed || logToConsole)(normalizeAuthModuleError(err));
2391
+ emitFatalAuthError(hostConfigToUse, normalizeAuthModuleError(err));
2259
2392
  throw err;
2260
2393
  }
2261
2394
  }
@@ -2263,7 +2396,7 @@ async function getWebResourceAuthParams(props) {
2263
2396
  * Calls and return handleAuthenticationError on the authModule a host config is associated with.
2264
2397
  */
2265
2398
  async function handleAuthenticationError(props) {
2266
- const hostConfigToUse = withResolvedHostConfig(props.hostConfig);
2399
+ const hostConfigToUse = resolveHostConfig(props.hostConfig);
2267
2400
  const result$1 = await (await getAuthModule(hostConfigToUse)).handleAuthenticationError({
2268
2401
  ...props,
2269
2402
  hostConfig: hostConfigToUse
@@ -2272,7 +2405,7 @@ async function handleAuthenticationError(props) {
2272
2405
  const willHangUntilANewPageIsLoaded = result$1.preventDefault;
2273
2406
  if (!willRetry && !willHangUntilANewPageIsLoaded) {
2274
2407
  const { status, errorBody } = props;
2275
- (hostConfigToUse.onAuthFailed || logToConsole)(normalizeInbandAuthError({
2408
+ emitFatalAuthError(hostConfigToUse, normalizeInbandAuthError({
2276
2409
  status,
2277
2410
  errorBody
2278
2411
  }));
@@ -2285,14 +2418,14 @@ async function handleAuthenticationError(props) {
2285
2418
  * @param props.method the http method, which may affect what authentication are needed.
2286
2419
  */
2287
2420
  async function getRestCallAuthParams(props) {
2288
- const hostConfigToUse = withResolvedHostConfig(props.hostConfig);
2421
+ const hostConfigToUse = resolveHostConfig(props.hostConfig);
2289
2422
  try {
2290
2423
  return await (await getAuthModule(hostConfigToUse)).getRestCallAuthParams({
2291
2424
  ...props,
2292
2425
  hostConfig: hostConfigToUse
2293
2426
  });
2294
2427
  } catch (err) {
2295
- (hostConfigToUse.onAuthFailed || logToConsole)(normalizeAuthModuleError(err));
2428
+ emitFatalAuthError(hostConfigToUse, normalizeAuthModuleError(err));
2296
2429
  throw err;
2297
2430
  }
2298
2431
  }
@@ -2314,48 +2447,54 @@ async function getAccessToken(props) {
2314
2447
  * @param name the name of the module
2315
2448
  * @param authModule the implementation of the AuthModule interface
2316
2449
  */
2317
- function registerAuthModule$1(name, authModule) {
2318
- registerAuthModule(name, authModule);
2450
+ function registerAuthModule(name, authModule) {
2451
+ registerAuthModule$1(name, authModule);
2319
2452
  }
2320
2453
  /**
2321
2454
  * Sets the default host config that will be used for all api calls that do not include a HostConfig
2322
2455
  * @param hostConfig the default HostConfig to use
2323
2456
  */
2324
- function setDefaultHostConfig$1(hostConfig) {
2325
- setDefaultHostConfig(hostConfig);
2457
+ function setDefaultHostConfig(hostConfig) {
2458
+ setDefaultHostConfig$1(hostConfig);
2326
2459
  }
2327
2460
  /**
2328
2461
  * Registers a host config with the given name.
2329
2462
  * @param name The name of the host config to be used to reference the host config later.
2330
2463
  * @param hostConfig The host config to register.
2331
2464
  */
2332
- function registerHostConfig$1(name, hostConfig) {
2333
- registerHostConfig(name, hostConfig);
2465
+ function registerHostConfig(name, hostConfig) {
2466
+ registerHostConfig$1(name, hostConfig);
2334
2467
  }
2335
2468
  /**
2336
2469
  * Unregisters a host config with the given name.
2337
2470
  * @param name The name of the host config to unregister.
2338
2471
  */
2339
- function unregisterHostConfig$1(name) {
2340
- unregisterHostConfig(name);
2472
+ function unregisterHostConfig(name) {
2473
+ unregisterHostConfig$1(name);
2341
2474
  }
2342
2475
  /**
2343
2476
  * Serializes the provided hostConfig, if present, otherwise the default one.
2344
2477
  */
2345
- function serializeHostConfig$1(hostConfig) {
2346
- return serializeHostConfig(hostConfig);
2478
+ function serializeHostConfig(hostConfig) {
2479
+ return serializeHostConfig$1(hostConfig);
2347
2480
  }
2348
2481
  /**
2349
2482
  * Throws errors if hostConfig is missing or missing properties on cross domain requests
2350
2483
  */
2351
2484
  function checkForCrossDomainRequest(hostConfig) {
2352
- const hostConfigToUse = withResolvedHostConfig(hostConfig);
2485
+ const hostConfigToUse = resolveHostConfig(hostConfig);
2353
2486
  if (isHostCrossOrigin(hostConfigToUse)) {
2354
2487
  if (Object.keys(hostConfigToUse).length === 0) throw new InvalidHostConfigError("a host config must be provided when making a cross domain request");
2355
2488
  if (!hostConfigToUse.host) throw new InvalidHostConfigError("A 'host' property must be set in host config when making a cross domain request");
2356
2489
  }
2357
2490
  }
2358
2491
  /**
2492
+ * Returns a normalized host config that will always be the same instance when the serialized host config is the same.
2493
+ */
2494
+ function normalizeHostConfig(hostConfig) {
2495
+ return normalizeHostConfig$1(hostConfig);
2496
+ }
2497
+ /**
2359
2498
  * Logs out the user and sets `global.loggingOut` to true.
2360
2499
  * **NOTE**: Does not abort pending requests.
2361
2500
  */
@@ -2386,29 +2525,242 @@ function normalizeAuthModuleError(err) {
2386
2525
  return { message: err.message || "Unknown error" };
2387
2526
  }
2388
2527
  /**
2389
- * Returns a resolved host config. If the host config is a reference to a registered host config, it will be resolved
2390
- * to the actual host config.
2391
- * If the host config is undefined or empty, the default host config will be used.
2392
- * If the host config is not a reference, it will be returned as is.
2393
- * @private
2528
+ * Replaces the supplied host config according the following rules:
2529
+ * * If the host config is a reference to a registered host config, the registered host config will be used.
2530
+ * * If the host config is undefined or empty, the default host config will be returned.
2531
+ * * If the host config is not a reference and not empty or undefined, it will be returned as is.
2532
+ * * If the host config is empty or undefined an empty object (which represents the default cookie mode) is returned.
2394
2533
  * @param hostConfig - The host config to resolve
2395
- * @returns
2396
2534
  */
2397
- function withResolvedHostConfig(hostConfig) {
2535
+ function resolveHostConfig(hostConfig) {
2398
2536
  if (hostConfig?.reference) {
2399
2537
  const refConfig = getRegisteredHostConfig(hostConfig.reference);
2400
2538
  if (!refConfig) throw new InvalidHostConfigError(`Host config with name "${hostConfig.reference}" not found.`);
2401
2539
  return refConfig;
2402
2540
  }
2403
2541
  if (hostConfig && Object.keys(hostConfig).length > 0) return hostConfig;
2404
- return getDefaultHostConfig();
2542
+ return getDefaultHostConfig$1();
2405
2543
  }
2406
2544
  /**
2407
2545
  * Returns the default host config that is used for all qmfe api calls that do not include a host config
2408
2546
  */
2409
- function getDefaultHostConfig$1() {
2410
- return getDefaultHostConfig();
2547
+ function getDefaultHostConfig() {
2548
+ return getDefaultHostConfig$1();
2549
+ }
2550
+ /**
2551
+ * Registers a callback to be invoked when a fatal authentication error occurs for the provided hostConfig.
2552
+ * @param callback The callback function to register
2553
+ * @returns A function to unregister the callback
2554
+ */
2555
+ function onFatalAuthError(hostConfig, callback) {
2556
+ return onFatalAuthError$1(hostConfig, callback);
2557
+ }
2558
+ /**
2559
+ * Registers a listener for page redirect requested by the auth module that is handling authentication for the provided host configuration.
2560
+ * This is typically used when embedded to let the end user explicitly approve a redirect by for instance clicking an "authorize" button. The user can then decide to leave that UI unauthorized
2561
+ * and stay on the page.
2562
+ * The listener is provided a `proceed` function that if called continues the redirect process. Before actually redirecting the page, the onPageRedirectStarted listeners are called.
2563
+ * Note that if more than one listener is registered, it still takes just one proceed call to continue the redirect process so it can not be used to block the redirect.
2564
+ */
2565
+ function onPageRedirectRequested(hostConfig, listener) {
2566
+ return onPageRedirectRequested$1(hostConfig, listener);
2567
+ }
2568
+ /**
2569
+ * Registers a listener that will be called when a page redirect is started by the auth module that is handling authentication for the provided host configuration.
2570
+ */
2571
+ function onPageRedirectStarted(hostConfig, listener) {
2572
+ return onPageRedirectStarted$1(hostConfig, listener);
2573
+ }
2574
+
2575
+ //#endregion
2576
+ //#region src/interceptors/boot-interceptors.ts
2577
+ /**
2578
+ * @internal
2579
+ * The paths expected in the from core-init BFF response.
2580
+ * Exposed for testing.
2581
+ */
2582
+ const coreBootPaths = new Set([
2583
+ "/api/v1/brands/active",
2584
+ "/api/v1/claims/me",
2585
+ "/api/v1/licenses/allotments",
2586
+ "/api/v1/licenses/allotments/me",
2587
+ "/api/v1/licenses/number",
2588
+ "/api/v1/licenses/status",
2589
+ "/api/v1/tenants/me",
2590
+ "/api/v1/users/me",
2591
+ "/api/v1/user-locale"
2592
+ ]);
2593
+ /**
2594
+ * @internal
2595
+ * The path of the core-init BFF response.
2596
+ * Exposed for testing.
2597
+ */
2598
+ const coreBootEndpoint = "/api/v1/boot/core-init";
2599
+ let coreBootPromises = {};
2600
+ let enableDespiteNode = false;
2601
+ function interceptorEnabled() {
2602
+ return !isNode() || enableDespiteNode;
2603
+ }
2604
+ /**
2605
+ * An interceptor that populates the cache from the response of a _backend
2606
+ * for frontend_ endpoint. This endpoint contains the response of the most common
2607
+ * initial calls, mainly from **qmfe-core**.
2608
+ *
2609
+ * If the interceptor finds a matching call it runs once and then removes itself after
2610
+ * populating the cache causing the original request (and following ones) to hit the cache instead.
2611
+ *
2612
+ * The endpoint is implemented in the _customizations_ service and should
2613
+ * contain the responses of the requests specified in 'coreBootPaths'.
2614
+ */
2615
+ const coreBootInterceptor = async (request, proceed) => {
2616
+ if (!interceptorEnabled()) return proceed(request);
2617
+ if (request.pathTemplate !== "/api/v1/features" && !coreBootPaths.has(request.pathTemplate)) return proceed(request);
2618
+ const hostConfig = request.options?.hostConfig;
2619
+ if (hostConfig?.authType === "noauth" || await isWindows(hostConfig) || (await getPlatform({ hostConfig })).isCloudConsole) return proceed(request);
2620
+ const serializedHostConfig = serializeHostConfig$1(request.options?.hostConfig);
2621
+ coreBootPromises[serializedHostConfig] ??= callCoreBootAndFillCache(hostConfig, serializedHostConfig);
2622
+ if (request.pathTemplate !== "/api/v1/features") await coreBootPromises[serializedHostConfig];
2623
+ return proceed(request);
2624
+ };
2625
+ async function callCoreBootAndFillCache(hostConfig, serializedHostConfig) {
2626
+ const bootRequest = {
2627
+ method: "GET",
2628
+ pathTemplate: coreBootEndpoint,
2629
+ options: { hostConfig }
2630
+ };
2631
+ try {
2632
+ const bootResponse = await invokeFetch(".global", bootRequest);
2633
+ const locationUrl = toValidLocationUrl(hostConfig);
2634
+ populateCacheFrom(bootResponse.data, coreBootPaths, serializedHostConfig, locationUrl);
2635
+ } catch (e) {
2636
+ console.error("Failed to bootstrap core-info:", e);
2637
+ }
2638
+ }
2639
+ function populateCacheFrom(responses, pathsToInclude, serializedHostConfig, locationUrl) {
2640
+ if (!responses) return;
2641
+ for (const res of responses) {
2642
+ if (!pathsToInclude.has(res.path)) continue;
2643
+ const completeUrl = locationUrl + res.path;
2644
+ const { status, method, data } = res;
2645
+ if (typeof data === "undefined") continue;
2646
+ if (status && (status < 200 || status >= 300)) continue;
2647
+ const response = Promise.resolve({
2648
+ status: status || 200,
2649
+ data
2650
+ });
2651
+ const cacheKey = toCacheKey({
2652
+ url: completeUrl,
2653
+ serializedHostConfig
2654
+ });
2655
+ updateCache(globalCacheNamespace, {
2656
+ method: method || "GET",
2657
+ completeUrl,
2658
+ cacheKey
2659
+ }, response);
2660
+ }
2411
2661
  }
2412
2662
 
2413
2663
  //#endregion
2414
- export { getPlatform as A, invokeFetch as C, InvokeFetchError as D, EncodingError as E, exposeInternalApiOnWindow as O, clearApiCache as S, appendQueryToUrl as T, unregisterHostConfig$1 as _, getWebResourceAuthParams as a, InvalidHostConfigError as b, isHostCrossOrigin as c, registerAuthModule$1 as d, registerHostConfig$1 as f, toValidWebsocketLocationUrl as g, toValidLocationUrl as h, getRestCallAuthParams as i, generateRandomString as k, isWindows as l, setDefaultHostConfig$1 as m, getAccessToken as n, getWebSocketAuthParams as o, serializeHostConfig$1 as p, getDefaultHostConfig$1 as r, handleAuthenticationError as s, determineAuthType$1 as t, logout as u, AuthorizationError as v, parseFetchResponse as w, UnexpectedAuthTypeError as x, InvalidAuthTypeError as y };
2664
+ //#region src/interceptors/interceptors.ts
2665
+ let GLOBAL_INTERCEPTORS;
2666
+ function createInterceptors() {
2667
+ const interceptors$1 = [...GLOBAL_INTERCEPTORS?.getInterceptors() || []];
2668
+ return {
2669
+ addInterceptor: (interceptor) => {
2670
+ interceptors$1.push(interceptor);
2671
+ return interceptor;
2672
+ },
2673
+ removeInterceptor: (interceptor) => {
2674
+ const index = interceptors$1.indexOf(interceptor);
2675
+ let removed;
2676
+ if (index !== -1) removed = interceptors$1.splice(index, 1)[0];
2677
+ return removed || null;
2678
+ },
2679
+ getInterceptors: () => interceptors$1
2680
+ };
2681
+ }
2682
+ let addDefaultInterceptorsRun = false;
2683
+ function addDefaultInterceptors() {
2684
+ if (addDefaultInterceptorsRun) return;
2685
+ if (isBrowser()) {
2686
+ const readFlagsFromUrlQuery = () => {
2687
+ const featuresParam = new URLSearchParams(window.location.search).get("features");
2688
+ if (!featuresParam) return {};
2689
+ return featuresParam.split(",").map((item) => item.trim()).reduce((map, obj) => {
2690
+ const value = !obj.startsWith("!");
2691
+ const key = value ? obj : obj.substring(1);
2692
+ map[key] = value;
2693
+ return map;
2694
+ }, {});
2695
+ };
2696
+ const readFlagsFromLocalStorage = () => {
2697
+ try {
2698
+ const featuresParam = localStorage.getItem("qcs-features");
2699
+ if (featuresParam) return JSON.parse(featuresParam);
2700
+ return {};
2701
+ } catch {
2702
+ return {};
2703
+ }
2704
+ };
2705
+ const flagsFromUrl = readFlagsFromUrlQuery();
2706
+ const flagsFromLocalStorage = readFlagsFromLocalStorage();
2707
+ const featuresInterceptor = async (request, proceed) => {
2708
+ let resultPromise;
2709
+ if (request.pathTemplate === "/api/v1/features") {
2710
+ resultPromise = proceed(request);
2711
+ const result$1 = await resultPromise;
2712
+ return {
2713
+ ...result$1,
2714
+ data: {
2715
+ ...result$1.data || {},
2716
+ ...flagsFromLocalStorage,
2717
+ ...flagsFromUrl
2718
+ }
2719
+ };
2720
+ }
2721
+ return proceed(request);
2722
+ };
2723
+ GLOBAL_INTERCEPTORS.addInterceptor(featuresInterceptor);
2724
+ GLOBAL_INTERCEPTORS.addInterceptor(coreBootInterceptor);
2725
+ }
2726
+ addDefaultInterceptorsRun = true;
2727
+ }
2728
+ /**
2729
+ * The global interceptor stack
2730
+ */
2731
+ GLOBAL_INTERCEPTORS = createInterceptors();
2732
+ /**
2733
+ * Adds an interceptor to the global interceptor stack
2734
+ * Returns the newly added interceptor
2735
+ * @param interceptor the interceptor to add
2736
+ * @returns the newly added interceptor
2737
+ */
2738
+ function addInterceptor(interceptor) {
2739
+ return GLOBAL_INTERCEPTORS.addInterceptor(interceptor);
2740
+ }
2741
+ /**
2742
+ * Removes an interceptor from the global interceptor stack
2743
+ * @param interceptor the interceptor remove
2744
+ */
2745
+ function removeInterceptor(interceptor) {
2746
+ return GLOBAL_INTERCEPTORS.removeInterceptor(interceptor);
2747
+ }
2748
+ /**
2749
+ * Gets all registered interceptors
2750
+ */
2751
+ function getInterceptors() {
2752
+ return GLOBAL_INTERCEPTORS.getInterceptors();
2753
+ }
2754
+ /**
2755
+ * The interceptors API
2756
+ */
2757
+ const interceptors = {
2758
+ addInterceptor,
2759
+ removeInterceptor,
2760
+ getInterceptors,
2761
+ createInterceptors
2762
+ };
2763
+ var interceptors_default = interceptors;
2764
+
2765
+ //#endregion
2766
+ export { InvalidHostConfigError as A, getPlatform as B, serializeHostConfig as C, unregisterHostConfig as D, toValidWebsocketLocationUrl as E, appendQueryToUrl as F, EncodingError as I, InvokeFetchError as L, clearApiCache as M, invokeFetch as N, AuthorizationError as O, parseFetchResponse as P, exposeInternalApiOnWindow as R, registerHostConfig as S, toValidLocationUrl as T, normalizeHostConfig as _, interceptors_default as a, onPageRedirectStarted as b, getAccessToken as c, getWebResourceAuthParams as d, getWebSocketAuthParams as f, logout as g, isWindows as h, getInterceptors as i, UnexpectedAuthTypeError as j, InvalidAuthTypeError as k, getDefaultHostConfig as l, isHostCrossOrigin as m, addInterceptor as n, removeInterceptor as o, handleAuthenticationError as p, createInterceptors as r, determineAuthType as s, addDefaultInterceptors as t, getRestCallAuthParams as u, onFatalAuthError as v, setDefaultHostConfig as w, registerAuthModule as x, onPageRedirectRequested as y, generateRandomString as z };