@thoughtspot/visual-embed-sdk 1.26.0-token-cache.0 → 1.26.0-token-cache.2

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 (164) hide show
  1. package/cjs/package.json +2 -2
  2. package/cjs/src/auth.d.ts.map +1 -1
  3. package/cjs/src/auth.js.map +1 -1
  4. package/cjs/src/auth.spec.d.ts.map +1 -1
  5. package/cjs/src/auth.spec.js +1 -1
  6. package/cjs/src/auth.spec.js.map +1 -1
  7. package/cjs/src/authToken.d.ts.map +1 -1
  8. package/cjs/src/authToken.js +3 -3
  9. package/cjs/src/authToken.js.map +1 -1
  10. package/cjs/src/embed/base.d.ts +0 -8
  11. package/cjs/src/embed/base.d.ts.map +1 -1
  12. package/cjs/src/embed/base.js +21 -45
  13. package/cjs/src/embed/base.js.map +1 -1
  14. package/cjs/src/embed/base.spec.js +12 -13
  15. package/cjs/src/embed/base.spec.js.map +1 -1
  16. package/cjs/src/embed/embedConfig.d.ts +18 -0
  17. package/cjs/src/embed/embedConfig.d.ts.map +1 -0
  18. package/cjs/src/embed/embedConfig.js +25 -0
  19. package/cjs/src/embed/embedConfig.js.map +1 -0
  20. package/cjs/src/embed/search.d.ts.map +1 -1
  21. package/cjs/src/embed/search.js +3 -2
  22. package/cjs/src/embed/search.js.map +1 -1
  23. package/cjs/src/embed/searchEmbed-basic-auth.spec.js +3 -2
  24. package/cjs/src/embed/searchEmbed-basic-auth.spec.js.map +1 -1
  25. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  26. package/cjs/src/embed/ts-embed.js +2 -1
  27. package/cjs/src/embed/ts-embed.js.map +1 -1
  28. package/cjs/src/embed/ts-embed.spec.js +11 -13
  29. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  30. package/cjs/src/index.d.ts +2 -1
  31. package/cjs/src/index.d.ts.map +1 -1
  32. package/cjs/src/index.js +2 -1
  33. package/cjs/src/index.js.map +1 -1
  34. package/cjs/src/tokenizedFetch.d.ts.map +1 -1
  35. package/cjs/src/tokenizedFetch.js +4 -4
  36. package/cjs/src/tokenizedFetch.js.map +1 -1
  37. package/cjs/src/utils/authService/authService.d.ts +45 -0
  38. package/cjs/src/utils/authService/authService.d.ts.map +1 -0
  39. package/cjs/src/utils/authService/authService.js +115 -0
  40. package/cjs/src/utils/authService/authService.js.map +1 -0
  41. package/cjs/src/utils/authService/authService.spec.d.ts +2 -0
  42. package/cjs/src/utils/authService/authService.spec.d.ts.map +1 -0
  43. package/cjs/src/utils/authService/authService.spec.js +82 -0
  44. package/cjs/src/utils/authService/authService.spec.js.map +1 -0
  45. package/cjs/src/utils/authService/index.d.ts +3 -0
  46. package/cjs/src/utils/authService/index.d.ts.map +1 -0
  47. package/cjs/src/utils/authService/index.js +14 -0
  48. package/cjs/src/utils/authService/index.js.map +1 -0
  49. package/cjs/src/utils/authService/tokenisedAuthSerice.d.ts +11 -0
  50. package/cjs/src/utils/authService/tokenisedAuthSerice.d.ts.map +1 -0
  51. package/cjs/src/utils/authService/tokenisedAuthSerice.js +44 -0
  52. package/cjs/src/utils/authService/tokenisedAuthSerice.js.map +1 -0
  53. package/cjs/src/utils/graphql/answerService/answerService.spec.js +2 -2
  54. package/cjs/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
  55. package/cjs/src/utils/processData.js +4 -3
  56. package/cjs/src/utils/processData.js.map +1 -1
  57. package/cjs/src/utils/processData.spec.js +8 -7
  58. package/cjs/src/utils/processData.spec.js.map +1 -1
  59. package/dist/src/auth.d.ts.map +1 -1
  60. package/dist/src/auth.spec.d.ts.map +1 -1
  61. package/dist/src/authToken.d.ts.map +1 -1
  62. package/dist/src/embed/base.d.ts +0 -8
  63. package/dist/src/embed/base.d.ts.map +1 -1
  64. package/dist/src/embed/embedConfig.d.ts +18 -0
  65. package/dist/src/embed/embedConfig.d.ts.map +1 -0
  66. package/dist/src/embed/search.d.ts.map +1 -1
  67. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  68. package/dist/src/index.d.ts +2 -1
  69. package/dist/src/index.d.ts.map +1 -1
  70. package/dist/src/tokenizedFetch.d.ts.map +1 -1
  71. package/dist/src/utils/authService/authService.d.ts +45 -0
  72. package/dist/src/utils/authService/authService.d.ts.map +1 -0
  73. package/dist/src/utils/authService/authService.spec.d.ts +2 -0
  74. package/dist/src/utils/authService/authService.spec.d.ts.map +1 -0
  75. package/dist/src/utils/authService/index.d.ts +3 -0
  76. package/dist/src/utils/authService/index.d.ts.map +1 -0
  77. package/dist/src/utils/authService/tokenisedAuthSerice.d.ts +11 -0
  78. package/dist/src/utils/authService/tokenisedAuthSerice.d.ts.map +1 -0
  79. package/dist/tsembed-react.es.js +1228 -1212
  80. package/dist/tsembed-react.js +1463 -1447
  81. package/dist/tsembed.es.js +1632 -1621
  82. package/dist/tsembed.js +1622 -1611
  83. package/dist/visual-embed-sdk-react-full.d.ts +17 -8
  84. package/dist/visual-embed-sdk-react.d.ts +17 -8
  85. package/dist/visual-embed-sdk.d.ts +17 -8
  86. package/lib/package.json +2 -2
  87. package/lib/src/auth.d.ts.map +1 -1
  88. package/lib/src/auth.js.map +1 -1
  89. package/lib/src/auth.spec.d.ts.map +1 -1
  90. package/lib/src/auth.spec.js +1 -1
  91. package/lib/src/auth.spec.js.map +1 -1
  92. package/lib/src/authToken.d.ts.map +1 -1
  93. package/lib/src/authToken.js +3 -3
  94. package/lib/src/authToken.js.map +1 -1
  95. package/lib/src/embed/base.d.ts +0 -8
  96. package/lib/src/embed/base.d.ts.map +1 -1
  97. package/lib/src/embed/base.js +20 -43
  98. package/lib/src/embed/base.js.map +1 -1
  99. package/lib/src/embed/base.spec.js +12 -13
  100. package/lib/src/embed/base.spec.js.map +1 -1
  101. package/lib/src/embed/embedConfig.d.ts +18 -0
  102. package/lib/src/embed/embedConfig.d.ts.map +1 -0
  103. package/lib/src/embed/embedConfig.js +20 -0
  104. package/lib/src/embed/embedConfig.js.map +1 -0
  105. package/lib/src/embed/search.d.ts.map +1 -1
  106. package/lib/src/embed/search.js +2 -1
  107. package/lib/src/embed/search.js.map +1 -1
  108. package/lib/src/embed/searchEmbed-basic-auth.spec.js +3 -2
  109. package/lib/src/embed/searchEmbed-basic-auth.spec.js.map +1 -1
  110. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  111. package/lib/src/embed/ts-embed.js +2 -1
  112. package/lib/src/embed/ts-embed.js.map +1 -1
  113. package/lib/src/embed/ts-embed.spec.js +11 -13
  114. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  115. package/lib/src/index.d.ts +2 -1
  116. package/lib/src/index.d.ts.map +1 -1
  117. package/lib/src/index.js +2 -1
  118. package/lib/src/index.js.map +1 -1
  119. package/lib/src/tokenizedFetch.d.ts.map +1 -1
  120. package/lib/src/tokenizedFetch.js +3 -3
  121. package/lib/src/tokenizedFetch.js.map +1 -1
  122. package/lib/src/utils/authService/authService.d.ts +45 -0
  123. package/lib/src/utils/authService/authService.d.ts.map +1 -0
  124. package/lib/src/utils/authService/authService.js +107 -0
  125. package/lib/src/utils/authService/authService.js.map +1 -0
  126. package/lib/src/utils/authService/authService.spec.d.ts +2 -0
  127. package/lib/src/utils/authService/authService.spec.d.ts.map +1 -0
  128. package/lib/src/utils/authService/authService.spec.js +80 -0
  129. package/lib/src/utils/authService/authService.spec.js.map +1 -0
  130. package/lib/src/utils/authService/index.d.ts +3 -0
  131. package/lib/src/utils/authService/index.d.ts.map +1 -0
  132. package/lib/src/utils/authService/index.js +3 -0
  133. package/lib/src/utils/authService/index.js.map +1 -0
  134. package/lib/src/utils/authService/tokenisedAuthSerice.d.ts +11 -0
  135. package/lib/src/utils/authService/tokenisedAuthSerice.d.ts.map +1 -0
  136. package/lib/src/utils/authService/tokenisedAuthSerice.js +39 -0
  137. package/lib/src/utils/authService/tokenisedAuthSerice.js.map +1 -0
  138. package/lib/src/utils/graphql/answerService/answerService.spec.js +2 -2
  139. package/lib/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
  140. package/lib/src/utils/processData.js +2 -1
  141. package/lib/src/utils/processData.js.map +1 -1
  142. package/lib/src/utils/processData.spec.js +8 -7
  143. package/lib/src/utils/processData.spec.js.map +1 -1
  144. package/lib/src/visual-embed-sdk.d.ts +22 -9
  145. package/package.json +2 -2
  146. package/src/auth.spec.ts +29 -28
  147. package/src/auth.ts +1 -5
  148. package/src/authToken.ts +11 -3
  149. package/src/embed/base.spec.ts +13 -13
  150. package/src/embed/base.ts +26 -50
  151. package/src/embed/embedConfig.ts +23 -0
  152. package/src/embed/search.ts +9 -10
  153. package/src/embed/searchEmbed-basic-auth.spec.ts +3 -2
  154. package/src/embed/ts-embed.spec.ts +34 -36
  155. package/src/embed/ts-embed.ts +9 -19
  156. package/src/index.ts +8 -2
  157. package/src/tokenizedFetch.ts +6 -4
  158. package/src/utils/{authService.spec.ts → authService/authService.spec.ts} +1 -1
  159. package/src/utils/{authService.ts → authService/authService.ts} +0 -24
  160. package/src/utils/authService/index.ts +9 -0
  161. package/src/utils/authService/tokenisedAuthSerice.ts +40 -0
  162. package/src/utils/graphql/answerService/answerService.spec.ts +2 -2
  163. package/src/utils/processData.spec.ts +19 -16
  164. package/src/utils/processData.ts +1 -1
@@ -5059,15 +5059,6 @@
5059
5059
  return r;
5060
5060
  });
5061
5061
  }
5062
- /**
5063
- *
5064
- * @param authVerificationUrl
5065
- */
5066
- function fetchSessionInfoService(authVerificationUrl) {
5067
- return failureLoggedFetch(authVerificationUrl, {
5068
- credentials: 'include',
5069
- });
5070
- }
5071
5062
  /**
5072
5063
  * Service to validate a auth token against a ThoughtSpot host.
5073
5064
  *
@@ -5150,6 +5141,53 @@
5150
5141
  });
5151
5142
  }
5152
5143
 
5144
+ let config = {};
5145
+ /**
5146
+ * Gets the configuration embed was initialized with.
5147
+ *
5148
+ * @returns {@link EmbedConfig} The configuration embed was initialized with.
5149
+ * @version SDK: 1.19.0 | ThoughtSpot: *
5150
+ * @group Global methods
5151
+ */
5152
+ const getEmbedConfig = () => config;
5153
+
5154
+ const tokenizedFetch = async (input, init) => {
5155
+ const embedConfig = getEmbedConfig();
5156
+ if (embedConfig.authType !== AuthType.TrustedAuthTokenCookieless) {
5157
+ return fetch(input, init);
5158
+ }
5159
+ const req = new Request(input, init);
5160
+ const authToken = await getAuthenticationToken(embedConfig);
5161
+ if (authToken) {
5162
+ req.headers.append('Authorization', `Bearer ${authToken}`);
5163
+ }
5164
+ return fetch(req);
5165
+ };
5166
+
5167
+ /**
5168
+ *
5169
+ * @param url
5170
+ * @param options
5171
+ */
5172
+ function tokenisedFailureLoggedFetch(url, options = {}) {
5173
+ return tokenizedFetch(url, options).then(async (r) => {
5174
+ var _a;
5175
+ if (!r.ok && r.type !== 'opaqueredirect' && r.type !== 'opaque') {
5176
+ console.error('Failure', await ((_a = r.text) === null || _a === void 0 ? void 0 : _a.call(r)));
5177
+ }
5178
+ return r;
5179
+ });
5180
+ }
5181
+ /**
5182
+ *
5183
+ * @param authVerificationUrl
5184
+ */
5185
+ function fetchSessionInfoService(authVerificationUrl) {
5186
+ return tokenisedFailureLoggedFetch(authVerificationUrl, {
5187
+ credentials: 'include',
5188
+ });
5189
+ }
5190
+
5153
5191
  const DUPLICATE_TOKEN_ERR = 'Duplicate token, please issue a new token every time getAuthToken callback is called.'
5154
5192
  + 'See https://developers.thoughtspot.com/docs/?pageid=embed-auth#trusted-auth-embed for more details.';
5155
5193
  const INVALID_TOKEN_ERR = 'Invalid token received form token callback or authToken endpoint.';
@@ -5158,7 +5196,7 @@
5158
5196
  const getAuthenticationToken = async (embedConfig) => {
5159
5197
  if (cachedAuthToken) {
5160
5198
  try {
5161
- const isCachedTokenStillValid = await validateAuthToken(embedConfig, cachedAuthToken);
5199
+ const isCachedTokenStillValid = await validateAuthToken(embedConfig, cachedAuthToken, true);
5162
5200
  if (isCachedTokenStillValid)
5163
5201
  return cachedAuthToken;
5164
5202
  }
@@ -5180,7 +5218,7 @@
5180
5218
  cachedAuthToken = authToken;
5181
5219
  return authToken;
5182
5220
  };
5183
- const validateAuthToken = async (embedConfig, authToken) => {
5221
+ const validateAuthToken = async (embedConfig, authToken, suppressAlert) => {
5184
5222
  try {
5185
5223
  const isTokenValid = await verifyTokenService(embedConfig.thoughtSpotHost, authToken);
5186
5224
  if (isTokenValid)
@@ -5190,7 +5228,7 @@
5190
5228
  return false;
5191
5229
  }
5192
5230
  if (cachedAuthToken && cachedAuthToken === authToken) {
5193
- if (!embedConfig.suppressErrorAlerts) {
5231
+ if (!embedConfig.suppressErrorAlerts && !suppressAlert) {
5194
5232
  // eslint-disable-next-line no-alert
5195
5233
  alert(DUPLICATE_TOKEN_ERR);
5196
5234
  }
@@ -5201,623 +5239,634 @@
5201
5239
  }
5202
5240
  };
5203
5241
 
5204
- var eventemitter3 = createCommonjsModule(function (module) {
5205
-
5206
- var has = Object.prototype.hasOwnProperty
5207
- , prefix = '~';
5208
-
5209
- /**
5210
- * Constructor to create a storage for our `EE` objects.
5211
- * An `Events` instance is a plain object whose properties are event names.
5212
- *
5213
- * @constructor
5214
- * @private
5215
- */
5216
- function Events() {}
5217
-
5218
- //
5219
- // We try to not inherit from `Object.prototype`. In some engines creating an
5220
- // instance in this way is faster than calling `Object.create(null)` directly.
5221
- // If `Object.create(null)` is not supported we prefix the event names with a
5222
- // character to make sure that the built-in object properties are not
5223
- // overridden or used as an attack vector.
5224
- //
5225
- if (Object.create) {
5226
- Events.prototype = Object.create(null);
5227
-
5228
- //
5229
- // This hack is needed because the `__proto__` property is still inherited in
5230
- // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.
5231
- //
5232
- if (!new Events().__proto__) prefix = false;
5233
- }
5234
-
5235
- /**
5236
- * Representation of a single event listener.
5237
- *
5238
- * @param {Function} fn The listener function.
5239
- * @param {*} context The context to invoke the listener with.
5240
- * @param {Boolean} [once=false] Specify if the listener is a one-time listener.
5241
- * @constructor
5242
- * @private
5243
- */
5244
- function EE(fn, context, once) {
5245
- this.fn = fn;
5246
- this.context = context;
5247
- this.once = once || false;
5248
- }
5249
-
5250
- /**
5251
- * Add a listener for a given event.
5252
- *
5253
- * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
5254
- * @param {(String|Symbol)} event The event name.
5255
- * @param {Function} fn The listener function.
5256
- * @param {*} context The context to invoke the listener with.
5257
- * @param {Boolean} once Specify if the listener is a one-time listener.
5258
- * @returns {EventEmitter}
5259
- * @private
5260
- */
5261
- function addListener(emitter, event, fn, context, once) {
5262
- if (typeof fn !== 'function') {
5263
- throw new TypeError('The listener must be a function');
5264
- }
5265
-
5266
- var listener = new EE(fn, context || emitter, once)
5267
- , evt = prefix ? prefix + event : event;
5268
-
5269
- if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;
5270
- else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);
5271
- else emitter._events[evt] = [emitter._events[evt], listener];
5272
-
5273
- return emitter;
5274
- }
5275
-
5276
- /**
5277
- * Clear event by name.
5278
- *
5279
- * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
5280
- * @param {(String|Symbol)} evt The Event name.
5281
- * @private
5282
- */
5283
- function clearEvent(emitter, evt) {
5284
- if (--emitter._eventsCount === 0) emitter._events = new Events();
5285
- else delete emitter._events[evt];
5242
+ /**
5243
+ *
5244
+ * @param root0
5245
+ * @param root0.query
5246
+ * @param root0.variables
5247
+ * @param root0.thoughtSpotHost
5248
+ * @param root0.isCompositeQuery
5249
+ */
5250
+ async function graphqlQuery({ query, variables, thoughtSpotHost, isCompositeQuery = false, }) {
5251
+ const operationName = getOperationNameFromQuery(query);
5252
+ try {
5253
+ const response = await fetch(`${thoughtSpotHost}/prism/?op=${operationName}`, {
5254
+ method: 'POST',
5255
+ headers: {
5256
+ 'content-type': 'application/json;charset=UTF-8',
5257
+ 'x-requested-by': 'ThoughtSpot',
5258
+ accept: '*/*',
5259
+ 'accept-language': 'en-us',
5260
+ },
5261
+ body: JSON.stringify({
5262
+ operationName,
5263
+ query,
5264
+ variables,
5265
+ }),
5266
+ credentials: 'include',
5267
+ });
5268
+ const result = await response.json();
5269
+ const dataValues = Object.values(result.data);
5270
+ return (isCompositeQuery) ? result.data : dataValues[0];
5271
+ }
5272
+ catch (error) {
5273
+ return error;
5274
+ }
5286
5275
  }
5287
5276
 
5288
- /**
5289
- * Minimal `EventEmitter` interface that is molded against the Node.js
5290
- * `EventEmitter` interface.
5291
- *
5292
- * @constructor
5293
- * @public
5294
- */
5295
- function EventEmitter() {
5296
- this._events = new Events();
5297
- this._eventsCount = 0;
5277
+ const getSourceDetailQuery = `
5278
+ query GetSourceDetail($ids: [GUID!]!) {
5279
+ getSourceDetailById(ids: $ids, type: LOGICAL_TABLE) {
5280
+ id
5281
+ name
5282
+ description
5283
+ authorName
5284
+ authorDisplayName
5285
+ isExternal
5286
+ type
5287
+ created
5288
+ modified
5289
+ columns {
5290
+ id
5291
+ name
5292
+ author
5293
+ authorDisplayName
5294
+ description
5295
+ dataType
5296
+ type
5297
+ modified
5298
+ ownerName
5299
+ owner
5300
+ dataRecency
5301
+ sources {
5302
+ tableId
5303
+ tableName
5304
+ columnId
5305
+ columnName
5306
+ __typename
5307
+ }
5308
+ synonyms
5309
+ cohortAnswerId
5310
+ __typename
5311
+ }
5312
+ relationships
5313
+ destinationRelationships
5314
+ dataSourceId
5315
+ __typename
5316
+ }
5317
+ }
5318
+ `;
5319
+ const sourceDetailCache = new Map();
5320
+ /**
5321
+ *
5322
+ * @param thoughtSpotHost
5323
+ * @param sourceId
5324
+ */
5325
+ async function getSourceDetail(thoughtSpotHost, sourceId) {
5326
+ if (sourceDetailCache.get(sourceId)) {
5327
+ return sourceDetailCache.get(sourceId);
5328
+ }
5329
+ const details = await graphqlQuery({
5330
+ query: getSourceDetailQuery,
5331
+ variables: {
5332
+ ids: [sourceId],
5333
+ },
5334
+ thoughtSpotHost,
5335
+ });
5336
+ const souceDetails = details[0];
5337
+ if (souceDetails) {
5338
+ sourceDetailCache.set(sourceId, souceDetails);
5339
+ }
5340
+ return souceDetails;
5298
5341
  }
5299
5342
 
5300
- /**
5301
- * Return an array listing the events for which the emitter has registered
5302
- * listeners.
5303
- *
5304
- * @returns {Array}
5305
- * @public
5306
- */
5307
- EventEmitter.prototype.eventNames = function eventNames() {
5308
- var names = []
5309
- , events
5310
- , name;
5311
-
5312
- if (this._eventsCount === 0) return names;
5313
-
5314
- for (name in (events = this._events)) {
5315
- if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
5316
- }
5317
-
5318
- if (Object.getOwnPropertySymbols) {
5319
- return names.concat(Object.getOwnPropertySymbols(events));
5320
- }
5321
-
5322
- return names;
5323
- };
5324
-
5325
- /**
5326
- * Return the listeners registered for a given event.
5327
- *
5328
- * @param {(String|Symbol)} event The event name.
5329
- * @returns {Array} The registered listeners.
5330
- * @public
5331
- */
5332
- EventEmitter.prototype.listeners = function listeners(event) {
5333
- var evt = prefix ? prefix + event : event
5334
- , handlers = this._events[evt];
5335
-
5336
- if (!handlers) return [];
5337
- if (handlers.fn) return [handlers.fn];
5338
-
5339
- for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {
5340
- ee[i] = handlers[i].fn;
5341
- }
5342
-
5343
- return ee;
5344
- };
5345
-
5346
- /**
5347
- * Return the number of listeners listening to a given event.
5348
- *
5349
- * @param {(String|Symbol)} event The event name.
5350
- * @returns {Number} The number of listeners.
5351
- * @public
5352
- */
5353
- EventEmitter.prototype.listenerCount = function listenerCount(event) {
5354
- var evt = prefix ? prefix + event : event
5355
- , listeners = this._events[evt];
5356
-
5357
- if (!listeners) return 0;
5358
- if (listeners.fn) return 1;
5359
- return listeners.length;
5360
- };
5361
-
5362
- /**
5363
- * Calls each of the listeners registered for a given event.
5364
- *
5365
- * @param {(String|Symbol)} event The event name.
5366
- * @returns {Boolean} `true` if the event had listeners, else `false`.
5367
- * @public
5368
- */
5369
- EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
5370
- var evt = prefix ? prefix + event : event;
5371
-
5372
- if (!this._events[evt]) return false;
5373
-
5374
- var listeners = this._events[evt]
5375
- , len = arguments.length
5376
- , args
5377
- , i;
5378
-
5379
- if (listeners.fn) {
5380
- if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);
5381
-
5382
- switch (len) {
5383
- case 1: return listeners.fn.call(listeners.context), true;
5384
- case 2: return listeners.fn.call(listeners.context, a1), true;
5385
- case 3: return listeners.fn.call(listeners.context, a1, a2), true;
5386
- case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;
5387
- case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
5388
- case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
5389
- }
5390
-
5391
- for (i = 1, args = new Array(len -1); i < len; i++) {
5392
- args[i - 1] = arguments[i];
5393
- }
5394
-
5395
- listeners.fn.apply(listeners.context, args);
5396
- } else {
5397
- var length = listeners.length
5398
- , j;
5399
-
5400
- for (i = 0; i < length; i++) {
5401
- if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);
5402
-
5403
- switch (len) {
5404
- case 1: listeners[i].fn.call(listeners[i].context); break;
5405
- case 2: listeners[i].fn.call(listeners[i].context, a1); break;
5406
- case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;
5407
- case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;
5408
- default:
5409
- if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {
5410
- args[j - 1] = arguments[j];
5411
- }
5412
-
5413
- listeners[i].fn.apply(listeners[i].context, args);
5414
- }
5415
- }
5416
- }
5417
-
5418
- return true;
5419
- };
5420
-
5421
- /**
5422
- * Add a listener for a given event.
5423
- *
5424
- * @param {(String|Symbol)} event The event name.
5425
- * @param {Function} fn The listener function.
5426
- * @param {*} [context=this] The context to invoke the listener with.
5427
- * @returns {EventEmitter} `this`.
5428
- * @public
5429
- */
5430
- EventEmitter.prototype.on = function on(event, fn, context) {
5431
- return addListener(this, event, fn, context, false);
5432
- };
5433
-
5434
- /**
5435
- * Add a one-time listener for a given event.
5436
- *
5437
- * @param {(String|Symbol)} event The event name.
5438
- * @param {Function} fn The listener function.
5439
- * @param {*} [context=this] The context to invoke the listener with.
5440
- * @returns {EventEmitter} `this`.
5441
- * @public
5442
- */
5443
- EventEmitter.prototype.once = function once(event, fn, context) {
5444
- return addListener(this, event, fn, context, true);
5445
- };
5446
-
5447
- /**
5448
- * Remove the listeners of a given event.
5449
- *
5450
- * @param {(String|Symbol)} event The event name.
5451
- * @param {Function} fn Only remove the listeners that match this function.
5452
- * @param {*} context Only remove the listeners that have this context.
5453
- * @param {Boolean} once Only remove one-time listeners.
5454
- * @returns {EventEmitter} `this`.
5455
- * @public
5456
- */
5457
- EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
5458
- var evt = prefix ? prefix + event : event;
5459
-
5460
- if (!this._events[evt]) return this;
5461
- if (!fn) {
5462
- clearEvent(this, evt);
5463
- return this;
5464
- }
5465
-
5466
- var listeners = this._events[evt];
5467
-
5468
- if (listeners.fn) {
5469
- if (
5470
- listeners.fn === fn &&
5471
- (!once || listeners.once) &&
5472
- (!context || listeners.context === context)
5473
- ) {
5474
- clearEvent(this, evt);
5475
- }
5476
- } else {
5477
- for (var i = 0, events = [], length = listeners.length; i < length; i++) {
5478
- if (
5479
- listeners[i].fn !== fn ||
5480
- (once && !listeners[i].once) ||
5481
- (context && listeners[i].context !== context)
5482
- ) {
5483
- events.push(listeners[i]);
5484
- }
5485
- }
5486
-
5487
- //
5488
- // Reset the array, or remove it completely if we have no more listeners.
5489
- //
5490
- if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;
5491
- else clearEvent(this, evt);
5492
- }
5493
-
5494
- return this;
5495
- };
5343
+ const bachSessionId = `
5344
+ id {
5345
+ sessionId
5346
+ genNo
5347
+ acSession {
5348
+ sessionId
5349
+ genNo
5350
+ }
5351
+ }
5352
+ `;
5353
+ const getUnaggregatedAnswerSession = `
5354
+ mutation GetUnAggregatedAnswerSession($session: BachSessionIdInput!, $columns: [UserPointSelectionInput!]!) {
5355
+ Answer__getUnaggregatedAnswer(session: $session, columns: $columns) {
5356
+ ${bachSessionId}
5357
+ answer {
5358
+ visualizations {
5359
+ ... on TableViz {
5360
+ columns {
5361
+ column {
5362
+ id
5363
+ name
5364
+ referencedColumns {
5365
+ guid
5366
+ displayName
5367
+ }
5368
+ }
5369
+ }
5370
+ }
5371
+ }
5372
+ }
5373
+ }
5374
+ }
5375
+ `;
5376
+ const removeColumns = `
5377
+ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!], $columnIds: [GUID!]) {
5378
+ Answer__removeColumns(
5379
+ session: $session
5380
+ logicalColumnIds: $logicalColumnIds
5381
+ columnIds: $columnIds
5382
+ ) {
5383
+ ${bachSessionId}
5384
+ }
5385
+ }
5386
+ `;
5387
+ const addColumns = `
5388
+ mutation AddColumns($session: BachSessionIdInput!, $columns: [AnswerColumnInfo!]!) {
5389
+ Answer__addColumn(session: $session, columns: $columns) {
5390
+ ${bachSessionId}
5391
+ }
5392
+ }
5393
+ `;
5394
+ const getAnswerData = `
5395
+ query GetTableWithHeadlineData($session: BachSessionIdInput!, $deadline: Int!, $dataPaginationParams: DataPaginationParamsInput!) {
5396
+ getAnswer(session: $session) {
5397
+ ${bachSessionId}
5398
+ answer {
5399
+ id
5400
+ visualizations {
5401
+ id
5402
+ ... on TableViz {
5403
+ columns {
5404
+ column {
5405
+ id
5406
+ name
5407
+ type
5408
+ aggregationType
5409
+ dataType
5410
+ }
5411
+ }
5412
+ data(deadline: $deadline, pagination: $dataPaginationParams)
5413
+ }
5414
+ }
5415
+ }
5416
+ }
5417
+ }
5418
+ `;
5496
5419
 
5497
- /**
5498
- * Remove all listeners, or those of the specified event.
5499
- *
5500
- * @param {(String|Symbol)} [event] The event name.
5501
- * @returns {EventEmitter} `this`.
5502
- * @public
5503
- */
5504
- EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
5505
- var evt;
5506
-
5507
- if (event) {
5508
- evt = prefix ? prefix + event : event;
5509
- if (this._events[evt]) clearEvent(this, evt);
5510
- } else {
5511
- this._events = new Events();
5512
- this._eventsCount = 0;
5513
- }
5514
-
5515
- return this;
5516
- };
5517
-
5518
- //
5519
- // Alias methods names because people roll like that.
5520
- //
5521
- EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
5522
- EventEmitter.prototype.addListener = EventEmitter.prototype.on;
5523
-
5524
- //
5525
- // Expose the prefix.
5526
- //
5527
- EventEmitter.prefixed = prefix;
5528
-
5529
- //
5530
- // Allow `EventEmitter` to be imported as module namespace.
5531
- //
5532
- EventEmitter.EventEmitter = EventEmitter;
5533
-
5534
- //
5535
- // Expose the module.
5536
- //
5537
- {
5538
- module.exports = EventEmitter;
5539
- }
5540
- });
5541
-
5542
- /**
5543
- * This method returns `undefined`.
5544
- *
5545
- * @static
5546
- * @memberOf _
5547
- * @since 2.3.0
5548
- * @category Util
5549
- * @example
5550
- *
5551
- * _.times(2, _.noop);
5552
- * // => [undefined, undefined]
5553
- */
5554
- function noop() {
5555
- // No operation performed.
5556
- }
5557
-
5558
- var noop_1 = noop;
5559
-
5560
- /** Used as references for various `Number` constants. */
5561
- var INFINITY = 1 / 0;
5562
-
5563
- /**
5564
- * Creates a set object of `values`.
5565
- *
5566
- * @private
5567
- * @param {Array} values The values to add to the set.
5568
- * @returns {Object} Returns the new set.
5569
- */
5570
- var createSet = !(_Set && (1 / _setToArray(new _Set([,-0]))[1]) == INFINITY) ? noop_1 : function(values) {
5571
- return new _Set(values);
5572
- };
5573
-
5574
- const ERROR_MESSAGE = {
5575
- INVALID_THOUGHTSPOT_HOST: 'Error parsing ThoughtSpot host. Please provide a valid URL.',
5576
- LIVEBOARD_VIZ_ID_VALIDATION: 'Please provide either liveboardId or pinboardId',
5577
- TRIGGER_TIMED_OUT: 'Trigger timedout in getting response',
5578
- SEARCHEMBED_BETA_WRANING_MESSAGE: 'Search Embed is in Beta in this release.',
5579
- SAGE_EMBED_BETA_WARNING_MESSAGE: 'Sage Embed is in Beta in this release.',
5580
- };
5581
-
5582
- /**
5583
- * Copyright (c) 2023
5584
- *
5585
- * Utilities related to reading configuration objects
5586
- *
5587
- * @summary Config-related utils
5588
- * @author Ayon Ghosh <ayon.ghosh@thoughtspot.com>
5589
- */
5590
- const urlRegex = new RegExp([
5591
- '(^(https?:)//)?',
5592
- '(([^:/?#]*)(?::([0-9]+))?)',
5593
- '(/{0,1}[^?#]*)',
5594
- '(\\?[^#]*|)',
5595
- '(#.*|)$', // hash
5596
- ].join(''));
5420
+ // eslint-disable-next-line no-shadow
5421
+ var OperationType;
5422
+ (function (OperationType) {
5423
+ OperationType["GetChartWithData"] = "GetChartWithData";
5424
+ OperationType["GetTableWithHeadlineData"] = "GetTableWithHeadlineData";
5425
+ })(OperationType || (OperationType = {}));
5597
5426
  /**
5598
- * Parse and construct the ThoughtSpot hostname or IP address
5599
- * from the embed configuration object.
5427
+ * Class representing the answer service provided with the
5428
+ * custom action payload. This service could be used to run
5429
+ * graphql queries in the context of the answer on which the
5430
+ * custom action was triggered.
5600
5431
  *
5601
- * @param config
5432
+ * @example
5433
+ * ```js
5434
+ * embed.on(EmbedEvent.CustomAction, e => {
5435
+ * const underlying = await e.answerService.getUnderlyingDataForPoint([
5436
+ * 'col name 1'
5437
+ * ]);
5438
+ * const data = await underlying.fetchData(0, 100);
5439
+ * })
5440
+ * ```
5441
+ * @version
5442
+ * ThoughtSpot: 9.9.0.cl / SDK: 1.25.0
5443
+ * @group Events
5602
5444
  */
5603
- const getThoughtSpotHost = (config) => {
5604
- if (!config.thoughtSpotHost) {
5605
- throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
5445
+ class AnswerService {
5446
+ constructor(session, answer, thoughtSpotHost, selectedPoints) {
5447
+ this.session = session;
5448
+ this.answer = answer;
5449
+ this.thoughtSpotHost = thoughtSpotHost;
5450
+ this.selectedPoints = selectedPoints;
5451
+ this.session = removeTypename(session);
5606
5452
  }
5607
- const urlParts = config.thoughtSpotHost.match(urlRegex);
5608
- if (!urlParts) {
5609
- throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
5453
+ async getSourceDetail() {
5454
+ const sourceId = this.answer.sources[0].header.guid;
5455
+ return getSourceDetail(this.thoughtSpotHost, sourceId);
5610
5456
  }
5611
- const protocol = urlParts[2] || window.location.protocol;
5612
- const host = urlParts[3];
5613
- let path = urlParts[6];
5614
- // Lose the trailing / if any
5615
- if (path.charAt(path.length - 1) === '/') {
5616
- path = path.substring(0, path.length - 1);
5457
+ async removeColumns(columnIds) {
5458
+ return this.executeQuery(removeColumns, {
5459
+ logicalColumnIds: columnIds,
5460
+ });
5617
5461
  }
5618
- // const urlParams = urlParts[7];
5619
- // const hash = urlParts[8];
5620
- return `${protocol}//${host}${path}`;
5621
- };
5622
- const getV2BasePath = (config) => {
5623
- if (config.basepath) {
5624
- return config.basepath;
5462
+ async addColumns(columnIds) {
5463
+ return this.executeQuery(addColumns, {
5464
+ columns: columnIds.map((colId) => ({ logicalColumnId: colId })),
5465
+ });
5625
5466
  }
5626
- const tsHost = getThoughtSpotHost(config);
5627
- // This is to handle when e2e's. Search is run on pods for
5628
- // comp-blink-test-pipeline with baseUrl=https://localhost:8443.
5629
- // This is to handle when the developer is developing in their local
5630
- // environment.
5631
- if (tsHost.includes('://localhost') && !tsHost.includes(':8443')) {
5632
- return '';
5467
+ async fetchData(offset = 0, size = 1000) {
5468
+ const { answer } = await this.executeQuery(getAnswerData, {
5469
+ deadline: 0,
5470
+ dataPaginationParams: {
5471
+ isClientPaginated: true,
5472
+ offset,
5473
+ size,
5474
+ },
5475
+ });
5476
+ const { columns, data } = answer.visualizations[0];
5477
+ return {
5478
+ columns,
5479
+ data,
5480
+ };
5633
5481
  }
5634
- return 'v2';
5635
- };
5636
- /**
5637
- * It is a good idea to keep URLs under 2000 chars.
5638
- * If this is ever breached, since we pass view configuration through
5639
- * URL params, we would like to log a warning.
5640
- * Reference: https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
5641
- */
5642
- const URL_MAX_LENGTH = 2000;
5643
- /**
5644
- * The default CSS dimensions of the embedded app
5645
- */
5646
- const DEFAULT_EMBED_WIDTH = '100%';
5647
- const DEFAULT_EMBED_HEIGHT = '100%';
5648
-
5649
- var Config = {
5650
- DEBUG: false,
5651
- LIB_VERSION: '2.45.0'
5652
- };
5653
-
5654
- // since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
5655
- var window$1;
5656
- if (typeof(window) === 'undefined') {
5657
- var loc = {
5658
- hostname: ''
5659
- };
5660
- window$1 = {
5661
- navigator: { userAgent: '' },
5662
- document: {
5663
- location: loc,
5664
- referrer: ''
5665
- },
5666
- screen: { width: 0, height: 0 },
5667
- location: loc
5668
- };
5669
- } else {
5670
- window$1 = window;
5671
- }
5672
-
5673
- /*
5674
- * Saved references to long variable names, so that closure compiler can
5675
- * minimize file size.
5676
- */
5677
-
5678
- var ArrayProto = Array.prototype;
5679
- var FuncProto = Function.prototype;
5680
- var ObjProto = Object.prototype;
5681
- var slice = ArrayProto.slice;
5682
- var toString = ObjProto.toString;
5683
- var hasOwnProperty$9 = ObjProto.hasOwnProperty;
5684
- var windowConsole = window$1.console;
5685
- var navigator = window$1.navigator;
5686
- var document$1 = window$1.document;
5687
- var windowOpera = window$1.opera;
5688
- var screen = window$1.screen;
5689
- var userAgent = navigator.userAgent;
5690
- var nativeBind = FuncProto.bind;
5691
- var nativeForEach = ArrayProto.forEach;
5692
- var nativeIndexOf = ArrayProto.indexOf;
5693
- var nativeMap = ArrayProto.map;
5694
- var nativeIsArray = Array.isArray;
5695
- var breaker = {};
5696
- var _ = {
5697
- trim: function(str) {
5698
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim#Polyfill
5699
- return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
5700
- }
5701
- };
5702
-
5703
- // Console override
5704
- var console$1 = {
5705
- /** @type {function(...*)} */
5706
- log: function() {
5707
- if (Config.DEBUG && !_.isUndefined(windowConsole) && windowConsole) {
5708
- try {
5709
- windowConsole.log.apply(windowConsole, arguments);
5710
- } catch (err) {
5711
- _.each(arguments, function(arg) {
5712
- windowConsole.log(arg);
5713
- });
5714
- }
5715
- }
5716
- },
5717
- /** @type {function(...*)} */
5718
- warn: function() {
5719
- if (Config.DEBUG && !_.isUndefined(windowConsole) && windowConsole) {
5720
- var args = ['Mixpanel warning:'].concat(_.toArray(arguments));
5721
- try {
5722
- windowConsole.warn.apply(windowConsole, args);
5723
- } catch (err) {
5724
- _.each(args, function(arg) {
5725
- windowConsole.warn(arg);
5726
- });
5727
- }
5728
- }
5729
- },
5730
- /** @type {function(...*)} */
5731
- error: function() {
5732
- if (Config.DEBUG && !_.isUndefined(windowConsole) && windowConsole) {
5733
- var args = ['Mixpanel error:'].concat(_.toArray(arguments));
5734
- try {
5735
- windowConsole.error.apply(windowConsole, args);
5736
- } catch (err) {
5737
- _.each(args, function(arg) {
5738
- windowConsole.error(arg);
5739
- });
5740
- }
5741
- }
5742
- },
5743
- /** @type {function(...*)} */
5744
- critical: function() {
5745
- if (!_.isUndefined(windowConsole) && windowConsole) {
5746
- var args = ['Mixpanel error:'].concat(_.toArray(arguments));
5747
- try {
5748
- windowConsole.error.apply(windowConsole, args);
5749
- } catch (err) {
5750
- _.each(args, function(arg) {
5751
- windowConsole.error(arg);
5752
- });
5753
- }
5754
- }
5755
- }
5756
- };
5757
-
5758
- var log_func_with_prefix = function(func, prefix) {
5759
- return function() {
5760
- arguments[0] = '[' + prefix + '] ' + arguments[0];
5761
- return func.apply(console$1, arguments);
5762
- };
5763
- };
5764
- var console_with_prefix = function(prefix) {
5765
- return {
5766
- log: log_func_with_prefix(console$1.log, prefix),
5767
- error: log_func_with_prefix(console$1.error, prefix),
5768
- critical: log_func_with_prefix(console$1.critical, prefix)
5769
- };
5770
- };
5771
-
5482
+ /**
5483
+ *
5484
+ * @param userLocale
5485
+ * @param includeInfo Include the CSV header in the output
5486
+ * @returns Response
5487
+ */
5488
+ async fetchCSVBlob(userLocale = 'en-us', includeInfo = false) {
5489
+ const fetchUrl = this.getFetchCSVBlobUrl(userLocale, includeInfo);
5490
+ return tokenizedFetch(fetchUrl, {
5491
+ credentials: 'include',
5492
+ });
5493
+ }
5494
+ getFetchCSVBlobUrl(userLocale = 'en-us', includeInfo = false) {
5495
+ return `${this.thoughtSpotHost}/prism/download/answer/csv?sessionId=${this.session.sessionId}&genNo=${this.session.genNo}&userLocale=${userLocale}&exportFileName=data&hideCsvHeader=${!includeInfo}`;
5496
+ }
5497
+ /**
5498
+ * Get underlying data given a point and the output column names.
5499
+ *
5500
+ * @param outputColumnNames
5501
+ * @param selectedPoints
5502
+ * @example
5503
+ * ```js
5504
+ * embed.on(EmbedEvent.CustomAction, e => {
5505
+ * const underlying = await e.answerService.getUnderlyingDataForPoint([
5506
+ * 'col name 1' // The column should exist in the data source.
5507
+ * ]);
5508
+ * const data = await underlying.fetchData(0, 100);
5509
+ * })
5510
+ * ```
5511
+ * @version
5512
+ * ThoughtSpot: 9.9.0.cl / SDK: 1.25.0
5513
+ */
5514
+ async getUnderlyingDataForPoint(outputColumnNames, selectedPoints) {
5515
+ if (!selectedPoints && !this.selectedPoints) {
5516
+ throw new Error('Needs to be triggered in context of a point');
5517
+ }
5518
+ if (!selectedPoints) {
5519
+ selectedPoints = getSelectedPointsForUnderlyingDataQuery(this.selectedPoints);
5520
+ }
5521
+ const sourceDetail = await this.getSourceDetail();
5522
+ const ouputColumnGuids = getGuidsFromColumnNames(sourceDetail, outputColumnNames);
5523
+ const unAggAnswer = await graphqlQuery({
5524
+ query: getUnaggregatedAnswerSession,
5525
+ variables: {
5526
+ session: this.session,
5527
+ columns: selectedPoints,
5528
+ },
5529
+ thoughtSpotHost: this.thoughtSpotHost,
5530
+ });
5531
+ const unaggAnswerSession = new AnswerService(unAggAnswer.id, unAggAnswer.answer, this.thoughtSpotHost);
5532
+ const currentColumns = new Set(unAggAnswer.answer.visualizations[0].columns
5533
+ .map((c) => c.column.referencedColumns[0].guid));
5534
+ const columnsToAdd = [...ouputColumnGuids].filter((col) => !currentColumns.has(col));
5535
+ if (columnsToAdd.length) {
5536
+ await unaggAnswerSession.addColumns(columnsToAdd);
5537
+ }
5538
+ const columnsToRemove = [...currentColumns].filter((col) => !ouputColumnGuids.has(col));
5539
+ if (columnsToRemove.length) {
5540
+ await unaggAnswerSession.removeColumns(columnsToRemove);
5541
+ }
5542
+ return unaggAnswerSession;
5543
+ }
5544
+ async executeQuery(query, variables) {
5545
+ const data = await graphqlQuery({
5546
+ query,
5547
+ variables: {
5548
+ session: this.session,
5549
+ ...variables,
5550
+ },
5551
+ thoughtSpotHost: this.thoughtSpotHost,
5552
+ isCompositeQuery: false,
5553
+ });
5554
+ this.session = deepMerge(this.session, (data === null || data === void 0 ? void 0 : data.id) || {});
5555
+ return data;
5556
+ }
5557
+ getSession() {
5558
+ return this.session;
5559
+ }
5560
+ }
5561
+ /**
5562
+ *
5563
+ * @param sourceDetail
5564
+ * @param colNames
5565
+ */
5566
+ function getGuidsFromColumnNames(sourceDetail, colNames) {
5567
+ const cols = sourceDetail.columns.reduce((colSet, col) => {
5568
+ colSet[col.name] = col;
5569
+ return colSet;
5570
+ }, {});
5571
+ return new Set(colNames.map((colName) => {
5572
+ const col = cols[colName];
5573
+ return col.id;
5574
+ }));
5575
+ }
5576
+ /**
5577
+ *
5578
+ * @param selectedPoints
5579
+ */
5580
+ function getSelectedPointsForUnderlyingDataQuery(selectedPoints) {
5581
+ const underlyingDataPoint = [];
5582
+ /**
5583
+ *
5584
+ * @param colVal
5585
+ */
5586
+ function addPointFromColVal(colVal) {
5587
+ var _a;
5588
+ const dataType = colVal.column.dataType;
5589
+ const id = colVal.column.id;
5590
+ let dataValue;
5591
+ if (dataType === 'DATE') {
5592
+ if (Number.isFinite(colVal.value)) {
5593
+ dataValue = [{
5594
+ epochRange: {
5595
+ startEpoch: colVal.value,
5596
+ },
5597
+ }];
5598
+ // Case for custom calendar.
5599
+ }
5600
+ else if ((_a = colVal.value) === null || _a === void 0 ? void 0 : _a.v) {
5601
+ dataValue = [{
5602
+ epochRange: {
5603
+ startEpoch: colVal.value.v.s,
5604
+ endEpoch: colVal.value.v.e,
5605
+ },
5606
+ }];
5607
+ }
5608
+ }
5609
+ else {
5610
+ dataValue = [{ value: colVal.value }];
5611
+ }
5612
+ underlyingDataPoint.push({
5613
+ columnId: colVal.column.id,
5614
+ dataValue,
5615
+ });
5616
+ }
5617
+ selectedPoints.forEach((p) => {
5618
+ p.selectedAttributes.forEach(addPointFromColVal);
5619
+ });
5620
+ return underlyingDataPoint;
5621
+ }
5772
5622
 
5773
- // UNDERSCORE
5774
- // Embed part of the Underscore Library
5775
- _.bind = function(func, context) {
5776
- var args, bound;
5777
- if (nativeBind && func.bind === nativeBind) {
5778
- return nativeBind.apply(func, slice.call(arguments, 1));
5779
- }
5780
- if (!_.isFunction(func)) {
5781
- throw new TypeError();
5782
- }
5783
- args = slice.call(arguments, 2);
5784
- bound = function() {
5785
- if (!(this instanceof bound)) {
5786
- return func.apply(context, args.concat(slice.call(arguments)));
5787
- }
5788
- var ctor = {};
5789
- ctor.prototype = func.prototype;
5790
- var self = new ctor();
5791
- ctor.prototype = null;
5792
- var result = func.apply(self, args.concat(slice.call(arguments)));
5793
- if (Object(result) === result) {
5794
- return result;
5795
- }
5796
- return self;
5797
- };
5798
- return bound;
5623
+ const ERROR_MESSAGE = {
5624
+ INVALID_THOUGHTSPOT_HOST: 'Error parsing ThoughtSpot host. Please provide a valid URL.',
5625
+ LIVEBOARD_VIZ_ID_VALIDATION: 'Please provide either liveboardId or pinboardId',
5626
+ TRIGGER_TIMED_OUT: 'Trigger timedout in getting response',
5627
+ SEARCHEMBED_BETA_WRANING_MESSAGE: 'Search Embed is in Beta in this release.',
5628
+ SAGE_EMBED_BETA_WARNING_MESSAGE: 'Sage Embed is in Beta in this release.',
5799
5629
  };
5800
5630
 
5801
- /**
5802
- * @param {*=} obj
5803
- * @param {function(...*)=} iterator
5804
- * @param {Object=} context
5805
- */
5806
- _.each = function(obj, iterator, context) {
5807
- if (obj === null || obj === undefined) {
5808
- return;
5809
- }
5810
- if (nativeForEach && obj.forEach === nativeForEach) {
5811
- obj.forEach(iterator, context);
5812
- } else if (obj.length === +obj.length) {
5813
- for (var i = 0, l = obj.length; i < l; i++) {
5814
- if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) {
5815
- return;
5816
- }
5817
- }
5818
- } else {
5819
- for (var key in obj) {
5820
- if (hasOwnProperty$9.call(obj, key)) {
5631
+ /**
5632
+ * Copyright (c) 2023
5633
+ *
5634
+ * Utilities related to reading configuration objects
5635
+ *
5636
+ * @summary Config-related utils
5637
+ * @author Ayon Ghosh <ayon.ghosh@thoughtspot.com>
5638
+ */
5639
+ const urlRegex = new RegExp([
5640
+ '(^(https?:)//)?',
5641
+ '(([^:/?#]*)(?::([0-9]+))?)',
5642
+ '(/{0,1}[^?#]*)',
5643
+ '(\\?[^#]*|)',
5644
+ '(#.*|)$', // hash
5645
+ ].join(''));
5646
+ /**
5647
+ * Parse and construct the ThoughtSpot hostname or IP address
5648
+ * from the embed configuration object.
5649
+ *
5650
+ * @param config
5651
+ */
5652
+ const getThoughtSpotHost = (config) => {
5653
+ if (!config.thoughtSpotHost) {
5654
+ throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
5655
+ }
5656
+ const urlParts = config.thoughtSpotHost.match(urlRegex);
5657
+ if (!urlParts) {
5658
+ throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
5659
+ }
5660
+ const protocol = urlParts[2] || window.location.protocol;
5661
+ const host = urlParts[3];
5662
+ let path = urlParts[6];
5663
+ // Lose the trailing / if any
5664
+ if (path.charAt(path.length - 1) === '/') {
5665
+ path = path.substring(0, path.length - 1);
5666
+ }
5667
+ // const urlParams = urlParts[7];
5668
+ // const hash = urlParts[8];
5669
+ return `${protocol}//${host}${path}`;
5670
+ };
5671
+ const getV2BasePath = (config) => {
5672
+ if (config.basepath) {
5673
+ return config.basepath;
5674
+ }
5675
+ const tsHost = getThoughtSpotHost(config);
5676
+ // This is to handle when e2e's. Search is run on pods for
5677
+ // comp-blink-test-pipeline with baseUrl=https://localhost:8443.
5678
+ // This is to handle when the developer is developing in their local
5679
+ // environment.
5680
+ if (tsHost.includes('://localhost') && !tsHost.includes(':8443')) {
5681
+ return '';
5682
+ }
5683
+ return 'v2';
5684
+ };
5685
+ /**
5686
+ * It is a good idea to keep URLs under 2000 chars.
5687
+ * If this is ever breached, since we pass view configuration through
5688
+ * URL params, we would like to log a warning.
5689
+ * Reference: https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
5690
+ */
5691
+ const URL_MAX_LENGTH = 2000;
5692
+ /**
5693
+ * The default CSS dimensions of the embedded app
5694
+ */
5695
+ const DEFAULT_EMBED_WIDTH = '100%';
5696
+ const DEFAULT_EMBED_HEIGHT = '100%';
5697
+
5698
+ var Config = {
5699
+ DEBUG: false,
5700
+ LIB_VERSION: '2.45.0'
5701
+ };
5702
+
5703
+ // since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
5704
+ var window$1;
5705
+ if (typeof(window) === 'undefined') {
5706
+ var loc = {
5707
+ hostname: ''
5708
+ };
5709
+ window$1 = {
5710
+ navigator: { userAgent: '' },
5711
+ document: {
5712
+ location: loc,
5713
+ referrer: ''
5714
+ },
5715
+ screen: { width: 0, height: 0 },
5716
+ location: loc
5717
+ };
5718
+ } else {
5719
+ window$1 = window;
5720
+ }
5721
+
5722
+ /*
5723
+ * Saved references to long variable names, so that closure compiler can
5724
+ * minimize file size.
5725
+ */
5726
+
5727
+ var ArrayProto = Array.prototype;
5728
+ var FuncProto = Function.prototype;
5729
+ var ObjProto = Object.prototype;
5730
+ var slice = ArrayProto.slice;
5731
+ var toString = ObjProto.toString;
5732
+ var hasOwnProperty$9 = ObjProto.hasOwnProperty;
5733
+ var windowConsole = window$1.console;
5734
+ var navigator = window$1.navigator;
5735
+ var document$1 = window$1.document;
5736
+ var windowOpera = window$1.opera;
5737
+ var screen = window$1.screen;
5738
+ var userAgent = navigator.userAgent;
5739
+ var nativeBind = FuncProto.bind;
5740
+ var nativeForEach = ArrayProto.forEach;
5741
+ var nativeIndexOf = ArrayProto.indexOf;
5742
+ var nativeMap = ArrayProto.map;
5743
+ var nativeIsArray = Array.isArray;
5744
+ var breaker = {};
5745
+ var _ = {
5746
+ trim: function(str) {
5747
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim#Polyfill
5748
+ return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
5749
+ }
5750
+ };
5751
+
5752
+ // Console override
5753
+ var console$1 = {
5754
+ /** @type {function(...*)} */
5755
+ log: function() {
5756
+ if (Config.DEBUG && !_.isUndefined(windowConsole) && windowConsole) {
5757
+ try {
5758
+ windowConsole.log.apply(windowConsole, arguments);
5759
+ } catch (err) {
5760
+ _.each(arguments, function(arg) {
5761
+ windowConsole.log(arg);
5762
+ });
5763
+ }
5764
+ }
5765
+ },
5766
+ /** @type {function(...*)} */
5767
+ warn: function() {
5768
+ if (Config.DEBUG && !_.isUndefined(windowConsole) && windowConsole) {
5769
+ var args = ['Mixpanel warning:'].concat(_.toArray(arguments));
5770
+ try {
5771
+ windowConsole.warn.apply(windowConsole, args);
5772
+ } catch (err) {
5773
+ _.each(args, function(arg) {
5774
+ windowConsole.warn(arg);
5775
+ });
5776
+ }
5777
+ }
5778
+ },
5779
+ /** @type {function(...*)} */
5780
+ error: function() {
5781
+ if (Config.DEBUG && !_.isUndefined(windowConsole) && windowConsole) {
5782
+ var args = ['Mixpanel error:'].concat(_.toArray(arguments));
5783
+ try {
5784
+ windowConsole.error.apply(windowConsole, args);
5785
+ } catch (err) {
5786
+ _.each(args, function(arg) {
5787
+ windowConsole.error(arg);
5788
+ });
5789
+ }
5790
+ }
5791
+ },
5792
+ /** @type {function(...*)} */
5793
+ critical: function() {
5794
+ if (!_.isUndefined(windowConsole) && windowConsole) {
5795
+ var args = ['Mixpanel error:'].concat(_.toArray(arguments));
5796
+ try {
5797
+ windowConsole.error.apply(windowConsole, args);
5798
+ } catch (err) {
5799
+ _.each(args, function(arg) {
5800
+ windowConsole.error(arg);
5801
+ });
5802
+ }
5803
+ }
5804
+ }
5805
+ };
5806
+
5807
+ var log_func_with_prefix = function(func, prefix) {
5808
+ return function() {
5809
+ arguments[0] = '[' + prefix + '] ' + arguments[0];
5810
+ return func.apply(console$1, arguments);
5811
+ };
5812
+ };
5813
+ var console_with_prefix = function(prefix) {
5814
+ return {
5815
+ log: log_func_with_prefix(console$1.log, prefix),
5816
+ error: log_func_with_prefix(console$1.error, prefix),
5817
+ critical: log_func_with_prefix(console$1.critical, prefix)
5818
+ };
5819
+ };
5820
+
5821
+
5822
+ // UNDERSCORE
5823
+ // Embed part of the Underscore Library
5824
+ _.bind = function(func, context) {
5825
+ var args, bound;
5826
+ if (nativeBind && func.bind === nativeBind) {
5827
+ return nativeBind.apply(func, slice.call(arguments, 1));
5828
+ }
5829
+ if (!_.isFunction(func)) {
5830
+ throw new TypeError();
5831
+ }
5832
+ args = slice.call(arguments, 2);
5833
+ bound = function() {
5834
+ if (!(this instanceof bound)) {
5835
+ return func.apply(context, args.concat(slice.call(arguments)));
5836
+ }
5837
+ var ctor = {};
5838
+ ctor.prototype = func.prototype;
5839
+ var self = new ctor();
5840
+ ctor.prototype = null;
5841
+ var result = func.apply(self, args.concat(slice.call(arguments)));
5842
+ if (Object(result) === result) {
5843
+ return result;
5844
+ }
5845
+ return self;
5846
+ };
5847
+ return bound;
5848
+ };
5849
+
5850
+ /**
5851
+ * @param {*=} obj
5852
+ * @param {function(...*)=} iterator
5853
+ * @param {Object=} context
5854
+ */
5855
+ _.each = function(obj, iterator, context) {
5856
+ if (obj === null || obj === undefined) {
5857
+ return;
5858
+ }
5859
+ if (nativeForEach && obj.forEach === nativeForEach) {
5860
+ obj.forEach(iterator, context);
5861
+ } else if (obj.length === +obj.length) {
5862
+ for (var i = 0, l = obj.length; i < l; i++) {
5863
+ if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) {
5864
+ return;
5865
+ }
5866
+ }
5867
+ } else {
5868
+ for (var key in obj) {
5869
+ if (hasOwnProperty$9.call(obj, key)) {
5821
5870
  if (iterator.call(context, obj[key], key, obj) === breaker) {
5822
5871
  return;
5823
5872
  }
@@ -11640,889 +11689,856 @@
11640
11689
  VISUAL_SDK_ON: 'visual-sdk-on',
11641
11690
  VISUAL_SDK_IFRAME_LOAD_PERFORMANCE: 'visual-sdk-iframe-load-performance',
11642
11691
  VISUAL_SDK_EMBED_CREATE: 'visual-sdk-embed-create',
11643
- };
11644
- let isMixpanelInitialized = false;
11645
- let eventQueue = [];
11646
- /**
11647
- * Pushes the event with its Property key-value map to mixpanel.
11648
- *
11649
- * @param eventId
11650
- * @param eventProps
11651
- */
11652
- function uploadMixpanelEvent(eventId, eventProps = {}) {
11653
- if (!isMixpanelInitialized) {
11654
- eventQueue.push({ eventId, eventProps });
11655
- return;
11656
- }
11657
- mixpanelInstance.track(eventId, eventProps);
11658
- }
11659
- /**
11660
- *
11661
- */
11662
- function emptyQueue() {
11663
- if (!isMixpanelInitialized) {
11664
- return;
11665
- }
11666
- eventQueue.forEach((event) => {
11667
- uploadMixpanelEvent(event.eventId, event.eventProps);
11668
- });
11669
- eventQueue = [];
11670
- }
11671
- /**
11672
- *
11673
- * @param sessionInfo
11674
- */
11675
- function initMixpanel(sessionInfo) {
11676
- var _a;
11677
- if (!sessionInfo || !sessionInfo.mixpanelToken) {
11678
- return;
11679
- }
11680
- // On a public cluster the user is anonymous, so don't set the identify to
11681
- // userGUID
11682
- const isPublicCluster = !!sessionInfo.isPublicUser;
11683
- const token = sessionInfo.mixpanelToken;
11684
- try {
11685
- if (token) {
11686
- mixpanelInstance = mixpanelLib.init(token, undefined, 'tsEmbed');
11687
- if (!isPublicCluster) {
11688
- mixpanelInstance.identify(sessionInfo.userGUID);
11689
- }
11690
- mixpanelInstance.register_once({
11691
- clusterId: sessionInfo.clusterId,
11692
- clusterName: sessionInfo.clusterName,
11693
- releaseVersion: sessionInfo.releaseVersion,
11694
- hostAppUrl: ((_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.host) || '',
11695
- });
11696
- isMixpanelInitialized = true;
11697
- emptyQueue();
11698
- }
11699
- }
11700
- catch (e) {
11701
- console.error('Error initializing mixpanel', e);
11702
- }
11703
- }
11704
-
11705
- // eslint-disable-next-line import/no-mutable-exports
11706
- let loggedInStatus = false;
11707
- // eslint-disable-next-line import/no-mutable-exports
11708
- let samlAuthWindow = null;
11709
- // eslint-disable-next-line import/no-mutable-exports
11710
- let samlCompletionPromise = null;
11711
- let sessionInfo = null;
11712
- let sessionInfoResolver = null;
11713
- const sessionInfoPromise = new Promise((resolve) => {
11714
- sessionInfoResolver = resolve;
11715
- });
11716
- let releaseVersion = '';
11717
- const SSO_REDIRECTION_MARKER_GUID = '5e16222e-ef02-43e9-9fbd-24226bf3ce5b';
11718
- /**
11719
- * Enum for auth failure types. This is the parameter passed to the listner
11720
- * of {@link AuthStatus.FAILURE}.
11721
- *
11722
- * @group Authentication / Init
11723
- */
11724
- var AuthFailureType;
11725
- (function (AuthFailureType) {
11726
- AuthFailureType["SDK"] = "SDK";
11727
- AuthFailureType["NO_COOKIE_ACCESS"] = "NO_COOKIE_ACCESS";
11728
- AuthFailureType["EXPIRY"] = "EXPIRY";
11729
- AuthFailureType["OTHER"] = "OTHER";
11730
- })(AuthFailureType || (AuthFailureType = {}));
11731
- /**
11732
- * Enum for auth status emitted by the emitter returned from {@link init}.
11733
- *
11734
- * @group Authentication / Init
11735
- */
11736
- var AuthStatus;
11737
- (function (AuthStatus) {
11738
- /**
11739
- * Emits when the SDK fails to authenticate
11740
- */
11741
- AuthStatus["FAILURE"] = "FAILURE";
11742
- /**
11743
- * Emits when the SDK authenticates successfully
11744
- */
11745
- AuthStatus["SDK_SUCCESS"] = "SDK_SUCCESS";
11746
- /**
11747
- * Emits when the app sends an authentication success message
11748
- */
11749
- AuthStatus["SUCCESS"] = "SUCCESS";
11750
- /**
11751
- * Emits when a user logs out
11752
- */
11753
- AuthStatus["LOGOUT"] = "LOGOUT";
11754
- /**
11755
- * Emitted when inPopup: true in the SAMLRedirect flow.
11756
- * And, we are waiting for popup to be triggered either programatically
11757
- * or by the trigger button.
11758
- *
11759
- * @version SDK: 1.19.0
11760
- */
11761
- AuthStatus["WAITING_FOR_POPUP"] = "WAITING_FOR_POPUP";
11762
- })(AuthStatus || (AuthStatus = {}));
11763
- /**
11764
- * Events which can be triggered on the emitter returned from {@link init}.
11765
- *
11766
- * @group Authentication / Init
11767
- */
11768
- var AuthEvent;
11769
- (function (AuthEvent) {
11770
- /**
11771
- * Manually trigger the SSO popup. This is useful with
11772
- * authStatus: SAMLRedirect/OIDCRedicre and inPopup: true
11773
- */
11774
- AuthEvent["TRIGGER_SSO_POPUP"] = "TRIGGER_SSO_POPUP";
11775
- })(AuthEvent || (AuthEvent = {}));
11776
- /**
11777
- *
11778
- */
11779
- function notifyAuthSDKSuccess() {
11780
- {
11781
- console.error('SDK not initialized');
11782
- return;
11783
- }
11784
- }
11785
- /**
11786
- *
11787
- */
11788
- function notifyAuthSuccess() {
11789
- {
11790
- console.error('SDK not initialized');
11791
- return;
11792
- }
11793
- }
11794
- /**
11795
- *
11796
- * @param failureType
11797
- */
11798
- function notifyAuthFailure(failureType) {
11799
- {
11800
- console.error('SDK not initialized');
11801
- return;
11802
- }
11803
- }
11804
- /**
11805
- *
11806
- */
11807
- function notifyLogout() {
11808
- {
11809
- console.error('SDK not initialized');
11810
- return;
11811
- }
11812
- }
11813
- const initSession = (sessionDetails) => {
11814
- if (sessionInfo == null) {
11815
- sessionInfo = sessionDetails;
11816
- initMixpanel(sessionInfo);
11817
- sessionInfoResolver(sessionInfo);
11818
- }
11819
- };
11820
- const getSessionDetails = (sessionInfoResp) => {
11821
- console.log('helloooo');
11822
- const devMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.devSdkKey;
11823
- const prodMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.prodSdkKey;
11824
- const mixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.production
11825
- ? prodMixpanelToken
11826
- : devMixpanelToken;
11827
- return {
11828
- userGUID: sessionInfoResp.userGUID,
11829
- mixpanelToken,
11830
- isPublicUser: sessionInfoResp.configInfo.isPublicUser,
11831
- releaseVersion: sessionInfoResp.releaseVersion,
11832
- clusterId: sessionInfoResp.configInfo.selfClusterId,
11833
- clusterName: sessionInfoResp.configInfo.selfClusterName,
11834
- ...sessionInfoResp,
11835
- };
11836
- };
11837
- /**
11838
- * Check if we are logged into the ThoughtSpot cluster
11839
- *
11840
- * @param thoughtSpotHost The ThoughtSpot cluster hostname or IP
11841
- */
11842
- async function isLoggedIn(thoughtSpotHost) {
11843
- const authVerificationUrl = `${thoughtSpotHost}${EndPoints.AUTH_VERIFICATION}`;
11844
- let response = null;
11845
- try {
11846
- response = await fetchSessionInfoService(authVerificationUrl);
11847
- const sessionInfoResp = await response.json();
11848
- const sessionDetails = getSessionDetails(sessionInfoResp);
11849
- // Store user session details from session info
11850
- initSession(sessionDetails);
11851
- releaseVersion = sessionInfoResp.releaseVersion;
11852
- }
11853
- catch (e) {
11854
- return false;
11855
- }
11856
- return response.status === 200;
11857
- }
11858
- /**
11859
- * Return releaseVersion if available
11860
- */
11861
- function getReleaseVersion() {
11862
- return releaseVersion;
11863
- }
11864
- /**
11865
- * Check if we are stuck at the SSO redirect URL
11866
- */
11867
- function isAtSSORedirectUrl() {
11868
- return window.location.href.indexOf(SSO_REDIRECTION_MARKER_GUID) >= 0;
11869
- }
11870
- /**
11871
- * Remove the SSO redirect URL marker
11872
- */
11873
- function removeSSORedirectUrlMarker() {
11874
- // Note (sunny): This will leave a # around even if it was not in the URL
11875
- // to begin with. Trying to remove the hash by changing window.location will
11876
- // reload the page which we don't want. We'll live with adding an
11877
- // unnecessary hash to the parent page URL until we find any use case where
11878
- // that creates an issue.
11879
- window.location.hash = window.location.hash.replace(SSO_REDIRECTION_MARKER_GUID, '');
11880
- }
11881
- /**
11882
- * Perform token based authentication
11883
- *
11884
- * @param embedConfig The embed configuration
11885
- */
11886
- const doTokenAuth = async (embedConfig) => {
11887
- const { thoughtSpotHost, username, authEndpoint, getAuthToken, } = embedConfig;
11888
- if (!authEndpoint && !getAuthToken) {
11889
- throw new Error('Either auth endpoint or getAuthToken function must be provided');
11890
- }
11891
- loggedInStatus = await isLoggedIn(thoughtSpotHost);
11892
- if (!loggedInStatus) {
11893
- const authToken = await getAuthenticationToken(embedConfig);
11894
- let resp;
11895
- try {
11896
- resp = await fetchAuthPostService(thoughtSpotHost, username, authToken);
11897
- }
11898
- catch (e) {
11899
- resp = await fetchAuthService(thoughtSpotHost, username, authToken);
11900
- }
11901
- // token login issues a 302 when successful
11902
- loggedInStatus = resp.ok || resp.type === 'opaqueredirect';
11903
- if (loggedInStatus && embedConfig.detectCookieAccessSlow) {
11904
- // When 3rd party cookie access is blocked, this will fail because
11905
- // cookies will not be sent with the call.
11906
- loggedInStatus = await isLoggedIn(thoughtSpotHost);
11907
- }
11908
- }
11909
- return loggedInStatus;
11910
- };
11911
- /**
11912
- * Validate embedConfig parameters required for cookielessTokenAuth
11913
- *
11914
- * @param embedConfig The embed configuration
11915
- */
11916
- const doCookielessTokenAuth = async (embedConfig) => {
11917
- const { authEndpoint, getAuthToken } = embedConfig;
11918
- if (!authEndpoint && !getAuthToken) {
11919
- throw new Error('Either auth endpoint or getAuthToken function must be provided');
11920
- }
11921
- try {
11922
- const authToken = await getAuthenticationToken(embedConfig);
11923
- if (authToken)
11924
- return true;
11925
- }
11926
- catch {
11927
- // return false if getAuthenticationToken fails
11928
- }
11929
- return false;
11930
- };
11931
- /**
11932
- * Perform basic authentication to the ThoughtSpot cluster using the cluster
11933
- * credentials.
11934
- *
11935
- * Warning: This feature is primarily intended for developer testing. It is
11936
- * strongly advised not to use this authentication method in production.
11937
- *
11938
- * @param embedConfig The embed configuration
11939
- */
11940
- const doBasicAuth = async (embedConfig) => {
11941
- const { thoughtSpotHost, username, password } = embedConfig;
11942
- const loggedIn = await isLoggedIn(thoughtSpotHost);
11943
- if (!loggedIn) {
11944
- const response = await fetchBasicAuthService(thoughtSpotHost, username, password);
11945
- loggedInStatus = response.ok;
11946
- if (embedConfig.detectCookieAccessSlow) {
11947
- loggedInStatus = await isLoggedIn(thoughtSpotHost);
11948
- }
11949
- }
11950
- else {
11951
- loggedInStatus = true;
11952
- }
11953
- return loggedInStatus;
11954
- };
11955
- /**
11956
- *
11957
- * @param ssoURL
11958
- * @param triggerContainer
11959
- * @param triggerText
11960
- */
11961
- async function samlPopupFlow(ssoURL, triggerContainer, triggerText) {
11962
- const openPopup = () => {
11963
- if (samlAuthWindow === null || samlAuthWindow.closed) {
11964
- samlAuthWindow = window.open(ssoURL, '_blank', 'location=no,height=570,width=520,scrollbars=yes,status=yes');
11965
- }
11966
- else {
11967
- samlAuthWindow.focus();
11968
- }
11969
- };
11970
- const containerEl = getDOMNode(triggerContainer);
11971
- if (containerEl) {
11972
- containerEl.innerHTML = '<button id="ts-auth-btn" class="ts-auth-btn" style="margin: auto;"></button>';
11973
- const authElem = document.getElementById('ts-auth-btn');
11974
- authElem.textContent = triggerText;
11975
- authElem.addEventListener('click', openPopup, { once: true });
11976
- }
11977
- samlCompletionPromise = samlCompletionPromise
11978
- || new Promise((resolve, reject) => {
11979
- window.addEventListener('message', (e) => {
11980
- if (e.data.type === exports.EmbedEvent.SAMLComplete) {
11981
- e.source.close();
11982
- resolve();
11983
- }
11984
- });
11985
- });
11986
- return samlCompletionPromise;
11987
- }
11692
+ };
11693
+ let isMixpanelInitialized = false;
11694
+ let eventQueue = [];
11988
11695
  /**
11989
- * Perform SAML authentication
11696
+ * Pushes the event with its Property key-value map to mixpanel.
11990
11697
  *
11991
- * @param embedConfig The embed configuration
11992
- * @param ssoEndPoint
11698
+ * @param eventId
11699
+ * @param eventProps
11993
11700
  */
11994
- const doSSOAuth = async (embedConfig, ssoEndPoint) => {
11995
- const { thoughtSpotHost } = embedConfig;
11996
- const loggedIn = await isLoggedIn(thoughtSpotHost);
11997
- if (loggedIn) {
11998
- if (isAtSSORedirectUrl()) {
11999
- removeSSORedirectUrlMarker();
12000
- }
12001
- loggedInStatus = true;
12002
- return;
12003
- }
12004
- // we have already tried authentication and it did not succeed, restore
12005
- // the current URL to the original one and invoke the callback.
12006
- if (isAtSSORedirectUrl()) {
12007
- removeSSORedirectUrlMarker();
12008
- loggedInStatus = false;
11701
+ function uploadMixpanelEvent(eventId, eventProps = {}) {
11702
+ if (!isMixpanelInitialized) {
11703
+ eventQueue.push({ eventId, eventProps });
12009
11704
  return;
12010
11705
  }
12011
- const ssoURL = `${thoughtSpotHost}${ssoEndPoint}`;
12012
- if (embedConfig.inPopup) {
12013
- await samlPopupFlow(ssoURL, embedConfig.authTriggerContainer, embedConfig.authTriggerText);
12014
- loggedInStatus = await isLoggedIn(thoughtSpotHost);
11706
+ mixpanelInstance.track(eventId, eventProps);
11707
+ }
11708
+ /**
11709
+ *
11710
+ */
11711
+ function emptyQueue() {
11712
+ if (!isMixpanelInitialized) {
12015
11713
  return;
12016
11714
  }
12017
- window.location.href = ssoURL;
12018
- };
12019
- const doSamlAuth = async (embedConfig) => {
12020
- const { thoughtSpotHost } = embedConfig;
12021
- // redirect for SSO, when the SSO authentication is done, this page will be
12022
- // loaded again and the same JS will execute again.
12023
- const ssoRedirectUrl = embedConfig.inPopup
12024
- ? `${thoughtSpotHost}/v2/#/embed/saml-complete`
12025
- : getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
12026
- // bring back the page to the same URL
12027
- const ssoEndPoint = `${EndPoints.SAML_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
12028
- await doSSOAuth(embedConfig, ssoEndPoint);
12029
- return loggedInStatus;
12030
- };
12031
- const doOIDCAuth = async (embedConfig) => {
12032
- const { thoughtSpotHost } = embedConfig;
12033
- // redirect for SSO, when the SSO authentication is done, this page will be
12034
- // loaded again and the same JS will execute again.
12035
- const ssoRedirectUrl = embedConfig.noRedirect || embedConfig.inPopup
12036
- ? `${thoughtSpotHost}/v2/#/embed/saml-complete`
12037
- : getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
12038
- // bring back the page to the same URL
12039
- const ssoEndPoint = `${EndPoints.OIDC_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
12040
- await doSSOAuth(embedConfig, ssoEndPoint);
12041
- return loggedInStatus;
12042
- };
11715
+ eventQueue.forEach((event) => {
11716
+ uploadMixpanelEvent(event.eventId, event.eventProps);
11717
+ });
11718
+ eventQueue = [];
11719
+ }
12043
11720
  /**
12044
- * Perform authentication on the ThoughtSpot cluster
12045
11721
  *
12046
- * @param embedConfig The embed configuration
11722
+ * @param sessionInfo
12047
11723
  */
12048
- const authenticate = async (embedConfig) => {
12049
- const { authType } = embedConfig;
12050
- switch (authType) {
12051
- case AuthType.SSO:
12052
- case AuthType.SAMLRedirect:
12053
- case AuthType.SAML:
12054
- return doSamlAuth(embedConfig);
12055
- case AuthType.OIDC:
12056
- case AuthType.OIDCRedirect:
12057
- return doOIDCAuth(embedConfig);
12058
- case AuthType.AuthServer:
12059
- case AuthType.TrustedAuthToken:
12060
- return doTokenAuth(embedConfig);
12061
- case AuthType.TrustedAuthTokenCookieless:
12062
- return doCookielessTokenAuth(embedConfig);
12063
- case AuthType.Basic:
12064
- return doBasicAuth(embedConfig);
12065
- default:
12066
- return Promise.resolve(true);
11724
+ function initMixpanel(sessionInfo) {
11725
+ var _a;
11726
+ if (!sessionInfo || !sessionInfo.mixpanelToken) {
11727
+ return;
11728
+ }
11729
+ // On a public cluster the user is anonymous, so don't set the identify to
11730
+ // userGUID
11731
+ const isPublicCluster = !!sessionInfo.isPublicUser;
11732
+ const token = sessionInfo.mixpanelToken;
11733
+ try {
11734
+ if (token) {
11735
+ mixpanelInstance = mixpanelLib.init(token, undefined, 'tsEmbed');
11736
+ if (!isPublicCluster) {
11737
+ mixpanelInstance.identify(sessionInfo.userGUID);
11738
+ }
11739
+ mixpanelInstance.register_once({
11740
+ clusterId: sessionInfo.clusterId,
11741
+ clusterName: sessionInfo.clusterName,
11742
+ releaseVersion: sessionInfo.releaseVersion,
11743
+ hostAppUrl: ((_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.host) || '',
11744
+ });
11745
+ isMixpanelInitialized = true;
11746
+ emptyQueue();
11747
+ }
11748
+ }
11749
+ catch (e) {
11750
+ console.error('Error initializing mixpanel', e);
12067
11751
  }
11752
+ }
11753
+
11754
+ var eventemitter3 = createCommonjsModule(function (module) {
11755
+
11756
+ var has = Object.prototype.hasOwnProperty
11757
+ , prefix = '~';
11758
+
11759
+ /**
11760
+ * Constructor to create a storage for our `EE` objects.
11761
+ * An `Events` instance is a plain object whose properties are event names.
11762
+ *
11763
+ * @constructor
11764
+ * @private
11765
+ */
11766
+ function Events() {}
11767
+
11768
+ //
11769
+ // We try to not inherit from `Object.prototype`. In some engines creating an
11770
+ // instance in this way is faster than calling `Object.create(null)` directly.
11771
+ // If `Object.create(null)` is not supported we prefix the event names with a
11772
+ // character to make sure that the built-in object properties are not
11773
+ // overridden or used as an attack vector.
11774
+ //
11775
+ if (Object.create) {
11776
+ Events.prototype = Object.create(null);
11777
+
11778
+ //
11779
+ // This hack is needed because the `__proto__` property is still inherited in
11780
+ // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.
11781
+ //
11782
+ if (!new Events().__proto__) prefix = false;
11783
+ }
11784
+
11785
+ /**
11786
+ * Representation of a single event listener.
11787
+ *
11788
+ * @param {Function} fn The listener function.
11789
+ * @param {*} context The context to invoke the listener with.
11790
+ * @param {Boolean} [once=false] Specify if the listener is a one-time listener.
11791
+ * @constructor
11792
+ * @private
11793
+ */
11794
+ function EE(fn, context, once) {
11795
+ this.fn = fn;
11796
+ this.context = context;
11797
+ this.once = once || false;
11798
+ }
11799
+
11800
+ /**
11801
+ * Add a listener for a given event.
11802
+ *
11803
+ * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
11804
+ * @param {(String|Symbol)} event The event name.
11805
+ * @param {Function} fn The listener function.
11806
+ * @param {*} context The context to invoke the listener with.
11807
+ * @param {Boolean} once Specify if the listener is a one-time listener.
11808
+ * @returns {EventEmitter}
11809
+ * @private
11810
+ */
11811
+ function addListener(emitter, event, fn, context, once) {
11812
+ if (typeof fn !== 'function') {
11813
+ throw new TypeError('The listener must be a function');
11814
+ }
11815
+
11816
+ var listener = new EE(fn, context || emitter, once)
11817
+ , evt = prefix ? prefix + event : event;
11818
+
11819
+ if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;
11820
+ else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);
11821
+ else emitter._events[evt] = [emitter._events[evt], listener];
11822
+
11823
+ return emitter;
11824
+ }
11825
+
11826
+ /**
11827
+ * Clear event by name.
11828
+ *
11829
+ * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
11830
+ * @param {(String|Symbol)} evt The Event name.
11831
+ * @private
11832
+ */
11833
+ function clearEvent(emitter, evt) {
11834
+ if (--emitter._eventsCount === 0) emitter._events = new Events();
11835
+ else delete emitter._events[evt];
11836
+ }
11837
+
11838
+ /**
11839
+ * Minimal `EventEmitter` interface that is molded against the Node.js
11840
+ * `EventEmitter` interface.
11841
+ *
11842
+ * @constructor
11843
+ * @public
11844
+ */
11845
+ function EventEmitter() {
11846
+ this._events = new Events();
11847
+ this._eventsCount = 0;
11848
+ }
11849
+
11850
+ /**
11851
+ * Return an array listing the events for which the emitter has registered
11852
+ * listeners.
11853
+ *
11854
+ * @returns {Array}
11855
+ * @public
11856
+ */
11857
+ EventEmitter.prototype.eventNames = function eventNames() {
11858
+ var names = []
11859
+ , events
11860
+ , name;
11861
+
11862
+ if (this._eventsCount === 0) return names;
11863
+
11864
+ for (name in (events = this._events)) {
11865
+ if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
11866
+ }
11867
+
11868
+ if (Object.getOwnPropertySymbols) {
11869
+ return names.concat(Object.getOwnPropertySymbols(events));
11870
+ }
11871
+
11872
+ return names;
11873
+ };
11874
+
11875
+ /**
11876
+ * Return the listeners registered for a given event.
11877
+ *
11878
+ * @param {(String|Symbol)} event The event name.
11879
+ * @returns {Array} The registered listeners.
11880
+ * @public
11881
+ */
11882
+ EventEmitter.prototype.listeners = function listeners(event) {
11883
+ var evt = prefix ? prefix + event : event
11884
+ , handlers = this._events[evt];
11885
+
11886
+ if (!handlers) return [];
11887
+ if (handlers.fn) return [handlers.fn];
11888
+
11889
+ for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {
11890
+ ee[i] = handlers[i].fn;
11891
+ }
11892
+
11893
+ return ee;
12068
11894
  };
12069
11895
 
12070
- /* eslint-disable camelcase */
12071
- let config = {};
12072
- const CONFIG_DEFAULTS = {
12073
- loginFailedMessage: 'Not logged in',
12074
- authTriggerText: 'Authorize',
12075
- authType: AuthType.None,
12076
- };
12077
- let authPromise;
12078
- /**
12079
- * Gets the configuration embed was initialized with.
12080
- *
12081
- * @returns {@link EmbedConfig} The configuration embed was initialized with.
12082
- * @version SDK: 1.19.0 | ThoughtSpot: *
12083
- * @group Global methods
12084
- */
12085
- const getEmbedConfig = () => config;
12086
- const getAuthPromise = () => authPromise;
12087
- /**
12088
- * Perform authentication on the ThoughtSpot app as applicable.
12089
- */
12090
- const handleAuth = () => {
12091
- authPromise = authenticate(config);
12092
- authPromise.then((isLoggedIn) => {
12093
- if (!isLoggedIn) {
12094
- notifyAuthFailure(AuthFailureType.SDK);
12095
- }
12096
- else {
12097
- notifyAuthSDKSuccess();
12098
- }
12099
- }, () => {
12100
- notifyAuthFailure(AuthFailureType.SDK);
12101
- });
12102
- return authPromise;
12103
- };
12104
- const hostUrlToFeatureUrl = {
12105
- [PrefetchFeatures.SearchEmbed]: (url) => `${url}v2/#/embed/answer`,
12106
- [PrefetchFeatures.LiveboardEmbed]: (url) => url,
12107
- [PrefetchFeatures.FullApp]: (url) => url,
12108
- [PrefetchFeatures.VizEmbed]: (url) => url,
12109
- };
12110
- /**
12111
- *
12112
- */
12113
- function disableAutoLogin() {
12114
- config.autoLogin = false;
12115
- }
12116
- let renderQueue = Promise.resolve();
12117
- /**
12118
- * Renders functions in a queue, resolves to next function only after the callback next
12119
- * is called
12120
- *
12121
- * @param fn The function being registered
12122
- */
12123
- const renderInQueue = (fn) => {
12124
- const { queueMultiRenders = false } = config;
12125
- if (queueMultiRenders) {
12126
- renderQueue = renderQueue.then(() => new Promise((res) => fn(res)));
12127
- return renderQueue;
12128
- }
12129
- // Sending an empty function to keep it consistent with the above usage.
12130
- return fn(() => { }); // eslint-disable-line @typescript-eslint/no-empty-function
11896
+ /**
11897
+ * Return the number of listeners listening to a given event.
11898
+ *
11899
+ * @param {(String|Symbol)} event The event name.
11900
+ * @returns {Number} The number of listeners.
11901
+ * @public
11902
+ */
11903
+ EventEmitter.prototype.listenerCount = function listenerCount(event) {
11904
+ var evt = prefix ? prefix + event : event
11905
+ , listeners = this._events[evt];
11906
+
11907
+ if (!listeners) return 0;
11908
+ if (listeners.fn) return 1;
11909
+ return listeners.length;
11910
+ };
11911
+
11912
+ /**
11913
+ * Calls each of the listeners registered for a given event.
11914
+ *
11915
+ * @param {(String|Symbol)} event The event name.
11916
+ * @returns {Boolean} `true` if the event had listeners, else `false`.
11917
+ * @public
11918
+ */
11919
+ EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
11920
+ var evt = prefix ? prefix + event : event;
11921
+
11922
+ if (!this._events[evt]) return false;
11923
+
11924
+ var listeners = this._events[evt]
11925
+ , len = arguments.length
11926
+ , args
11927
+ , i;
11928
+
11929
+ if (listeners.fn) {
11930
+ if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);
11931
+
11932
+ switch (len) {
11933
+ case 1: return listeners.fn.call(listeners.context), true;
11934
+ case 2: return listeners.fn.call(listeners.context, a1), true;
11935
+ case 3: return listeners.fn.call(listeners.context, a1, a2), true;
11936
+ case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;
11937
+ case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
11938
+ case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
11939
+ }
11940
+
11941
+ for (i = 1, args = new Array(len -1); i < len; i++) {
11942
+ args[i - 1] = arguments[i];
11943
+ }
11944
+
11945
+ listeners.fn.apply(listeners.context, args);
11946
+ } else {
11947
+ var length = listeners.length
11948
+ , j;
11949
+
11950
+ for (i = 0; i < length; i++) {
11951
+ if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);
11952
+
11953
+ switch (len) {
11954
+ case 1: listeners[i].fn.call(listeners[i].context); break;
11955
+ case 2: listeners[i].fn.call(listeners[i].context, a1); break;
11956
+ case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;
11957
+ case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;
11958
+ default:
11959
+ if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {
11960
+ args[j - 1] = arguments[j];
11961
+ }
11962
+
11963
+ listeners[i].fn.apply(listeners[i].context, args);
11964
+ }
11965
+ }
11966
+ }
11967
+
11968
+ return true;
11969
+ };
11970
+
11971
+ /**
11972
+ * Add a listener for a given event.
11973
+ *
11974
+ * @param {(String|Symbol)} event The event name.
11975
+ * @param {Function} fn The listener function.
11976
+ * @param {*} [context=this] The context to invoke the listener with.
11977
+ * @returns {EventEmitter} `this`.
11978
+ * @public
11979
+ */
11980
+ EventEmitter.prototype.on = function on(event, fn, context) {
11981
+ return addListener(this, event, fn, context, false);
11982
+ };
11983
+
11984
+ /**
11985
+ * Add a one-time listener for a given event.
11986
+ *
11987
+ * @param {(String|Symbol)} event The event name.
11988
+ * @param {Function} fn The listener function.
11989
+ * @param {*} [context=this] The context to invoke the listener with.
11990
+ * @returns {EventEmitter} `this`.
11991
+ * @public
11992
+ */
11993
+ EventEmitter.prototype.once = function once(event, fn, context) {
11994
+ return addListener(this, event, fn, context, true);
11995
+ };
11996
+
11997
+ /**
11998
+ * Remove the listeners of a given event.
11999
+ *
12000
+ * @param {(String|Symbol)} event The event name.
12001
+ * @param {Function} fn Only remove the listeners that match this function.
12002
+ * @param {*} context Only remove the listeners that have this context.
12003
+ * @param {Boolean} once Only remove one-time listeners.
12004
+ * @returns {EventEmitter} `this`.
12005
+ * @public
12006
+ */
12007
+ EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
12008
+ var evt = prefix ? prefix + event : event;
12009
+
12010
+ if (!this._events[evt]) return this;
12011
+ if (!fn) {
12012
+ clearEvent(this, evt);
12013
+ return this;
12014
+ }
12015
+
12016
+ var listeners = this._events[evt];
12017
+
12018
+ if (listeners.fn) {
12019
+ if (
12020
+ listeners.fn === fn &&
12021
+ (!once || listeners.once) &&
12022
+ (!context || listeners.context === context)
12023
+ ) {
12024
+ clearEvent(this, evt);
12025
+ }
12026
+ } else {
12027
+ for (var i = 0, events = [], length = listeners.length; i < length; i++) {
12028
+ if (
12029
+ listeners[i].fn !== fn ||
12030
+ (once && !listeners[i].once) ||
12031
+ (context && listeners[i].context !== context)
12032
+ ) {
12033
+ events.push(listeners[i]);
12034
+ }
12035
+ }
12036
+
12037
+ //
12038
+ // Reset the array, or remove it completely if we have no more listeners.
12039
+ //
12040
+ if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;
12041
+ else clearEvent(this, evt);
12042
+ }
12043
+
12044
+ return this;
12045
+ };
12046
+
12047
+ /**
12048
+ * Remove all listeners, or those of the specified event.
12049
+ *
12050
+ * @param {(String|Symbol)} [event] The event name.
12051
+ * @returns {EventEmitter} `this`.
12052
+ * @public
12053
+ */
12054
+ EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
12055
+ var evt;
12056
+
12057
+ if (event) {
12058
+ evt = prefix ? prefix + event : event;
12059
+ if (this._events[evt]) clearEvent(this, evt);
12060
+ } else {
12061
+ this._events = new Events();
12062
+ this._eventsCount = 0;
12063
+ }
12064
+
12065
+ return this;
12131
12066
  };
12132
12067
 
12133
- const tokenizedFetch = async (input, init) => {
12134
- const req = new Request(input, init);
12135
- const embedConfig = getEmbedConfig();
12136
- if (embedConfig.authType !== AuthType.TrustedAuthTokenCookieless) {
12137
- return fetch(req);
12138
- }
12139
- const authToken = await getAuthenticationToken(embedConfig);
12140
- if (authToken) {
12141
- req.headers.append('Authorization', `Bearer ${authToken}`);
12142
- }
12143
- return fetch(req);
12068
+ //
12069
+ // Alias methods names because people roll like that.
12070
+ //
12071
+ EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
12072
+ EventEmitter.prototype.addListener = EventEmitter.prototype.on;
12073
+
12074
+ //
12075
+ // Expose the prefix.
12076
+ //
12077
+ EventEmitter.prefixed = prefix;
12078
+
12079
+ //
12080
+ // Allow `EventEmitter` to be imported as module namespace.
12081
+ //
12082
+ EventEmitter.EventEmitter = EventEmitter;
12083
+
12084
+ //
12085
+ // Expose the module.
12086
+ //
12087
+ {
12088
+ module.exports = EventEmitter;
12089
+ }
12090
+ });
12091
+
12092
+ /**
12093
+ * This method returns `undefined`.
12094
+ *
12095
+ * @static
12096
+ * @memberOf _
12097
+ * @since 2.3.0
12098
+ * @category Util
12099
+ * @example
12100
+ *
12101
+ * _.times(2, _.noop);
12102
+ * // => [undefined, undefined]
12103
+ */
12104
+ function noop() {
12105
+ // No operation performed.
12106
+ }
12107
+
12108
+ var noop_1 = noop;
12109
+
12110
+ /** Used as references for various `Number` constants. */
12111
+ var INFINITY = 1 / 0;
12112
+
12113
+ /**
12114
+ * Creates a set object of `values`.
12115
+ *
12116
+ * @private
12117
+ * @param {Array} values The values to add to the set.
12118
+ * @returns {Object} Returns the new set.
12119
+ */
12120
+ var createSet = !(_Set && (1 / _setToArray(new _Set([,-0]))[1]) == INFINITY) ? noop_1 : function(values) {
12121
+ return new _Set(values);
12144
12122
  };
12145
12123
 
12124
+ // eslint-disable-next-line import/no-mutable-exports
12125
+ let loggedInStatus = false;
12126
+ // eslint-disable-next-line import/no-mutable-exports
12127
+ let samlAuthWindow = null;
12128
+ // eslint-disable-next-line import/no-mutable-exports
12129
+ let samlCompletionPromise = null;
12130
+ let sessionInfo = null;
12131
+ let sessionInfoResolver = null;
12132
+ const sessionInfoPromise = new Promise((resolve) => {
12133
+ sessionInfoResolver = resolve;
12134
+ });
12135
+ let releaseVersion = '';
12136
+ const SSO_REDIRECTION_MARKER_GUID = '5e16222e-ef02-43e9-9fbd-24226bf3ce5b';
12146
12137
  /**
12138
+ * Enum for auth failure types. This is the parameter passed to the listner
12139
+ * of {@link AuthStatus.FAILURE}.
12147
12140
  *
12148
- * @param root0
12149
- * @param root0.query
12150
- * @param root0.variables
12151
- * @param root0.thoughtSpotHost
12152
- * @param root0.isCompositeQuery
12141
+ * @group Authentication / Init
12153
12142
  */
12154
- async function graphqlQuery({ query, variables, thoughtSpotHost, isCompositeQuery = false, }) {
12155
- const operationName = getOperationNameFromQuery(query);
12156
- try {
12157
- const response = await fetch(`${thoughtSpotHost}/prism/?op=${operationName}`, {
12158
- method: 'POST',
12159
- headers: {
12160
- 'content-type': 'application/json;charset=UTF-8',
12161
- 'x-requested-by': 'ThoughtSpot',
12162
- accept: '*/*',
12163
- 'accept-language': 'en-us',
12164
- },
12165
- body: JSON.stringify({
12166
- operationName,
12167
- query,
12168
- variables,
12169
- }),
12170
- credentials: 'include',
12171
- });
12172
- const result = await response.json();
12173
- const dataValues = Object.values(result.data);
12174
- return (isCompositeQuery) ? result.data : dataValues[0];
12175
- }
12176
- catch (error) {
12177
- return error;
12178
- }
12179
- }
12180
-
12181
- const getSourceDetailQuery = `
12182
- query GetSourceDetail($ids: [GUID!]!) {
12183
- getSourceDetailById(ids: $ids, type: LOGICAL_TABLE) {
12184
- id
12185
- name
12186
- description
12187
- authorName
12188
- authorDisplayName
12189
- isExternal
12190
- type
12191
- created
12192
- modified
12193
- columns {
12194
- id
12195
- name
12196
- author
12197
- authorDisplayName
12198
- description
12199
- dataType
12200
- type
12201
- modified
12202
- ownerName
12203
- owner
12204
- dataRecency
12205
- sources {
12206
- tableId
12207
- tableName
12208
- columnId
12209
- columnName
12210
- __typename
12211
- }
12212
- synonyms
12213
- cohortAnswerId
12214
- __typename
12215
- }
12216
- relationships
12217
- destinationRelationships
12218
- dataSourceId
12219
- __typename
12220
- }
12221
- }
12222
- `;
12223
- const sourceDetailCache = new Map();
12143
+ var AuthFailureType;
12144
+ (function (AuthFailureType) {
12145
+ AuthFailureType["SDK"] = "SDK";
12146
+ AuthFailureType["NO_COOKIE_ACCESS"] = "NO_COOKIE_ACCESS";
12147
+ AuthFailureType["EXPIRY"] = "EXPIRY";
12148
+ AuthFailureType["OTHER"] = "OTHER";
12149
+ })(AuthFailureType || (AuthFailureType = {}));
12224
12150
  /**
12151
+ * Enum for auth status emitted by the emitter returned from {@link init}.
12225
12152
  *
12226
- * @param thoughtSpotHost
12227
- * @param sourceId
12153
+ * @group Authentication / Init
12228
12154
  */
12229
- async function getSourceDetail(thoughtSpotHost, sourceId) {
12230
- if (sourceDetailCache.get(sourceId)) {
12231
- return sourceDetailCache.get(sourceId);
12232
- }
12233
- const details = await graphqlQuery({
12234
- query: getSourceDetailQuery,
12235
- variables: {
12236
- ids: [sourceId],
12237
- },
12238
- thoughtSpotHost,
12239
- });
12240
- const souceDetails = details[0];
12241
- if (souceDetails) {
12242
- sourceDetailCache.set(sourceId, souceDetails);
12243
- }
12244
- return souceDetails;
12245
- }
12246
-
12247
- const bachSessionId = `
12248
- id {
12249
- sessionId
12250
- genNo
12251
- acSession {
12252
- sessionId
12253
- genNo
12254
- }
12255
- }
12256
- `;
12257
- const getUnaggregatedAnswerSession = `
12258
- mutation GetUnAggregatedAnswerSession($session: BachSessionIdInput!, $columns: [UserPointSelectionInput!]!) {
12259
- Answer__getUnaggregatedAnswer(session: $session, columns: $columns) {
12260
- ${bachSessionId}
12261
- answer {
12262
- visualizations {
12263
- ... on TableViz {
12264
- columns {
12265
- column {
12266
- id
12267
- name
12268
- referencedColumns {
12269
- guid
12270
- displayName
12271
- }
12272
- }
12273
- }
12274
- }
12275
- }
12276
- }
12277
- }
12278
- }
12279
- `;
12280
- const removeColumns = `
12281
- mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!], $columnIds: [GUID!]) {
12282
- Answer__removeColumns(
12283
- session: $session
12284
- logicalColumnIds: $logicalColumnIds
12285
- columnIds: $columnIds
12286
- ) {
12287
- ${bachSessionId}
12288
- }
12289
- }
12290
- `;
12291
- const addColumns = `
12292
- mutation AddColumns($session: BachSessionIdInput!, $columns: [AnswerColumnInfo!]!) {
12293
- Answer__addColumn(session: $session, columns: $columns) {
12294
- ${bachSessionId}
12295
- }
12296
- }
12297
- `;
12298
- const getAnswerData = `
12299
- query GetTableWithHeadlineData($session: BachSessionIdInput!, $deadline: Int!, $dataPaginationParams: DataPaginationParamsInput!) {
12300
- getAnswer(session: $session) {
12301
- ${bachSessionId}
12302
- answer {
12303
- id
12304
- visualizations {
12305
- id
12306
- ... on TableViz {
12307
- columns {
12308
- column {
12309
- id
12310
- name
12311
- type
12312
- aggregationType
12313
- dataType
12314
- }
12315
- }
12316
- data(deadline: $deadline, pagination: $dataPaginationParams)
12317
- }
12318
- }
12319
- }
12320
- }
12321
- }
12322
- `;
12323
-
12324
- // eslint-disable-next-line no-shadow
12325
- var OperationType;
12326
- (function (OperationType) {
12327
- OperationType["GetChartWithData"] = "GetChartWithData";
12328
- OperationType["GetTableWithHeadlineData"] = "GetTableWithHeadlineData";
12329
- })(OperationType || (OperationType = {}));
12155
+ var AuthStatus;
12156
+ (function (AuthStatus) {
12157
+ /**
12158
+ * Emits when the SDK fails to authenticate
12159
+ */
12160
+ AuthStatus["FAILURE"] = "FAILURE";
12161
+ /**
12162
+ * Emits when the SDK authenticates successfully
12163
+ */
12164
+ AuthStatus["SDK_SUCCESS"] = "SDK_SUCCESS";
12165
+ /**
12166
+ * Emits when the app sends an authentication success message
12167
+ */
12168
+ AuthStatus["SUCCESS"] = "SUCCESS";
12169
+ /**
12170
+ * Emits when a user logs out
12171
+ */
12172
+ AuthStatus["LOGOUT"] = "LOGOUT";
12173
+ /**
12174
+ * Emitted when inPopup: true in the SAMLRedirect flow.
12175
+ * And, we are waiting for popup to be triggered either programatically
12176
+ * or by the trigger button.
12177
+ *
12178
+ * @version SDK: 1.19.0
12179
+ */
12180
+ AuthStatus["WAITING_FOR_POPUP"] = "WAITING_FOR_POPUP";
12181
+ })(AuthStatus || (AuthStatus = {}));
12330
12182
  /**
12331
- * Class representing the answer service provided with the
12332
- * custom action payload. This service could be used to run
12333
- * graphql queries in the context of the answer on which the
12334
- * custom action was triggered.
12183
+ * Events which can be triggered on the emitter returned from {@link init}.
12335
12184
  *
12336
- * @example
12337
- * ```js
12338
- * embed.on(EmbedEvent.CustomAction, e => {
12339
- * const underlying = await e.answerService.getUnderlyingDataForPoint([
12340
- * 'col name 1'
12341
- * ]);
12342
- * const data = await underlying.fetchData(0, 100);
12343
- * })
12344
- * ```
12345
- * @version
12346
- * ThoughtSpot: 9.9.0.cl / SDK: 1.25.0
12347
- * @group Events
12185
+ * @group Authentication / Init
12348
12186
  */
12349
- class AnswerService {
12350
- constructor(session, answer, thoughtSpotHost, selectedPoints) {
12351
- this.session = session;
12352
- this.answer = answer;
12353
- this.thoughtSpotHost = thoughtSpotHost;
12354
- this.selectedPoints = selectedPoints;
12355
- this.session = removeTypename(session);
12187
+ var AuthEvent;
12188
+ (function (AuthEvent) {
12189
+ /**
12190
+ * Manually trigger the SSO popup. This is useful with
12191
+ * authStatus: SAMLRedirect/OIDCRedicre and inPopup: true
12192
+ */
12193
+ AuthEvent["TRIGGER_SSO_POPUP"] = "TRIGGER_SSO_POPUP";
12194
+ })(AuthEvent || (AuthEvent = {}));
12195
+ /**
12196
+ *
12197
+ */
12198
+ function notifyAuthSDKSuccess() {
12199
+ {
12200
+ console.error('SDK not initialized');
12201
+ return;
12356
12202
  }
12357
- async getSourceDetail() {
12358
- const sourceId = this.answer.sources[0].header.guid;
12359
- return getSourceDetail(this.thoughtSpotHost, sourceId);
12203
+ }
12204
+ /**
12205
+ *
12206
+ */
12207
+ function notifyAuthSuccess() {
12208
+ {
12209
+ console.error('SDK not initialized');
12210
+ return;
12360
12211
  }
12361
- async removeColumns(columnIds) {
12362
- return this.executeQuery(removeColumns, {
12363
- logicalColumnIds: columnIds,
12364
- });
12212
+ }
12213
+ /**
12214
+ *
12215
+ * @param failureType
12216
+ */
12217
+ function notifyAuthFailure(failureType) {
12218
+ {
12219
+ console.error('SDK not initialized');
12220
+ return;
12365
12221
  }
12366
- async addColumns(columnIds) {
12367
- return this.executeQuery(addColumns, {
12368
- columns: columnIds.map((colId) => ({ logicalColumnId: colId })),
12369
- });
12222
+ }
12223
+ /**
12224
+ *
12225
+ */
12226
+ function notifyLogout() {
12227
+ {
12228
+ console.error('SDK not initialized');
12229
+ return;
12370
12230
  }
12371
- async fetchData(offset = 0, size = 1000) {
12372
- const { answer } = await this.executeQuery(getAnswerData, {
12373
- deadline: 0,
12374
- dataPaginationParams: {
12375
- isClientPaginated: true,
12376
- offset,
12377
- size,
12378
- },
12379
- });
12380
- const { columns, data } = answer.visualizations[0];
12381
- return {
12382
- columns,
12383
- data,
12384
- };
12231
+ }
12232
+ const initSession = (sessionDetails) => {
12233
+ if (sessionInfo == null) {
12234
+ sessionInfo = sessionDetails;
12235
+ initMixpanel(sessionInfo);
12236
+ sessionInfoResolver(sessionInfo);
12385
12237
  }
12386
- /**
12387
- *
12388
- * @param userLocale
12389
- * @param includeInfo Include the CSV header in the output
12390
- * @returns Response
12391
- */
12392
- async fetchCSVBlob(userLocale = 'en-us', includeInfo = false) {
12393
- const fetchUrl = this.getFetchCSVBlobUrl(userLocale, includeInfo);
12394
- return tokenizedFetch(fetchUrl, {
12395
- credentials: 'include',
12396
- });
12238
+ };
12239
+ const getSessionDetails = (sessionInfoResp) => {
12240
+ console.log('helloooo');
12241
+ const devMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.devSdkKey;
12242
+ const prodMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.prodSdkKey;
12243
+ const mixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.production
12244
+ ? prodMixpanelToken
12245
+ : devMixpanelToken;
12246
+ return {
12247
+ userGUID: sessionInfoResp.userGUID,
12248
+ mixpanelToken,
12249
+ isPublicUser: sessionInfoResp.configInfo.isPublicUser,
12250
+ releaseVersion: sessionInfoResp.releaseVersion,
12251
+ clusterId: sessionInfoResp.configInfo.selfClusterId,
12252
+ clusterName: sessionInfoResp.configInfo.selfClusterName,
12253
+ ...sessionInfoResp,
12254
+ };
12255
+ };
12256
+ /**
12257
+ * Check if we are logged into the ThoughtSpot cluster
12258
+ *
12259
+ * @param thoughtSpotHost The ThoughtSpot cluster hostname or IP
12260
+ */
12261
+ async function isLoggedIn(thoughtSpotHost) {
12262
+ const authVerificationUrl = `${thoughtSpotHost}${EndPoints.AUTH_VERIFICATION}`;
12263
+ let response = null;
12264
+ try {
12265
+ response = await fetchSessionInfoService(authVerificationUrl);
12266
+ const sessionInfoResp = await response.json();
12267
+ const sessionDetails = getSessionDetails(sessionInfoResp);
12268
+ // Store user session details from session info
12269
+ initSession(sessionDetails);
12270
+ releaseVersion = sessionInfoResp.releaseVersion;
12397
12271
  }
12398
- getFetchCSVBlobUrl(userLocale = 'en-us', includeInfo = false) {
12399
- return `${this.thoughtSpotHost}/prism/download/answer/csv?sessionId=${this.session.sessionId}&genNo=${this.session.genNo}&userLocale=${userLocale}&exportFileName=data&hideCsvHeader=${!includeInfo}`;
12272
+ catch (e) {
12273
+ return false;
12400
12274
  }
12401
- /**
12402
- * Get underlying data given a point and the output column names.
12403
- *
12404
- * @param outputColumnNames
12405
- * @param selectedPoints
12406
- * @example
12407
- * ```js
12408
- * embed.on(EmbedEvent.CustomAction, e => {
12409
- * const underlying = await e.answerService.getUnderlyingDataForPoint([
12410
- * 'col name 1' // The column should exist in the data source.
12411
- * ]);
12412
- * const data = await underlying.fetchData(0, 100);
12413
- * })
12414
- * ```
12415
- * @version
12416
- * ThoughtSpot: 9.9.0.cl / SDK: 1.25.0
12417
- */
12418
- async getUnderlyingDataForPoint(outputColumnNames, selectedPoints) {
12419
- if (!selectedPoints && !this.selectedPoints) {
12420
- throw new Error('Needs to be triggered in context of a point');
12275
+ return response.status === 200;
12276
+ }
12277
+ /**
12278
+ * Return releaseVersion if available
12279
+ */
12280
+ function getReleaseVersion() {
12281
+ return releaseVersion;
12282
+ }
12283
+ /**
12284
+ * Check if we are stuck at the SSO redirect URL
12285
+ */
12286
+ function isAtSSORedirectUrl() {
12287
+ return window.location.href.indexOf(SSO_REDIRECTION_MARKER_GUID) >= 0;
12288
+ }
12289
+ /**
12290
+ * Remove the SSO redirect URL marker
12291
+ */
12292
+ function removeSSORedirectUrlMarker() {
12293
+ // Note (sunny): This will leave a # around even if it was not in the URL
12294
+ // to begin with. Trying to remove the hash by changing window.location will
12295
+ // reload the page which we don't want. We'll live with adding an
12296
+ // unnecessary hash to the parent page URL until we find any use case where
12297
+ // that creates an issue.
12298
+ window.location.hash = window.location.hash.replace(SSO_REDIRECTION_MARKER_GUID, '');
12299
+ }
12300
+ /**
12301
+ * Perform token based authentication
12302
+ *
12303
+ * @param embedConfig The embed configuration
12304
+ */
12305
+ const doTokenAuth = async (embedConfig) => {
12306
+ const { thoughtSpotHost, username, authEndpoint, getAuthToken, } = embedConfig;
12307
+ if (!authEndpoint && !getAuthToken) {
12308
+ throw new Error('Either auth endpoint or getAuthToken function must be provided');
12309
+ }
12310
+ loggedInStatus = await isLoggedIn(thoughtSpotHost);
12311
+ if (!loggedInStatus) {
12312
+ const authToken = await getAuthenticationToken(embedConfig);
12313
+ let resp;
12314
+ try {
12315
+ resp = await fetchAuthPostService(thoughtSpotHost, username, authToken);
12421
12316
  }
12422
- if (!selectedPoints) {
12423
- selectedPoints = getSelectedPointsForUnderlyingDataQuery(this.selectedPoints);
12317
+ catch (e) {
12318
+ resp = await fetchAuthService(thoughtSpotHost, username, authToken);
12319
+ }
12320
+ // token login issues a 302 when successful
12321
+ loggedInStatus = resp.ok || resp.type === 'opaqueredirect';
12322
+ if (loggedInStatus && embedConfig.detectCookieAccessSlow) {
12323
+ // When 3rd party cookie access is blocked, this will fail because
12324
+ // cookies will not be sent with the call.
12325
+ loggedInStatus = await isLoggedIn(thoughtSpotHost);
12326
+ }
12327
+ }
12328
+ return loggedInStatus;
12329
+ };
12330
+ /**
12331
+ * Validate embedConfig parameters required for cookielessTokenAuth
12332
+ *
12333
+ * @param embedConfig The embed configuration
12334
+ */
12335
+ const doCookielessTokenAuth = async (embedConfig) => {
12336
+ const { authEndpoint, getAuthToken } = embedConfig;
12337
+ if (!authEndpoint && !getAuthToken) {
12338
+ throw new Error('Either auth endpoint or getAuthToken function must be provided');
12339
+ }
12340
+ try {
12341
+ const authToken = await getAuthenticationToken(embedConfig);
12342
+ if (authToken)
12343
+ return true;
12344
+ }
12345
+ catch {
12346
+ // return false if getAuthenticationToken fails
12347
+ }
12348
+ return false;
12349
+ };
12350
+ /**
12351
+ * Perform basic authentication to the ThoughtSpot cluster using the cluster
12352
+ * credentials.
12353
+ *
12354
+ * Warning: This feature is primarily intended for developer testing. It is
12355
+ * strongly advised not to use this authentication method in production.
12356
+ *
12357
+ * @param embedConfig The embed configuration
12358
+ */
12359
+ const doBasicAuth = async (embedConfig) => {
12360
+ const { thoughtSpotHost, username, password } = embedConfig;
12361
+ const loggedIn = await isLoggedIn(thoughtSpotHost);
12362
+ if (!loggedIn) {
12363
+ const response = await fetchBasicAuthService(thoughtSpotHost, username, password);
12364
+ loggedInStatus = response.ok;
12365
+ if (embedConfig.detectCookieAccessSlow) {
12366
+ loggedInStatus = await isLoggedIn(thoughtSpotHost);
12424
12367
  }
12425
- const sourceDetail = await this.getSourceDetail();
12426
- const ouputColumnGuids = getGuidsFromColumnNames(sourceDetail, outputColumnNames);
12427
- const unAggAnswer = await graphqlQuery({
12428
- query: getUnaggregatedAnswerSession,
12429
- variables: {
12430
- session: this.session,
12431
- columns: selectedPoints,
12432
- },
12433
- thoughtSpotHost: this.thoughtSpotHost,
12434
- });
12435
- const unaggAnswerSession = new AnswerService(unAggAnswer.id, unAggAnswer.answer, this.thoughtSpotHost);
12436
- const currentColumns = new Set(unAggAnswer.answer.visualizations[0].columns
12437
- .map((c) => c.column.referencedColumns[0].guid));
12438
- const columnsToAdd = [...ouputColumnGuids].filter((col) => !currentColumns.has(col));
12439
- if (columnsToAdd.length) {
12440
- await unaggAnswerSession.addColumns(columnsToAdd);
12368
+ }
12369
+ else {
12370
+ loggedInStatus = true;
12371
+ }
12372
+ return loggedInStatus;
12373
+ };
12374
+ /**
12375
+ *
12376
+ * @param ssoURL
12377
+ * @param triggerContainer
12378
+ * @param triggerText
12379
+ */
12380
+ async function samlPopupFlow(ssoURL, triggerContainer, triggerText) {
12381
+ const openPopup = () => {
12382
+ if (samlAuthWindow === null || samlAuthWindow.closed) {
12383
+ samlAuthWindow = window.open(ssoURL, '_blank', 'location=no,height=570,width=520,scrollbars=yes,status=yes');
12441
12384
  }
12442
- const columnsToRemove = [...currentColumns].filter((col) => !ouputColumnGuids.has(col));
12443
- if (columnsToRemove.length) {
12444
- await unaggAnswerSession.removeColumns(columnsToRemove);
12385
+ else {
12386
+ samlAuthWindow.focus();
12445
12387
  }
12446
- return unaggAnswerSession;
12388
+ };
12389
+ const containerEl = getDOMNode(triggerContainer);
12390
+ if (containerEl) {
12391
+ containerEl.innerHTML = '<button id="ts-auth-btn" class="ts-auth-btn" style="margin: auto;"></button>';
12392
+ const authElem = document.getElementById('ts-auth-btn');
12393
+ authElem.textContent = triggerText;
12394
+ authElem.addEventListener('click', openPopup, { once: true });
12447
12395
  }
12448
- async executeQuery(query, variables) {
12449
- const data = await graphqlQuery({
12450
- query,
12451
- variables: {
12452
- session: this.session,
12453
- ...variables,
12454
- },
12455
- thoughtSpotHost: this.thoughtSpotHost,
12456
- isCompositeQuery: false,
12396
+ samlCompletionPromise = samlCompletionPromise
12397
+ || new Promise((resolve, reject) => {
12398
+ window.addEventListener('message', (e) => {
12399
+ if (e.data.type === exports.EmbedEvent.SAMLComplete) {
12400
+ e.source.close();
12401
+ resolve();
12402
+ }
12403
+ });
12457
12404
  });
12458
- this.session = deepMerge(this.session, (data === null || data === void 0 ? void 0 : data.id) || {});
12459
- return data;
12460
- }
12461
- getSession() {
12462
- return this.session;
12463
- }
12405
+ return samlCompletionPromise;
12464
12406
  }
12465
12407
  /**
12408
+ * Perform SAML authentication
12466
12409
  *
12467
- * @param sourceDetail
12468
- * @param colNames
12410
+ * @param embedConfig The embed configuration
12411
+ * @param ssoEndPoint
12469
12412
  */
12470
- function getGuidsFromColumnNames(sourceDetail, colNames) {
12471
- const cols = sourceDetail.columns.reduce((colSet, col) => {
12472
- colSet[col.name] = col;
12473
- return colSet;
12474
- }, {});
12475
- return new Set(colNames.map((colName) => {
12476
- const col = cols[colName];
12477
- return col.id;
12478
- }));
12479
- }
12413
+ const doSSOAuth = async (embedConfig, ssoEndPoint) => {
12414
+ const { thoughtSpotHost } = embedConfig;
12415
+ const loggedIn = await isLoggedIn(thoughtSpotHost);
12416
+ if (loggedIn) {
12417
+ if (isAtSSORedirectUrl()) {
12418
+ removeSSORedirectUrlMarker();
12419
+ }
12420
+ loggedInStatus = true;
12421
+ return;
12422
+ }
12423
+ // we have already tried authentication and it did not succeed, restore
12424
+ // the current URL to the original one and invoke the callback.
12425
+ if (isAtSSORedirectUrl()) {
12426
+ removeSSORedirectUrlMarker();
12427
+ loggedInStatus = false;
12428
+ return;
12429
+ }
12430
+ const ssoURL = `${thoughtSpotHost}${ssoEndPoint}`;
12431
+ if (embedConfig.inPopup) {
12432
+ await samlPopupFlow(ssoURL, embedConfig.authTriggerContainer, embedConfig.authTriggerText);
12433
+ loggedInStatus = await isLoggedIn(thoughtSpotHost);
12434
+ return;
12435
+ }
12436
+ window.location.href = ssoURL;
12437
+ };
12438
+ const doSamlAuth = async (embedConfig) => {
12439
+ const { thoughtSpotHost } = embedConfig;
12440
+ // redirect for SSO, when the SSO authentication is done, this page will be
12441
+ // loaded again and the same JS will execute again.
12442
+ const ssoRedirectUrl = embedConfig.inPopup
12443
+ ? `${thoughtSpotHost}/v2/#/embed/saml-complete`
12444
+ : getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
12445
+ // bring back the page to the same URL
12446
+ const ssoEndPoint = `${EndPoints.SAML_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
12447
+ await doSSOAuth(embedConfig, ssoEndPoint);
12448
+ return loggedInStatus;
12449
+ };
12450
+ const doOIDCAuth = async (embedConfig) => {
12451
+ const { thoughtSpotHost } = embedConfig;
12452
+ // redirect for SSO, when the SSO authentication is done, this page will be
12453
+ // loaded again and the same JS will execute again.
12454
+ const ssoRedirectUrl = embedConfig.noRedirect || embedConfig.inPopup
12455
+ ? `${thoughtSpotHost}/v2/#/embed/saml-complete`
12456
+ : getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
12457
+ // bring back the page to the same URL
12458
+ const ssoEndPoint = `${EndPoints.OIDC_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
12459
+ await doSSOAuth(embedConfig, ssoEndPoint);
12460
+ return loggedInStatus;
12461
+ };
12480
12462
  /**
12463
+ * Perform authentication on the ThoughtSpot cluster
12481
12464
  *
12482
- * @param selectedPoints
12465
+ * @param embedConfig The embed configuration
12483
12466
  */
12484
- function getSelectedPointsForUnderlyingDataQuery(selectedPoints) {
12485
- const underlyingDataPoint = [];
12486
- /**
12487
- *
12488
- * @param colVal
12489
- */
12490
- function addPointFromColVal(colVal) {
12491
- var _a;
12492
- const dataType = colVal.column.dataType;
12493
- const id = colVal.column.id;
12494
- let dataValue;
12495
- if (dataType === 'DATE') {
12496
- if (Number.isFinite(colVal.value)) {
12497
- dataValue = [{
12498
- epochRange: {
12499
- startEpoch: colVal.value,
12500
- },
12501
- }];
12502
- // Case for custom calendar.
12503
- }
12504
- else if ((_a = colVal.value) === null || _a === void 0 ? void 0 : _a.v) {
12505
- dataValue = [{
12506
- epochRange: {
12507
- startEpoch: colVal.value.v.s,
12508
- endEpoch: colVal.value.v.e,
12509
- },
12510
- }];
12511
- }
12467
+ const authenticate = async (embedConfig) => {
12468
+ const { authType } = embedConfig;
12469
+ switch (authType) {
12470
+ case AuthType.SSO:
12471
+ case AuthType.SAMLRedirect:
12472
+ case AuthType.SAML:
12473
+ return doSamlAuth(embedConfig);
12474
+ case AuthType.OIDC:
12475
+ case AuthType.OIDCRedirect:
12476
+ return doOIDCAuth(embedConfig);
12477
+ case AuthType.AuthServer:
12478
+ case AuthType.TrustedAuthToken:
12479
+ return doTokenAuth(embedConfig);
12480
+ case AuthType.TrustedAuthTokenCookieless:
12481
+ return doCookielessTokenAuth(embedConfig);
12482
+ case AuthType.Basic:
12483
+ return doBasicAuth(embedConfig);
12484
+ default:
12485
+ return Promise.resolve(true);
12486
+ }
12487
+ };
12488
+
12489
+ /* eslint-disable camelcase */
12490
+ const CONFIG_DEFAULTS = {
12491
+ loginFailedMessage: 'Not logged in',
12492
+ authTriggerText: 'Authorize',
12493
+ authType: AuthType.None,
12494
+ };
12495
+ let authPromise;
12496
+ const getAuthPromise = () => authPromise;
12497
+ /**
12498
+ * Perform authentication on the ThoughtSpot app as applicable.
12499
+ */
12500
+ const handleAuth = () => {
12501
+ authPromise = authenticate(getEmbedConfig());
12502
+ authPromise.then((isLoggedIn) => {
12503
+ if (!isLoggedIn) {
12504
+ notifyAuthFailure(AuthFailureType.SDK);
12512
12505
  }
12513
12506
  else {
12514
- dataValue = [{ value: colVal.value }];
12507
+ notifyAuthSDKSuccess();
12515
12508
  }
12516
- underlyingDataPoint.push({
12517
- columnId: colVal.column.id,
12518
- dataValue,
12519
- });
12520
- }
12521
- selectedPoints.forEach((p) => {
12522
- p.selectedAttributes.forEach(addPointFromColVal);
12509
+ }, () => {
12510
+ notifyAuthFailure(AuthFailureType.SDK);
12523
12511
  });
12524
- return underlyingDataPoint;
12525
- }
12512
+ return authPromise;
12513
+ };
12514
+ const hostUrlToFeatureUrl = {
12515
+ [PrefetchFeatures.SearchEmbed]: (url) => `${url}v2/#/embed/answer`,
12516
+ [PrefetchFeatures.LiveboardEmbed]: (url) => url,
12517
+ [PrefetchFeatures.FullApp]: (url) => url,
12518
+ [PrefetchFeatures.VizEmbed]: (url) => url,
12519
+ };
12520
+ /**
12521
+ *
12522
+ */
12523
+ function disableAutoLogin() {
12524
+ getEmbedConfig().autoLogin = false;
12525
+ }
12526
+ let renderQueue = Promise.resolve();
12527
+ /**
12528
+ * Renders functions in a queue, resolves to next function only after the callback next
12529
+ * is called
12530
+ *
12531
+ * @param fn The function being registered
12532
+ */
12533
+ const renderInQueue = (fn) => {
12534
+ const { queueMultiRenders = false } = getEmbedConfig();
12535
+ if (queueMultiRenders) {
12536
+ renderQueue = renderQueue.then(() => new Promise((res) => fn(res)));
12537
+ return renderQueue;
12538
+ }
12539
+ // Sending an empty function to keep it consistent with the above usage.
12540
+ return fn(() => { }); // eslint-disable-line @typescript-eslint/no-empty-function
12541
+ };
12526
12542
 
12527
12543
  /**
12528
12544
  *
@@ -12680,7 +12696,7 @@ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!]
12680
12696
  });
12681
12697
  }
12682
12698
 
12683
- var name="@thoughtspot/visual-embed-sdk";var version="1.26.0-token-cache.0";var description="ThoughtSpot Embed SDK";var module="lib/src/index.js";var main="dist/tsembed.js";var types="lib/src/index.d.ts";var files=["dist/**","lib/**","src/**","cjs/**"];var exports$1={".":{"import":"./lib/src/index.js",require:"./cjs/src/index.js",types:"./lib/src/index.d.ts"},"./react":{"import":"./lib/src/react/all-types-export.js",require:"./cjs/src/react/all-types-export.js",types:"./lib/src/react/all-types-export.d.ts"},"./lib/src/react":{"import":"./lib/src/react/all-types-export.js",require:"./cjs/src/react/all-types-export.js",types:"./lib/src/react/all-types-export.d.ts"}};var typesVersions={"*":{react:["./lib/src/react/all-types-export.d.ts"]}};var scripts={lint:"eslint 'src/**'","lint:fix":"eslint 'src/**/*.*' --fix",tsc:"tsc -p . --incremental false; tsc -p . --incremental false --module commonjs --outDir cjs",start:"gatsby develop","build:gatsby":"npm run clean:gatsby && gatsby build --prefix-paths","build:gatsby:noprefix":"npm run clean:gatsby && gatsby build","serve:gatsby":"gatsby serve","clean:gatsby":"gatsby clean","build-and-publish":"npm run build:gatsby && npm run publish","bundle-dts-file":"dts-bundle --name @thoughtspot/visual-embed-sdk --out visual-embed-sdk.d.ts --main lib/src/index.d.ts","bundle-dts":"dts-bundle --name ../../dist/visual-embed-sdk --main lib/src/index.d.ts --outputAsModuleFolder=true","bundle-dts-react":"dts-bundle --name ../../../dist/visual-embed-sdk-react --main lib/src/react/index.d.ts --outputAsModuleFolder=true","bundle-dts-react-full":"dts-bundle --name ../../../dist/visual-embed-sdk-react-full --main lib/src/react/all-types-export.d.ts --outputAsModuleFolder=true",build:"rollup -c",watch:"rollup -cw","docs-cmd":"node scripts/gatsby-commands.js",docgen:"typedoc --tsconfig tsconfig.json --theme typedoc-theme","test-sdk":"jest -c jest.config.sdk.js --runInBand","test-docs":"jest -c jest.config.docs.js",test:"npm run test-sdk && npm run test-docs",posttest:"cat ./coverage/sdk/lcov.info | coveralls","is-publish-allowed":"node scripts/is-publish-allowed.js",prepublishOnly:"npm run is-publish-allowed && npm run test && npm run tsc && npm run bundle-dts-file && npm run bundle-dts && npm run bundle-dts-react && npm run bundle-dts-react-full && npm run build","check-size":"npm run build && size-limit","publish-dev":"npm publish --tag dev","publish-prod":"npm publish --tag latest"};var peerDependencies={react:"> 16.8.0","react-dom":"> 16.8.0"};var dependencies={algoliasearch:"^4.10.5",classnames:"^2.3.1",dompurify:"^2.3.4","eslint-plugin-comment-length":"^0.9.2","eslint-plugin-jsdoc":"^40.1.0",eventemitter3:"^4.0.7","gatsby-plugin-vercel":"^1.0.3","html-react-parser":"^1.4.12",lodash:"^4.17.21","mixpanel-browser":"^2.45.0","ts-deepmerge":"^6.0.2",tslib:"^2.5.3","use-deep-compare-effect":"^1.8.1"};var devDependencies={"@mdx-js/mdx":"^1.6.22","@mdx-js/react":"^1.6.22","@react-icons/all-files":"^4.1.0","@rollup/plugin-commonjs":"^18.0.0","@rollup/plugin-json":"^4.1.0","@rollup/plugin-node-resolve":"^11.2.1","@rollup/plugin-replace":"^5.0.2","@size-limit/preset-big-lib":"^8.2.6","@testing-library/dom":"^7.31.0","@testing-library/jest-dom":"^5.14.1","@testing-library/react":"^11.2.7","@testing-library/user-event":"^13.1.8","@types/jest":"^22.2.3","@types/mixpanel-browser":"^2.35.6","@types/react-test-renderer":"^17.0.1","@typescript-eslint/eslint-plugin":"^4.6.0","@typescript-eslint/parser":"^4.6.0",asciidoctor:"^2.2.1","babel-jest":"^26.6.3","babel-preset-gatsby":"^1.10.0","command-line-args":"^5.1.1",coveralls:"^3.1.0","current-git-branch":"^1.1.0","dts-bundle":"^0.7.3",eslint:"^7.12.1","eslint-config-airbnb-base":"^14.2.0","eslint-config-prettier":"^6.15.0","eslint-import-resolver-typescript":"^2.3.0","eslint-plugin-import":"^2.22.1","eslint-plugin-prettier":"^3.1.4","eslint-plugin-react-hooks":"^4.2.0","fs-extra":"^10.0.0",gatsby:"3.13.1","gatsby-plugin-algolia":"^0.22.2","gatsby-plugin-catch-links":"^3.1.0","gatsby-plugin-env-variables":"^2.1.0","gatsby-plugin-intl":"^0.3.3","gatsby-plugin-manifest":"^3.2.0","gatsby-plugin-output":"^0.1.3","gatsby-plugin-sass":"6.7.0","gatsby-plugin-sitemap":"^4.10.0","gatsby-source-filesystem":"3.1.0","gatsby-transformer-asciidoc":"2.1.0","gatsby-transformer-rehype":"2.0.0","gh-pages":"^3.1.0","highlight.js":"^10.6.0","html-to-text":"^8.0.0","identity-obj-proxy":"^3.0.0","istanbul-merge":"^1.1.1",jest:"^26.6.3","jest-fetch-mock":"^3.0.3",jsdom:"^17.0.0","node-sass":"^8.0.0",prettier:"2.1.2",react:"^16.14.0","react-dom":"^16.14.0","react-resizable":"^1.11.0","react-resize-detector":"^6.6.0","react-test-renderer":"^17.0.2","react-use-flexsearch":"^0.1.1",rollup:"2.30.0","rollup-plugin-typescript2":"0.27.3","ts-jest":"^26.5.5","ts-loader":"8.0.4",typedoc:"0.21.6","typedoc-plugin-toc-group":"thoughtspot/typedoc-plugin-toc-group",typescript:"^4.9.4","url-search-params-polyfill":"^8.1.0",util:"^0.12.4"};var author="ThoughtSpot";var email="support@thoughtspot.com";var license="ThoughtSpot Development Tools End User License Agreement";var directories={lib:"lib"};var repository={type:"git",url:"git+https://github.com/thoughtspot/visual-embed-sdk.git"};var publishConfig={registry:"https://registry.npmjs.org"};var keywords=["thoughtspot","everywhere","embed","sdk","analytics"];var bugs={url:"https://github.com/thoughtspot/visual-embed-sdk/issues"};var homepage="https://github.com/thoughtspot/visual-embed-sdk#readme";var globals={window:{}};var pkgInfo = {name:name,version:version,description:description,module:module,main:main,types:types,files:files,exports:exports$1,typesVersions:typesVersions,"size-limit":[{path:"dist/tsembed.js",limit:"43 kB"}],scripts:scripts,peerDependencies:peerDependencies,dependencies:dependencies,devDependencies:devDependencies,author:author,email:email,license:license,directories:directories,repository:repository,publishConfig:publishConfig,keywords:keywords,bugs:bugs,homepage:homepage,globals:globals};
12699
+ var name="@thoughtspot/visual-embed-sdk";var version="1.26.0-token-cache.2";var description="ThoughtSpot Embed SDK";var module="lib/src/index.js";var main="dist/tsembed.js";var types="lib/src/index.d.ts";var files=["dist/**","lib/**","src/**","cjs/**"];var exports$1={".":{"import":"./lib/src/index.js",require:"./cjs/src/index.js",types:"./lib/src/index.d.ts"},"./react":{"import":"./lib/src/react/all-types-export.js",require:"./cjs/src/react/all-types-export.js",types:"./lib/src/react/all-types-export.d.ts"},"./lib/src/react":{"import":"./lib/src/react/all-types-export.js",require:"./cjs/src/react/all-types-export.js",types:"./lib/src/react/all-types-export.d.ts"}};var typesVersions={"*":{react:["./lib/src/react/all-types-export.d.ts"]}};var scripts={lint:"eslint 'src/**'","lint:fix":"eslint 'src/**/*.*' --fix",tsc:"tsc -p . --incremental false; tsc -p . --incremental false --module commonjs --outDir cjs",start:"gatsby develop","build:gatsby":"npm run clean:gatsby && gatsby build --prefix-paths","build:gatsby:noprefix":"npm run clean:gatsby && gatsby build","serve:gatsby":"gatsby serve","clean:gatsby":"gatsby clean","build-and-publish":"npm run build:gatsby && npm run publish","bundle-dts-file":"dts-bundle --name @thoughtspot/visual-embed-sdk --out visual-embed-sdk.d.ts --main lib/src/index.d.ts","bundle-dts":"dts-bundle --name ../../dist/visual-embed-sdk --main lib/src/index.d.ts --outputAsModuleFolder=true","bundle-dts-react":"dts-bundle --name ../../../dist/visual-embed-sdk-react --main lib/src/react/index.d.ts --outputAsModuleFolder=true","bundle-dts-react-full":"dts-bundle --name ../../../dist/visual-embed-sdk-react-full --main lib/src/react/all-types-export.d.ts --outputAsModuleFolder=true",build:"rollup -c",watch:"rollup -cw","docs-cmd":"node scripts/gatsby-commands.js",docgen:"typedoc --tsconfig tsconfig.json --theme typedoc-theme","test-sdk":"jest -c jest.config.sdk.js --runInBand","test-docs":"jest -c jest.config.docs.js",test:"npm run test-sdk && npm run test-docs",posttest:"cat ./coverage/sdk/lcov.info | coveralls","is-publish-allowed":"node scripts/is-publish-allowed.js",prepublishOnly:"npm run is-publish-allowed && npm run test && npm run tsc && npm run bundle-dts-file && npm run bundle-dts && npm run bundle-dts-react && npm run bundle-dts-react-full && npm run build","check-size":"npm run build && size-limit","publish-dev":"npm publish --tag dev","publish-prod":"npm publish --tag latest"};var peerDependencies={react:"> 16.8.0","react-dom":"> 16.8.0"};var dependencies={algoliasearch:"^4.10.5",classnames:"^2.3.1",dompurify:"^2.3.4","eslint-plugin-comment-length":"^0.9.2","eslint-plugin-jsdoc":"^40.1.0",eventemitter3:"^4.0.7","gatsby-plugin-vercel":"^1.0.3","html-react-parser":"^1.4.12",lodash:"^4.17.21","mixpanel-browser":"^2.45.0","ts-deepmerge":"^6.0.2",tslib:"^2.5.3","use-deep-compare-effect":"^1.8.1"};var devDependencies={"@mdx-js/mdx":"^1.6.22","@mdx-js/react":"^1.6.22","@react-icons/all-files":"^4.1.0","@rollup/plugin-commonjs":"^18.0.0","@rollup/plugin-json":"^4.1.0","@rollup/plugin-node-resolve":"^11.2.1","@rollup/plugin-replace":"^5.0.2","@size-limit/preset-big-lib":"^8.2.6","@testing-library/dom":"^7.31.0","@testing-library/jest-dom":"^5.14.1","@testing-library/react":"^11.2.7","@testing-library/user-event":"^13.1.8","@types/jest":"^22.2.3","@types/mixpanel-browser":"^2.35.6","@types/react-test-renderer":"^17.0.1","@typescript-eslint/eslint-plugin":"^4.6.0","@typescript-eslint/parser":"^4.6.0",asciidoctor:"^2.2.1","babel-jest":"^26.6.3","babel-preset-gatsby":"^1.10.0","command-line-args":"^5.1.1",coveralls:"^3.1.0","current-git-branch":"^1.1.0","dts-bundle":"^0.7.3",eslint:"^7.12.1","eslint-config-airbnb-base":"^14.2.0","eslint-config-prettier":"^6.15.0","eslint-import-resolver-typescript":"^2.3.0","eslint-plugin-import":"^2.22.1","eslint-plugin-prettier":"^3.1.4","eslint-plugin-react-hooks":"^4.2.0","fs-extra":"^10.0.0",gatsby:"3.13.1","gatsby-plugin-algolia":"^0.22.2","gatsby-plugin-catch-links":"^3.1.0","gatsby-plugin-env-variables":"^2.1.0","gatsby-plugin-intl":"^0.3.3","gatsby-plugin-manifest":"^3.2.0","gatsby-plugin-output":"^0.1.3","gatsby-plugin-sass":"6.7.0","gatsby-plugin-sitemap":"^4.10.0","gatsby-source-filesystem":"3.1.0","gatsby-transformer-asciidoc":"2.1.0","gatsby-transformer-rehype":"2.0.0","gh-pages":"^3.1.0","highlight.js":"^10.6.0","html-to-text":"^8.0.0","identity-obj-proxy":"^3.0.0","istanbul-merge":"^1.1.1",jest:"^26.6.3","jest-fetch-mock":"^3.0.3",jsdom:"^17.0.0","node-sass":"^8.0.0",prettier:"2.1.2",react:"^16.14.0","react-dom":"^16.14.0","react-resizable":"^1.11.0","react-resize-detector":"^6.6.0","react-test-renderer":"^17.0.2","react-use-flexsearch":"^0.1.1",rollup:"2.30.0","rollup-plugin-typescript2":"0.27.3","ts-jest":"^26.5.5","ts-loader":"8.0.4",typedoc:"0.21.6","typedoc-plugin-toc-group":"thoughtspot/typedoc-plugin-toc-group",typescript:"^4.9.4","url-search-params-polyfill":"^8.1.0",util:"^0.12.4"};var author="ThoughtSpot";var email="support@thoughtspot.com";var license="ThoughtSpot Development Tools End User License Agreement";var directories={lib:"lib"};var repository={type:"git",url:"git+https://github.com/thoughtspot/visual-embed-sdk.git"};var publishConfig={registry:"https://registry.npmjs.org"};var keywords=["thoughtspot","everywhere","embed","sdk","analytics"];var bugs={url:"https://github.com/thoughtspot/visual-embed-sdk/issues"};var homepage="https://github.com/thoughtspot/visual-embed-sdk#readme";var globals={window:{}};var pkgInfo = {name:name,version:version,description:description,module:module,main:main,types:types,files:files,exports:exports$1,typesVersions:typesVersions,"size-limit":[{path:"dist/tsembed.js",limit:"44 kB"}],scripts:scripts,peerDependencies:peerDependencies,dependencies:dependencies,devDependencies:devDependencies,author:author,email:email,license:license,directories:directories,repository:repository,publishConfig:publishConfig,keywords:keywords,bugs:bugs,homepage:homepage,globals:globals};
12684
12700
 
12685
12701
  /**
12686
12702
  * Copyright (c) 2022