@thoughtspot/visual-embed-sdk 1.11.0-auth.9 → 1.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/CHANGELOG.md +24 -2
  2. package/README.md +15 -2
  3. package/dist/src/auth.d.ts +13 -0
  4. package/dist/src/embed/base.d.ts +34 -4
  5. package/dist/src/embed/search.d.ts +4 -0
  6. package/dist/src/embed/ts-embed.d.ts +2 -2
  7. package/dist/src/index.d.ts +3 -2
  8. package/dist/src/types.d.ts +32 -1
  9. package/dist/src/utils/authService.d.ts +1 -0
  10. package/dist/src/utils/processData.d.ts +1 -1
  11. package/dist/src/utils.d.ts +1 -0
  12. package/dist/tsembed.es.js +1483 -2869
  13. package/dist/tsembed.js +1481 -2868
  14. package/lib/package.json +3 -2
  15. package/lib/src/auth.d.ts +13 -0
  16. package/lib/src/auth.js +35 -9
  17. package/lib/src/auth.js.map +1 -1
  18. package/lib/src/auth.spec.js +76 -1
  19. package/lib/src/auth.spec.js.map +1 -1
  20. package/lib/src/embed/app.spec.js +4 -3
  21. package/lib/src/embed/app.spec.js.map +1 -1
  22. package/lib/src/embed/base.d.ts +34 -4
  23. package/lib/src/embed/base.js +79 -11
  24. package/lib/src/embed/base.js.map +1 -1
  25. package/lib/src/embed/base.spec.js +50 -2
  26. package/lib/src/embed/base.spec.js.map +1 -1
  27. package/lib/src/embed/embed.spec.js +1 -1
  28. package/lib/src/embed/embed.spec.js.map +1 -1
  29. package/lib/src/embed/liveboard.spec.js +4 -3
  30. package/lib/src/embed/liveboard.spec.js.map +1 -1
  31. package/lib/src/embed/pinboard.spec.js +4 -3
  32. package/lib/src/embed/pinboard.spec.js.map +1 -1
  33. package/lib/src/embed/search.d.ts +4 -0
  34. package/lib/src/embed/search.js +1 -1
  35. package/lib/src/embed/search.js.map +1 -1
  36. package/lib/src/embed/search.spec.js +6 -1
  37. package/lib/src/embed/search.spec.js.map +1 -1
  38. package/lib/src/embed/ts-embed.d.ts +2 -2
  39. package/lib/src/embed/ts-embed.js +11 -20
  40. package/lib/src/embed/ts-embed.js.map +1 -1
  41. package/lib/src/embed/ts-embed.spec.js +1 -1
  42. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  43. package/lib/src/index.d.ts +3 -2
  44. package/lib/src/index.js +3 -2
  45. package/lib/src/index.js.map +1 -1
  46. package/lib/src/react/index.spec.js +2 -2
  47. package/lib/src/react/index.spec.js.map +1 -1
  48. package/lib/src/types.d.ts +32 -1
  49. package/lib/src/types.js +14 -0
  50. package/lib/src/types.js.map +1 -1
  51. package/lib/src/utils/authService.d.ts +1 -0
  52. package/lib/src/utils/authService.js +12 -2
  53. package/lib/src/utils/authService.js.map +1 -1
  54. package/lib/src/utils/authService.spec.js +10 -0
  55. package/lib/src/utils/authService.spec.js.map +1 -1
  56. package/lib/src/utils/processData.d.ts +1 -1
  57. package/lib/src/utils/processData.js +37 -3
  58. package/lib/src/utils/processData.js.map +1 -1
  59. package/lib/src/utils/processData.spec.js +106 -4
  60. package/lib/src/utils/processData.spec.js.map +1 -1
  61. package/lib/src/utils.d.ts +1 -0
  62. package/lib/src/utils.js +4 -0
  63. package/lib/src/utils.js.map +1 -1
  64. package/lib/src/utils.spec.js +14 -1
  65. package/lib/src/utils.spec.js.map +1 -1
  66. package/lib/src/visual-embed-sdk.d.ts +135 -8
  67. package/package.json +3 -2
  68. package/src/auth.spec.ts +98 -2
  69. package/src/auth.ts +44 -7
  70. package/src/embed/app.spec.ts +4 -3
  71. package/src/embed/base.spec.ts +57 -3
  72. package/src/embed/base.ts +96 -15
  73. package/src/embed/embed.spec.ts +1 -1
  74. package/src/embed/liveboard.spec.ts +4 -3
  75. package/src/embed/pinboard.spec.ts +4 -3
  76. package/src/embed/search.spec.ts +6 -1
  77. package/src/embed/search.ts +5 -0
  78. package/src/embed/ts-embed.spec.ts +1 -1
  79. package/src/embed/ts-embed.ts +17 -23
  80. package/src/index.ts +5 -1
  81. package/src/react/index.spec.tsx +3 -2
  82. package/src/types.ts +32 -0
  83. package/src/utils/authService.spec.ts +13 -0
  84. package/src/utils/authService.ts +14 -2
  85. package/src/utils/processData.spec.ts +139 -4
  86. package/src/utils/processData.ts +54 -4
  87. package/src/utils.spec.ts +26 -0
  88. package/src/utils.ts +5 -0
  89. package/dist/src/embed/pinboard.d.ts +0 -91
  90. package/dist/src/utils/plugin.d.ts +0 -0
  91. package/dist/src/v1/api.d.ts +0 -19
  92. package/lib/src/embed/pinboard.d.ts +0 -91
  93. package/lib/src/embed/pinboard.js +0 -110
  94. package/lib/src/embed/pinboard.js.map +0 -1
  95. package/lib/src/utils/plugin.d.ts +0 -0
  96. package/lib/src/utils/plugin.js +0 -1
  97. package/lib/src/utils/plugin.js.map +0 -1
package/src/embed/base.ts CHANGED
@@ -7,31 +7,72 @@
7
7
  * @summary Base classes
8
8
  * @author Ayon Ghosh <ayon.ghosh@thoughtspot.com>
9
9
  */
10
+ import EventEmitter from 'eventemitter3';
10
11
  import { getThoughtSpotHost } from '../config';
11
- import { EmbedConfig } from '../types';
12
- import { authenticate } from '../auth';
12
+ import { AuthType, EmbedConfig } from '../types';
13
+ import {
14
+ authenticate,
15
+ logout as _logout,
16
+ AuthFailureType,
17
+ AuthStatus,
18
+ } from '../auth';
13
19
  import { uploadMixpanelEvent, MIXPANEL_EVENT } from '../mixpanel-service';
14
20
 
15
21
  let config = {} as EmbedConfig;
22
+ const CONFIG_DEFAULTS: Partial<EmbedConfig> = {
23
+ loginFailedMessage: 'Not logged in',
24
+ authType: AuthType.None,
25
+ };
16
26
 
17
27
  export let authPromise: Promise<boolean>;
18
28
 
29
+ export const getEmbedConfig = (): EmbedConfig => config;
30
+
31
+ export const getAuthPromise = (): Promise<boolean> => authPromise;
32
+
33
+ let authEE: EventEmitter;
34
+
35
+ export function notifyAuthSuccess(): void {
36
+ if (!authEE) {
37
+ console.error('SDK not initialized');
38
+ return;
39
+ }
40
+ authEE.emit(AuthStatus.SUCCESS);
41
+ }
42
+
43
+ export function notifyAuthFailure(failureType: AuthFailureType): void {
44
+ if (!authEE) {
45
+ console.error('SDK not initialized');
46
+ return;
47
+ }
48
+ authEE.emit(AuthStatus.FAILURE, failureType);
49
+ }
50
+
51
+ export function notifyLogout(): void {
52
+ if (!authEE) {
53
+ console.error('SDK not initialized');
54
+ return;
55
+ }
56
+ authEE.emit(AuthStatus.LOGOUT);
57
+ }
19
58
  /**
20
59
  * Perform authentication on the ThoughtSpot app as applicable.
21
60
  */
22
61
  export const handleAuth = (): Promise<boolean> => {
23
- const authConfig = {
24
- ...config,
25
- thoughtSpotHost: getThoughtSpotHost(config),
26
- };
27
- authPromise = authenticate(authConfig);
62
+ authPromise = authenticate(config);
63
+ authPromise.then(
64
+ (isLoggedIn) => {
65
+ if (!isLoggedIn) {
66
+ notifyAuthFailure(AuthFailureType.SDK);
67
+ }
68
+ },
69
+ () => {
70
+ notifyAuthFailure(AuthFailureType.SDK);
71
+ },
72
+ );
28
73
  return authPromise;
29
74
  };
30
75
 
31
- export const getEmbedConfig = (): EmbedConfig => config;
32
-
33
- export const getAuthPromise = (): Promise<boolean> => authPromise;
34
-
35
76
  /**
36
77
  * Prefetches static resources from the specified URL. Web browsers can then cache the prefetched resources and serve them from the user's local disk to provide faster access to your app.
37
78
  * @param url The URL provided for prefetch
@@ -57,10 +98,18 @@ export const prefetch = (url?: string): void => {
57
98
  * @param embedConfig The configuration object containing ThoughtSpot host,
58
99
  * authentication mechanism and so on.
59
100
  *
60
- * @returns authPromise Promise which resolves when authentication is complete.
101
+ * eg: authStatus = init(config);
102
+ * authStatus.on(AuthStatus.FAILURE, (reason) => { // do something here });
103
+ *
104
+ * @returns event emitter which emits events on authentication success, failure and logout. {@link AuthStatus}
61
105
  */
62
- export const init = (embedConfig: EmbedConfig): Promise<boolean> => {
63
- config = embedConfig;
106
+ export const init = (embedConfig: EmbedConfig): EventEmitter => {
107
+ config = {
108
+ ...CONFIG_DEFAULTS,
109
+ ...embedConfig,
110
+ thoughtSpotHost: getThoughtSpotHost(embedConfig),
111
+ };
112
+ authEE = new EventEmitter();
64
113
  handleAuth();
65
114
 
66
115
  uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_CALLED_INIT, {
@@ -71,7 +120,32 @@ export const init = (embedConfig: EmbedConfig): Promise<boolean> => {
71
120
  if (config.callPrefetch) {
72
121
  prefetch(config.thoughtSpotHost);
73
122
  }
74
- return authPromise;
123
+ return authEE;
124
+ };
125
+
126
+ export function disableAutoLogin(): void {
127
+ config.autoLogin = false;
128
+ }
129
+
130
+ /**
131
+ * Logout from ThoughtSpot. This also sets the autoLogin flag to false, to prevent
132
+ * the SDK from automatically logging in again.
133
+ *
134
+ * You can call the `init` method again to re login, if autoLogin is set to true in this
135
+ * second call it will be honored.
136
+ *
137
+ * @param doNotDisableAutoLogin This flag when passed will not disable autoLogin
138
+ * @returns Promise which resolves when logout completes.
139
+ * @version SDK: 1.10.1 | ThoughtSpot: *
140
+ */
141
+ export const logout = (doNotDisableAutoLogin = false): Promise<boolean> => {
142
+ if (!doNotDisableAutoLogin) {
143
+ disableAutoLogin();
144
+ }
145
+ return _logout(config).then((isLoggedIn) => {
146
+ notifyLogout();
147
+ return isLoggedIn;
148
+ });
75
149
  };
76
150
 
77
151
  let renderQueue: Promise<any> = Promise.resolve();
@@ -89,3 +163,10 @@ export const renderInQueue = (fn: (next?: (val?: any) => void) => void) => {
89
163
  fn(() => {}); // eslint-disable-line @typescript-eslint/no-empty-function
90
164
  }
91
165
  };
166
+
167
+ // For testing purposes only
168
+ export function reset(): void {
169
+ config = {} as any;
170
+ authEE = null;
171
+ authPromise = null;
172
+ }
@@ -71,7 +71,7 @@ describe('Custom CSS Url', () => {
71
71
  document.body.innerHTML = getDocumentBody();
72
72
  });
73
73
 
74
- test.only('passing customCssUrl should set the correct query params on the iframe', async (done) => {
74
+ test('passing customCssUrl should set the correct query params on the iframe', async (done) => {
75
75
  init({
76
76
  thoughtSpotHost,
77
77
  authType: AuthType.None,
@@ -18,7 +18,8 @@ const defaultViewConfig = {
18
18
  const liveboardId = 'eca215d4-0d2c-4a55-90e3-d81ef6848ae0';
19
19
  const vizId = '6e73f724-660e-11eb-ae93-0242ac130002';
20
20
  const thoughtSpotHost = 'tshost';
21
- const defaultParams = `&hostAppUrl=local-host&viewPortHeight=768&viewPortWidth=1024&sdkVersion=${version}`;
21
+ const defaultParamsSansHideAction = `&hostAppUrl=local-host&viewPortHeight=768&viewPortWidth=1024&sdkVersion=${version}`;
22
+ const defaultParams = `${defaultParamsSansHideAction}&hideAction=[%22${Action.ReportError}%22]`;
22
23
  const prefixParams = '&isLiveboardEmbed=true&isPinboardV2Enabled=false';
23
24
 
24
25
  beforeAll(() => {
@@ -60,7 +61,7 @@ describe('Liveboard/viz embed tests', () => {
60
61
  liveboardEmbed.render();
61
62
  await executeAfterWait(() => {
62
63
  expect(getIFrameSrc()).toBe(
63
- `http://${thoughtSpotHost}/?embedApp=true${defaultParams}&disableAction=[%22${Action.DownloadAsCsv}%22,%22${Action.DownloadAsPdf}%22,%22${Action.DownloadAsXlsx}%22]&disableHint=Action%20denied${prefixParams}#/embed/viz/${liveboardId}`,
64
+ `http://${thoughtSpotHost}/?embedApp=true${defaultParamsSansHideAction}&disableAction=[%22${Action.DownloadAsCsv}%22,%22${Action.DownloadAsPdf}%22,%22${Action.DownloadAsXlsx}%22]&disableHint=Action%20denied&hideAction=[%22${Action.ReportError}%22]${prefixParams}#/embed/viz/${liveboardId}`,
64
65
  );
65
66
  });
66
67
  });
@@ -78,7 +79,7 @@ describe('Liveboard/viz embed tests', () => {
78
79
  liveboardEmbed.render();
79
80
  await executeAfterWait(() => {
80
81
  expect(getIFrameSrc()).toBe(
81
- `http://${thoughtSpotHost}/?embedApp=true${defaultParams}&hideAction=[%22${Action.DownloadAsCsv}%22,%22${Action.DownloadAsPdf}%22,%22${Action.DownloadAsXlsx}%22]${prefixParams}#/embed/viz/${liveboardId}`,
82
+ `http://${thoughtSpotHost}/?embedApp=true${defaultParamsSansHideAction}&hideAction=[%22${Action.ReportError}%22,%22${Action.DownloadAsCsv}%22,%22${Action.DownloadAsPdf}%22,%22${Action.DownloadAsXlsx}%22]${prefixParams}#/embed/viz/${liveboardId}`,
82
83
  );
83
84
  });
84
85
  });
@@ -18,7 +18,8 @@ const defaultViewConfig = {
18
18
  const pinboardId = 'eca215d4-0d2c-4a55-90e3-d81ef6848ae0';
19
19
  const vizId = '6e73f724-660e-11eb-ae93-0242ac130002';
20
20
  const thoughtSpotHost = 'tshost';
21
- const defaultParams = `&hostAppUrl=local-host&viewPortHeight=768&viewPortWidth=1024&sdkVersion=${version}`;
21
+ const defaultParamsWithoutHideActions = `&hostAppUrl=local-host&viewPortHeight=768&viewPortWidth=1024&sdkVersion=${version}`;
22
+ const defaultParams = `${defaultParamsWithoutHideActions}&hideAction=[%22${Action.ReportError}%22]`;
22
23
  const prefixParams = '&isLiveboardEmbed=true&isPinboardV2Enabled=false';
23
24
 
24
25
  beforeAll(() => {
@@ -60,7 +61,7 @@ describe('Pinboard/viz embed tests', () => {
60
61
  pinboardEmbed.render();
61
62
  await executeAfterWait(() => {
62
63
  expect(getIFrameSrc()).toBe(
63
- `http://${thoughtSpotHost}/?embedApp=true${defaultParams}&disableAction=[%22${Action.DownloadAsCsv}%22,%22${Action.DownloadAsPdf}%22,%22${Action.DownloadAsXlsx}%22]&disableHint=Action%20denied${prefixParams}#/embed/viz/${pinboardId}`,
64
+ `http://${thoughtSpotHost}/?embedApp=true${defaultParamsWithoutHideActions}&disableAction=[%22${Action.DownloadAsCsv}%22,%22${Action.DownloadAsPdf}%22,%22${Action.DownloadAsXlsx}%22]&disableHint=Action%20denied&hideAction=[%22${Action.ReportError}%22]${prefixParams}#/embed/viz/${pinboardId}`,
64
65
  );
65
66
  });
66
67
  });
@@ -78,7 +79,7 @@ describe('Pinboard/viz embed tests', () => {
78
79
  pinboardEmbed.render();
79
80
  await executeAfterWait(() => {
80
81
  expect(getIFrameSrc()).toBe(
81
- `http://${thoughtSpotHost}/?embedApp=true${defaultParams}&hideAction=[%22${Action.DownloadAsCsv}%22,%22${Action.DownloadAsPdf}%22,%22${Action.DownloadAsXlsx}%22]${prefixParams}#/embed/viz/${pinboardId}`,
82
+ `http://${thoughtSpotHost}/?embedApp=true${defaultParamsWithoutHideActions}&hideAction=[%22${Action.ReportError}%22,%22${Action.DownloadAsCsv}%22,%22${Action.DownloadAsPdf}%22,%22${Action.DownloadAsXlsx}%22]${prefixParams}#/embed/viz/${pinboardId}`,
82
83
  );
83
84
  });
84
85
  });
@@ -20,7 +20,10 @@ const answerId = 'eca215d4-0d2c-4a55-90e3-d81ef6848ae0';
20
20
  const thoughtSpotHost = 'tshost';
21
21
  const defaultParams = `hostAppUrl=local-host&viewPortHeight=768&viewPortWidth=1024&sdkVersion=${version}`;
22
22
  const hideBydefault = `&hideAction=${fixedEncodeURI(
23
- JSON.stringify(HiddenActionItemByDefaultForSearchEmbed),
23
+ JSON.stringify([
24
+ Action.ReportError,
25
+ ...HiddenActionItemByDefaultForSearchEmbed,
26
+ ]),
24
27
  )}`;
25
28
  const defaultParamsWithHiddenActions = defaultParams + hideBydefault;
26
29
  const prefixParams = '&isSearchEmbed=true';
@@ -197,6 +200,7 @@ describe('Search embed tests', () => {
197
200
  searchEmbed.render();
198
201
  const hideActionUrl = fixedEncodeURI(
199
202
  JSON.stringify([
203
+ Action.ReportError,
200
204
  ...hiddenActionsForSearch,
201
205
  ...HiddenActionItemByDefaultForSearchEmbed,
202
206
  ]),
@@ -220,6 +224,7 @@ describe('Search embed tests', () => {
220
224
  searchEmbed.render();
221
225
  const hideActionUrl = fixedEncodeURI(
222
226
  JSON.stringify([
227
+ Action.ReportError,
223
228
  ...hiddenActionsForSearch,
224
229
  ...HiddenActionItemByDefaultForSearchEmbed,
225
230
  ]),
@@ -49,6 +49,10 @@ export interface SearchViewConfig extends ViewConfig {
49
49
  * using raw answer data.
50
50
  */
51
51
  hideResults?: boolean;
52
+ /**
53
+ * If set to true, expands all the data sources panel.
54
+ */
55
+ expandAllDataSource?: boolean;
52
56
  /**
53
57
  * If set to true, the Search Assist feature is enabled.
54
58
  */
@@ -126,6 +130,7 @@ export class SearchEmbed extends TsEmbed {
126
130
  private getIFrameSrc(answerId: string, dataSources?: string[]) {
127
131
  const {
128
132
  hideResults,
133
+ expandAllDataSource,
129
134
  enableSearchAssist,
130
135
  forceTable,
131
136
  searchOptions,
@@ -34,7 +34,7 @@ const defaultViewConfig = {
34
34
  const pinboardId = 'eca215d4-0d2c-4a55-90e3-d81ef6848ae0';
35
35
  const liveboardId = 'eca215d4-0d2c-4a55-90e3-d81ef6848ae0';
36
36
  const thoughtSpotHost = 'tshost';
37
- const defaultParamsForPinboardEmbed = `hostAppUrl=local-host&viewPortHeight=768&viewPortWidth=1024&sdkVersion=${version}`;
37
+ const defaultParamsForPinboardEmbed = `hostAppUrl=local-host&viewPortHeight=768&viewPortWidth=1024&sdkVersion=${version}&hideAction=[%22${Action.ReportError}%22]`;
38
38
  const defaultParamsPost = '&isPinboardV2Enabled=false';
39
39
 
40
40
  describe('Unit test case for ts embed', () => {
@@ -34,7 +34,7 @@ import {
34
34
  MessageCallbackObj,
35
35
  } from '../types';
36
36
  import { uploadMixpanelEvent, MIXPANEL_EVENT } from '../mixpanel-service';
37
- import { getProcessData } from '../utils/processData';
37
+ import { processEventData } from '../utils/processData';
38
38
  import { processTrigger } from '../utils/processTrigger';
39
39
  import pkgInfo from '../../package.json';
40
40
  import { getAuthPromise, getEmbedConfig, renderInQueue } from './base';
@@ -75,7 +75,7 @@ export interface FrameParams {
75
75
  * This parameters will be passed on the iframe
76
76
  * as is.
77
77
  */
78
- [key: string]: string | number | boolean;
78
+ [key: string]: string | number | boolean | undefined;
79
79
  }
80
80
 
81
81
  /**
@@ -202,6 +202,8 @@ export class TsEmbed {
202
202
  */
203
203
  private shouldEncodeUrlQueryParams = false;
204
204
 
205
+ private defaultHiddenActions = [Action.ReportError];
206
+
205
207
  constructor(domSelector: DOMSelector, viewConfig?: ViewConfig) {
206
208
  this.el = this.getDOMNode(domSelector);
207
209
  // TODO: handle error
@@ -212,20 +214,6 @@ export class TsEmbed {
212
214
  this.isError = false;
213
215
  this.viewConfig = viewConfig;
214
216
  this.shouldEncodeUrlQueryParams = this.embedConfig.shouldEncodeUrlQueryParams;
215
- this.on(EmbedEvent.NoCookieAccess, () => {
216
- if (!this.embedConfig.suppressNoCookieAccessAlert) {
217
- // eslint-disable-next-line no-alert
218
- alert(
219
- 'Third party cookie access is blocked on this browser, please allow third party cookies for this to work properly. \nYou can use `suppressNoCookieAccessAlert` to suppress this message.',
220
- );
221
- }
222
- this.el.innerHTML = this.getLoginFiledMessage();
223
- });
224
- }
225
-
226
- private getLoginFiledMessage(): string {
227
- const { loginFailedMessage } = this.embedConfig;
228
- return loginFailedMessage || 'Login failed';
229
217
  }
230
218
 
231
219
  /**
@@ -310,7 +298,12 @@ export class TsEmbed {
310
298
  if (event.source === this.iFrame.contentWindow) {
311
299
  this.executeCallbacks(
312
300
  eventType,
313
- getProcessData(eventType, eventData, this.thoughtSpotHost),
301
+ processEventData(
302
+ eventType,
303
+ eventData,
304
+ this.thoughtSpotHost,
305
+ this.el,
306
+ ),
314
307
  eventPort,
315
308
  );
316
309
  }
@@ -391,9 +384,10 @@ export class TsEmbed {
391
384
  if (disabledActionReason) {
392
385
  queryParams[Param.DisableActionReason] = disabledActionReason;
393
386
  }
394
- if (hiddenActions?.length) {
395
- queryParams[Param.HideActions] = hiddenActions;
396
- }
387
+ queryParams[Param.HideActions] = [
388
+ ...this.defaultHiddenActions,
389
+ ...(hiddenActions ?? []),
390
+ ];
397
391
  if (Array.isArray(visibleActions)) {
398
392
  queryParams[Param.VisibleActions] = visibleActions;
399
393
  }
@@ -472,7 +466,7 @@ export class TsEmbed {
472
466
  getAuthPromise()
473
467
  ?.then((isLoggedIn: boolean) => {
474
468
  if (!isLoggedIn) {
475
- this.el.innerHTML = this.getLoginFiledMessage();
469
+ this.el.innerHTML = this.embedConfig.loginFailedMessage;
476
470
  return;
477
471
  }
478
472
 
@@ -503,7 +497,7 @@ export class TsEmbed {
503
497
  frameWidth || DEFAULT_EMBED_WIDTH,
504
498
  );
505
499
  const height = getCssDimension(
506
- frameWidth || DEFAULT_EMBED_HEIGHT,
500
+ frameHeight || DEFAULT_EMBED_HEIGHT,
507
501
  );
508
502
  setAttributes(this.iFrame, restParams);
509
503
 
@@ -547,7 +541,7 @@ export class TsEmbed {
547
541
  uploadMixpanelEvent(
548
542
  MIXPANEL_EVENT.VISUAL_SDK_RENDER_FAILED,
549
543
  );
550
- this.el.innerHTML = this.getLoginFiledMessage();
544
+ this.el.innerHTML = this.embedConfig.loginFailedMessage;
551
545
  this.handleError(error);
552
546
  });
553
547
  });
package/src/index.ts CHANGED
@@ -9,13 +9,14 @@
9
9
  */
10
10
 
11
11
  import { AppEmbed, Page, AppViewConfig } from './embed/app';
12
- import { init, prefetch } from './embed/base';
12
+ import { init, prefetch, logout } from './embed/base';
13
13
  import {
14
14
  PinboardEmbed,
15
15
  LiveboardViewConfig,
16
16
  LiveboardEmbed,
17
17
  } from './embed/liveboard';
18
18
  import { SearchEmbed, SearchViewConfig } from './embed/search';
19
+ import { AuthFailureType, AuthStatus } from './auth';
19
20
  import {
20
21
  AuthType,
21
22
  RuntimeFilter,
@@ -29,11 +30,14 @@ import {
29
30
 
30
31
  export {
31
32
  init,
33
+ logout,
32
34
  prefetch,
33
35
  SearchEmbed,
34
36
  PinboardEmbed,
35
37
  LiveboardEmbed,
36
38
  AppEmbed,
39
+ AuthFailureType,
40
+ AuthStatus,
37
41
  // types
38
42
  Page,
39
43
  AuthType,
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  import '@testing-library/jest-dom';
3
3
  import '@testing-library/jest-dom/extend-expect';
4
4
  import { cleanup, fireEvent, render, waitFor } from '@testing-library/react';
5
+ import { Action, EmbedEvent, HostEvent } from '../types';
5
6
  import {
6
7
  executeAfterWait,
7
8
  getIFrameEl,
@@ -10,7 +11,7 @@ import {
10
11
  } from '../test/test-utils';
11
12
  import { SearchEmbed, AppEmbed, LiveboardEmbed, useEmbedRef } from './index';
12
13
  import { AuthType, init } from '../index';
13
- import { EmbedEvent, HostEvent } from '../types';
14
+
14
15
  import { version } from '../../package.json';
15
16
 
16
17
  const thoughtSpotHost = 'localhost';
@@ -37,7 +38,7 @@ describe('React Components', () => {
37
38
  ),
38
39
  ).toBe(true);
39
40
  expect(getIFrameSrc(container)).toBe(
40
- `http://${thoughtSpotHost}/?hostAppUrl=local-host&viewPortHeight=768&viewPortWidth=1024&sdkVersion=${version}&hideAction=[%22editACopy%22,%22saveAsView%22,%22updateTSL%22,%22editTSL%22,%22onDeleteAnswer%22]&dataSourceMode=hide&useLastSelectedSources=false&isSearchEmbed=true#/embed/answer`,
41
+ `http://${thoughtSpotHost}/?hostAppUrl=local-host&viewPortHeight=768&viewPortWidth=1024&sdkVersion=${version}&hideAction=[%22${Action.ReportError}%22,%22editACopy%22,%22saveAsView%22,%22updateTSL%22,%22editTSL%22,%22onDeleteAnswer%22]&dataSourceMode=hide&useLastSelectedSources=false&isSearchEmbed=true#/embed/answer`,
41
42
  );
42
43
  });
43
44
 
package/src/types.ts CHANGED
@@ -97,6 +97,16 @@ export interface EmbedConfig {
97
97
  */
98
98
  noRedirect?: boolean;
99
99
 
100
+ /**
101
+ * [SSO] For SSO Authentication, one can supply an optional path param,
102
+ * this will be the path on the host origin where the SAML flow will be
103
+ * terminated.
104
+ *
105
+ * Eg: "/dashboard", "#/foo" [Do not include the host]
106
+ * @version SDK: 1.10.2 | ThoughtSpot: *
107
+ */
108
+ redirectPath?: string;
109
+
100
110
  /** @internal */
101
111
  basepath?: string;
102
112
 
@@ -159,6 +169,14 @@ export interface EmbedConfig {
159
169
  * @default ''
160
170
  */
161
171
  customCssUrl?: string;
172
+ /**
173
+ * [AuthServer|Basic] Detect if 3rd party cookies are enabled by doing an additional call. This is slower
174
+ * and should be avoided. Listen to the NO_COOKIE_ACCESS event to handle the situation.
175
+ *
176
+ * This is slightly slower than letting the browser handle the cookie check, as it involves an extra network call.
177
+ * @version SDK: 1.10.4 | ThoughtSpot: *
178
+ */
179
+ detectCookieAccessSlow?: boolean;
162
180
  }
163
181
 
164
182
  /**
@@ -371,6 +389,16 @@ export enum EmbedEvent {
371
389
  * The ThoughtSpot auth session has expired.
372
390
  */
373
391
  AuthExpire = 'ThoughtspotAuthExpired',
392
+ /**
393
+ * ThoughtSpot failed to validate the auth session.
394
+ * @hidden
395
+ */
396
+ AuthFailure = 'ThoughtspotAuthFailure',
397
+ /**
398
+ * ThoughtSpot failed to validate the auth session.
399
+ * @hidden
400
+ */
401
+ AuthLogout = 'ThoughtspotAuthLogout',
374
402
  /**
375
403
  * The height of the embedded Liveboard or visualization has been computed.
376
404
  * @return data - The height of the embedded Liveboard or visualization
@@ -780,6 +808,10 @@ export enum Action {
780
808
  * @version SDK: 1.11.0 | ThoughtSpot: 8.3.0.cl
781
809
  */
782
810
  CreateMonitor = 'createMonitor',
811
+ /**
812
+ * @version SDK: 1.11.1 | ThoughtSpot: 8.3.0.cl
813
+ */
814
+ ReportError = 'reportError',
783
815
  }
784
816
 
785
817
  export interface SessionInterface {
@@ -63,4 +63,17 @@ describe('Unit test for authService', () => {
63
63
  await fetchBasicAuthService(thoughtSpotHost, username, password);
64
64
  expect(fetch).toBeCalled();
65
65
  });
66
+
67
+ test('log error on API failures', async () => {
68
+ jest.spyOn(global.console, 'error').mockImplementation(() => undefined);
69
+ global.fetch = jest.fn(() =>
70
+ Promise.resolve({
71
+ text: () => Promise.resolve('error'),
72
+ status: 500,
73
+ ok: false,
74
+ }),
75
+ );
76
+ await fetchSessionInfoService(authVerificationUrl);
77
+ expect(global.console.error).toHaveBeenCalledWith('Failure', 'error');
78
+ });
66
79
  });
@@ -6,8 +6,8 @@ function failureLoggedFetch(
6
6
  options: RequestInit = {},
7
7
  ): Promise<Response> {
8
8
  return fetch(url, options).then(async (r) => {
9
- if (!r.ok && r.type !== 'opaqueredirect') {
10
- console.error('Failure', await r.text());
9
+ if (!r.ok && r.type !== 'opaqueredirect' && r.type !== 'opaque') {
10
+ console.error('Failure', await r.text?.());
11
11
  }
12
12
  return r;
13
13
  });
@@ -59,3 +59,15 @@ export async function fetchBasicAuthService(
59
59
  credentials: 'include',
60
60
  });
61
61
  }
62
+
63
+ export async function fetchLogoutService(
64
+ thoughtSpotHost: string,
65
+ ): Promise<any> {
66
+ return failureLoggedFetch(`${thoughtSpotHost}${EndPoints.LOGOUT}`, {
67
+ credentials: 'include',
68
+ method: 'POST',
69
+ headers: {
70
+ 'x-requested-by': 'ThoughtSpot',
71
+ },
72
+ });
73
+ }