@thoughtspot/visual-embed-sdk 1.28.0 → 1.28.1-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/README.md +1 -1
  2. package/cjs/package.json +1 -1
  3. package/cjs/src/auth.d.ts.map +1 -1
  4. package/cjs/src/auth.js +2 -2
  5. package/cjs/src/auth.js.map +1 -1
  6. package/cjs/src/authToken.d.ts +6 -0
  7. package/cjs/src/authToken.d.ts.map +1 -1
  8. package/cjs/src/authToken.js +6 -0
  9. package/cjs/src/authToken.js.map +1 -1
  10. package/cjs/src/embed/app.d.ts +12 -6
  11. package/cjs/src/embed/app.d.ts.map +1 -1
  12. package/cjs/src/embed/app.js +2 -2
  13. package/cjs/src/embed/app.js.map +1 -1
  14. package/cjs/src/embed/app.spec.js +3 -2
  15. package/cjs/src/embed/app.spec.js.map +1 -1
  16. package/cjs/src/embed/base.d.ts +1 -1
  17. package/cjs/src/embed/base.d.ts.map +1 -1
  18. package/cjs/src/embed/base.js +7 -5
  19. package/cjs/src/embed/base.js.map +1 -1
  20. package/cjs/src/embed/base.spec.js +1 -1
  21. package/cjs/src/embed/base.spec.js.map +1 -1
  22. package/cjs/src/embed/liveboard.d.ts +8 -2
  23. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  24. package/cjs/src/embed/liveboard.js.map +1 -1
  25. package/cjs/src/embed/liveboard.spec.js +3 -3
  26. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  27. package/cjs/src/embed/pinboard.spec.js +3 -2
  28. package/cjs/src/embed/pinboard.spec.js.map +1 -1
  29. package/cjs/src/embed/search.d.ts +11 -5
  30. package/cjs/src/embed/search.d.ts.map +1 -1
  31. package/cjs/src/embed/search.js +4 -4
  32. package/cjs/src/embed/search.js.map +1 -1
  33. package/cjs/src/embed/search.spec.js +3 -2
  34. package/cjs/src/embed/search.spec.js.map +1 -1
  35. package/cjs/src/embed/ts-embed.d.ts +1 -1
  36. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  37. package/cjs/src/embed/ts-embed.js +8 -8
  38. package/cjs/src/embed/ts-embed.js.map +1 -1
  39. package/cjs/src/embed/ts-embed.spec.js +11 -21
  40. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  41. package/cjs/src/index.d.ts +1 -0
  42. package/cjs/src/index.d.ts.map +1 -1
  43. package/cjs/src/index.js +3 -1
  44. package/cjs/src/index.js.map +1 -1
  45. package/cjs/src/react/index.spec.js +0 -12
  46. package/cjs/src/react/index.spec.js.map +1 -1
  47. package/cjs/src/types.d.ts +25 -15
  48. package/cjs/src/types.d.ts.map +1 -1
  49. package/cjs/src/types.js +11 -3
  50. package/cjs/src/types.js.map +1 -1
  51. package/dist/src/auth.d.ts.map +1 -1
  52. package/dist/src/authToken.d.ts +6 -0
  53. package/dist/src/authToken.d.ts.map +1 -1
  54. package/dist/src/embed/app.d.ts +12 -6
  55. package/dist/src/embed/app.d.ts.map +1 -1
  56. package/dist/src/embed/base.d.ts +1 -1
  57. package/dist/src/embed/base.d.ts.map +1 -1
  58. package/dist/src/embed/liveboard.d.ts +8 -2
  59. package/dist/src/embed/liveboard.d.ts.map +1 -1
  60. package/dist/src/embed/search.d.ts +11 -5
  61. package/dist/src/embed/search.d.ts.map +1 -1
  62. package/dist/src/embed/ts-embed.d.ts +1 -1
  63. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  64. package/dist/src/index.d.ts +1 -0
  65. package/dist/src/index.d.ts.map +1 -1
  66. package/dist/src/types.d.ts +25 -15
  67. package/dist/src/types.d.ts.map +1 -1
  68. package/dist/tsembed-react.es.js +6921 -6907
  69. package/dist/tsembed-react.js +1697 -1683
  70. package/dist/tsembed.es.js +7218 -7203
  71. package/dist/tsembed.js +15362 -15346
  72. package/dist/visual-embed-sdk-react-full.d.ts +63 -26
  73. package/dist/visual-embed-sdk-react.d.ts +63 -26
  74. package/dist/visual-embed-sdk.d.ts +63 -26
  75. package/lib/package.json +1 -1
  76. package/lib/src/auth.d.ts.map +1 -1
  77. package/lib/src/auth.js +3 -3
  78. package/lib/src/auth.js.map +1 -1
  79. package/lib/src/authToken.d.ts +6 -0
  80. package/lib/src/authToken.d.ts.map +1 -1
  81. package/lib/src/authToken.js +6 -0
  82. package/lib/src/authToken.js.map +1 -1
  83. package/lib/src/embed/app.d.ts +12 -6
  84. package/lib/src/embed/app.d.ts.map +1 -1
  85. package/lib/src/embed/app.js +2 -2
  86. package/lib/src/embed/app.js.map +1 -1
  87. package/lib/src/embed/app.spec.js +3 -2
  88. package/lib/src/embed/app.spec.js.map +1 -1
  89. package/lib/src/embed/base.d.ts +1 -1
  90. package/lib/src/embed/base.d.ts.map +1 -1
  91. package/lib/src/embed/base.js +7 -5
  92. package/lib/src/embed/base.js.map +1 -1
  93. package/lib/src/embed/base.spec.js +2 -2
  94. package/lib/src/embed/base.spec.js.map +1 -1
  95. package/lib/src/embed/liveboard.d.ts +8 -2
  96. package/lib/src/embed/liveboard.d.ts.map +1 -1
  97. package/lib/src/embed/liveboard.js +1 -1
  98. package/lib/src/embed/liveboard.js.map +1 -1
  99. package/lib/src/embed/liveboard.spec.js +3 -3
  100. package/lib/src/embed/liveboard.spec.js.map +1 -1
  101. package/lib/src/embed/pinboard.spec.js +3 -2
  102. package/lib/src/embed/pinboard.spec.js.map +1 -1
  103. package/lib/src/embed/search.d.ts +11 -5
  104. package/lib/src/embed/search.d.ts.map +1 -1
  105. package/lib/src/embed/search.js +5 -5
  106. package/lib/src/embed/search.js.map +1 -1
  107. package/lib/src/embed/search.spec.js +3 -2
  108. package/lib/src/embed/search.spec.js.map +1 -1
  109. package/lib/src/embed/ts-embed.d.ts +1 -1
  110. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  111. package/lib/src/embed/ts-embed.js +11 -11
  112. package/lib/src/embed/ts-embed.js.map +1 -1
  113. package/lib/src/embed/ts-embed.spec.js +11 -21
  114. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  115. package/lib/src/index.d.ts +1 -0
  116. package/lib/src/index.d.ts.map +1 -1
  117. package/lib/src/index.js +1 -0
  118. package/lib/src/index.js.map +1 -1
  119. package/lib/src/react/index.spec.js +0 -12
  120. package/lib/src/react/index.spec.js.map +1 -1
  121. package/lib/src/types.d.ts +25 -15
  122. package/lib/src/types.d.ts.map +1 -1
  123. package/lib/src/types.js +11 -3
  124. package/lib/src/types.js.map +1 -1
  125. package/lib/src/utils/authService/authService.spec.js +1 -1
  126. package/lib/src/utils/authService/authService.spec.js.map +1 -1
  127. package/lib/src/visual-embed-sdk.d.ts +71 -30
  128. package/package.json +1 -1
  129. package/src/auth.ts +6 -6
  130. package/src/authToken.ts +6 -0
  131. package/src/embed/app.spec.ts +3 -2
  132. package/src/embed/app.ts +19 -8
  133. package/src/embed/base.spec.ts +3 -3
  134. package/src/embed/base.ts +14 -12
  135. package/src/embed/liveboard.spec.ts +3 -3
  136. package/src/embed/liveboard.ts +16 -3
  137. package/src/embed/pinboard.spec.ts +3 -2
  138. package/src/embed/search.spec.ts +3 -2
  139. package/src/embed/search.ts +20 -11
  140. package/src/embed/ts-embed.spec.ts +28 -37
  141. package/src/embed/ts-embed.ts +45 -41
  142. package/src/index.ts +2 -0
  143. package/src/react/index.spec.tsx +0 -29
  144. package/src/types.ts +26 -16
  145. package/src/utils/authService/authService.spec.ts +4 -4
@@ -572,7 +572,6 @@
572
572
  * .then((data) => data.token);
573
573
  * }
574
574
  * });
575
- * });
576
575
  * ```
577
576
  */
578
577
  AuthType["TrustedAuthToken"] = "AuthServer";
@@ -901,8 +900,7 @@
901
900
  *
902
901
  * API - API call failure error.
903
902
  *
904
- * FULLSCREEN - Error when presenting a Liveboard or visualization in full screen
905
- * mode.
903
+ * FULLSCREEN - Error when presenting a Liveboard or visualization in full screen mode.
906
904
  *
907
905
  * SINGLE_VALUE_FILTER - Error due to multiple values in the single value filter.
908
906
  *
@@ -3399,6 +3397,16 @@
3399
3397
  * @version SDK : 1.27.9 | Thoughtspot: 9.12.5.cl
3400
3398
  */
3401
3399
  Action["CopyKpiLink"] = "copyKpiLink";
3400
+ /**
3401
+ * The **Organise Favourites** action on Homepage Favourite Module.
3402
+ *
3403
+ * @example
3404
+ * ```js
3405
+ * disabledActions: [Action.OrganiseFavourites]
3406
+ * ```
3407
+ * @version SDK : 1.32.0 | Thoughtspot: 10.0.0.cl
3408
+ */
3409
+ Action["OrganiseFavourites"] = "organiseFavourites";
3402
3410
  /**
3403
3411
  * Action ID for AI Highlights button
3404
3412
  *
@@ -5711,8 +5719,6 @@
5711
5719
 
5712
5720
  var isEqual_1 = isEqual;
5713
5721
 
5714
- var name="@thoughtspot/visual-embed-sdk";var version="1.28.0";var description="ThoughtSpot Embed SDK";var module="lib/src/index.js";var main="dist/tsembed.js";var types="lib/src/index.d.ts";var files=["dist/**","lib/**","src/**","cjs/**"];var exports$1={".":{"import":"./lib/src/index.js",require:"./cjs/src/index.js",types:"./lib/src/index.d.ts"},"./react":{"import":"./lib/src/react/all-types-export.js",require:"./cjs/src/react/all-types-export.js",types:"./lib/src/react/all-types-export.d.ts"},"./lib/src/react":{"import":"./lib/src/react/all-types-export.js",require:"./cjs/src/react/all-types-export.js",types:"./lib/src/react/all-types-export.d.ts"}};var typesVersions={"*":{react:["./lib/src/react/all-types-export.d.ts"]}};var scripts={lint:"eslint 'src/**'","lint:fix":"eslint 'src/**/*.*' --fix",tsc:"tsc -p . --incremental false; tsc -p . --incremental false --module commonjs --outDir cjs",start:"gatsby develop","build:gatsby":"npm run clean:gatsby && gatsby build --prefix-paths","build:gatsby:noprefix":"npm run clean:gatsby && gatsby build","serve:gatsby":"gatsby serve","clean:gatsby":"gatsby clean","build-and-publish":"npm run build:gatsby && npm run publish","bundle-dts-file":"dts-bundle --name @thoughtspot/visual-embed-sdk --out visual-embed-sdk.d.ts --main lib/src/index.d.ts","bundle-dts":"dts-bundle --name ../../dist/visual-embed-sdk --main lib/src/index.d.ts --outputAsModuleFolder=true","bundle-dts-react":"dts-bundle --name ../../../dist/visual-embed-sdk-react --main lib/src/react/index.d.ts --outputAsModuleFolder=true","bundle-dts-react-full":"dts-bundle --name ../../../dist/visual-embed-sdk-react-full --main lib/src/react/all-types-export.d.ts --outputAsModuleFolder=true",build:"rollup -c",watch:"rollup -cw","docs-cmd":"node scripts/gatsby-commands.js",docgen:"typedoc --tsconfig tsconfig.json --theme typedoc-theme","test-sdk":"jest -c jest.config.sdk.js --runInBand","test-docs":"jest -c jest.config.docs.js",test:"npm run test-sdk && npm run test-docs",posttest:"cat ./coverage/sdk/lcov.info | coveralls","is-publish-allowed":"node scripts/is-publish-allowed.js",prepublishOnly:"npm run is-publish-allowed && npm run test && npm run tsc && npm run bundle-dts-file && npm run bundle-dts && npm run bundle-dts-react && npm run bundle-dts-react-full && npm run build","check-size":"npm run build && size-limit","publish-dev":"npm publish --tag dev","publish-prod":"npm publish --tag latest"};var peerDependencies={react:"> 16.8.0","react-dom":"> 16.8.0"};var dependencies={algoliasearch:"^4.10.5",classnames:"^2.3.1",dompurify:"^2.3.4","eslint-plugin-comment-length":"^0.9.2","eslint-plugin-jsdoc":"^46.9.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:"45 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};
5715
-
5716
5722
  /**
5717
5723
  * Checks if `value` is `undefined`.
5718
5724
  *
@@ -5985,379 +5991,926 @@
5985
5991
  throw new Error(INVALID_TOKEN_ERR);
5986
5992
  }
5987
5993
  };
5994
+ /**
5995
+ * Resets the auth token and a new token will be fetched on the next request.
5996
+ *
5997
+ * @version SDK: 1.28.0 | ThoughtSpot: *
5998
+ * @group Authentication / Init
5999
+ */
5988
6000
  const resetCachedAuthToken = () => {
5989
6001
  cachedAuthToken = null;
5990
6002
  };
5991
6003
 
5992
- var Config = {
5993
- DEBUG: false,
5994
- LIB_VERSION: '2.45.0'
6004
+ let config = {};
6005
+ /**
6006
+ * Gets the configuration embed was initialized with.
6007
+ *
6008
+ * @returns {@link EmbedConfig} The configuration embed was initialized with.
6009
+ * @version SDK: 1.19.0 | ThoughtSpot: *
6010
+ * @group Global methods
6011
+ */
6012
+ const getEmbedConfig = () => config;
6013
+
6014
+ /**
6015
+ * Fetch wrapper that adds the authentication token to the request.
6016
+ * Use this to call the ThoughtSpot APIs when using the visual embed sdk.
6017
+ *
6018
+ * @param input
6019
+ * @param init
6020
+ * @version SDK: 1.28.0
6021
+ * @group Global methods
6022
+ */
6023
+ const tokenizedFetch = async (input, init) => {
6024
+ const embedConfig = getEmbedConfig();
6025
+ if (embedConfig.authType !== AuthType.TrustedAuthTokenCookieless) {
6026
+ return fetch(input, init);
6027
+ }
6028
+ const req = new Request(input, init);
6029
+ const authToken = await getAuthenticationToken(embedConfig);
6030
+ if (authToken) {
6031
+ req.headers.append('Authorization', `Bearer ${authToken}`);
6032
+ }
6033
+ return fetch(req);
5995
6034
  };
5996
6035
 
5997
- // since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
5998
- var window$1;
5999
- if (typeof(window) === 'undefined') {
6000
- var loc = {
6001
- hostname: ''
6002
- };
6003
- window$1 = {
6004
- navigator: { userAgent: '' },
6005
- document: {
6006
- location: loc,
6007
- referrer: ''
6008
- },
6009
- screen: { width: 0, height: 0 },
6010
- location: loc
6011
- };
6012
- } else {
6013
- window$1 = window;
6036
+ /**
6037
+ *
6038
+ * @param root0
6039
+ * @param root0.query
6040
+ * @param root0.variables
6041
+ * @param root0.thoughtSpotHost
6042
+ * @param root0.isCompositeQuery
6043
+ */
6044
+ async function graphqlQuery({ query, variables, thoughtSpotHost, isCompositeQuery = false, }) {
6045
+ const operationName = getOperationNameFromQuery(query);
6046
+ try {
6047
+ const response = await fetch(`${thoughtSpotHost}/prism/?op=${operationName}`, {
6048
+ method: 'POST',
6049
+ headers: {
6050
+ 'content-type': 'application/json;charset=UTF-8',
6051
+ 'x-requested-by': 'ThoughtSpot',
6052
+ accept: '*/*',
6053
+ 'accept-language': 'en-us',
6054
+ },
6055
+ body: JSON.stringify({
6056
+ operationName,
6057
+ query,
6058
+ variables,
6059
+ }),
6060
+ credentials: 'include',
6061
+ });
6062
+ const result = await response.json();
6063
+ const dataValues = Object.values(result.data);
6064
+ return (isCompositeQuery) ? result.data : dataValues[0];
6065
+ }
6066
+ catch (error) {
6067
+ return error;
6068
+ }
6014
6069
  }
6015
6070
 
6016
- /*
6017
- * Saved references to long variable names, so that closure compiler can
6018
- * minimize file size.
6019
- */
6020
-
6021
- var ArrayProto = Array.prototype;
6022
- var FuncProto = Function.prototype;
6023
- var ObjProto = Object.prototype;
6024
- var slice = ArrayProto.slice;
6025
- var toString = ObjProto.toString;
6026
- var hasOwnProperty$9 = ObjProto.hasOwnProperty;
6027
- var windowConsole = window$1.console;
6028
- var navigator = window$1.navigator;
6029
- var document$1 = window$1.document;
6030
- var windowOpera = window$1.opera;
6031
- var screen = window$1.screen;
6032
- var userAgent = navigator.userAgent;
6033
- var nativeBind = FuncProto.bind;
6034
- var nativeForEach = ArrayProto.forEach;
6035
- var nativeIndexOf = ArrayProto.indexOf;
6036
- var nativeMap = ArrayProto.map;
6037
- var nativeIsArray = Array.isArray;
6038
- var breaker = {};
6039
- var _ = {
6040
- trim: function(str) {
6041
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim#Polyfill
6042
- return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
6043
- }
6044
- };
6045
-
6046
- // Console override
6047
- var console$1 = {
6048
- /** @type {function(...*)} */
6049
- log: function() {
6050
- if (Config.DEBUG && !_.isUndefined(windowConsole) && windowConsole) {
6051
- try {
6052
- windowConsole.log.apply(windowConsole, arguments);
6053
- } catch (err) {
6054
- _.each(arguments, function(arg) {
6055
- windowConsole.log(arg);
6056
- });
6057
- }
6058
- }
6059
- },
6060
- /** @type {function(...*)} */
6061
- warn: function() {
6062
- if (Config.DEBUG && !_.isUndefined(windowConsole) && windowConsole) {
6063
- var args = ['Mixpanel warning:'].concat(_.toArray(arguments));
6064
- try {
6065
- windowConsole.warn.apply(windowConsole, args);
6066
- } catch (err) {
6067
- _.each(args, function(arg) {
6068
- windowConsole.warn(arg);
6069
- });
6070
- }
6071
- }
6072
- },
6073
- /** @type {function(...*)} */
6074
- error: function() {
6075
- if (Config.DEBUG && !_.isUndefined(windowConsole) && windowConsole) {
6076
- var args = ['Mixpanel error:'].concat(_.toArray(arguments));
6077
- try {
6078
- windowConsole.error.apply(windowConsole, args);
6079
- } catch (err) {
6080
- _.each(args, function(arg) {
6081
- windowConsole.error(arg);
6082
- });
6083
- }
6084
- }
6085
- },
6086
- /** @type {function(...*)} */
6087
- critical: function() {
6088
- if (!_.isUndefined(windowConsole) && windowConsole) {
6089
- var args = ['Mixpanel error:'].concat(_.toArray(arguments));
6090
- try {
6091
- windowConsole.error.apply(windowConsole, args);
6092
- } catch (err) {
6093
- _.each(args, function(arg) {
6094
- windowConsole.error(arg);
6095
- });
6096
- }
6097
- }
6098
- }
6099
- };
6071
+ const getSourceDetailQuery = `
6072
+ query GetSourceDetail($ids: [GUID!]!) {
6073
+ getSourceDetailById(ids: $ids, type: LOGICAL_TABLE) {
6074
+ id
6075
+ name
6076
+ description
6077
+ authorName
6078
+ authorDisplayName
6079
+ isExternal
6080
+ type
6081
+ created
6082
+ modified
6083
+ columns {
6084
+ id
6085
+ name
6086
+ author
6087
+ authorDisplayName
6088
+ description
6089
+ dataType
6090
+ type
6091
+ modified
6092
+ ownerName
6093
+ owner
6094
+ dataRecency
6095
+ sources {
6096
+ tableId
6097
+ tableName
6098
+ columnId
6099
+ columnName
6100
+ __typename
6101
+ }
6102
+ synonyms
6103
+ cohortAnswerId
6104
+ __typename
6105
+ }
6106
+ relationships
6107
+ destinationRelationships
6108
+ dataSourceId
6109
+ __typename
6110
+ }
6111
+ }
6112
+ `;
6113
+ const sourceDetailCache = new Map();
6114
+ /**
6115
+ *
6116
+ * @param thoughtSpotHost
6117
+ * @param sourceId
6118
+ */
6119
+ async function getSourceDetail(thoughtSpotHost, sourceId) {
6120
+ if (sourceDetailCache.get(sourceId)) {
6121
+ return sourceDetailCache.get(sourceId);
6122
+ }
6123
+ const details = await graphqlQuery({
6124
+ query: getSourceDetailQuery,
6125
+ variables: {
6126
+ ids: [sourceId],
6127
+ },
6128
+ thoughtSpotHost,
6129
+ });
6130
+ const souceDetails = details[0];
6131
+ if (souceDetails) {
6132
+ sourceDetailCache.set(sourceId, souceDetails);
6133
+ }
6134
+ return souceDetails;
6135
+ }
6100
6136
 
6101
- var log_func_with_prefix = function(func, prefix) {
6102
- return function() {
6103
- arguments[0] = '[' + prefix + '] ' + arguments[0];
6104
- return func.apply(console$1, arguments);
6105
- };
6106
- };
6107
- var console_with_prefix = function(prefix) {
6108
- return {
6109
- log: log_func_with_prefix(console$1.log, prefix),
6110
- error: log_func_with_prefix(console$1.error, prefix),
6111
- critical: log_func_with_prefix(console$1.critical, prefix)
6112
- };
6113
- };
6114
-
6115
-
6116
- // UNDERSCORE
6117
- // Embed part of the Underscore Library
6118
- _.bind = function(func, context) {
6119
- var args, bound;
6120
- if (nativeBind && func.bind === nativeBind) {
6121
- return nativeBind.apply(func, slice.call(arguments, 1));
6122
- }
6123
- if (!_.isFunction(func)) {
6124
- throw new TypeError();
6125
- }
6126
- args = slice.call(arguments, 2);
6127
- bound = function() {
6128
- if (!(this instanceof bound)) {
6129
- return func.apply(context, args.concat(slice.call(arguments)));
6130
- }
6131
- var ctor = {};
6132
- ctor.prototype = func.prototype;
6133
- var self = new ctor();
6134
- ctor.prototype = null;
6135
- var result = func.apply(self, args.concat(slice.call(arguments)));
6136
- if (Object(result) === result) {
6137
- return result;
6138
- }
6139
- return self;
6140
- };
6141
- return bound;
6142
- };
6143
-
6144
- /**
6145
- * @param {*=} obj
6146
- * @param {function(...*)=} iterator
6147
- * @param {Object=} context
6148
- */
6149
- _.each = function(obj, iterator, context) {
6150
- if (obj === null || obj === undefined) {
6151
- return;
6152
- }
6153
- if (nativeForEach && obj.forEach === nativeForEach) {
6154
- obj.forEach(iterator, context);
6155
- } else if (obj.length === +obj.length) {
6156
- for (var i = 0, l = obj.length; i < l; i++) {
6157
- if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) {
6158
- return;
6159
- }
6160
- }
6161
- } else {
6162
- for (var key in obj) {
6163
- if (hasOwnProperty$9.call(obj, key)) {
6164
- if (iterator.call(context, obj[key], key, obj) === breaker) {
6165
- return;
6166
- }
6167
- }
6168
- }
6169
- }
6170
- };
6171
-
6172
- _.extend = function(obj) {
6173
- _.each(slice.call(arguments, 1), function(source) {
6174
- for (var prop in source) {
6175
- if (source[prop] !== void 0) {
6176
- obj[prop] = source[prop];
6177
- }
6178
- }
6179
- });
6180
- return obj;
6181
- };
6182
-
6183
- _.isArray = nativeIsArray || function(obj) {
6184
- return toString.call(obj) === '[object Array]';
6185
- };
6186
-
6187
- // from a comment on http://dbj.org/dbj/?p=286
6188
- // fails on only one very rare and deliberate custom object:
6189
- // var bomb = { toString : undefined, valueOf: function(o) { return "function BOMBA!"; }};
6190
- _.isFunction = function(f) {
6191
- try {
6192
- return /^\s*\bfunction\b/.test(f);
6193
- } catch (x) {
6194
- return false;
6195
- }
6196
- };
6197
-
6198
- _.isArguments = function(obj) {
6199
- return !!(obj && hasOwnProperty$9.call(obj, 'callee'));
6200
- };
6201
-
6202
- _.toArray = function(iterable) {
6203
- if (!iterable) {
6204
- return [];
6205
- }
6206
- if (iterable.toArray) {
6207
- return iterable.toArray();
6208
- }
6209
- if (_.isArray(iterable)) {
6210
- return slice.call(iterable);
6211
- }
6212
- if (_.isArguments(iterable)) {
6213
- return slice.call(iterable);
6214
- }
6215
- return _.values(iterable);
6216
- };
6217
-
6218
- _.map = function(arr, callback, context) {
6219
- if (nativeMap && arr.map === nativeMap) {
6220
- return arr.map(callback, context);
6221
- } else {
6222
- var results = [];
6223
- _.each(arr, function(item) {
6224
- results.push(callback.call(context, item));
6225
- });
6226
- return results;
6227
- }
6228
- };
6229
-
6230
- _.keys = function(obj) {
6231
- var results = [];
6232
- if (obj === null) {
6233
- return results;
6234
- }
6235
- _.each(obj, function(value, key) {
6236
- results[results.length] = key;
6237
- });
6238
- return results;
6239
- };
6240
-
6241
- _.values = function(obj) {
6242
- var results = [];
6243
- if (obj === null) {
6244
- return results;
6245
- }
6246
- _.each(obj, function(value) {
6247
- results[results.length] = value;
6248
- });
6249
- return results;
6250
- };
6251
-
6252
- _.include = function(obj, target) {
6253
- var found = false;
6254
- if (obj === null) {
6255
- return found;
6256
- }
6257
- if (nativeIndexOf && obj.indexOf === nativeIndexOf) {
6258
- return obj.indexOf(target) != -1;
6259
- }
6260
- _.each(obj, function(value) {
6261
- if (found || (found = (value === target))) {
6262
- return breaker;
6263
- }
6264
- });
6265
- return found;
6266
- };
6267
-
6268
- _.includes = function(str, needle) {
6269
- return str.indexOf(needle) !== -1;
6270
- };
6271
-
6272
- // Underscore Addons
6273
- _.inherit = function(subclass, superclass) {
6274
- subclass.prototype = new superclass();
6275
- subclass.prototype.constructor = subclass;
6276
- subclass.superclass = superclass.prototype;
6277
- return subclass;
6278
- };
6279
-
6280
- _.isObject = function(obj) {
6281
- return (obj === Object(obj) && !_.isArray(obj));
6282
- };
6137
+ const bachSessionId = `
6138
+ id {
6139
+ sessionId
6140
+ genNo
6141
+ acSession {
6142
+ sessionId
6143
+ genNo
6144
+ }
6145
+ }
6146
+ `;
6147
+ const getUnaggregatedAnswerSession = `
6148
+ mutation GetUnAggregatedAnswerSession($session: BachSessionIdInput!, $columns: [UserPointSelectionInput!]!) {
6149
+ Answer__getUnaggregatedAnswer(session: $session, columns: $columns) {
6150
+ ${bachSessionId}
6151
+ answer {
6152
+ visualizations {
6153
+ ... on TableViz {
6154
+ columns {
6155
+ column {
6156
+ id
6157
+ name
6158
+ referencedColumns {
6159
+ guid
6160
+ displayName
6161
+ }
6162
+ }
6163
+ }
6164
+ }
6165
+ }
6166
+ }
6167
+ }
6168
+ }
6169
+ `;
6170
+ const removeColumns = `
6171
+ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!], $columnIds: [GUID!]) {
6172
+ Answer__removeColumns(
6173
+ session: $session
6174
+ logicalColumnIds: $logicalColumnIds
6175
+ columnIds: $columnIds
6176
+ ) {
6177
+ ${bachSessionId}
6178
+ }
6179
+ }
6180
+ `;
6181
+ const addColumns = `
6182
+ mutation AddColumns($session: BachSessionIdInput!, $columns: [AnswerColumnInfo!]!) {
6183
+ Answer__addColumn(session: $session, columns: $columns) {
6184
+ ${bachSessionId}
6185
+ }
6186
+ }
6187
+ `;
6188
+ const getAnswerData = `
6189
+ query GetTableWithHeadlineData($session: BachSessionIdInput!, $deadline: Int!, $dataPaginationParams: DataPaginationParamsInput!) {
6190
+ getAnswer(session: $session) {
6191
+ ${bachSessionId}
6192
+ answer {
6193
+ id
6194
+ visualizations {
6195
+ id
6196
+ ... on TableViz {
6197
+ columns {
6198
+ column {
6199
+ id
6200
+ name
6201
+ type
6202
+ aggregationType
6203
+ dataType
6204
+ }
6205
+ }
6206
+ data(deadline: $deadline, pagination: $dataPaginationParams)
6207
+ }
6208
+ }
6209
+ }
6210
+ }
6211
+ }
6212
+ `;
6283
6213
 
6284
- _.isEmptyObject = function(obj) {
6285
- if (_.isObject(obj)) {
6286
- for (var key in obj) {
6287
- if (hasOwnProperty$9.call(obj, key)) {
6288
- return false;
6289
- }
6290
- }
6291
- return true;
6292
- }
6293
- return false;
6294
- };
6214
+ // eslint-disable-next-line no-shadow
6215
+ var OperationType;
6216
+ (function (OperationType) {
6217
+ OperationType["GetChartWithData"] = "GetChartWithData";
6218
+ OperationType["GetTableWithHeadlineData"] = "GetTableWithHeadlineData";
6219
+ })(OperationType || (OperationType = {}));
6220
+ /**
6221
+ * Class representing the answer service provided with the
6222
+ * custom action payload. This service could be used to run
6223
+ * graphql queries in the context of the answer on which the
6224
+ * custom action was triggered.
6225
+ *
6226
+ * @example
6227
+ * ```js
6228
+ * embed.on(EmbedEvent.CustomAction, e => {
6229
+ * const underlying = await e.answerService.getUnderlyingDataForPoint([
6230
+ * 'col name 1'
6231
+ * ]);
6232
+ * const data = await underlying.fetchData(0, 100);
6233
+ * })
6234
+ * ```
6235
+ * @version SDK: 1.25.0| ThoughtSpot: 9.10.0.cl
6236
+ * @group Events
6237
+ */
6238
+ class AnswerService {
6239
+ /**
6240
+ * Should not need to be called directly.
6241
+ *
6242
+ * @param session
6243
+ * @param answer
6244
+ * @param thoughtSpotHost
6245
+ * @param selectedPoints
6246
+ */
6247
+ constructor(session, answer, thoughtSpotHost, selectedPoints) {
6248
+ this.session = session;
6249
+ this.answer = answer;
6250
+ this.thoughtSpotHost = thoughtSpotHost;
6251
+ this.selectedPoints = selectedPoints;
6252
+ this.session = removeTypename(session);
6253
+ }
6254
+ /**
6255
+ * Get the details about the source used in the answer.
6256
+ * This can be used to get the list of all columns in the data source for example.
6257
+ */
6258
+ async getSourceDetail() {
6259
+ const sourceId = this.answer.sources[0].header.guid;
6260
+ return getSourceDetail(this.thoughtSpotHost, sourceId);
6261
+ }
6262
+ /**
6263
+ * Remove columnIds and return updated answer session.
6264
+ *
6265
+ * @param columnIds
6266
+ * @returns
6267
+ */
6268
+ async removeColumns(columnIds) {
6269
+ return this.executeQuery(removeColumns, {
6270
+ logicalColumnIds: columnIds,
6271
+ });
6272
+ }
6273
+ /**
6274
+ * Add columnIds and return updated answer session.
6275
+ *
6276
+ * @param columnIds
6277
+ * @returns
6278
+ */
6279
+ async addColumns(columnIds) {
6280
+ return this.executeQuery(addColumns, {
6281
+ columns: columnIds.map((colId) => ({ logicalColumnId: colId })),
6282
+ });
6283
+ }
6284
+ /**
6285
+ * Fetch data from the answer.
6286
+ *
6287
+ * @param offset
6288
+ * @param size
6289
+ * @returns
6290
+ */
6291
+ async fetchData(offset = 0, size = 1000) {
6292
+ const { answer } = await this.executeQuery(getAnswerData, {
6293
+ deadline: 0,
6294
+ dataPaginationParams: {
6295
+ isClientPaginated: true,
6296
+ offset,
6297
+ size,
6298
+ },
6299
+ });
6300
+ const { columns, data } = answer.visualizations.find((viz) => !!viz.data) || {};
6301
+ return {
6302
+ columns,
6303
+ data,
6304
+ };
6305
+ }
6306
+ /**
6307
+ * Fetch the data for the answer as a CSV blob. This might be
6308
+ * quicker for larger data.
6309
+ *
6310
+ * @param userLocale
6311
+ * @param includeInfo Include the CSV header in the output
6312
+ * @returns Response
6313
+ */
6314
+ async fetchCSVBlob(userLocale = 'en-us', includeInfo = false) {
6315
+ const fetchUrl = this.getFetchCSVBlobUrl(userLocale, includeInfo);
6316
+ return tokenizedFetch(fetchUrl, {
6317
+ credentials: 'include',
6318
+ });
6319
+ }
6320
+ /**
6321
+ * Just get the internal URL for this answer's data
6322
+ * as a CSV blob.
6323
+ *
6324
+ * @param userLocale
6325
+ * @param includeInfo
6326
+ * @returns
6327
+ */
6328
+ getFetchCSVBlobUrl(userLocale = 'en-us', includeInfo = false) {
6329
+ return `${this.thoughtSpotHost}/prism/download/answer/csv?sessionId=${this.session.sessionId}&genNo=${this.session.genNo}&userLocale=${userLocale}&exportFileName=data&hideCsvHeader=${!includeInfo}`;
6330
+ }
6331
+ /**
6332
+ * Get underlying data given a point and the output column names.
6333
+ * In case of a context menu action, the selectedPoints are
6334
+ * automatically passed.
6335
+ *
6336
+ * @param outputColumnNames
6337
+ * @param selectedPoints
6338
+ * @example
6339
+ * ```js
6340
+ * embed.on(EmbedEvent.CustomAction, e => {
6341
+ * const underlying = await e.answerService.getUnderlyingDataForPoint([
6342
+ * 'col name 1' // The column should exist in the data source.
6343
+ * ]);
6344
+ * const data = await underlying.fetchData(0, 100);
6345
+ * })
6346
+ * ```
6347
+ * @version SDK: 1.25.0| ThoughtSpot: 9.10.0.cl
6348
+ */
6349
+ async getUnderlyingDataForPoint(outputColumnNames, selectedPoints) {
6350
+ if (!selectedPoints && !this.selectedPoints) {
6351
+ throw new Error('Needs to be triggered in context of a point');
6352
+ }
6353
+ if (!selectedPoints) {
6354
+ selectedPoints = getSelectedPointsForUnderlyingDataQuery(this.selectedPoints);
6355
+ }
6356
+ const sourceDetail = await this.getSourceDetail();
6357
+ const ouputColumnGuids = getGuidsFromColumnNames(sourceDetail, outputColumnNames);
6358
+ const unAggAnswer = await graphqlQuery({
6359
+ query: getUnaggregatedAnswerSession,
6360
+ variables: {
6361
+ session: this.session,
6362
+ columns: selectedPoints,
6363
+ },
6364
+ thoughtSpotHost: this.thoughtSpotHost,
6365
+ });
6366
+ const unaggAnswerSession = new AnswerService(unAggAnswer.id, unAggAnswer.answer, this.thoughtSpotHost);
6367
+ const currentColumns = new Set(unAggAnswer.answer.visualizations[0].columns
6368
+ .map((c) => c.column.referencedColumns[0].guid));
6369
+ const columnsToAdd = [...ouputColumnGuids].filter((col) => !currentColumns.has(col));
6370
+ if (columnsToAdd.length) {
6371
+ await unaggAnswerSession.addColumns(columnsToAdd);
6372
+ }
6373
+ const columnsToRemove = [...currentColumns].filter((col) => !ouputColumnGuids.has(col));
6374
+ if (columnsToRemove.length) {
6375
+ await unaggAnswerSession.removeColumns(columnsToRemove);
6376
+ }
6377
+ return unaggAnswerSession;
6378
+ }
6379
+ /**
6380
+ * Execute a custom graphql query in the context of the answer.
6381
+ *
6382
+ * @param query graphql query
6383
+ * @param variables graphql variables
6384
+ * @returns
6385
+ */
6386
+ async executeQuery(query, variables) {
6387
+ const data = await graphqlQuery({
6388
+ query,
6389
+ variables: {
6390
+ session: this.session,
6391
+ ...variables,
6392
+ },
6393
+ thoughtSpotHost: this.thoughtSpotHost,
6394
+ isCompositeQuery: false,
6395
+ });
6396
+ this.session = deepMerge(this.session, (data === null || data === void 0 ? void 0 : data.id) || {});
6397
+ return data;
6398
+ }
6399
+ /**
6400
+ * Get the internal session details for the answer.
6401
+ *
6402
+ * @returns
6403
+ */
6404
+ getSession() {
6405
+ return this.session;
6406
+ }
6407
+ }
6408
+ /**
6409
+ *
6410
+ * @param sourceDetail
6411
+ * @param colNames
6412
+ */
6413
+ function getGuidsFromColumnNames(sourceDetail, colNames) {
6414
+ const cols = sourceDetail.columns.reduce((colSet, col) => {
6415
+ colSet[col.name] = col;
6416
+ return colSet;
6417
+ }, {});
6418
+ return new Set(colNames.map((colName) => {
6419
+ const col = cols[colName];
6420
+ return col.id;
6421
+ }));
6422
+ }
6423
+ /**
6424
+ *
6425
+ * @param selectedPoints
6426
+ */
6427
+ function getSelectedPointsForUnderlyingDataQuery(selectedPoints) {
6428
+ const underlyingDataPoint = [];
6429
+ /**
6430
+ *
6431
+ * @param colVal
6432
+ */
6433
+ function addPointFromColVal(colVal) {
6434
+ var _a;
6435
+ const dataType = colVal.column.dataType;
6436
+ const id = colVal.column.id;
6437
+ let dataValue;
6438
+ if (dataType === 'DATE') {
6439
+ if (Number.isFinite(colVal.value)) {
6440
+ dataValue = [{
6441
+ epochRange: {
6442
+ startEpoch: colVal.value,
6443
+ },
6444
+ }];
6445
+ // Case for custom calendar.
6446
+ }
6447
+ else if ((_a = colVal.value) === null || _a === void 0 ? void 0 : _a.v) {
6448
+ dataValue = [{
6449
+ epochRange: {
6450
+ startEpoch: colVal.value.v.s,
6451
+ endEpoch: colVal.value.v.e,
6452
+ },
6453
+ }];
6454
+ }
6455
+ }
6456
+ else {
6457
+ dataValue = [{ value: colVal.value }];
6458
+ }
6459
+ underlyingDataPoint.push({
6460
+ columnId: colVal.column.id,
6461
+ dataValue,
6462
+ });
6463
+ }
6464
+ selectedPoints.forEach((p) => {
6465
+ p.selectedAttributes.forEach(addPointFromColVal);
6466
+ });
6467
+ return underlyingDataPoint;
6468
+ }
6295
6469
 
6296
- _.isUndefined = function(obj) {
6297
- return obj === void 0;
6470
+ const ERROR_MESSAGE = {
6471
+ INVALID_THOUGHTSPOT_HOST: 'Error parsing ThoughtSpot host. Please provide a valid URL.',
6472
+ LIVEBOARD_VIZ_ID_VALIDATION: 'Please provide either liveboardId or pinboardId',
6473
+ TRIGGER_TIMED_OUT: 'Trigger timedout in getting response',
6474
+ SEARCHEMBED_BETA_WRANING_MESSAGE: 'Search Embed is in Beta in this release.',
6475
+ SAGE_EMBED_BETA_WARNING_MESSAGE: 'Sage Embed is in Beta in this release.',
6298
6476
  };
6299
6477
 
6300
- _.isString = function(obj) {
6301
- return toString.call(obj) == '[object String]';
6302
- };
6478
+ /**
6479
+ * Copyright (c) 2023
6480
+ *
6481
+ * Utilities related to reading configuration objects
6482
+ *
6483
+ * @summary Config-related utils
6484
+ * @author Ayon Ghosh <ayon.ghosh@thoughtspot.com>
6485
+ */
6486
+ const urlRegex = new RegExp([
6487
+ '(^(https?:)//)?',
6488
+ '(([^:/?#]*)(?::([0-9]+))?)',
6489
+ '(/{0,1}[^?#]*)',
6490
+ '(\\?[^#]*|)',
6491
+ '(#.*|)$', // hash
6492
+ ].join(''));
6493
+ /**
6494
+ * Parse and construct the ThoughtSpot hostname or IP address
6495
+ * from the embed configuration object.
6496
+ *
6497
+ * @param config
6498
+ */
6499
+ const getThoughtSpotHost = (config) => {
6500
+ if (!config.thoughtSpotHost) {
6501
+ throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
6502
+ }
6503
+ const urlParts = config.thoughtSpotHost.match(urlRegex);
6504
+ if (!urlParts) {
6505
+ throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
6506
+ }
6507
+ const protocol = urlParts[2] || window.location.protocol;
6508
+ const host = urlParts[3];
6509
+ let path = urlParts[6];
6510
+ // Lose the trailing / if any
6511
+ if (path.charAt(path.length - 1) === '/') {
6512
+ path = path.substring(0, path.length - 1);
6513
+ }
6514
+ // const urlParams = urlParts[7];
6515
+ // const hash = urlParts[8];
6516
+ return `${protocol}//${host}${path}`;
6517
+ };
6518
+ const getV2BasePath = (config) => {
6519
+ if (config.basepath) {
6520
+ return config.basepath;
6521
+ }
6522
+ const tsHost = getThoughtSpotHost(config);
6523
+ // This is to handle when e2e's. Search is run on pods for
6524
+ // comp-blink-test-pipeline with baseUrl=https://localhost:8443.
6525
+ // This is to handle when the developer is developing in their local
6526
+ // environment.
6527
+ if (tsHost.includes('://localhost') && !tsHost.includes(':8443')) {
6528
+ return '';
6529
+ }
6530
+ return 'v2';
6531
+ };
6532
+ /**
6533
+ * It is a good idea to keep URLs under 2000 chars.
6534
+ * If this is ever breached, since we pass view configuration through
6535
+ * URL params, we would like to log a warning.
6536
+ * Reference: https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
6537
+ */
6538
+ const URL_MAX_LENGTH = 2000;
6539
+ /**
6540
+ * The default CSS dimensions of the embedded app
6541
+ */
6542
+ const DEFAULT_EMBED_WIDTH = '100%';
6543
+ const DEFAULT_EMBED_HEIGHT = '100%';
6303
6544
 
6304
- _.isDate = function(obj) {
6305
- return toString.call(obj) == '[object Date]';
6545
+ var Config = {
6546
+ DEBUG: false,
6547
+ LIB_VERSION: '2.45.0'
6306
6548
  };
6307
6549
 
6308
- _.isNumber = function(obj) {
6309
- return toString.call(obj) == '[object Number]';
6310
- };
6550
+ // since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
6551
+ var window$1;
6552
+ if (typeof(window) === 'undefined') {
6553
+ var loc = {
6554
+ hostname: ''
6555
+ };
6556
+ window$1 = {
6557
+ navigator: { userAgent: '' },
6558
+ document: {
6559
+ location: loc,
6560
+ referrer: ''
6561
+ },
6562
+ screen: { width: 0, height: 0 },
6563
+ location: loc
6564
+ };
6565
+ } else {
6566
+ window$1 = window;
6567
+ }
6311
6568
 
6312
- _.isElement = function(obj) {
6313
- return !!(obj && obj.nodeType === 1);
6569
+ /*
6570
+ * Saved references to long variable names, so that closure compiler can
6571
+ * minimize file size.
6572
+ */
6573
+
6574
+ var ArrayProto = Array.prototype;
6575
+ var FuncProto = Function.prototype;
6576
+ var ObjProto = Object.prototype;
6577
+ var slice = ArrayProto.slice;
6578
+ var toString = ObjProto.toString;
6579
+ var hasOwnProperty$9 = ObjProto.hasOwnProperty;
6580
+ var windowConsole = window$1.console;
6581
+ var navigator = window$1.navigator;
6582
+ var document$1 = window$1.document;
6583
+ var windowOpera = window$1.opera;
6584
+ var screen = window$1.screen;
6585
+ var userAgent = navigator.userAgent;
6586
+ var nativeBind = FuncProto.bind;
6587
+ var nativeForEach = ArrayProto.forEach;
6588
+ var nativeIndexOf = ArrayProto.indexOf;
6589
+ var nativeMap = ArrayProto.map;
6590
+ var nativeIsArray = Array.isArray;
6591
+ var breaker = {};
6592
+ var _ = {
6593
+ trim: function(str) {
6594
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim#Polyfill
6595
+ return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
6596
+ }
6314
6597
  };
6315
6598
 
6316
- _.encodeDates = function(obj) {
6317
- _.each(obj, function(v, k) {
6318
- if (_.isDate(v)) {
6319
- obj[k] = _.formatDate(v);
6320
- } else if (_.isObject(v)) {
6321
- obj[k] = _.encodeDates(v); // recurse
6599
+ // Console override
6600
+ var console$1 = {
6601
+ /** @type {function(...*)} */
6602
+ log: function() {
6603
+ if (Config.DEBUG && !_.isUndefined(windowConsole) && windowConsole) {
6604
+ try {
6605
+ windowConsole.log.apply(windowConsole, arguments);
6606
+ } catch (err) {
6607
+ _.each(arguments, function(arg) {
6608
+ windowConsole.log(arg);
6609
+ });
6610
+ }
6322
6611
  }
6323
- });
6324
- return obj;
6612
+ },
6613
+ /** @type {function(...*)} */
6614
+ warn: function() {
6615
+ if (Config.DEBUG && !_.isUndefined(windowConsole) && windowConsole) {
6616
+ var args = ['Mixpanel warning:'].concat(_.toArray(arguments));
6617
+ try {
6618
+ windowConsole.warn.apply(windowConsole, args);
6619
+ } catch (err) {
6620
+ _.each(args, function(arg) {
6621
+ windowConsole.warn(arg);
6622
+ });
6623
+ }
6624
+ }
6625
+ },
6626
+ /** @type {function(...*)} */
6627
+ error: function() {
6628
+ if (Config.DEBUG && !_.isUndefined(windowConsole) && windowConsole) {
6629
+ var args = ['Mixpanel error:'].concat(_.toArray(arguments));
6630
+ try {
6631
+ windowConsole.error.apply(windowConsole, args);
6632
+ } catch (err) {
6633
+ _.each(args, function(arg) {
6634
+ windowConsole.error(arg);
6635
+ });
6636
+ }
6637
+ }
6638
+ },
6639
+ /** @type {function(...*)} */
6640
+ critical: function() {
6641
+ if (!_.isUndefined(windowConsole) && windowConsole) {
6642
+ var args = ['Mixpanel error:'].concat(_.toArray(arguments));
6643
+ try {
6644
+ windowConsole.error.apply(windowConsole, args);
6645
+ } catch (err) {
6646
+ _.each(args, function(arg) {
6647
+ windowConsole.error(arg);
6648
+ });
6649
+ }
6650
+ }
6651
+ }
6325
6652
  };
6326
6653
 
6327
- _.timestamp = function() {
6328
- Date.now = Date.now || function() {
6329
- return +new Date;
6654
+ var log_func_with_prefix = function(func, prefix) {
6655
+ return function() {
6656
+ arguments[0] = '[' + prefix + '] ' + arguments[0];
6657
+ return func.apply(console$1, arguments);
6330
6658
  };
6331
- return Date.now();
6332
6659
  };
6333
-
6334
- _.formatDate = function(d) {
6335
- // YYYY-MM-DDTHH:MM:SS in UTC
6336
- function pad(n) {
6337
- return n < 10 ? '0' + n : n;
6338
- }
6339
- return d.getUTCFullYear() + '-' +
6340
- pad(d.getUTCMonth() + 1) + '-' +
6341
- pad(d.getUTCDate()) + 'T' +
6342
- pad(d.getUTCHours()) + ':' +
6343
- pad(d.getUTCMinutes()) + ':' +
6344
- pad(d.getUTCSeconds());
6660
+ var console_with_prefix = function(prefix) {
6661
+ return {
6662
+ log: log_func_with_prefix(console$1.log, prefix),
6663
+ error: log_func_with_prefix(console$1.error, prefix),
6664
+ critical: log_func_with_prefix(console$1.critical, prefix)
6665
+ };
6345
6666
  };
6346
6667
 
6347
- _.strip_empty_properties = function(p) {
6348
- var ret = {};
6349
- _.each(p, function(v, k) {
6350
- if (_.isString(v) && v.length > 0) {
6351
- ret[k] = v;
6668
+
6669
+ // UNDERSCORE
6670
+ // Embed part of the Underscore Library
6671
+ _.bind = function(func, context) {
6672
+ var args, bound;
6673
+ if (nativeBind && func.bind === nativeBind) {
6674
+ return nativeBind.apply(func, slice.call(arguments, 1));
6675
+ }
6676
+ if (!_.isFunction(func)) {
6677
+ throw new TypeError();
6678
+ }
6679
+ args = slice.call(arguments, 2);
6680
+ bound = function() {
6681
+ if (!(this instanceof bound)) {
6682
+ return func.apply(context, args.concat(slice.call(arguments)));
6352
6683
  }
6353
- });
6354
- return ret;
6684
+ var ctor = {};
6685
+ ctor.prototype = func.prototype;
6686
+ var self = new ctor();
6687
+ ctor.prototype = null;
6688
+ var result = func.apply(self, args.concat(slice.call(arguments)));
6689
+ if (Object(result) === result) {
6690
+ return result;
6691
+ }
6692
+ return self;
6693
+ };
6694
+ return bound;
6355
6695
  };
6356
6696
 
6357
- /*
6358
- * this function returns a copy of object after truncating it. If
6359
- * passed an Array or Object it will iterate through obj and
6360
- * truncate all the values recursively.
6697
+ /**
6698
+ * @param {*=} obj
6699
+ * @param {function(...*)=} iterator
6700
+ * @param {Object=} context
6701
+ */
6702
+ _.each = function(obj, iterator, context) {
6703
+ if (obj === null || obj === undefined) {
6704
+ return;
6705
+ }
6706
+ if (nativeForEach && obj.forEach === nativeForEach) {
6707
+ obj.forEach(iterator, context);
6708
+ } else if (obj.length === +obj.length) {
6709
+ for (var i = 0, l = obj.length; i < l; i++) {
6710
+ if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) {
6711
+ return;
6712
+ }
6713
+ }
6714
+ } else {
6715
+ for (var key in obj) {
6716
+ if (hasOwnProperty$9.call(obj, key)) {
6717
+ if (iterator.call(context, obj[key], key, obj) === breaker) {
6718
+ return;
6719
+ }
6720
+ }
6721
+ }
6722
+ }
6723
+ };
6724
+
6725
+ _.extend = function(obj) {
6726
+ _.each(slice.call(arguments, 1), function(source) {
6727
+ for (var prop in source) {
6728
+ if (source[prop] !== void 0) {
6729
+ obj[prop] = source[prop];
6730
+ }
6731
+ }
6732
+ });
6733
+ return obj;
6734
+ };
6735
+
6736
+ _.isArray = nativeIsArray || function(obj) {
6737
+ return toString.call(obj) === '[object Array]';
6738
+ };
6739
+
6740
+ // from a comment on http://dbj.org/dbj/?p=286
6741
+ // fails on only one very rare and deliberate custom object:
6742
+ // var bomb = { toString : undefined, valueOf: function(o) { return "function BOMBA!"; }};
6743
+ _.isFunction = function(f) {
6744
+ try {
6745
+ return /^\s*\bfunction\b/.test(f);
6746
+ } catch (x) {
6747
+ return false;
6748
+ }
6749
+ };
6750
+
6751
+ _.isArguments = function(obj) {
6752
+ return !!(obj && hasOwnProperty$9.call(obj, 'callee'));
6753
+ };
6754
+
6755
+ _.toArray = function(iterable) {
6756
+ if (!iterable) {
6757
+ return [];
6758
+ }
6759
+ if (iterable.toArray) {
6760
+ return iterable.toArray();
6761
+ }
6762
+ if (_.isArray(iterable)) {
6763
+ return slice.call(iterable);
6764
+ }
6765
+ if (_.isArguments(iterable)) {
6766
+ return slice.call(iterable);
6767
+ }
6768
+ return _.values(iterable);
6769
+ };
6770
+
6771
+ _.map = function(arr, callback, context) {
6772
+ if (nativeMap && arr.map === nativeMap) {
6773
+ return arr.map(callback, context);
6774
+ } else {
6775
+ var results = [];
6776
+ _.each(arr, function(item) {
6777
+ results.push(callback.call(context, item));
6778
+ });
6779
+ return results;
6780
+ }
6781
+ };
6782
+
6783
+ _.keys = function(obj) {
6784
+ var results = [];
6785
+ if (obj === null) {
6786
+ return results;
6787
+ }
6788
+ _.each(obj, function(value, key) {
6789
+ results[results.length] = key;
6790
+ });
6791
+ return results;
6792
+ };
6793
+
6794
+ _.values = function(obj) {
6795
+ var results = [];
6796
+ if (obj === null) {
6797
+ return results;
6798
+ }
6799
+ _.each(obj, function(value) {
6800
+ results[results.length] = value;
6801
+ });
6802
+ return results;
6803
+ };
6804
+
6805
+ _.include = function(obj, target) {
6806
+ var found = false;
6807
+ if (obj === null) {
6808
+ return found;
6809
+ }
6810
+ if (nativeIndexOf && obj.indexOf === nativeIndexOf) {
6811
+ return obj.indexOf(target) != -1;
6812
+ }
6813
+ _.each(obj, function(value) {
6814
+ if (found || (found = (value === target))) {
6815
+ return breaker;
6816
+ }
6817
+ });
6818
+ return found;
6819
+ };
6820
+
6821
+ _.includes = function(str, needle) {
6822
+ return str.indexOf(needle) !== -1;
6823
+ };
6824
+
6825
+ // Underscore Addons
6826
+ _.inherit = function(subclass, superclass) {
6827
+ subclass.prototype = new superclass();
6828
+ subclass.prototype.constructor = subclass;
6829
+ subclass.superclass = superclass.prototype;
6830
+ return subclass;
6831
+ };
6832
+
6833
+ _.isObject = function(obj) {
6834
+ return (obj === Object(obj) && !_.isArray(obj));
6835
+ };
6836
+
6837
+ _.isEmptyObject = function(obj) {
6838
+ if (_.isObject(obj)) {
6839
+ for (var key in obj) {
6840
+ if (hasOwnProperty$9.call(obj, key)) {
6841
+ return false;
6842
+ }
6843
+ }
6844
+ return true;
6845
+ }
6846
+ return false;
6847
+ };
6848
+
6849
+ _.isUndefined = function(obj) {
6850
+ return obj === void 0;
6851
+ };
6852
+
6853
+ _.isString = function(obj) {
6854
+ return toString.call(obj) == '[object String]';
6855
+ };
6856
+
6857
+ _.isDate = function(obj) {
6858
+ return toString.call(obj) == '[object Date]';
6859
+ };
6860
+
6861
+ _.isNumber = function(obj) {
6862
+ return toString.call(obj) == '[object Number]';
6863
+ };
6864
+
6865
+ _.isElement = function(obj) {
6866
+ return !!(obj && obj.nodeType === 1);
6867
+ };
6868
+
6869
+ _.encodeDates = function(obj) {
6870
+ _.each(obj, function(v, k) {
6871
+ if (_.isDate(v)) {
6872
+ obj[k] = _.formatDate(v);
6873
+ } else if (_.isObject(v)) {
6874
+ obj[k] = _.encodeDates(v); // recurse
6875
+ }
6876
+ });
6877
+ return obj;
6878
+ };
6879
+
6880
+ _.timestamp = function() {
6881
+ Date.now = Date.now || function() {
6882
+ return +new Date;
6883
+ };
6884
+ return Date.now();
6885
+ };
6886
+
6887
+ _.formatDate = function(d) {
6888
+ // YYYY-MM-DDTHH:MM:SS in UTC
6889
+ function pad(n) {
6890
+ return n < 10 ? '0' + n : n;
6891
+ }
6892
+ return d.getUTCFullYear() + '-' +
6893
+ pad(d.getUTCMonth() + 1) + '-' +
6894
+ pad(d.getUTCDate()) + 'T' +
6895
+ pad(d.getUTCHours()) + ':' +
6896
+ pad(d.getUTCMinutes()) + ':' +
6897
+ pad(d.getUTCSeconds());
6898
+ };
6899
+
6900
+ _.strip_empty_properties = function(p) {
6901
+ var ret = {};
6902
+ _.each(p, function(v, k) {
6903
+ if (_.isString(v) && v.length > 0) {
6904
+ ret[k] = v;
6905
+ }
6906
+ });
6907
+ return ret;
6908
+ };
6909
+
6910
+ /*
6911
+ * this function returns a copy of object after truncating it. If
6912
+ * passed an Array or Object it will iterate through obj and
6913
+ * truncate all the values recursively.
6361
6914
  */
6362
6915
  _.truncate = function(obj, length) {
6363
6916
  var ret;
@@ -11627,1357 +12180,423 @@
11627
12180
  'ignore_dnt': this.get_config('ignore_dnt')
11628
12181
  }, options);
11629
12182
 
11630
- // check if localStorage can be used for recording opt out status, fall back to cookie if not
11631
- if (!_.localStorage.is_supported()) {
11632
- options['persistence_type'] = 'cookie';
11633
- }
11634
-
11635
- return func(this.get_config('token'), {
11636
- track: options['track'],
11637
- trackEventName: options['track_event_name'],
11638
- trackProperties: options['track_properties'],
11639
- persistenceType: options['persistence_type'],
11640
- persistencePrefix: options['cookie_prefix'],
11641
- cookieDomain: options['cookie_domain'],
11642
- cookieExpiration: options['cookie_expiration'],
11643
- crossSiteCookie: options['cross_site_cookie'],
11644
- crossSubdomainCookie: options['cross_subdomain_cookie'],
11645
- secureCookie: options['secure_cookie'],
11646
- ignoreDnt: options['ignore_dnt']
11647
- });
11648
- };
11649
-
11650
- /**
11651
- * Opt the user in to data tracking and cookies/localstorage for this Mixpanel instance
11652
- *
11653
- * ### Usage
11654
- *
11655
- * // opt user in
11656
- * mixpanel.opt_in_tracking();
11657
- *
11658
- * // opt user in with specific event name, properties, cookie configuration
11659
- * mixpanel.opt_in_tracking({
11660
- * track_event_name: 'User opted in',
11661
- * track_event_properties: {
11662
- * 'Email': 'jdoe@example.com'
11663
- * },
11664
- * cookie_expiration: 30,
11665
- * secure_cookie: true
11666
- * });
11667
- *
11668
- * @param {Object} [options] A dictionary of config options to override
11669
- * @param {function} [options.track] Function used for tracking a Mixpanel event to record the opt-in action (default is this Mixpanel instance's track method)
11670
- * @param {string} [options.track_event_name=$opt_in] Event name to be used for tracking the opt-in action
11671
- * @param {Object} [options.track_properties] Set of properties to be tracked along with the opt-in action
11672
- * @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence
11673
- * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11674
- * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11675
- * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
11676
- * @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
11677
- * @param {boolean} [options.cross_site_cookie] Whether the opt-in cookie is set as cross-site-enabled (overrides value specified in this Mixpanel instance's config)
11678
- * @param {boolean} [options.cross_subdomain_cookie] Whether the opt-in cookie is set as cross-subdomain or not (overrides value specified in this Mixpanel instance's config)
11679
- * @param {boolean} [options.secure_cookie] Whether the opt-in cookie is set as secure or not (overrides value specified in this Mixpanel instance's config)
11680
- */
11681
- MixpanelLib.prototype.opt_in_tracking = function(options) {
11682
- options = _.extend({
11683
- 'enable_persistence': true
11684
- }, options);
11685
-
11686
- this._gdpr_call_func(optIn, options);
11687
- this._gdpr_update_persistence(options);
11688
- };
11689
-
11690
- /**
11691
- * Opt the user out of data tracking and cookies/localstorage for this Mixpanel instance
11692
- *
11693
- * ### Usage
11694
- *
11695
- * // opt user out
11696
- * mixpanel.opt_out_tracking();
11697
- *
11698
- * // opt user out with different cookie configuration from Mixpanel instance
11699
- * mixpanel.opt_out_tracking({
11700
- * cookie_expiration: 30,
11701
- * secure_cookie: true
11702
- * });
11703
- *
11704
- * @param {Object} [options] A dictionary of config options to override
11705
- * @param {boolean} [options.delete_user=true] If true, will delete the currently identified user's profile and clear all charges after opting the user out
11706
- * @param {boolean} [options.clear_persistence=true] If true, will delete all data stored by the sdk in persistence
11707
- * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11708
- * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11709
- * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
11710
- * @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
11711
- * @param {boolean} [options.cross_site_cookie] Whether the opt-in cookie is set as cross-site-enabled (overrides value specified in this Mixpanel instance's config)
11712
- * @param {boolean} [options.cross_subdomain_cookie] Whether the opt-in cookie is set as cross-subdomain or not (overrides value specified in this Mixpanel instance's config)
11713
- * @param {boolean} [options.secure_cookie] Whether the opt-in cookie is set as secure or not (overrides value specified in this Mixpanel instance's config)
11714
- */
11715
- MixpanelLib.prototype.opt_out_tracking = function(options) {
11716
- options = _.extend({
11717
- 'clear_persistence': true,
11718
- 'delete_user': true
11719
- }, options);
11720
-
11721
- // delete user and clear charges since these methods may be disabled by opt-out
11722
- if (options['delete_user'] && this['people'] && this['people']._identify_called()) {
11723
- this['people'].delete_user();
11724
- this['people'].clear_charges();
11725
- }
11726
-
11727
- this._gdpr_call_func(optOut, options);
11728
- this._gdpr_update_persistence(options);
11729
- };
11730
-
11731
- /**
11732
- * Check whether the user has opted in to data tracking and cookies/localstorage for this Mixpanel instance
11733
- *
11734
- * ### Usage
11735
- *
11736
- * var has_opted_in = mixpanel.has_opted_in_tracking();
11737
- * // use has_opted_in value
11738
- *
11739
- * @param {Object} [options] A dictionary of config options to override
11740
- * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11741
- * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11742
- * @returns {boolean} current opt-in status
11743
- */
11744
- MixpanelLib.prototype.has_opted_in_tracking = function(options) {
11745
- return this._gdpr_call_func(hasOptedIn, options);
11746
- };
11747
-
11748
- /**
11749
- * Check whether the user has opted out of data tracking and cookies/localstorage for this Mixpanel instance
11750
- *
11751
- * ### Usage
11752
- *
11753
- * var has_opted_out = mixpanel.has_opted_out_tracking();
11754
- * // use has_opted_out value
11755
- *
11756
- * @param {Object} [options] A dictionary of config options to override
11757
- * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11758
- * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11759
- * @returns {boolean} current opt-out status
11760
- */
11761
- MixpanelLib.prototype.has_opted_out_tracking = function(options) {
11762
- return this._gdpr_call_func(hasOptedOut, options);
11763
- };
11764
-
11765
- /**
11766
- * Clear the user's opt in/out status of data tracking and cookies/localstorage for this Mixpanel instance
11767
- *
11768
- * ### Usage
11769
- *
11770
- * // clear user's opt-in/out status
11771
- * mixpanel.clear_opt_in_out_tracking();
11772
- *
11773
- * // clear user's opt-in/out status with specific cookie configuration - should match
11774
- * // configuration used when opt_in_tracking/opt_out_tracking methods were called.
11775
- * mixpanel.clear_opt_in_out_tracking({
11776
- * cookie_expiration: 30,
11777
- * secure_cookie: true
11778
- * });
11779
- *
11780
- * @param {Object} [options] A dictionary of config options to override
11781
- * @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence
11782
- * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11783
- * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11784
- * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
11785
- * @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
11786
- * @param {boolean} [options.cross_site_cookie] Whether the opt-in cookie is set as cross-site-enabled (overrides value specified in this Mixpanel instance's config)
11787
- * @param {boolean} [options.cross_subdomain_cookie] Whether the opt-in cookie is set as cross-subdomain or not (overrides value specified in this Mixpanel instance's config)
11788
- * @param {boolean} [options.secure_cookie] Whether the opt-in cookie is set as secure or not (overrides value specified in this Mixpanel instance's config)
11789
- */
11790
- MixpanelLib.prototype.clear_opt_in_out_tracking = function(options) {
11791
- options = _.extend({
11792
- 'enable_persistence': true
11793
- }, options);
11794
-
11795
- this._gdpr_call_func(clearOptInOut, options);
11796
- this._gdpr_update_persistence(options);
11797
- };
11798
-
11799
- MixpanelLib.prototype.report_error = function(msg, err) {
11800
- console$1.error.apply(console$1.error, arguments);
11801
- try {
11802
- if (!err && !(msg instanceof Error)) {
11803
- msg = new Error(msg);
11804
- }
11805
- this.get_config('error_reporter')(msg, err);
11806
- } catch(err) {
11807
- console$1.error(err);
11808
- }
11809
- };
11810
-
11811
- // EXPORTS (for closure compiler)
11812
-
11813
- // MixpanelLib Exports
11814
- MixpanelLib.prototype['init'] = MixpanelLib.prototype.init;
11815
- MixpanelLib.prototype['reset'] = MixpanelLib.prototype.reset;
11816
- MixpanelLib.prototype['disable'] = MixpanelLib.prototype.disable;
11817
- MixpanelLib.prototype['time_event'] = MixpanelLib.prototype.time_event;
11818
- MixpanelLib.prototype['track'] = MixpanelLib.prototype.track;
11819
- MixpanelLib.prototype['track_links'] = MixpanelLib.prototype.track_links;
11820
- MixpanelLib.prototype['track_forms'] = MixpanelLib.prototype.track_forms;
11821
- MixpanelLib.prototype['track_pageview'] = MixpanelLib.prototype.track_pageview;
11822
- MixpanelLib.prototype['register'] = MixpanelLib.prototype.register;
11823
- MixpanelLib.prototype['register_once'] = MixpanelLib.prototype.register_once;
11824
- MixpanelLib.prototype['unregister'] = MixpanelLib.prototype.unregister;
11825
- MixpanelLib.prototype['identify'] = MixpanelLib.prototype.identify;
11826
- MixpanelLib.prototype['alias'] = MixpanelLib.prototype.alias;
11827
- MixpanelLib.prototype['name_tag'] = MixpanelLib.prototype.name_tag;
11828
- MixpanelLib.prototype['set_config'] = MixpanelLib.prototype.set_config;
11829
- MixpanelLib.prototype['get_config'] = MixpanelLib.prototype.get_config;
11830
- MixpanelLib.prototype['get_property'] = MixpanelLib.prototype.get_property;
11831
- MixpanelLib.prototype['get_distinct_id'] = MixpanelLib.prototype.get_distinct_id;
11832
- MixpanelLib.prototype['toString'] = MixpanelLib.prototype.toString;
11833
- MixpanelLib.prototype['opt_out_tracking'] = MixpanelLib.prototype.opt_out_tracking;
11834
- MixpanelLib.prototype['opt_in_tracking'] = MixpanelLib.prototype.opt_in_tracking;
11835
- MixpanelLib.prototype['has_opted_out_tracking'] = MixpanelLib.prototype.has_opted_out_tracking;
11836
- MixpanelLib.prototype['has_opted_in_tracking'] = MixpanelLib.prototype.has_opted_in_tracking;
11837
- MixpanelLib.prototype['clear_opt_in_out_tracking'] = MixpanelLib.prototype.clear_opt_in_out_tracking;
11838
- MixpanelLib.prototype['get_group'] = MixpanelLib.prototype.get_group;
11839
- MixpanelLib.prototype['set_group'] = MixpanelLib.prototype.set_group;
11840
- MixpanelLib.prototype['add_group'] = MixpanelLib.prototype.add_group;
11841
- MixpanelLib.prototype['remove_group'] = MixpanelLib.prototype.remove_group;
11842
- MixpanelLib.prototype['track_with_groups'] = MixpanelLib.prototype.track_with_groups;
11843
- MixpanelLib.prototype['start_batch_senders'] = MixpanelLib.prototype.start_batch_senders;
11844
- MixpanelLib.prototype['stop_batch_senders'] = MixpanelLib.prototype.stop_batch_senders;
11845
-
11846
- // MixpanelPersistence Exports
11847
- MixpanelPersistence.prototype['properties'] = MixpanelPersistence.prototype.properties;
11848
- MixpanelPersistence.prototype['update_search_keyword'] = MixpanelPersistence.prototype.update_search_keyword;
11849
- MixpanelPersistence.prototype['update_referrer_info'] = MixpanelPersistence.prototype.update_referrer_info;
11850
- MixpanelPersistence.prototype['get_cross_subdomain'] = MixpanelPersistence.prototype.get_cross_subdomain;
11851
- MixpanelPersistence.prototype['clear'] = MixpanelPersistence.prototype.clear;
11852
-
11853
-
11854
- var instances = {};
11855
- var extend_mp = function() {
11856
- // add all the sub mixpanel instances
11857
- _.each(instances, function(instance, name) {
11858
- if (name !== PRIMARY_INSTANCE_NAME) { mixpanel_master[name] = instance; }
11859
- });
11860
-
11861
- // add private functions as _
11862
- mixpanel_master['_'] = _;
11863
- };
11864
-
11865
- var override_mp_init_func = function() {
11866
- // we override the snippets init function to handle the case where a
11867
- // user initializes the mixpanel library after the script loads & runs
11868
- mixpanel_master['init'] = function(token, config, name) {
11869
- if (name) {
11870
- // initialize a sub library
11871
- if (!mixpanel_master[name]) {
11872
- mixpanel_master[name] = instances[name] = create_mplib(token, config, name);
11873
- mixpanel_master[name]._loaded();
11874
- }
11875
- return mixpanel_master[name];
11876
- } else {
11877
- var instance = mixpanel_master;
11878
-
11879
- if (instances[PRIMARY_INSTANCE_NAME]) {
11880
- // main mixpanel lib already initialized
11881
- instance = instances[PRIMARY_INSTANCE_NAME];
11882
- } else if (token) {
11883
- // intialize the main mixpanel lib
11884
- instance = create_mplib(token, config, PRIMARY_INSTANCE_NAME);
11885
- instance._loaded();
11886
- instances[PRIMARY_INSTANCE_NAME] = instance;
11887
- }
11888
-
11889
- mixpanel_master = instance;
11890
- if (init_type === INIT_SNIPPET) {
11891
- window$1[PRIMARY_INSTANCE_NAME] = mixpanel_master;
11892
- }
11893
- extend_mp();
11894
- }
11895
- };
11896
- };
11897
-
11898
- var add_dom_loaded_handler = function() {
11899
- // Cross browser DOM Loaded support
11900
- function dom_loaded_handler() {
11901
- // function flag since we only want to execute this once
11902
- if (dom_loaded_handler.done) { return; }
11903
- dom_loaded_handler.done = true;
11904
-
11905
- DOM_LOADED = true;
11906
- ENQUEUE_REQUESTS = false;
11907
-
11908
- _.each(instances, function(inst) {
11909
- inst._dom_loaded();
11910
- });
11911
- }
11912
-
11913
- function do_scroll_check() {
11914
- try {
11915
- document$1.documentElement.doScroll('left');
11916
- } catch(e) {
11917
- setTimeout(do_scroll_check, 1);
11918
- return;
11919
- }
11920
-
11921
- dom_loaded_handler();
11922
- }
11923
-
11924
- if (document$1.addEventListener) {
11925
- if (document$1.readyState === 'complete') {
11926
- // safari 4 can fire the DOMContentLoaded event before loading all
11927
- // external JS (including this file). you will see some copypasta
11928
- // on the internet that checks for 'complete' and 'loaded', but
11929
- // 'loaded' is an IE thing
11930
- dom_loaded_handler();
11931
- } else {
11932
- document$1.addEventListener('DOMContentLoaded', dom_loaded_handler, false);
11933
- }
11934
- } else if (document$1.attachEvent) {
11935
- // IE
11936
- document$1.attachEvent('onreadystatechange', dom_loaded_handler);
11937
-
11938
- // check to make sure we arn't in a frame
11939
- var toplevel = false;
11940
- try {
11941
- toplevel = window$1.frameElement === null;
11942
- } catch(e) {
11943
- // noop
11944
- }
11945
-
11946
- if (document$1.documentElement.doScroll && toplevel) {
11947
- do_scroll_check();
11948
- }
11949
- }
11950
-
11951
- // fallback handler, always will work
11952
- _.register_event(window$1, 'load', dom_loaded_handler, true);
11953
- };
11954
-
11955
- function init_as_module() {
11956
- init_type = INIT_MODULE;
11957
- mixpanel_master = new MixpanelLib();
11958
-
11959
- override_mp_init_func();
11960
- mixpanel_master['init']();
11961
- add_dom_loaded_handler();
11962
-
11963
- return mixpanel_master;
11964
- }
11965
-
11966
- var mixpanel = init_as_module();
11967
-
11968
- var mixpanel_cjs = mixpanel;
11969
-
11970
- var mixpanel$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), mixpanel_cjs, {
11971
- 'default': mixpanel_cjs
11972
- }));
11973
-
11974
- // Needed to avoid error in CJS builds on some bundlers.
11975
- const mixpanelLib = mixpanel_cjs || mixpanel$1;
11976
- let mixpanelInstance;
11977
- const MIXPANEL_EVENT = {
11978
- VISUAL_SDK_RENDER_START: 'visual-sdk-render-start',
11979
- VISUAL_SDK_CALLED_INIT: 'visual-sdk-called-init',
11980
- VISUAL_SDK_RENDER_COMPLETE: 'visual-sdk-render-complete',
11981
- VISUAL_SDK_RENDER_FAILED: 'visual-sdk-render-failed',
11982
- VISUAL_SDK_TRIGGER: 'visual-sdk-trigger',
11983
- VISUAL_SDK_ON: 'visual-sdk-on',
11984
- VISUAL_SDK_IFRAME_LOAD_PERFORMANCE: 'visual-sdk-iframe-load-performance',
11985
- VISUAL_SDK_EMBED_CREATE: 'visual-sdk-embed-create',
11986
- VERCEL_INTEGRATION_COMPLETED: 'vercel-integration-completed',
11987
- };
11988
- let isMixpanelInitialized = false;
11989
- let eventQueue = [];
11990
- /**
11991
- * Pushes the event with its Property key-value map to mixpanel.
11992
- *
11993
- * @param eventId
11994
- * @param eventProps
11995
- */
11996
- function uploadMixpanelEvent(eventId, eventProps = {}) {
11997
- if (!isMixpanelInitialized) {
11998
- eventQueue.push({ eventId, eventProps });
11999
- return;
12000
- }
12001
- mixpanelInstance.track(eventId, eventProps);
12002
- }
12003
- /**
12004
- *
12005
- */
12006
- function emptyQueue() {
12007
- if (!isMixpanelInitialized) {
12008
- return;
12009
- }
12010
- eventQueue.forEach((event) => {
12011
- uploadMixpanelEvent(event.eventId, event.eventProps);
12012
- });
12013
- eventQueue = [];
12014
- }
12015
- /**
12016
- *
12017
- * @param sessionInfo
12018
- */
12019
- function initMixpanel(sessionInfo) {
12020
- var _a;
12021
- if (!sessionInfo || !sessionInfo.mixpanelToken) {
12022
- return;
12023
- }
12024
- // On a public cluster the user is anonymous, so don't set the identify to
12025
- // userGUID
12026
- const isPublicCluster = !!sessionInfo.isPublicUser;
12027
- const token = sessionInfo.mixpanelToken;
12028
- try {
12029
- if (token) {
12030
- mixpanelInstance = mixpanelLib.init(token, undefined, 'tsEmbed');
12031
- if (!isPublicCluster) {
12032
- mixpanelInstance.identify(sessionInfo.userGUID);
12033
- }
12034
- mixpanelInstance.register_once({
12035
- clusterId: sessionInfo.clusterId,
12036
- clusterName: sessionInfo.clusterName,
12037
- releaseVersion: sessionInfo.releaseVersion,
12038
- hostAppUrl: ((_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.host) || '',
12039
- });
12040
- isMixpanelInitialized = true;
12041
- emptyQueue();
12042
- }
12043
- }
12044
- catch (e) {
12045
- logger.error('Error initializing mixpanel', e);
12046
- }
12047
- }
12048
-
12049
- let config = {};
12050
- /**
12051
- * Gets the configuration embed was initialized with.
12052
- *
12053
- * @returns {@link EmbedConfig} The configuration embed was initialized with.
12054
- * @version SDK: 1.19.0 | ThoughtSpot: *
12055
- * @group Global methods
12056
- */
12057
- const getEmbedConfig = () => config;
12058
-
12059
- /**
12060
- * Fetch wrapper that adds the authentication token to the request.
12061
- * Use this to call the ThoughtSpot APIs when using the visual embed sdk.
12062
- *
12063
- * @param input
12064
- * @param init
12065
- * @version SDK: 1.28.0
12066
- * @group Global methods
12067
- */
12068
- const tokenizedFetch = async (input, init) => {
12069
- const embedConfig = getEmbedConfig();
12070
- if (embedConfig.authType !== AuthType.TrustedAuthTokenCookieless) {
12071
- return fetch(input, init);
12072
- }
12073
- const req = new Request(input, init);
12074
- const authToken = await getAuthenticationToken(embedConfig);
12075
- if (authToken) {
12076
- req.headers.append('Authorization', `Bearer ${authToken}`);
12077
- }
12078
- return fetch(req);
12079
- };
12080
-
12081
- /**
12082
- *
12083
- * @param url
12084
- * @param options
12085
- */
12086
- function tokenisedFailureLoggedFetch(url, options = {}) {
12087
- return tokenizedFetch(url, options).then(async (r) => {
12088
- var _a;
12089
- if (!r.ok && r.type !== 'opaqueredirect' && r.type !== 'opaque') {
12090
- logger.error('Failure', await ((_a = r.text) === null || _a === void 0 ? void 0 : _a.call(r)));
12091
- }
12092
- return r;
12093
- });
12094
- }
12095
- /**
12096
- *
12097
- * @param authVerificationUrl
12098
- */
12099
- function fetchSessionInfoService(authVerificationUrl) {
12100
- return tokenisedFailureLoggedFetch(authVerificationUrl, {
12101
- credentials: 'include',
12102
- });
12103
- }
12104
-
12105
- // eslint-disable-next-line import/no-mutable-exports
12106
- let loggedInStatus = false;
12107
- // eslint-disable-next-line import/no-mutable-exports
12108
- let samlAuthWindow = null;
12109
- // eslint-disable-next-line import/no-mutable-exports
12110
- let samlCompletionPromise = null;
12111
- let sessionInfo = null;
12112
- let sessionInfoResolver = null;
12113
- const sessionInfoPromise = new Promise((resolve) => {
12114
- sessionInfoResolver = resolve;
12115
- });
12116
- let releaseVersion = '';
12117
- const SSO_REDIRECTION_MARKER_GUID = '5e16222e-ef02-43e9-9fbd-24226bf3ce5b';
12118
- /**
12119
- * Enum for auth failure types. This is the parameter passed to the listner
12120
- * of {@link AuthStatus.FAILURE}.
12121
- *
12122
- * @group Authentication / Init
12123
- */
12124
- var AuthFailureType;
12125
- (function (AuthFailureType) {
12126
- AuthFailureType["SDK"] = "SDK";
12127
- AuthFailureType["NO_COOKIE_ACCESS"] = "NO_COOKIE_ACCESS";
12128
- AuthFailureType["EXPIRY"] = "EXPIRY";
12129
- AuthFailureType["OTHER"] = "OTHER";
12130
- })(AuthFailureType || (AuthFailureType = {}));
12131
- /**
12132
- * Enum for auth status emitted by the emitter returned from {@link init}.
12133
- *
12134
- * @group Authentication / Init
12135
- */
12136
- var AuthStatus;
12137
- (function (AuthStatus) {
12138
- /**
12139
- * Emits when the SDK fails to authenticate
12140
- */
12141
- AuthStatus["FAILURE"] = "FAILURE";
12142
- /**
12143
- * Emits when the SDK authenticates successfully
12144
- */
12145
- AuthStatus["SDK_SUCCESS"] = "SDK_SUCCESS";
12146
- /**
12147
- * Emits when the app sends an authentication success message
12148
- */
12149
- AuthStatus["SUCCESS"] = "SUCCESS";
12150
- /**
12151
- * Emits when a user logs out
12152
- */
12153
- AuthStatus["LOGOUT"] = "LOGOUT";
12154
- /**
12155
- * Emitted when inPopup is true in the SAMLRedirect flow and the
12156
- * popup is waiting to be triggered either programmatically
12157
- * or by the trigger button.
12158
- *
12159
- * @version SDK: 1.19.0
12160
- */
12161
- AuthStatus["WAITING_FOR_POPUP"] = "WAITING_FOR_POPUP";
12162
- })(AuthStatus || (AuthStatus = {}));
12163
- /**
12164
- * Events which can be triggered on the emitter returned from {@link init}.
12165
- *
12166
- * @group Authentication / Init
12167
- */
12168
- var AuthEvent;
12169
- (function (AuthEvent) {
12170
- /**
12171
- * Manually trigger the SSO popup. This is useful when
12172
- * authStatus is SAMLRedirect/OIDCRedirect and inPopup is set to true
12173
- */
12174
- AuthEvent["TRIGGER_SSO_POPUP"] = "TRIGGER_SSO_POPUP";
12175
- })(AuthEvent || (AuthEvent = {}));
12176
- /**
12177
- *
12178
- */
12179
- function notifyAuthSDKSuccess() {
12180
- {
12181
- logger.error('SDK not initialized');
12182
- return;
12183
- }
12184
- }
12185
- /**
12186
- *
12187
- */
12188
- function notifyAuthSuccess() {
12189
- {
12190
- logger.error('SDK not initialized');
12191
- return;
12192
- }
12193
- }
12194
- /**
12195
- *
12196
- * @param failureType
12197
- */
12198
- function notifyAuthFailure(failureType) {
12199
- {
12200
- logger.error('SDK not initialized');
12201
- return;
12202
- }
12203
- }
12204
- /**
12205
- *
12206
- */
12207
- function notifyLogout() {
12208
- {
12209
- logger.error('SDK not initialized');
12210
- return;
12211
- }
12212
- }
12213
- const initSession = (sessionDetails) => {
12214
- const embedConfig = getEmbedConfig();
12215
- if (sessionInfo == null) {
12216
- sessionInfo = sessionDetails;
12217
- if (!embedConfig.disableSDKTracking) {
12218
- initMixpanel(sessionInfo);
12219
- }
12220
- sessionInfoResolver(sessionInfo);
12221
- }
12222
- };
12223
- const getSessionDetails = (sessionInfoResp) => {
12224
- const devMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.devSdkKey;
12225
- const prodMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.prodSdkKey;
12226
- const mixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.production
12227
- ? prodMixpanelToken
12228
- : devMixpanelToken;
12229
- return {
12230
- userGUID: sessionInfoResp.userGUID,
12231
- mixpanelToken,
12232
- isPublicUser: sessionInfoResp.configInfo.isPublicUser,
12233
- releaseVersion: sessionInfoResp.releaseVersion,
12234
- clusterId: sessionInfoResp.configInfo.selfClusterId,
12235
- clusterName: sessionInfoResp.configInfo.selfClusterName,
12236
- ...sessionInfoResp,
12237
- };
12238
- };
12239
- /**
12240
- * Check if we are logged into the ThoughtSpot cluster
12241
- *
12242
- * @param thoughtSpotHost The ThoughtSpot cluster hostname or IP
12243
- */
12244
- async function isLoggedIn(thoughtSpotHost) {
12245
- const authVerificationUrl = `${thoughtSpotHost}${EndPoints.AUTH_VERIFICATION}`;
12246
- let response = null;
12247
- try {
12248
- response = await fetchSessionInfoService(authVerificationUrl);
12249
- const sessionInfoResp = await response.json();
12250
- const sessionDetails = getSessionDetails(sessionInfoResp);
12251
- // Store user session details from session info
12252
- initSession(sessionDetails);
12253
- releaseVersion = sessionInfoResp.releaseVersion;
12254
- }
12255
- catch (e) {
12256
- return false;
12257
- }
12258
- return response.status === 200;
12259
- }
12260
- /**
12261
- * Return releaseVersion if available
12262
- */
12263
- function getReleaseVersion() {
12264
- return releaseVersion;
12265
- }
12266
- /**
12267
- * Check if we are stuck at the SSO redirect URL
12268
- */
12269
- function isAtSSORedirectUrl() {
12270
- return window.location.href.indexOf(SSO_REDIRECTION_MARKER_GUID) >= 0;
12271
- }
12272
- /**
12273
- * Remove the SSO redirect URL marker
12274
- */
12275
- function removeSSORedirectUrlMarker() {
12276
- // Note (sunny): This will leave a # around even if it was not in the URL
12277
- // to begin with. Trying to remove the hash by changing window.location will
12278
- // reload the page which we don't want. We'll live with adding an
12279
- // unnecessary hash to the parent page URL until we find any use case where
12280
- // that creates an issue.
12281
- window.location.hash = window.location.hash.replace(SSO_REDIRECTION_MARKER_GUID, '');
12282
- }
12283
- /**
12284
- * Perform token based authentication
12285
- *
12286
- * @param embedConfig The embed configuration
12287
- */
12288
- const doTokenAuth = async (embedConfig) => {
12289
- const { thoughtSpotHost, username, authEndpoint, getAuthToken, } = embedConfig;
12290
- if (!authEndpoint && !getAuthToken) {
12291
- throw new Error('Either auth endpoint or getAuthToken function must be provided');
12292
- }
12293
- loggedInStatus = await isLoggedIn(thoughtSpotHost);
12294
- if (!loggedInStatus) {
12295
- const authToken = await getAuthenticationToken(embedConfig);
12296
- let resp;
12297
- try {
12298
- resp = await fetchAuthPostService(thoughtSpotHost, username, authToken);
12299
- }
12300
- catch (e) {
12301
- resp = await fetchAuthService(thoughtSpotHost, username, authToken);
12302
- }
12303
- // token login issues a 302 when successful
12304
- loggedInStatus = resp.ok || resp.type === 'opaqueredirect';
12305
- if (loggedInStatus && embedConfig.detectCookieAccessSlow) {
12306
- // When 3rd party cookie access is blocked, this will fail because
12307
- // cookies will not be sent with the call.
12308
- loggedInStatus = await isLoggedIn(thoughtSpotHost);
12309
- }
12310
- }
12311
- return loggedInStatus;
12312
- };
12313
- /**
12314
- * Validate embedConfig parameters required for cookielessTokenAuth
12315
- *
12316
- * @param embedConfig The embed configuration
12317
- */
12318
- const doCookielessTokenAuth = async (embedConfig) => {
12319
- const { authEndpoint, getAuthToken } = embedConfig;
12320
- if (!authEndpoint && !getAuthToken) {
12321
- throw new Error('Either auth endpoint or getAuthToken function must be provided');
12322
- }
12323
- let authSuccess = false;
12324
- try {
12325
- const authToken = await getAuthenticationToken(embedConfig);
12326
- if (authToken) {
12327
- authSuccess = true;
12328
- }
12329
- }
12330
- catch {
12331
- authSuccess = false;
12332
- }
12333
- return authSuccess;
12334
- };
12335
- /**
12336
- * Perform basic authentication to the ThoughtSpot cluster using the cluster
12337
- * credentials.
12338
- *
12339
- * Warning: This feature is primarily intended for developer testing. It is
12340
- * strongly advised not to use this authentication method in production.
12341
- *
12342
- * @param embedConfig The embed configuration
12343
- */
12344
- const doBasicAuth = async (embedConfig) => {
12345
- const { thoughtSpotHost, username, password } = embedConfig;
12346
- const loggedIn = await isLoggedIn(thoughtSpotHost);
12347
- if (!loggedIn) {
12348
- const response = await fetchBasicAuthService(thoughtSpotHost, username, password);
12349
- loggedInStatus = response.ok;
12350
- if (embedConfig.detectCookieAccessSlow) {
12351
- loggedInStatus = await isLoggedIn(thoughtSpotHost);
12352
- }
12353
- }
12354
- else {
12355
- loggedInStatus = true;
12356
- }
12357
- return loggedInStatus;
12358
- };
12359
- /**
12360
- *
12361
- * @param ssoURL
12362
- * @param triggerContainer
12363
- * @param triggerText
12364
- */
12365
- async function samlPopupFlow(ssoURL, triggerContainer, triggerText) {
12366
- const openPopup = () => {
12367
- if (samlAuthWindow === null || samlAuthWindow.closed) {
12368
- samlAuthWindow = window.open(ssoURL, '_blank', 'location=no,height=570,width=520,scrollbars=yes,status=yes');
12369
- }
12370
- else {
12371
- samlAuthWindow.focus();
12372
- }
12373
- };
12374
- const containerEl = getDOMNode(triggerContainer);
12375
- if (containerEl) {
12376
- containerEl.innerHTML = '<button id="ts-auth-btn" class="ts-auth-btn" style="margin: auto;"></button>';
12377
- const authElem = document.getElementById('ts-auth-btn');
12378
- authElem.textContent = triggerText;
12379
- authElem.addEventListener('click', openPopup, { once: true });
12380
- }
12381
- samlCompletionPromise = samlCompletionPromise
12382
- || new Promise((resolve, reject) => {
12383
- window.addEventListener('message', (e) => {
12384
- if (e.data.type === exports.EmbedEvent.SAMLComplete) {
12385
- e.source.close();
12386
- resolve();
12387
- }
12388
- });
12389
- });
12390
- return samlCompletionPromise;
12391
- }
12392
- /**
12393
- * Perform SAML authentication
12394
- *
12395
- * @param embedConfig The embed configuration
12396
- * @param ssoEndPoint
12397
- */
12398
- const doSSOAuth = async (embedConfig, ssoEndPoint) => {
12399
- const { thoughtSpotHost } = embedConfig;
12400
- const loggedIn = await isLoggedIn(thoughtSpotHost);
12401
- if (loggedIn) {
12402
- if (isAtSSORedirectUrl()) {
12403
- removeSSORedirectUrlMarker();
12404
- }
12405
- loggedInStatus = true;
12406
- return;
12407
- }
12408
- // we have already tried authentication and it did not succeed, restore
12409
- // the current URL to the original one and invoke the callback.
12410
- if (isAtSSORedirectUrl()) {
12411
- removeSSORedirectUrlMarker();
12412
- loggedInStatus = false;
12413
- return;
12414
- }
12415
- const ssoURL = `${thoughtSpotHost}${ssoEndPoint}`;
12416
- if (embedConfig.inPopup) {
12417
- await samlPopupFlow(ssoURL, embedConfig.authTriggerContainer, embedConfig.authTriggerText);
12418
- loggedInStatus = await isLoggedIn(thoughtSpotHost);
12419
- return;
12420
- }
12421
- window.location.href = ssoURL;
12422
- };
12423
- const doSamlAuth = async (embedConfig) => {
12424
- const { thoughtSpotHost } = embedConfig;
12425
- // redirect for SSO, when the SSO authentication is done, this page will be
12426
- // loaded again and the same JS will execute again.
12427
- const ssoRedirectUrl = embedConfig.inPopup
12428
- ? `${thoughtSpotHost}/v2/#/embed/saml-complete`
12429
- : getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
12430
- // bring back the page to the same URL
12431
- const ssoEndPoint = `${EndPoints.SAML_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
12432
- await doSSOAuth(embedConfig, ssoEndPoint);
12433
- return loggedInStatus;
12434
- };
12435
- const doOIDCAuth = async (embedConfig) => {
12436
- const { thoughtSpotHost } = embedConfig;
12437
- // redirect for SSO, when the SSO authentication is done, this page will be
12438
- // loaded again and the same JS will execute again.
12439
- const ssoRedirectUrl = embedConfig.noRedirect || embedConfig.inPopup
12440
- ? `${thoughtSpotHost}/v2/#/embed/saml-complete`
12441
- : getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
12442
- // bring back the page to the same URL
12443
- const ssoEndPoint = `${EndPoints.OIDC_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
12444
- await doSSOAuth(embedConfig, ssoEndPoint);
12445
- return loggedInStatus;
12446
- };
12447
- /**
12448
- * Perform authentication on the ThoughtSpot cluster
12449
- *
12450
- * @param embedConfig The embed configuration
12451
- */
12452
- const authenticate = async (embedConfig) => {
12453
- const { authType } = embedConfig;
12454
- switch (authType) {
12455
- case AuthType.SSO:
12456
- case AuthType.SAMLRedirect:
12457
- case AuthType.SAML:
12458
- return doSamlAuth(embedConfig);
12459
- case AuthType.OIDC:
12460
- case AuthType.OIDCRedirect:
12461
- return doOIDCAuth(embedConfig);
12462
- case AuthType.AuthServer:
12463
- case AuthType.TrustedAuthToken:
12464
- return doTokenAuth(embedConfig);
12465
- case AuthType.TrustedAuthTokenCookieless:
12466
- return doCookielessTokenAuth(embedConfig);
12467
- case AuthType.Basic:
12468
- return doBasicAuth(embedConfig);
12469
- default:
12470
- return Promise.resolve(true);
12471
- }
12183
+ // check if localStorage can be used for recording opt out status, fall back to cookie if not
12184
+ if (!_.localStorage.is_supported()) {
12185
+ options['persistence_type'] = 'cookie';
12186
+ }
12187
+
12188
+ return func(this.get_config('token'), {
12189
+ track: options['track'],
12190
+ trackEventName: options['track_event_name'],
12191
+ trackProperties: options['track_properties'],
12192
+ persistenceType: options['persistence_type'],
12193
+ persistencePrefix: options['cookie_prefix'],
12194
+ cookieDomain: options['cookie_domain'],
12195
+ cookieExpiration: options['cookie_expiration'],
12196
+ crossSiteCookie: options['cross_site_cookie'],
12197
+ crossSubdomainCookie: options['cross_subdomain_cookie'],
12198
+ secureCookie: options['secure_cookie'],
12199
+ ignoreDnt: options['ignore_dnt']
12200
+ });
12472
12201
  };
12473
12202
 
12474
- const ERROR_MESSAGE = {
12475
- INVALID_THOUGHTSPOT_HOST: 'Error parsing ThoughtSpot host. Please provide a valid URL.',
12476
- LIVEBOARD_VIZ_ID_VALIDATION: 'Please provide either liveboardId or pinboardId',
12477
- TRIGGER_TIMED_OUT: 'Trigger timedout in getting response',
12478
- SEARCHEMBED_BETA_WRANING_MESSAGE: 'Search Embed is in Beta in this release.',
12479
- SAGE_EMBED_BETA_WARNING_MESSAGE: 'Sage Embed is in Beta in this release.',
12203
+ /**
12204
+ * Opt the user in to data tracking and cookies/localstorage for this Mixpanel instance
12205
+ *
12206
+ * ### Usage
12207
+ *
12208
+ * // opt user in
12209
+ * mixpanel.opt_in_tracking();
12210
+ *
12211
+ * // opt user in with specific event name, properties, cookie configuration
12212
+ * mixpanel.opt_in_tracking({
12213
+ * track_event_name: 'User opted in',
12214
+ * track_event_properties: {
12215
+ * 'Email': 'jdoe@example.com'
12216
+ * },
12217
+ * cookie_expiration: 30,
12218
+ * secure_cookie: true
12219
+ * });
12220
+ *
12221
+ * @param {Object} [options] A dictionary of config options to override
12222
+ * @param {function} [options.track] Function used for tracking a Mixpanel event to record the opt-in action (default is this Mixpanel instance's track method)
12223
+ * @param {string} [options.track_event_name=$opt_in] Event name to be used for tracking the opt-in action
12224
+ * @param {Object} [options.track_properties] Set of properties to be tracked along with the opt-in action
12225
+ * @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence
12226
+ * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
12227
+ * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
12228
+ * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
12229
+ * @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
12230
+ * @param {boolean} [options.cross_site_cookie] Whether the opt-in cookie is set as cross-site-enabled (overrides value specified in this Mixpanel instance's config)
12231
+ * @param {boolean} [options.cross_subdomain_cookie] Whether the opt-in cookie is set as cross-subdomain or not (overrides value specified in this Mixpanel instance's config)
12232
+ * @param {boolean} [options.secure_cookie] Whether the opt-in cookie is set as secure or not (overrides value specified in this Mixpanel instance's config)
12233
+ */
12234
+ MixpanelLib.prototype.opt_in_tracking = function(options) {
12235
+ options = _.extend({
12236
+ 'enable_persistence': true
12237
+ }, options);
12238
+
12239
+ this._gdpr_call_func(optIn, options);
12240
+ this._gdpr_update_persistence(options);
12480
12241
  };
12481
12242
 
12482
- /**
12483
- * Copyright (c) 2023
12484
- *
12485
- * Utilities related to reading configuration objects
12486
- *
12487
- * @summary Config-related utils
12488
- * @author Ayon Ghosh <ayon.ghosh@thoughtspot.com>
12489
- */
12490
- const urlRegex = new RegExp([
12491
- '(^(https?:)//)?',
12492
- '(([^:/?#]*)(?::([0-9]+))?)',
12493
- '(/{0,1}[^?#]*)',
12494
- '(\\?[^#]*|)',
12495
- '(#.*|)$', // hash
12496
- ].join(''));
12497
- /**
12498
- * Parse and construct the ThoughtSpot hostname or IP address
12499
- * from the embed configuration object.
12500
- *
12501
- * @param config
12502
- */
12503
- const getThoughtSpotHost = (config) => {
12504
- if (!config.thoughtSpotHost) {
12505
- throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
12506
- }
12507
- const urlParts = config.thoughtSpotHost.match(urlRegex);
12508
- if (!urlParts) {
12509
- throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
12510
- }
12511
- const protocol = urlParts[2] || window.location.protocol;
12512
- const host = urlParts[3];
12513
- let path = urlParts[6];
12514
- // Lose the trailing / if any
12515
- if (path.charAt(path.length - 1) === '/') {
12516
- path = path.substring(0, path.length - 1);
12517
- }
12518
- // const urlParams = urlParts[7];
12519
- // const hash = urlParts[8];
12520
- return `${protocol}//${host}${path}`;
12521
- };
12522
- const getV2BasePath = (config) => {
12523
- if (config.basepath) {
12524
- return config.basepath;
12525
- }
12526
- const tsHost = getThoughtSpotHost(config);
12527
- // This is to handle when e2e's. Search is run on pods for
12528
- // comp-blink-test-pipeline with baseUrl=https://localhost:8443.
12529
- // This is to handle when the developer is developing in their local
12530
- // environment.
12531
- if (tsHost.includes('://localhost') && !tsHost.includes(':8443')) {
12532
- return '';
12533
- }
12534
- return 'v2';
12535
- };
12536
- /**
12537
- * It is a good idea to keep URLs under 2000 chars.
12538
- * If this is ever breached, since we pass view configuration through
12539
- * URL params, we would like to log a warning.
12540
- * Reference: https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
12541
- */
12542
- const URL_MAX_LENGTH = 2000;
12543
- /**
12544
- * The default CSS dimensions of the embedded app
12545
- */
12546
- const DEFAULT_EMBED_WIDTH = '100%';
12547
- const DEFAULT_EMBED_HEIGHT = '100%';
12243
+ /**
12244
+ * Opt the user out of data tracking and cookies/localstorage for this Mixpanel instance
12245
+ *
12246
+ * ### Usage
12247
+ *
12248
+ * // opt user out
12249
+ * mixpanel.opt_out_tracking();
12250
+ *
12251
+ * // opt user out with different cookie configuration from Mixpanel instance
12252
+ * mixpanel.opt_out_tracking({
12253
+ * cookie_expiration: 30,
12254
+ * secure_cookie: true
12255
+ * });
12256
+ *
12257
+ * @param {Object} [options] A dictionary of config options to override
12258
+ * @param {boolean} [options.delete_user=true] If true, will delete the currently identified user's profile and clear all charges after opting the user out
12259
+ * @param {boolean} [options.clear_persistence=true] If true, will delete all data stored by the sdk in persistence
12260
+ * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
12261
+ * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
12262
+ * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
12263
+ * @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
12264
+ * @param {boolean} [options.cross_site_cookie] Whether the opt-in cookie is set as cross-site-enabled (overrides value specified in this Mixpanel instance's config)
12265
+ * @param {boolean} [options.cross_subdomain_cookie] Whether the opt-in cookie is set as cross-subdomain or not (overrides value specified in this Mixpanel instance's config)
12266
+ * @param {boolean} [options.secure_cookie] Whether the opt-in cookie is set as secure or not (overrides value specified in this Mixpanel instance's config)
12267
+ */
12268
+ MixpanelLib.prototype.opt_out_tracking = function(options) {
12269
+ options = _.extend({
12270
+ 'clear_persistence': true,
12271
+ 'delete_user': true
12272
+ }, options);
12273
+
12274
+ // delete user and clear charges since these methods may be disabled by opt-out
12275
+ if (options['delete_user'] && this['people'] && this['people']._identify_called()) {
12276
+ this['people'].delete_user();
12277
+ this['people'].clear_charges();
12278
+ }
12279
+
12280
+ this._gdpr_call_func(optOut, options);
12281
+ this._gdpr_update_persistence(options);
12282
+ };
12283
+
12284
+ /**
12285
+ * Check whether the user has opted in to data tracking and cookies/localstorage for this Mixpanel instance
12286
+ *
12287
+ * ### Usage
12288
+ *
12289
+ * var has_opted_in = mixpanel.has_opted_in_tracking();
12290
+ * // use has_opted_in value
12291
+ *
12292
+ * @param {Object} [options] A dictionary of config options to override
12293
+ * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
12294
+ * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
12295
+ * @returns {boolean} current opt-in status
12296
+ */
12297
+ MixpanelLib.prototype.has_opted_in_tracking = function(options) {
12298
+ return this._gdpr_call_func(hasOptedIn, options);
12299
+ };
12300
+
12301
+ /**
12302
+ * Check whether the user has opted out of data tracking and cookies/localstorage for this Mixpanel instance
12303
+ *
12304
+ * ### Usage
12305
+ *
12306
+ * var has_opted_out = mixpanel.has_opted_out_tracking();
12307
+ * // use has_opted_out value
12308
+ *
12309
+ * @param {Object} [options] A dictionary of config options to override
12310
+ * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
12311
+ * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
12312
+ * @returns {boolean} current opt-out status
12313
+ */
12314
+ MixpanelLib.prototype.has_opted_out_tracking = function(options) {
12315
+ return this._gdpr_call_func(hasOptedOut, options);
12316
+ };
12317
+
12318
+ /**
12319
+ * Clear the user's opt in/out status of data tracking and cookies/localstorage for this Mixpanel instance
12320
+ *
12321
+ * ### Usage
12322
+ *
12323
+ * // clear user's opt-in/out status
12324
+ * mixpanel.clear_opt_in_out_tracking();
12325
+ *
12326
+ * // clear user's opt-in/out status with specific cookie configuration - should match
12327
+ * // configuration used when opt_in_tracking/opt_out_tracking methods were called.
12328
+ * mixpanel.clear_opt_in_out_tracking({
12329
+ * cookie_expiration: 30,
12330
+ * secure_cookie: true
12331
+ * });
12332
+ *
12333
+ * @param {Object} [options] A dictionary of config options to override
12334
+ * @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence
12335
+ * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
12336
+ * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
12337
+ * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
12338
+ * @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
12339
+ * @param {boolean} [options.cross_site_cookie] Whether the opt-in cookie is set as cross-site-enabled (overrides value specified in this Mixpanel instance's config)
12340
+ * @param {boolean} [options.cross_subdomain_cookie] Whether the opt-in cookie is set as cross-subdomain or not (overrides value specified in this Mixpanel instance's config)
12341
+ * @param {boolean} [options.secure_cookie] Whether the opt-in cookie is set as secure or not (overrides value specified in this Mixpanel instance's config)
12342
+ */
12343
+ MixpanelLib.prototype.clear_opt_in_out_tracking = function(options) {
12344
+ options = _.extend({
12345
+ 'enable_persistence': true
12346
+ }, options);
12347
+
12348
+ this._gdpr_call_func(clearOptInOut, options);
12349
+ this._gdpr_update_persistence(options);
12350
+ };
12351
+
12352
+ MixpanelLib.prototype.report_error = function(msg, err) {
12353
+ console$1.error.apply(console$1.error, arguments);
12354
+ try {
12355
+ if (!err && !(msg instanceof Error)) {
12356
+ msg = new Error(msg);
12357
+ }
12358
+ this.get_config('error_reporter')(msg, err);
12359
+ } catch(err) {
12360
+ console$1.error(err);
12361
+ }
12362
+ };
12363
+
12364
+ // EXPORTS (for closure compiler)
12365
+
12366
+ // MixpanelLib Exports
12367
+ MixpanelLib.prototype['init'] = MixpanelLib.prototype.init;
12368
+ MixpanelLib.prototype['reset'] = MixpanelLib.prototype.reset;
12369
+ MixpanelLib.prototype['disable'] = MixpanelLib.prototype.disable;
12370
+ MixpanelLib.prototype['time_event'] = MixpanelLib.prototype.time_event;
12371
+ MixpanelLib.prototype['track'] = MixpanelLib.prototype.track;
12372
+ MixpanelLib.prototype['track_links'] = MixpanelLib.prototype.track_links;
12373
+ MixpanelLib.prototype['track_forms'] = MixpanelLib.prototype.track_forms;
12374
+ MixpanelLib.prototype['track_pageview'] = MixpanelLib.prototype.track_pageview;
12375
+ MixpanelLib.prototype['register'] = MixpanelLib.prototype.register;
12376
+ MixpanelLib.prototype['register_once'] = MixpanelLib.prototype.register_once;
12377
+ MixpanelLib.prototype['unregister'] = MixpanelLib.prototype.unregister;
12378
+ MixpanelLib.prototype['identify'] = MixpanelLib.prototype.identify;
12379
+ MixpanelLib.prototype['alias'] = MixpanelLib.prototype.alias;
12380
+ MixpanelLib.prototype['name_tag'] = MixpanelLib.prototype.name_tag;
12381
+ MixpanelLib.prototype['set_config'] = MixpanelLib.prototype.set_config;
12382
+ MixpanelLib.prototype['get_config'] = MixpanelLib.prototype.get_config;
12383
+ MixpanelLib.prototype['get_property'] = MixpanelLib.prototype.get_property;
12384
+ MixpanelLib.prototype['get_distinct_id'] = MixpanelLib.prototype.get_distinct_id;
12385
+ MixpanelLib.prototype['toString'] = MixpanelLib.prototype.toString;
12386
+ MixpanelLib.prototype['opt_out_tracking'] = MixpanelLib.prototype.opt_out_tracking;
12387
+ MixpanelLib.prototype['opt_in_tracking'] = MixpanelLib.prototype.opt_in_tracking;
12388
+ MixpanelLib.prototype['has_opted_out_tracking'] = MixpanelLib.prototype.has_opted_out_tracking;
12389
+ MixpanelLib.prototype['has_opted_in_tracking'] = MixpanelLib.prototype.has_opted_in_tracking;
12390
+ MixpanelLib.prototype['clear_opt_in_out_tracking'] = MixpanelLib.prototype.clear_opt_in_out_tracking;
12391
+ MixpanelLib.prototype['get_group'] = MixpanelLib.prototype.get_group;
12392
+ MixpanelLib.prototype['set_group'] = MixpanelLib.prototype.set_group;
12393
+ MixpanelLib.prototype['add_group'] = MixpanelLib.prototype.add_group;
12394
+ MixpanelLib.prototype['remove_group'] = MixpanelLib.prototype.remove_group;
12395
+ MixpanelLib.prototype['track_with_groups'] = MixpanelLib.prototype.track_with_groups;
12396
+ MixpanelLib.prototype['start_batch_senders'] = MixpanelLib.prototype.start_batch_senders;
12397
+ MixpanelLib.prototype['stop_batch_senders'] = MixpanelLib.prototype.stop_batch_senders;
12548
12398
 
12549
- /**
12550
- *
12551
- * @param root0
12552
- * @param root0.query
12553
- * @param root0.variables
12554
- * @param root0.thoughtSpotHost
12555
- * @param root0.isCompositeQuery
12556
- */
12557
- async function graphqlQuery({ query, variables, thoughtSpotHost, isCompositeQuery = false, }) {
12558
- const operationName = getOperationNameFromQuery(query);
12559
- try {
12560
- const response = await fetch(`${thoughtSpotHost}/prism/?op=${operationName}`, {
12561
- method: 'POST',
12562
- headers: {
12563
- 'content-type': 'application/json;charset=UTF-8',
12564
- 'x-requested-by': 'ThoughtSpot',
12565
- accept: '*/*',
12566
- 'accept-language': 'en-us',
12567
- },
12568
- body: JSON.stringify({
12569
- operationName,
12570
- query,
12571
- variables,
12572
- }),
12573
- credentials: 'include',
12574
- });
12575
- const result = await response.json();
12576
- const dataValues = Object.values(result.data);
12577
- return (isCompositeQuery) ? result.data : dataValues[0];
12578
- }
12579
- catch (error) {
12580
- return error;
12581
- }
12582
- }
12399
+ // MixpanelPersistence Exports
12400
+ MixpanelPersistence.prototype['properties'] = MixpanelPersistence.prototype.properties;
12401
+ MixpanelPersistence.prototype['update_search_keyword'] = MixpanelPersistence.prototype.update_search_keyword;
12402
+ MixpanelPersistence.prototype['update_referrer_info'] = MixpanelPersistence.prototype.update_referrer_info;
12403
+ MixpanelPersistence.prototype['get_cross_subdomain'] = MixpanelPersistence.prototype.get_cross_subdomain;
12404
+ MixpanelPersistence.prototype['clear'] = MixpanelPersistence.prototype.clear;
12583
12405
 
12584
- const getSourceDetailQuery = `
12585
- query GetSourceDetail($ids: [GUID!]!) {
12586
- getSourceDetailById(ids: $ids, type: LOGICAL_TABLE) {
12587
- id
12588
- name
12589
- description
12590
- authorName
12591
- authorDisplayName
12592
- isExternal
12593
- type
12594
- created
12595
- modified
12596
- columns {
12597
- id
12598
- name
12599
- author
12600
- authorDisplayName
12601
- description
12602
- dataType
12603
- type
12604
- modified
12605
- ownerName
12606
- owner
12607
- dataRecency
12608
- sources {
12609
- tableId
12610
- tableName
12611
- columnId
12612
- columnName
12613
- __typename
12614
- }
12615
- synonyms
12616
- cohortAnswerId
12617
- __typename
12618
- }
12619
- relationships
12620
- destinationRelationships
12621
- dataSourceId
12622
- __typename
12623
- }
12624
- }
12625
- `;
12626
- const sourceDetailCache = new Map();
12627
- /**
12628
- *
12629
- * @param thoughtSpotHost
12630
- * @param sourceId
12631
- */
12632
- async function getSourceDetail(thoughtSpotHost, sourceId) {
12633
- if (sourceDetailCache.get(sourceId)) {
12634
- return sourceDetailCache.get(sourceId);
12635
- }
12636
- const details = await graphqlQuery({
12637
- query: getSourceDetailQuery,
12638
- variables: {
12639
- ids: [sourceId],
12640
- },
12641
- thoughtSpotHost,
12642
- });
12643
- const souceDetails = details[0];
12644
- if (souceDetails) {
12645
- sourceDetailCache.set(sourceId, souceDetails);
12646
- }
12647
- return souceDetails;
12648
- }
12649
12406
 
12650
- const bachSessionId = `
12651
- id {
12652
- sessionId
12653
- genNo
12654
- acSession {
12655
- sessionId
12656
- genNo
12657
- }
12658
- }
12659
- `;
12660
- const getUnaggregatedAnswerSession = `
12661
- mutation GetUnAggregatedAnswerSession($session: BachSessionIdInput!, $columns: [UserPointSelectionInput!]!) {
12662
- Answer__getUnaggregatedAnswer(session: $session, columns: $columns) {
12663
- ${bachSessionId}
12664
- answer {
12665
- visualizations {
12666
- ... on TableViz {
12667
- columns {
12668
- column {
12669
- id
12670
- name
12671
- referencedColumns {
12672
- guid
12673
- displayName
12674
- }
12675
- }
12676
- }
12677
- }
12678
- }
12679
- }
12680
- }
12681
- }
12682
- `;
12683
- const removeColumns = `
12684
- mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!], $columnIds: [GUID!]) {
12685
- Answer__removeColumns(
12686
- session: $session
12687
- logicalColumnIds: $logicalColumnIds
12688
- columnIds: $columnIds
12689
- ) {
12690
- ${bachSessionId}
12691
- }
12692
- }
12693
- `;
12694
- const addColumns = `
12695
- mutation AddColumns($session: BachSessionIdInput!, $columns: [AnswerColumnInfo!]!) {
12696
- Answer__addColumn(session: $session, columns: $columns) {
12697
- ${bachSessionId}
12698
- }
12699
- }
12700
- `;
12701
- const getAnswerData = `
12702
- query GetTableWithHeadlineData($session: BachSessionIdInput!, $deadline: Int!, $dataPaginationParams: DataPaginationParamsInput!) {
12703
- getAnswer(session: $session) {
12704
- ${bachSessionId}
12705
- answer {
12706
- id
12707
- visualizations {
12708
- id
12709
- ... on TableViz {
12710
- columns {
12711
- column {
12712
- id
12713
- name
12714
- type
12715
- aggregationType
12716
- dataType
12717
- }
12718
- }
12719
- data(deadline: $deadline, pagination: $dataPaginationParams)
12720
- }
12721
- }
12722
- }
12723
- }
12724
- }
12725
- `;
12407
+ var instances = {};
12408
+ var extend_mp = function() {
12409
+ // add all the sub mixpanel instances
12410
+ _.each(instances, function(instance, name) {
12411
+ if (name !== PRIMARY_INSTANCE_NAME) { mixpanel_master[name] = instance; }
12412
+ });
12413
+
12414
+ // add private functions as _
12415
+ mixpanel_master['_'] = _;
12416
+ };
12417
+
12418
+ var override_mp_init_func = function() {
12419
+ // we override the snippets init function to handle the case where a
12420
+ // user initializes the mixpanel library after the script loads & runs
12421
+ mixpanel_master['init'] = function(token, config, name) {
12422
+ if (name) {
12423
+ // initialize a sub library
12424
+ if (!mixpanel_master[name]) {
12425
+ mixpanel_master[name] = instances[name] = create_mplib(token, config, name);
12426
+ mixpanel_master[name]._loaded();
12427
+ }
12428
+ return mixpanel_master[name];
12429
+ } else {
12430
+ var instance = mixpanel_master;
12431
+
12432
+ if (instances[PRIMARY_INSTANCE_NAME]) {
12433
+ // main mixpanel lib already initialized
12434
+ instance = instances[PRIMARY_INSTANCE_NAME];
12435
+ } else if (token) {
12436
+ // intialize the main mixpanel lib
12437
+ instance = create_mplib(token, config, PRIMARY_INSTANCE_NAME);
12438
+ instance._loaded();
12439
+ instances[PRIMARY_INSTANCE_NAME] = instance;
12440
+ }
12441
+
12442
+ mixpanel_master = instance;
12443
+ if (init_type === INIT_SNIPPET) {
12444
+ window$1[PRIMARY_INSTANCE_NAME] = mixpanel_master;
12445
+ }
12446
+ extend_mp();
12447
+ }
12448
+ };
12449
+ };
12450
+
12451
+ var add_dom_loaded_handler = function() {
12452
+ // Cross browser DOM Loaded support
12453
+ function dom_loaded_handler() {
12454
+ // function flag since we only want to execute this once
12455
+ if (dom_loaded_handler.done) { return; }
12456
+ dom_loaded_handler.done = true;
12726
12457
 
12727
- // eslint-disable-next-line no-shadow
12728
- var OperationType;
12729
- (function (OperationType) {
12730
- OperationType["GetChartWithData"] = "GetChartWithData";
12731
- OperationType["GetTableWithHeadlineData"] = "GetTableWithHeadlineData";
12732
- })(OperationType || (OperationType = {}));
12733
- /**
12734
- * Class representing the answer service provided with the
12735
- * custom action payload. This service could be used to run
12736
- * graphql queries in the context of the answer on which the
12737
- * custom action was triggered.
12738
- *
12739
- * @example
12740
- * ```js
12741
- * embed.on(EmbedEvent.CustomAction, e => {
12742
- * const underlying = await e.answerService.getUnderlyingDataForPoint([
12743
- * 'col name 1'
12744
- * ]);
12745
- * const data = await underlying.fetchData(0, 100);
12746
- * })
12747
- * ```
12748
- * @version SDK: 1.25.0| ThoughtSpot: 9.10.0.cl
12749
- * @group Events
12750
- */
12751
- class AnswerService {
12752
- /**
12753
- * Should not need to be called directly.
12754
- *
12755
- * @param session
12756
- * @param answer
12757
- * @param thoughtSpotHost
12758
- * @param selectedPoints
12759
- */
12760
- constructor(session, answer, thoughtSpotHost, selectedPoints) {
12761
- this.session = session;
12762
- this.answer = answer;
12763
- this.thoughtSpotHost = thoughtSpotHost;
12764
- this.selectedPoints = selectedPoints;
12765
- this.session = removeTypename(session);
12766
- }
12767
- /**
12768
- * Get the details about the source used in the answer.
12769
- * This can be used to get the list of all columns in the data source for example.
12770
- */
12771
- async getSourceDetail() {
12772
- const sourceId = this.answer.sources[0].header.guid;
12773
- return getSourceDetail(this.thoughtSpotHost, sourceId);
12774
- }
12775
- /**
12776
- * Remove columnIds and return updated answer session.
12777
- *
12778
- * @param columnIds
12779
- * @returns
12780
- */
12781
- async removeColumns(columnIds) {
12782
- return this.executeQuery(removeColumns, {
12783
- logicalColumnIds: columnIds,
12784
- });
12785
- }
12786
- /**
12787
- * Add columnIds and return updated answer session.
12788
- *
12789
- * @param columnIds
12790
- * @returns
12791
- */
12792
- async addColumns(columnIds) {
12793
- return this.executeQuery(addColumns, {
12794
- columns: columnIds.map((colId) => ({ logicalColumnId: colId })),
12795
- });
12796
- }
12797
- /**
12798
- * Fetch data from the answer.
12799
- *
12800
- * @param offset
12801
- * @param size
12802
- * @returns
12803
- */
12804
- async fetchData(offset = 0, size = 1000) {
12805
- const { answer } = await this.executeQuery(getAnswerData, {
12806
- deadline: 0,
12807
- dataPaginationParams: {
12808
- isClientPaginated: true,
12809
- offset,
12810
- size,
12811
- },
12812
- });
12813
- const { columns, data } = answer.visualizations.find((viz) => !!viz.data) || {};
12814
- return {
12815
- columns,
12816
- data,
12817
- };
12818
- }
12819
- /**
12820
- * Fetch the data for the answer as a CSV blob. This might be
12821
- * quicker for larger data.
12822
- *
12823
- * @param userLocale
12824
- * @param includeInfo Include the CSV header in the output
12825
- * @returns Response
12826
- */
12827
- async fetchCSVBlob(userLocale = 'en-us', includeInfo = false) {
12828
- const fetchUrl = this.getFetchCSVBlobUrl(userLocale, includeInfo);
12829
- return tokenizedFetch(fetchUrl, {
12830
- credentials: 'include',
12831
- });
12832
- }
12833
- /**
12834
- * Just get the internal URL for this answer's data
12835
- * as a CSV blob.
12836
- *
12837
- * @param userLocale
12838
- * @param includeInfo
12839
- * @returns
12840
- */
12841
- getFetchCSVBlobUrl(userLocale = 'en-us', includeInfo = false) {
12842
- return `${this.thoughtSpotHost}/prism/download/answer/csv?sessionId=${this.session.sessionId}&genNo=${this.session.genNo}&userLocale=${userLocale}&exportFileName=data&hideCsvHeader=${!includeInfo}`;
12843
- }
12844
- /**
12845
- * Get underlying data given a point and the output column names.
12846
- * In case of a context menu action, the selectedPoints are
12847
- * automatically passed.
12848
- *
12849
- * @param outputColumnNames
12850
- * @param selectedPoints
12851
- * @example
12852
- * ```js
12853
- * embed.on(EmbedEvent.CustomAction, e => {
12854
- * const underlying = await e.answerService.getUnderlyingDataForPoint([
12855
- * 'col name 1' // The column should exist in the data source.
12856
- * ]);
12857
- * const data = await underlying.fetchData(0, 100);
12858
- * })
12859
- * ```
12860
- * @version SDK: 1.25.0| ThoughtSpot: 9.10.0.cl
12861
- */
12862
- async getUnderlyingDataForPoint(outputColumnNames, selectedPoints) {
12863
- if (!selectedPoints && !this.selectedPoints) {
12864
- throw new Error('Needs to be triggered in context of a point');
12865
- }
12866
- if (!selectedPoints) {
12867
- selectedPoints = getSelectedPointsForUnderlyingDataQuery(this.selectedPoints);
12868
- }
12869
- const sourceDetail = await this.getSourceDetail();
12870
- const ouputColumnGuids = getGuidsFromColumnNames(sourceDetail, outputColumnNames);
12871
- const unAggAnswer = await graphqlQuery({
12872
- query: getUnaggregatedAnswerSession,
12873
- variables: {
12874
- session: this.session,
12875
- columns: selectedPoints,
12876
- },
12877
- thoughtSpotHost: this.thoughtSpotHost,
12878
- });
12879
- const unaggAnswerSession = new AnswerService(unAggAnswer.id, unAggAnswer.answer, this.thoughtSpotHost);
12880
- const currentColumns = new Set(unAggAnswer.answer.visualizations[0].columns
12881
- .map((c) => c.column.referencedColumns[0].guid));
12882
- const columnsToAdd = [...ouputColumnGuids].filter((col) => !currentColumns.has(col));
12883
- if (columnsToAdd.length) {
12884
- await unaggAnswerSession.addColumns(columnsToAdd);
12885
- }
12886
- const columnsToRemove = [...currentColumns].filter((col) => !ouputColumnGuids.has(col));
12887
- if (columnsToRemove.length) {
12888
- await unaggAnswerSession.removeColumns(columnsToRemove);
12889
- }
12890
- return unaggAnswerSession;
12891
- }
12892
- /**
12893
- * Execute a custom graphql query in the context of the answer.
12894
- *
12895
- * @param query graphql query
12896
- * @param variables graphql variables
12897
- * @returns
12898
- */
12899
- async executeQuery(query, variables) {
12900
- const data = await graphqlQuery({
12901
- query,
12902
- variables: {
12903
- session: this.session,
12904
- ...variables,
12905
- },
12906
- thoughtSpotHost: this.thoughtSpotHost,
12907
- isCompositeQuery: false,
12908
- });
12909
- this.session = deepMerge(this.session, (data === null || data === void 0 ? void 0 : data.id) || {});
12910
- return data;
12911
- }
12912
- /**
12913
- * Get the internal session details for the answer.
12914
- *
12915
- * @returns
12916
- */
12917
- getSession() {
12918
- return this.session;
12458
+ DOM_LOADED = true;
12459
+ ENQUEUE_REQUESTS = false;
12460
+
12461
+ _.each(instances, function(inst) {
12462
+ inst._dom_loaded();
12463
+ });
12464
+ }
12465
+
12466
+ function do_scroll_check() {
12467
+ try {
12468
+ document$1.documentElement.doScroll('left');
12469
+ } catch(e) {
12470
+ setTimeout(do_scroll_check, 1);
12471
+ return;
12472
+ }
12473
+
12474
+ dom_loaded_handler();
12475
+ }
12476
+
12477
+ if (document$1.addEventListener) {
12478
+ if (document$1.readyState === 'complete') {
12479
+ // safari 4 can fire the DOMContentLoaded event before loading all
12480
+ // external JS (including this file). you will see some copypasta
12481
+ // on the internet that checks for 'complete' and 'loaded', but
12482
+ // 'loaded' is an IE thing
12483
+ dom_loaded_handler();
12484
+ } else {
12485
+ document$1.addEventListener('DOMContentLoaded', dom_loaded_handler, false);
12486
+ }
12487
+ } else if (document$1.attachEvent) {
12488
+ // IE
12489
+ document$1.attachEvent('onreadystatechange', dom_loaded_handler);
12490
+
12491
+ // check to make sure we arn't in a frame
12492
+ var toplevel = false;
12493
+ try {
12494
+ toplevel = window$1.frameElement === null;
12495
+ } catch(e) {
12496
+ // noop
12497
+ }
12498
+
12499
+ if (document$1.documentElement.doScroll && toplevel) {
12500
+ do_scroll_check();
12501
+ }
12502
+ }
12503
+
12504
+ // fallback handler, always will work
12505
+ _.register_event(window$1, 'load', dom_loaded_handler, true);
12506
+ };
12507
+
12508
+ function init_as_module() {
12509
+ init_type = INIT_MODULE;
12510
+ mixpanel_master = new MixpanelLib();
12511
+
12512
+ override_mp_init_func();
12513
+ mixpanel_master['init']();
12514
+ add_dom_loaded_handler();
12515
+
12516
+ return mixpanel_master;
12517
+ }
12518
+
12519
+ var mixpanel = init_as_module();
12520
+
12521
+ var mixpanel_cjs = mixpanel;
12522
+
12523
+ var mixpanel$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), mixpanel_cjs, {
12524
+ 'default': mixpanel_cjs
12525
+ }));
12526
+
12527
+ // Needed to avoid error in CJS builds on some bundlers.
12528
+ const mixpanelLib = mixpanel_cjs || mixpanel$1;
12529
+ let mixpanelInstance;
12530
+ const MIXPANEL_EVENT = {
12531
+ VISUAL_SDK_RENDER_START: 'visual-sdk-render-start',
12532
+ VISUAL_SDK_CALLED_INIT: 'visual-sdk-called-init',
12533
+ VISUAL_SDK_RENDER_COMPLETE: 'visual-sdk-render-complete',
12534
+ VISUAL_SDK_RENDER_FAILED: 'visual-sdk-render-failed',
12535
+ VISUAL_SDK_TRIGGER: 'visual-sdk-trigger',
12536
+ VISUAL_SDK_ON: 'visual-sdk-on',
12537
+ VISUAL_SDK_IFRAME_LOAD_PERFORMANCE: 'visual-sdk-iframe-load-performance',
12538
+ VISUAL_SDK_EMBED_CREATE: 'visual-sdk-embed-create',
12539
+ VERCEL_INTEGRATION_COMPLETED: 'vercel-integration-completed',
12540
+ };
12541
+ let isMixpanelInitialized = false;
12542
+ let eventQueue = [];
12543
+ /**
12544
+ * Pushes the event with its Property key-value map to mixpanel.
12545
+ *
12546
+ * @param eventId
12547
+ * @param eventProps
12548
+ */
12549
+ function uploadMixpanelEvent(eventId, eventProps = {}) {
12550
+ if (!isMixpanelInitialized) {
12551
+ eventQueue.push({ eventId, eventProps });
12552
+ return;
12919
12553
  }
12554
+ mixpanelInstance.track(eventId, eventProps);
12920
12555
  }
12921
12556
  /**
12922
12557
  *
12923
- * @param sourceDetail
12924
- * @param colNames
12925
12558
  */
12926
- function getGuidsFromColumnNames(sourceDetail, colNames) {
12927
- const cols = sourceDetail.columns.reduce((colSet, col) => {
12928
- colSet[col.name] = col;
12929
- return colSet;
12930
- }, {});
12931
- return new Set(colNames.map((colName) => {
12932
- const col = cols[colName];
12933
- return col.id;
12934
- }));
12559
+ function emptyQueue() {
12560
+ if (!isMixpanelInitialized) {
12561
+ return;
12562
+ }
12563
+ eventQueue.forEach((event) => {
12564
+ uploadMixpanelEvent(event.eventId, event.eventProps);
12565
+ });
12566
+ eventQueue = [];
12935
12567
  }
12936
12568
  /**
12937
12569
  *
12938
- * @param selectedPoints
12570
+ * @param sessionInfo
12939
12571
  */
12940
- function getSelectedPointsForUnderlyingDataQuery(selectedPoints) {
12941
- const underlyingDataPoint = [];
12942
- /**
12943
- *
12944
- * @param colVal
12945
- */
12946
- function addPointFromColVal(colVal) {
12947
- var _a;
12948
- const dataType = colVal.column.dataType;
12949
- const id = colVal.column.id;
12950
- let dataValue;
12951
- if (dataType === 'DATE') {
12952
- if (Number.isFinite(colVal.value)) {
12953
- dataValue = [{
12954
- epochRange: {
12955
- startEpoch: colVal.value,
12956
- },
12957
- }];
12958
- // Case for custom calendar.
12959
- }
12960
- else if ((_a = colVal.value) === null || _a === void 0 ? void 0 : _a.v) {
12961
- dataValue = [{
12962
- epochRange: {
12963
- startEpoch: colVal.value.v.s,
12964
- endEpoch: colVal.value.v.e,
12965
- },
12966
- }];
12572
+ function initMixpanel(sessionInfo) {
12573
+ var _a;
12574
+ if (!sessionInfo || !sessionInfo.mixpanelToken) {
12575
+ return;
12576
+ }
12577
+ // On a public cluster the user is anonymous, so don't set the identify to
12578
+ // userGUID
12579
+ const isPublicCluster = !!sessionInfo.isPublicUser;
12580
+ const token = sessionInfo.mixpanelToken;
12581
+ try {
12582
+ if (token) {
12583
+ mixpanelInstance = mixpanelLib.init(token, undefined, 'tsEmbed');
12584
+ if (!isPublicCluster) {
12585
+ mixpanelInstance.identify(sessionInfo.userGUID);
12967
12586
  }
12587
+ mixpanelInstance.register_once({
12588
+ clusterId: sessionInfo.clusterId,
12589
+ clusterName: sessionInfo.clusterName,
12590
+ releaseVersion: sessionInfo.releaseVersion,
12591
+ hostAppUrl: ((_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.host) || '',
12592
+ });
12593
+ isMixpanelInitialized = true;
12594
+ emptyQueue();
12968
12595
  }
12969
- else {
12970
- dataValue = [{ value: colVal.value }];
12971
- }
12972
- underlyingDataPoint.push({
12973
- columnId: colVal.column.id,
12974
- dataValue,
12975
- });
12976
12596
  }
12977
- selectedPoints.forEach((p) => {
12978
- p.selectedAttributes.forEach(addPointFromColVal);
12979
- });
12980
- return underlyingDataPoint;
12597
+ catch (e) {
12598
+ logger.error('Error initializing mixpanel', e);
12599
+ }
12981
12600
  }
12982
12601
 
12983
12602
  var eventemitter3 = createCommonjsModule(function (module) {
@@ -13332,6 +12951,399 @@ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!]
13332
12951
  return new _Set(values);
13333
12952
  };
13334
12953
 
12954
+ /**
12955
+ *
12956
+ * @param url
12957
+ * @param options
12958
+ */
12959
+ function tokenisedFailureLoggedFetch(url, options = {}) {
12960
+ return tokenizedFetch(url, options).then(async (r) => {
12961
+ var _a;
12962
+ if (!r.ok && r.type !== 'opaqueredirect' && r.type !== 'opaque') {
12963
+ logger.error('Failure', await ((_a = r.text) === null || _a === void 0 ? void 0 : _a.call(r)));
12964
+ }
12965
+ return r;
12966
+ });
12967
+ }
12968
+ /**
12969
+ *
12970
+ * @param authVerificationUrl
12971
+ */
12972
+ function fetchSessionInfoService(authVerificationUrl) {
12973
+ return tokenisedFailureLoggedFetch(authVerificationUrl, {
12974
+ credentials: 'include',
12975
+ });
12976
+ }
12977
+
12978
+ // eslint-disable-next-line import/no-mutable-exports
12979
+ let loggedInStatus = false;
12980
+ // eslint-disable-next-line import/no-mutable-exports
12981
+ let samlAuthWindow = null;
12982
+ // eslint-disable-next-line import/no-mutable-exports
12983
+ let samlCompletionPromise = null;
12984
+ let sessionInfo = null;
12985
+ let sessionInfoResolver = null;
12986
+ const sessionInfoPromise = new Promise((resolve) => {
12987
+ sessionInfoResolver = resolve;
12988
+ });
12989
+ let releaseVersion = '';
12990
+ const SSO_REDIRECTION_MARKER_GUID = '5e16222e-ef02-43e9-9fbd-24226bf3ce5b';
12991
+ /**
12992
+ * Enum for auth failure types. This is the parameter passed to the listner
12993
+ * of {@link AuthStatus.FAILURE}.
12994
+ *
12995
+ * @group Authentication / Init
12996
+ */
12997
+ var AuthFailureType;
12998
+ (function (AuthFailureType) {
12999
+ AuthFailureType["SDK"] = "SDK";
13000
+ AuthFailureType["NO_COOKIE_ACCESS"] = "NO_COOKIE_ACCESS";
13001
+ AuthFailureType["EXPIRY"] = "EXPIRY";
13002
+ AuthFailureType["OTHER"] = "OTHER";
13003
+ })(AuthFailureType || (AuthFailureType = {}));
13004
+ /**
13005
+ * Enum for auth status emitted by the emitter returned from {@link init}.
13006
+ *
13007
+ * @group Authentication / Init
13008
+ */
13009
+ var AuthStatus;
13010
+ (function (AuthStatus) {
13011
+ /**
13012
+ * Emits when the SDK fails to authenticate
13013
+ */
13014
+ AuthStatus["FAILURE"] = "FAILURE";
13015
+ /**
13016
+ * Emits when the SDK authenticates successfully
13017
+ */
13018
+ AuthStatus["SDK_SUCCESS"] = "SDK_SUCCESS";
13019
+ /**
13020
+ * Emits when the app sends an authentication success message
13021
+ */
13022
+ AuthStatus["SUCCESS"] = "SUCCESS";
13023
+ /**
13024
+ * Emits when a user logs out
13025
+ */
13026
+ AuthStatus["LOGOUT"] = "LOGOUT";
13027
+ /**
13028
+ * Emitted when inPopup is true in the SAMLRedirect flow and the
13029
+ * popup is waiting to be triggered either programmatically
13030
+ * or by the trigger button.
13031
+ *
13032
+ * @version SDK: 1.19.0
13033
+ */
13034
+ AuthStatus["WAITING_FOR_POPUP"] = "WAITING_FOR_POPUP";
13035
+ })(AuthStatus || (AuthStatus = {}));
13036
+ /**
13037
+ * Events which can be triggered on the emitter returned from {@link init}.
13038
+ *
13039
+ * @group Authentication / Init
13040
+ */
13041
+ var AuthEvent;
13042
+ (function (AuthEvent) {
13043
+ /**
13044
+ * Manually trigger the SSO popup. This is useful when
13045
+ * authStatus is SAMLRedirect/OIDCRedirect and inPopup is set to true
13046
+ */
13047
+ AuthEvent["TRIGGER_SSO_POPUP"] = "TRIGGER_SSO_POPUP";
13048
+ })(AuthEvent || (AuthEvent = {}));
13049
+ /**
13050
+ *
13051
+ */
13052
+ function notifyAuthSDKSuccess() {
13053
+ {
13054
+ logger.error('SDK not initialized');
13055
+ return;
13056
+ }
13057
+ }
13058
+ /**
13059
+ *
13060
+ */
13061
+ function notifyAuthSuccess() {
13062
+ {
13063
+ logger.error('SDK not initialized');
13064
+ return;
13065
+ }
13066
+ }
13067
+ /**
13068
+ *
13069
+ * @param failureType
13070
+ */
13071
+ function notifyAuthFailure(failureType) {
13072
+ {
13073
+ logger.error('SDK not initialized');
13074
+ return;
13075
+ }
13076
+ }
13077
+ /**
13078
+ *
13079
+ */
13080
+ function notifyLogout() {
13081
+ {
13082
+ logger.error('SDK not initialized');
13083
+ return;
13084
+ }
13085
+ }
13086
+ const initSession = (sessionDetails) => {
13087
+ const embedConfig = getEmbedConfig();
13088
+ if (sessionInfo == null) {
13089
+ sessionInfo = sessionDetails;
13090
+ if (!embedConfig.disableSDKTracking) {
13091
+ initMixpanel(sessionInfo);
13092
+ }
13093
+ sessionInfoResolver(sessionInfo);
13094
+ }
13095
+ };
13096
+ const getSessionDetails = (sessionInfoResp) => {
13097
+ const devMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.devSdkKey;
13098
+ const prodMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.prodSdkKey;
13099
+ const mixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.production
13100
+ ? prodMixpanelToken
13101
+ : devMixpanelToken;
13102
+ return {
13103
+ userGUID: sessionInfoResp.userGUID,
13104
+ mixpanelToken,
13105
+ isPublicUser: sessionInfoResp.configInfo.isPublicUser,
13106
+ releaseVersion: sessionInfoResp.releaseVersion,
13107
+ clusterId: sessionInfoResp.configInfo.selfClusterId,
13108
+ clusterName: sessionInfoResp.configInfo.selfClusterName,
13109
+ ...sessionInfoResp,
13110
+ };
13111
+ };
13112
+ /**
13113
+ * Check if we are logged into the ThoughtSpot cluster
13114
+ *
13115
+ * @param thoughtSpotHost The ThoughtSpot cluster hostname or IP
13116
+ */
13117
+ async function isLoggedIn(thoughtSpotHost) {
13118
+ const authVerificationUrl = `${thoughtSpotHost}${EndPoints.AUTH_VERIFICATION}`;
13119
+ let response = null;
13120
+ try {
13121
+ response = await fetchSessionInfoService(authVerificationUrl);
13122
+ const sessionInfoResp = await response.json();
13123
+ const sessionDetails = getSessionDetails(sessionInfoResp);
13124
+ // Store user session details from session info
13125
+ initSession(sessionDetails);
13126
+ releaseVersion = sessionInfoResp.releaseVersion;
13127
+ }
13128
+ catch (e) {
13129
+ return false;
13130
+ }
13131
+ return response.status === 200;
13132
+ }
13133
+ /**
13134
+ * Return releaseVersion if available
13135
+ */
13136
+ function getReleaseVersion() {
13137
+ return releaseVersion;
13138
+ }
13139
+ /**
13140
+ * Check if we are stuck at the SSO redirect URL
13141
+ */
13142
+ function isAtSSORedirectUrl() {
13143
+ return window.location.href.indexOf(SSO_REDIRECTION_MARKER_GUID) >= 0;
13144
+ }
13145
+ /**
13146
+ * Remove the SSO redirect URL marker
13147
+ */
13148
+ function removeSSORedirectUrlMarker() {
13149
+ // Note (sunny): This will leave a # around even if it was not in the URL
13150
+ // to begin with. Trying to remove the hash by changing window.location will
13151
+ // reload the page which we don't want. We'll live with adding an
13152
+ // unnecessary hash to the parent page URL until we find any use case where
13153
+ // that creates an issue.
13154
+ window.location.hash = window.location.hash.replace(SSO_REDIRECTION_MARKER_GUID, '');
13155
+ }
13156
+ /**
13157
+ * Perform token based authentication
13158
+ *
13159
+ * @param embedConfig The embed configuration
13160
+ */
13161
+ const doTokenAuth = async (embedConfig) => {
13162
+ const { thoughtSpotHost, username, authEndpoint, getAuthToken, } = embedConfig;
13163
+ if (!authEndpoint && !getAuthToken) {
13164
+ throw new Error('Either auth endpoint or getAuthToken function must be provided');
13165
+ }
13166
+ loggedInStatus = await isLoggedIn(thoughtSpotHost);
13167
+ if (!loggedInStatus) {
13168
+ const authToken = await getAuthenticationToken(embedConfig);
13169
+ let resp;
13170
+ try {
13171
+ resp = await fetchAuthPostService(thoughtSpotHost, username, authToken);
13172
+ }
13173
+ catch (e) {
13174
+ resp = await fetchAuthService(thoughtSpotHost, username, authToken);
13175
+ }
13176
+ // token login issues a 302 when successful
13177
+ loggedInStatus = resp.ok || resp.type === 'opaqueredirect';
13178
+ if (loggedInStatus && embedConfig.detectCookieAccessSlow) {
13179
+ // When 3rd party cookie access is blocked, this will fail because
13180
+ // cookies will not be sent with the call.
13181
+ loggedInStatus = await isLoggedIn(thoughtSpotHost);
13182
+ }
13183
+ }
13184
+ return loggedInStatus;
13185
+ };
13186
+ /**
13187
+ * Validate embedConfig parameters required for cookielessTokenAuth
13188
+ *
13189
+ * @param embedConfig The embed configuration
13190
+ */
13191
+ const doCookielessTokenAuth = async (embedConfig) => {
13192
+ const { authEndpoint, getAuthToken } = embedConfig;
13193
+ if (!authEndpoint && !getAuthToken) {
13194
+ throw new Error('Either auth endpoint or getAuthToken function must be provided');
13195
+ }
13196
+ let authSuccess = false;
13197
+ try {
13198
+ const authToken = await getAuthenticationToken(embedConfig);
13199
+ if (authToken) {
13200
+ authSuccess = true;
13201
+ }
13202
+ }
13203
+ catch {
13204
+ authSuccess = false;
13205
+ }
13206
+ return authSuccess;
13207
+ };
13208
+ /**
13209
+ * Perform basic authentication to the ThoughtSpot cluster using the cluster
13210
+ * credentials.
13211
+ *
13212
+ * Warning: This feature is primarily intended for developer testing. It is
13213
+ * strongly advised not to use this authentication method in production.
13214
+ *
13215
+ * @param embedConfig The embed configuration
13216
+ */
13217
+ const doBasicAuth = async (embedConfig) => {
13218
+ const { thoughtSpotHost, username, password } = embedConfig;
13219
+ const loggedIn = await isLoggedIn(thoughtSpotHost);
13220
+ if (!loggedIn) {
13221
+ const response = await fetchBasicAuthService(thoughtSpotHost, username, password);
13222
+ loggedInStatus = response.ok;
13223
+ if (embedConfig.detectCookieAccessSlow) {
13224
+ loggedInStatus = await isLoggedIn(thoughtSpotHost);
13225
+ }
13226
+ }
13227
+ else {
13228
+ loggedInStatus = true;
13229
+ }
13230
+ return loggedInStatus;
13231
+ };
13232
+ /**
13233
+ *
13234
+ * @param ssoURL
13235
+ * @param triggerContainer
13236
+ * @param triggerText
13237
+ */
13238
+ async function samlPopupFlow(ssoURL, triggerContainer, triggerText) {
13239
+ const openPopup = () => {
13240
+ if (samlAuthWindow === null || samlAuthWindow.closed) {
13241
+ samlAuthWindow = window.open(ssoURL, '_blank', 'location=no,height=570,width=520,scrollbars=yes,status=yes');
13242
+ }
13243
+ else {
13244
+ samlAuthWindow.focus();
13245
+ }
13246
+ };
13247
+ const containerEl = getDOMNode(triggerContainer);
13248
+ if (containerEl) {
13249
+ containerEl.innerHTML = '<button id="ts-auth-btn" class="ts-auth-btn" style="margin: auto;"></button>';
13250
+ const authElem = document.getElementById('ts-auth-btn');
13251
+ authElem.textContent = triggerText;
13252
+ authElem.addEventListener('click', openPopup, { once: true });
13253
+ }
13254
+ samlCompletionPromise = samlCompletionPromise
13255
+ || new Promise((resolve, reject) => {
13256
+ window.addEventListener('message', (e) => {
13257
+ if (e.data.type === exports.EmbedEvent.SAMLComplete) {
13258
+ e.source.close();
13259
+ resolve();
13260
+ }
13261
+ });
13262
+ });
13263
+ return samlCompletionPromise;
13264
+ }
13265
+ /**
13266
+ * Perform SAML authentication
13267
+ *
13268
+ * @param embedConfig The embed configuration
13269
+ * @param ssoEndPoint
13270
+ */
13271
+ const doSSOAuth = async (embedConfig, ssoEndPoint) => {
13272
+ const { thoughtSpotHost } = embedConfig;
13273
+ const loggedIn = await isLoggedIn(thoughtSpotHost);
13274
+ if (loggedIn) {
13275
+ if (isAtSSORedirectUrl()) {
13276
+ removeSSORedirectUrlMarker();
13277
+ }
13278
+ loggedInStatus = true;
13279
+ return;
13280
+ }
13281
+ // we have already tried authentication and it did not succeed, restore
13282
+ // the current URL to the original one and invoke the callback.
13283
+ if (isAtSSORedirectUrl()) {
13284
+ removeSSORedirectUrlMarker();
13285
+ loggedInStatus = false;
13286
+ return;
13287
+ }
13288
+ const ssoURL = `${thoughtSpotHost}${ssoEndPoint}`;
13289
+ if (embedConfig.inPopup) {
13290
+ await samlPopupFlow(ssoURL, embedConfig.authTriggerContainer, embedConfig.authTriggerText);
13291
+ loggedInStatus = await isLoggedIn(thoughtSpotHost);
13292
+ return;
13293
+ }
13294
+ window.location.href = ssoURL;
13295
+ };
13296
+ const doSamlAuth = async (embedConfig) => {
13297
+ const { thoughtSpotHost } = embedConfig;
13298
+ // redirect for SSO, when the SSO authentication is done, this page will be
13299
+ // loaded again and the same JS will execute again.
13300
+ const ssoRedirectUrl = embedConfig.inPopup
13301
+ ? `${thoughtSpotHost}/v2/#/embed/saml-complete`
13302
+ : getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
13303
+ // bring back the page to the same URL
13304
+ const ssoEndPoint = `${EndPoints.SAML_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
13305
+ await doSSOAuth(embedConfig, ssoEndPoint);
13306
+ return loggedInStatus;
13307
+ };
13308
+ const doOIDCAuth = async (embedConfig) => {
13309
+ const { thoughtSpotHost } = embedConfig;
13310
+ // redirect for SSO, when the SSO authentication is done, this page will be
13311
+ // loaded again and the same JS will execute again.
13312
+ const ssoRedirectUrl = embedConfig.noRedirect || embedConfig.inPopup
13313
+ ? `${thoughtSpotHost}/v2/#/embed/saml-complete`
13314
+ : getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
13315
+ // bring back the page to the same URL
13316
+ const ssoEndPoint = `${EndPoints.OIDC_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
13317
+ await doSSOAuth(embedConfig, ssoEndPoint);
13318
+ return loggedInStatus;
13319
+ };
13320
+ /**
13321
+ * Perform authentication on the ThoughtSpot cluster
13322
+ *
13323
+ * @param embedConfig The embed configuration
13324
+ */
13325
+ const authenticate = async (embedConfig) => {
13326
+ const { authType } = embedConfig;
13327
+ switch (authType) {
13328
+ case AuthType.SSO:
13329
+ case AuthType.SAMLRedirect:
13330
+ case AuthType.SAML:
13331
+ return doSamlAuth(embedConfig);
13332
+ case AuthType.OIDC:
13333
+ case AuthType.OIDCRedirect:
13334
+ return doOIDCAuth(embedConfig);
13335
+ case AuthType.AuthServer:
13336
+ case AuthType.TrustedAuthToken:
13337
+ return doTokenAuth(embedConfig);
13338
+ case AuthType.TrustedAuthTokenCookieless:
13339
+ return doCookielessTokenAuth(embedConfig);
13340
+ case AuthType.Basic:
13341
+ return doBasicAuth(embedConfig);
13342
+ default:
13343
+ return Promise.resolve(true);
13344
+ }
13345
+ };
13346
+
13335
13347
  /* eslint-disable camelcase */
13336
13348
  const CONFIG_DEFAULTS = {
13337
13349
  loginFailedMessage: 'Not logged in',
@@ -13545,6 +13557,8 @@ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!]
13545
13557
  });
13546
13558
  }
13547
13559
 
13560
+ var name="@thoughtspot/visual-embed-sdk";var version="1.28.1-alpha.1";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":"^46.9.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:"45 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};
13561
+
13548
13562
  /**
13549
13563
  * Copyright (c) 2022
13550
13564
  *
@@ -13690,7 +13704,7 @@ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!]
13690
13704
  this.thoughtSpotV2Base = getV2BasePath(this.embedConfig);
13691
13705
  this.eventHandlerMap = new Map();
13692
13706
  this.isError = false;
13693
- this.viewConfig = { excludeRuntimeFiltersfromURL: true, ...viewConfig };
13707
+ this.viewConfig = { excludeRuntimeFiltersfromURL: false, ...viewConfig };
13694
13708
  this.shouldEncodeUrlQueryParams = this.embedConfig.shouldEncodeUrlQueryParams;
13695
13709
  this.registerAppInit();
13696
13710
  uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_EMBED_CREATE, {
@@ -14531,7 +14545,7 @@ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!]
14531
14545
  class V1Embed extends TsEmbed {
14532
14546
  constructor(domSelector, viewConfig) {
14533
14547
  super(domSelector, viewConfig);
14534
- this.viewConfig = { excludeRuntimeFiltersfromURL: true, ...viewConfig };
14548
+ this.viewConfig = { excludeRuntimeFiltersfromURL: false, ...viewConfig };
14535
14549
  }
14536
14550
  /**
14537
14551
  * Render the app in an iframe and set up event handlers
@@ -14777,7 +14791,7 @@ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!]
14777
14791
  }
14778
14792
  getEmbedParams() {
14779
14793
  var _a;
14780
- const { hideResults, expandAllDataSource, enableSearchAssist, forceTable, searchOptions, runtimeFilters, dataSource, dataSources, excludeRuntimeFiltersfromURL = true, hideSearchBar, dataPanelV2 = false, useLastSelectedSources = false, runtimeParameters, } = this.viewConfig;
14794
+ const { hideResults, enableSearchAssist, forceTable, searchOptions, runtimeFilters, dataSource, dataSources, excludeRuntimeFiltersfromURL, hideSearchBar, dataPanelV2 = false, useLastSelectedSources = false, runtimeParameters, } = this.viewConfig;
14781
14795
  const queryParams = this.getBaseQueryParams();
14782
14796
  queryParams[Param.HideActions] = [
14783
14797
  ...((_a = queryParams[Param.HideActions]) !== null && _a !== void 0 ? _a : []),