@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.
- package/cjs/package.json +2 -2
- package/cjs/src/auth.d.ts.map +1 -1
- package/cjs/src/auth.js.map +1 -1
- package/cjs/src/auth.spec.d.ts.map +1 -1
- package/cjs/src/auth.spec.js +1 -1
- package/cjs/src/auth.spec.js.map +1 -1
- package/cjs/src/authToken.d.ts.map +1 -1
- package/cjs/src/authToken.js +3 -3
- package/cjs/src/authToken.js.map +1 -1
- package/cjs/src/embed/base.d.ts +0 -8
- package/cjs/src/embed/base.d.ts.map +1 -1
- package/cjs/src/embed/base.js +21 -45
- package/cjs/src/embed/base.js.map +1 -1
- package/cjs/src/embed/base.spec.js +12 -13
- package/cjs/src/embed/base.spec.js.map +1 -1
- package/cjs/src/embed/embedConfig.d.ts +18 -0
- package/cjs/src/embed/embedConfig.d.ts.map +1 -0
- package/cjs/src/embed/embedConfig.js +25 -0
- package/cjs/src/embed/embedConfig.js.map +1 -0
- package/cjs/src/embed/search.d.ts.map +1 -1
- package/cjs/src/embed/search.js +3 -2
- package/cjs/src/embed/search.js.map +1 -1
- package/cjs/src/embed/searchEmbed-basic-auth.spec.js +3 -2
- package/cjs/src/embed/searchEmbed-basic-auth.spec.js.map +1 -1
- package/cjs/src/embed/ts-embed.d.ts.map +1 -1
- package/cjs/src/embed/ts-embed.js +2 -1
- package/cjs/src/embed/ts-embed.js.map +1 -1
- package/cjs/src/embed/ts-embed.spec.js +11 -13
- package/cjs/src/embed/ts-embed.spec.js.map +1 -1
- package/cjs/src/index.d.ts +2 -1
- package/cjs/src/index.d.ts.map +1 -1
- package/cjs/src/index.js +2 -1
- package/cjs/src/index.js.map +1 -1
- package/cjs/src/tokenizedFetch.d.ts.map +1 -1
- package/cjs/src/tokenizedFetch.js +4 -4
- package/cjs/src/tokenizedFetch.js.map +1 -1
- package/cjs/src/utils/authService/authService.d.ts +45 -0
- package/cjs/src/utils/authService/authService.d.ts.map +1 -0
- package/cjs/src/utils/authService/authService.js +115 -0
- package/cjs/src/utils/authService/authService.js.map +1 -0
- package/cjs/src/utils/authService/authService.spec.d.ts +2 -0
- package/cjs/src/utils/authService/authService.spec.d.ts.map +1 -0
- package/cjs/src/utils/authService/authService.spec.js +82 -0
- package/cjs/src/utils/authService/authService.spec.js.map +1 -0
- package/cjs/src/utils/authService/index.d.ts +3 -0
- package/cjs/src/utils/authService/index.d.ts.map +1 -0
- package/cjs/src/utils/authService/index.js +14 -0
- package/cjs/src/utils/authService/index.js.map +1 -0
- package/cjs/src/utils/authService/tokenisedAuthSerice.d.ts +11 -0
- package/cjs/src/utils/authService/tokenisedAuthSerice.d.ts.map +1 -0
- package/cjs/src/utils/authService/tokenisedAuthSerice.js +44 -0
- package/cjs/src/utils/authService/tokenisedAuthSerice.js.map +1 -0
- package/cjs/src/utils/graphql/answerService/answerService.spec.js +2 -2
- package/cjs/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
- package/cjs/src/utils/processData.js +4 -3
- package/cjs/src/utils/processData.js.map +1 -1
- package/cjs/src/utils/processData.spec.js +8 -7
- package/cjs/src/utils/processData.spec.js.map +1 -1
- package/dist/src/auth.d.ts.map +1 -1
- package/dist/src/auth.spec.d.ts.map +1 -1
- package/dist/src/authToken.d.ts.map +1 -1
- package/dist/src/embed/base.d.ts +0 -8
- package/dist/src/embed/base.d.ts.map +1 -1
- package/dist/src/embed/embedConfig.d.ts +18 -0
- package/dist/src/embed/embedConfig.d.ts.map +1 -0
- package/dist/src/embed/search.d.ts.map +1 -1
- package/dist/src/embed/ts-embed.d.ts.map +1 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/tokenizedFetch.d.ts.map +1 -1
- package/dist/src/utils/authService/authService.d.ts +45 -0
- package/dist/src/utils/authService/authService.d.ts.map +1 -0
- package/dist/src/utils/authService/authService.spec.d.ts +2 -0
- package/dist/src/utils/authService/authService.spec.d.ts.map +1 -0
- package/dist/src/utils/authService/index.d.ts +3 -0
- package/dist/src/utils/authService/index.d.ts.map +1 -0
- package/dist/src/utils/authService/tokenisedAuthSerice.d.ts +11 -0
- package/dist/src/utils/authService/tokenisedAuthSerice.d.ts.map +1 -0
- package/dist/tsembed-react.es.js +1228 -1212
- package/dist/tsembed-react.js +1463 -1447
- package/dist/tsembed.es.js +1632 -1621
- package/dist/tsembed.js +1622 -1611
- package/dist/visual-embed-sdk-react-full.d.ts +17 -8
- package/dist/visual-embed-sdk-react.d.ts +17 -8
- package/dist/visual-embed-sdk.d.ts +17 -8
- package/lib/package.json +2 -2
- package/lib/src/auth.d.ts.map +1 -1
- package/lib/src/auth.js.map +1 -1
- package/lib/src/auth.spec.d.ts.map +1 -1
- package/lib/src/auth.spec.js +1 -1
- package/lib/src/auth.spec.js.map +1 -1
- package/lib/src/authToken.d.ts.map +1 -1
- package/lib/src/authToken.js +3 -3
- package/lib/src/authToken.js.map +1 -1
- package/lib/src/embed/base.d.ts +0 -8
- package/lib/src/embed/base.d.ts.map +1 -1
- package/lib/src/embed/base.js +20 -43
- package/lib/src/embed/base.js.map +1 -1
- package/lib/src/embed/base.spec.js +12 -13
- package/lib/src/embed/base.spec.js.map +1 -1
- package/lib/src/embed/embedConfig.d.ts +18 -0
- package/lib/src/embed/embedConfig.d.ts.map +1 -0
- package/lib/src/embed/embedConfig.js +20 -0
- package/lib/src/embed/embedConfig.js.map +1 -0
- package/lib/src/embed/search.d.ts.map +1 -1
- package/lib/src/embed/search.js +2 -1
- package/lib/src/embed/search.js.map +1 -1
- package/lib/src/embed/searchEmbed-basic-auth.spec.js +3 -2
- package/lib/src/embed/searchEmbed-basic-auth.spec.js.map +1 -1
- package/lib/src/embed/ts-embed.d.ts.map +1 -1
- package/lib/src/embed/ts-embed.js +2 -1
- package/lib/src/embed/ts-embed.js.map +1 -1
- package/lib/src/embed/ts-embed.spec.js +11 -13
- package/lib/src/embed/ts-embed.spec.js.map +1 -1
- package/lib/src/index.d.ts +2 -1
- package/lib/src/index.d.ts.map +1 -1
- package/lib/src/index.js +2 -1
- package/lib/src/index.js.map +1 -1
- package/lib/src/tokenizedFetch.d.ts.map +1 -1
- package/lib/src/tokenizedFetch.js +3 -3
- package/lib/src/tokenizedFetch.js.map +1 -1
- package/lib/src/utils/authService/authService.d.ts +45 -0
- package/lib/src/utils/authService/authService.d.ts.map +1 -0
- package/lib/src/utils/authService/authService.js +107 -0
- package/lib/src/utils/authService/authService.js.map +1 -0
- package/lib/src/utils/authService/authService.spec.d.ts +2 -0
- package/lib/src/utils/authService/authService.spec.d.ts.map +1 -0
- package/lib/src/utils/authService/authService.spec.js +80 -0
- package/lib/src/utils/authService/authService.spec.js.map +1 -0
- package/lib/src/utils/authService/index.d.ts +3 -0
- package/lib/src/utils/authService/index.d.ts.map +1 -0
- package/lib/src/utils/authService/index.js +3 -0
- package/lib/src/utils/authService/index.js.map +1 -0
- package/lib/src/utils/authService/tokenisedAuthSerice.d.ts +11 -0
- package/lib/src/utils/authService/tokenisedAuthSerice.d.ts.map +1 -0
- package/lib/src/utils/authService/tokenisedAuthSerice.js +39 -0
- package/lib/src/utils/authService/tokenisedAuthSerice.js.map +1 -0
- package/lib/src/utils/graphql/answerService/answerService.spec.js +2 -2
- package/lib/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
- package/lib/src/utils/processData.js +2 -1
- package/lib/src/utils/processData.js.map +1 -1
- package/lib/src/utils/processData.spec.js +8 -7
- package/lib/src/utils/processData.spec.js.map +1 -1
- package/lib/src/visual-embed-sdk.d.ts +22 -9
- package/package.json +2 -2
- package/src/auth.spec.ts +29 -28
- package/src/auth.ts +1 -5
- package/src/authToken.ts +11 -3
- package/src/embed/base.spec.ts +13 -13
- package/src/embed/base.ts +26 -50
- package/src/embed/embedConfig.ts +23 -0
- package/src/embed/search.ts +9 -10
- package/src/embed/searchEmbed-basic-auth.spec.ts +3 -2
- package/src/embed/ts-embed.spec.ts +34 -36
- package/src/embed/ts-embed.ts +9 -19
- package/src/index.ts +8 -2
- package/src/tokenizedFetch.ts +6 -4
- package/src/utils/{authService.spec.ts → authService/authService.spec.ts} +1 -1
- package/src/utils/{authService.ts → authService/authService.ts} +0 -24
- package/src/utils/authService/index.ts +9 -0
- package/src/utils/authService/tokenisedAuthSerice.ts +40 -0
- package/src/utils/graphql/answerService/answerService.spec.ts +2 -2
- package/src/utils/processData.spec.ts +19 -16
- package/src/utils/processData.ts +1 -1
package/dist/tsembed-react.js
CHANGED
|
@@ -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
|
-
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5208
|
-
|
|
5209
|
-
|
|
5210
|
-
*
|
|
5211
|
-
|
|
5212
|
-
|
|
5213
|
-
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
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
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
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
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
|
|
5350
|
-
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
|
|
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
|
-
|
|
5499
|
-
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
|
|
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
|
-
*
|
|
5599
|
-
*
|
|
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
|
-
* @
|
|
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
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
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
|
-
|
|
5608
|
-
|
|
5609
|
-
|
|
5453
|
+
async getSourceDetail() {
|
|
5454
|
+
const sourceId = this.answer.sources[0].header.guid;
|
|
5455
|
+
return getSourceDetail(this.thoughtSpotHost, sourceId);
|
|
5610
5456
|
}
|
|
5611
|
-
|
|
5612
|
-
|
|
5613
|
-
|
|
5614
|
-
|
|
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
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
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
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
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
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
|
|
5653
|
-
|
|
5654
|
-
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
|
|
5658
|
-
|
|
5659
|
-
|
|
5660
|
-
|
|
5661
|
-
|
|
5662
|
-
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
5671
|
-
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
|
|
5714
|
-
|
|
5715
|
-
|
|
5716
|
-
|
|
5717
|
-
|
|
5718
|
-
|
|
5719
|
-
|
|
5720
|
-
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
|
|
5766
|
-
|
|
5767
|
-
|
|
5768
|
-
|
|
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
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
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
|
-
*
|
|
5803
|
-
*
|
|
5804
|
-
*
|
|
5805
|
-
|
|
5806
|
-
|
|
5807
|
-
|
|
5808
|
-
|
|
5809
|
-
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
}
|
|
5813
|
-
|
|
5814
|
-
|
|
5815
|
-
|
|
5816
|
-
|
|
5817
|
-
|
|
5818
|
-
|
|
5819
|
-
|
|
5820
|
-
|
|
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
|
-
*
|
|
11696
|
+
* Pushes the event with its Property key-value map to mixpanel.
|
|
11990
11697
|
*
|
|
11991
|
-
* @param
|
|
11992
|
-
* @param
|
|
11698
|
+
* @param eventId
|
|
11699
|
+
* @param eventProps
|
|
11993
11700
|
*/
|
|
11994
|
-
|
|
11995
|
-
|
|
11996
|
-
|
|
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
|
-
|
|
12012
|
-
|
|
12013
|
-
|
|
12014
|
-
|
|
11706
|
+
mixpanelInstance.track(eventId, eventProps);
|
|
11707
|
+
}
|
|
11708
|
+
/**
|
|
11709
|
+
*
|
|
11710
|
+
*/
|
|
11711
|
+
function emptyQueue() {
|
|
11712
|
+
if (!isMixpanelInitialized) {
|
|
12015
11713
|
return;
|
|
12016
11714
|
}
|
|
12017
|
-
|
|
12018
|
-
|
|
12019
|
-
|
|
12020
|
-
|
|
12021
|
-
|
|
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
|
|
11722
|
+
* @param sessionInfo
|
|
12047
11723
|
*/
|
|
12048
|
-
|
|
12049
|
-
|
|
12050
|
-
|
|
12051
|
-
|
|
12052
|
-
|
|
12053
|
-
|
|
12054
|
-
|
|
12055
|
-
|
|
12056
|
-
|
|
12057
|
-
|
|
12058
|
-
|
|
12059
|
-
|
|
12060
|
-
|
|
12061
|
-
|
|
12062
|
-
|
|
12063
|
-
|
|
12064
|
-
|
|
12065
|
-
|
|
12066
|
-
|
|
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
|
-
|
|
12071
|
-
|
|
12072
|
-
|
|
12073
|
-
|
|
12074
|
-
|
|
12075
|
-
|
|
12076
|
-
|
|
12077
|
-
|
|
12078
|
-
|
|
12079
|
-
|
|
12080
|
-
|
|
12081
|
-
|
|
12082
|
-
|
|
12083
|
-
|
|
12084
|
-
|
|
12085
|
-
|
|
12086
|
-
|
|
12087
|
-
|
|
12088
|
-
*
|
|
12089
|
-
|
|
12090
|
-
|
|
12091
|
-
|
|
12092
|
-
|
|
12093
|
-
|
|
12094
|
-
|
|
12095
|
-
|
|
12096
|
-
|
|
12097
|
-
|
|
12098
|
-
|
|
12099
|
-
|
|
12100
|
-
|
|
12101
|
-
|
|
12102
|
-
|
|
12103
|
-
|
|
12104
|
-
|
|
12105
|
-
|
|
12106
|
-
|
|
12107
|
-
|
|
12108
|
-
|
|
12109
|
-
|
|
12110
|
-
|
|
12111
|
-
|
|
12112
|
-
|
|
12113
|
-
|
|
12114
|
-
|
|
12115
|
-
|
|
12116
|
-
|
|
12117
|
-
|
|
12118
|
-
|
|
12119
|
-
|
|
12120
|
-
|
|
12121
|
-
|
|
12122
|
-
|
|
12123
|
-
|
|
12124
|
-
|
|
12125
|
-
|
|
12126
|
-
|
|
12127
|
-
|
|
12128
|
-
|
|
12129
|
-
|
|
12130
|
-
|
|
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
|
-
|
|
12134
|
-
|
|
12135
|
-
|
|
12136
|
-
|
|
12137
|
-
|
|
12138
|
-
|
|
12139
|
-
|
|
12140
|
-
|
|
12141
|
-
|
|
12142
|
-
|
|
12143
|
-
|
|
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
|
-
* @
|
|
12149
|
-
* @param root0.query
|
|
12150
|
-
* @param root0.variables
|
|
12151
|
-
* @param root0.thoughtSpotHost
|
|
12152
|
-
* @param root0.isCompositeQuery
|
|
12141
|
+
* @group Authentication / Init
|
|
12153
12142
|
*/
|
|
12154
|
-
|
|
12155
|
-
|
|
12156
|
-
|
|
12157
|
-
|
|
12158
|
-
|
|
12159
|
-
|
|
12160
|
-
|
|
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
|
-
* @
|
|
12227
|
-
* @param sourceId
|
|
12153
|
+
* @group Authentication / Init
|
|
12228
12154
|
*/
|
|
12229
|
-
|
|
12230
|
-
|
|
12231
|
-
|
|
12232
|
-
|
|
12233
|
-
|
|
12234
|
-
|
|
12235
|
-
|
|
12236
|
-
|
|
12237
|
-
|
|
12238
|
-
|
|
12239
|
-
|
|
12240
|
-
|
|
12241
|
-
|
|
12242
|
-
|
|
12243
|
-
|
|
12244
|
-
|
|
12245
|
-
|
|
12246
|
-
|
|
12247
|
-
|
|
12248
|
-
|
|
12249
|
-
|
|
12250
|
-
|
|
12251
|
-
|
|
12252
|
-
|
|
12253
|
-
|
|
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
|
-
*
|
|
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
|
-
* @
|
|
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
|
-
|
|
12350
|
-
|
|
12351
|
-
|
|
12352
|
-
|
|
12353
|
-
|
|
12354
|
-
|
|
12355
|
-
|
|
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
|
-
|
|
12358
|
-
|
|
12359
|
-
|
|
12203
|
+
}
|
|
12204
|
+
/**
|
|
12205
|
+
*
|
|
12206
|
+
*/
|
|
12207
|
+
function notifyAuthSuccess() {
|
|
12208
|
+
{
|
|
12209
|
+
console.error('SDK not initialized');
|
|
12210
|
+
return;
|
|
12360
12211
|
}
|
|
12361
|
-
|
|
12362
|
-
|
|
12363
|
-
|
|
12364
|
-
|
|
12212
|
+
}
|
|
12213
|
+
/**
|
|
12214
|
+
*
|
|
12215
|
+
* @param failureType
|
|
12216
|
+
*/
|
|
12217
|
+
function notifyAuthFailure(failureType) {
|
|
12218
|
+
{
|
|
12219
|
+
console.error('SDK not initialized');
|
|
12220
|
+
return;
|
|
12365
12221
|
}
|
|
12366
|
-
|
|
12367
|
-
|
|
12368
|
-
|
|
12369
|
-
|
|
12222
|
+
}
|
|
12223
|
+
/**
|
|
12224
|
+
*
|
|
12225
|
+
*/
|
|
12226
|
+
function notifyLogout() {
|
|
12227
|
+
{
|
|
12228
|
+
console.error('SDK not initialized');
|
|
12229
|
+
return;
|
|
12370
12230
|
}
|
|
12371
|
-
|
|
12372
|
-
|
|
12373
|
-
|
|
12374
|
-
|
|
12375
|
-
|
|
12376
|
-
|
|
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
|
-
|
|
12389
|
-
|
|
12390
|
-
|
|
12391
|
-
|
|
12392
|
-
|
|
12393
|
-
|
|
12394
|
-
|
|
12395
|
-
|
|
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
|
-
|
|
12399
|
-
return
|
|
12272
|
+
catch (e) {
|
|
12273
|
+
return false;
|
|
12400
12274
|
}
|
|
12401
|
-
|
|
12402
|
-
|
|
12403
|
-
|
|
12404
|
-
|
|
12405
|
-
|
|
12406
|
-
|
|
12407
|
-
|
|
12408
|
-
|
|
12409
|
-
|
|
12410
|
-
|
|
12411
|
-
|
|
12412
|
-
|
|
12413
|
-
|
|
12414
|
-
|
|
12415
|
-
|
|
12416
|
-
|
|
12417
|
-
|
|
12418
|
-
|
|
12419
|
-
|
|
12420
|
-
|
|
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
|
-
|
|
12423
|
-
|
|
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
|
-
|
|
12426
|
-
|
|
12427
|
-
|
|
12428
|
-
|
|
12429
|
-
|
|
12430
|
-
|
|
12431
|
-
|
|
12432
|
-
|
|
12433
|
-
|
|
12434
|
-
|
|
12435
|
-
|
|
12436
|
-
|
|
12437
|
-
|
|
12438
|
-
|
|
12439
|
-
if (
|
|
12440
|
-
|
|
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
|
-
|
|
12443
|
-
|
|
12444
|
-
await unaggAnswerSession.removeColumns(columnsToRemove);
|
|
12385
|
+
else {
|
|
12386
|
+
samlAuthWindow.focus();
|
|
12445
12387
|
}
|
|
12446
|
-
|
|
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
|
-
|
|
12449
|
-
|
|
12450
|
-
|
|
12451
|
-
|
|
12452
|
-
|
|
12453
|
-
|
|
12454
|
-
|
|
12455
|
-
|
|
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
|
-
|
|
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
|
|
12468
|
-
* @param
|
|
12410
|
+
* @param embedConfig The embed configuration
|
|
12411
|
+
* @param ssoEndPoint
|
|
12469
12412
|
*/
|
|
12470
|
-
|
|
12471
|
-
const
|
|
12472
|
-
|
|
12473
|
-
|
|
12474
|
-
|
|
12475
|
-
|
|
12476
|
-
|
|
12477
|
-
|
|
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
|
|
12465
|
+
* @param embedConfig The embed configuration
|
|
12483
12466
|
*/
|
|
12484
|
-
|
|
12485
|
-
const
|
|
12486
|
-
|
|
12487
|
-
|
|
12488
|
-
|
|
12489
|
-
|
|
12490
|
-
|
|
12491
|
-
|
|
12492
|
-
|
|
12493
|
-
|
|
12494
|
-
|
|
12495
|
-
|
|
12496
|
-
|
|
12497
|
-
|
|
12498
|
-
|
|
12499
|
-
|
|
12500
|
-
|
|
12501
|
-
|
|
12502
|
-
|
|
12503
|
-
|
|
12504
|
-
|
|
12505
|
-
|
|
12506
|
-
|
|
12507
|
-
|
|
12508
|
-
|
|
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
|
-
|
|
12507
|
+
notifyAuthSDKSuccess();
|
|
12515
12508
|
}
|
|
12516
|
-
|
|
12517
|
-
|
|
12518
|
-
dataValue,
|
|
12519
|
-
});
|
|
12520
|
-
}
|
|
12521
|
-
selectedPoints.forEach((p) => {
|
|
12522
|
-
p.selectedAttributes.forEach(addPointFromColVal);
|
|
12509
|
+
}, () => {
|
|
12510
|
+
notifyAuthFailure(AuthFailureType.SDK);
|
|
12523
12511
|
});
|
|
12524
|
-
return
|
|
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.
|
|
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
|