@thoughtspot/visual-embed-sdk 1.27.8 → 1.28.0-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 (126) 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/embed/base.d.ts +1 -1
  7. package/cjs/src/embed/base.d.ts.map +1 -1
  8. package/cjs/src/embed/base.js +5 -5
  9. package/cjs/src/embed/base.js.map +1 -1
  10. package/cjs/src/embed/base.spec.js +1 -1
  11. package/cjs/src/embed/base.spec.js.map +1 -1
  12. package/cjs/src/embed/search.d.ts +1 -5
  13. package/cjs/src/embed/search.d.ts.map +1 -1
  14. package/cjs/src/embed/search.js +4 -4
  15. package/cjs/src/embed/search.js.map +1 -1
  16. package/cjs/src/embed/ts-embed.d.ts +1 -1
  17. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  18. package/cjs/src/embed/ts-embed.js +6 -6
  19. package/cjs/src/embed/ts-embed.js.map +1 -1
  20. package/cjs/src/embed/ts-embed.spec.js +8 -14
  21. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  22. package/cjs/src/index.d.ts +4 -3
  23. package/cjs/src/index.d.ts.map +1 -1
  24. package/cjs/src/index.js +4 -1
  25. package/cjs/src/index.js.map +1 -1
  26. package/cjs/src/mixpanel-service.d.ts +1 -0
  27. package/cjs/src/mixpanel-service.d.ts.map +1 -1
  28. package/cjs/src/mixpanel-service.js +1 -0
  29. package/cjs/src/mixpanel-service.js.map +1 -1
  30. package/cjs/src/react/all-types-export.d.ts +1 -1
  31. package/cjs/src/react/all-types-export.d.ts.map +1 -1
  32. package/cjs/src/react/all-types-export.js +2 -1
  33. package/cjs/src/react/all-types-export.js.map +1 -1
  34. package/cjs/src/react/index.spec.js +0 -12
  35. package/cjs/src/react/index.spec.js.map +1 -1
  36. package/cjs/src/types.d.ts +6 -2
  37. package/cjs/src/types.d.ts.map +1 -1
  38. package/cjs/src/types.js +3 -2
  39. package/cjs/src/types.js.map +1 -1
  40. package/cjs/src/utils/graphql/answerService/answerService.d.ts +56 -2
  41. package/cjs/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  42. package/cjs/src/utils/graphql/answerService/answerService.js +55 -0
  43. package/cjs/src/utils/graphql/answerService/answerService.js.map +1 -1
  44. package/dist/src/auth.d.ts.map +1 -1
  45. package/dist/src/embed/base.d.ts +1 -1
  46. package/dist/src/embed/base.d.ts.map +1 -1
  47. package/dist/src/embed/search.d.ts +1 -5
  48. package/dist/src/embed/search.d.ts.map +1 -1
  49. package/dist/src/embed/ts-embed.d.ts +1 -1
  50. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  51. package/dist/src/index.d.ts +4 -3
  52. package/dist/src/index.d.ts.map +1 -1
  53. package/dist/src/mixpanel-service.d.ts +1 -0
  54. package/dist/src/mixpanel-service.d.ts.map +1 -1
  55. package/dist/src/react/all-types-export.d.ts +1 -1
  56. package/dist/src/react/all-types-export.d.ts.map +1 -1
  57. package/dist/src/types.d.ts +6 -2
  58. package/dist/src/types.d.ts.map +1 -1
  59. package/dist/src/utils/graphql/answerService/answerService.d.ts +56 -2
  60. package/dist/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  61. package/dist/tsembed-react.es.js +2267 -2210
  62. package/dist/tsembed-react.js +6915 -6858
  63. package/dist/tsembed.es.js +2741 -2684
  64. package/dist/tsembed.js +2039 -1980
  65. package/dist/visual-embed-sdk-react-full.d.ts +94 -9
  66. package/dist/visual-embed-sdk-react.d.ts +94 -9
  67. package/dist/visual-embed-sdk.d.ts +94 -9
  68. package/lib/package.json +1 -1
  69. package/lib/src/auth.d.ts.map +1 -1
  70. package/lib/src/auth.js +3 -3
  71. package/lib/src/auth.js.map +1 -1
  72. package/lib/src/embed/base.d.ts +1 -1
  73. package/lib/src/embed/base.d.ts.map +1 -1
  74. package/lib/src/embed/base.js +5 -5
  75. package/lib/src/embed/base.js.map +1 -1
  76. package/lib/src/embed/base.spec.js +2 -2
  77. package/lib/src/embed/base.spec.js.map +1 -1
  78. package/lib/src/embed/search.d.ts +1 -5
  79. package/lib/src/embed/search.d.ts.map +1 -1
  80. package/lib/src/embed/search.js +5 -5
  81. package/lib/src/embed/search.js.map +1 -1
  82. package/lib/src/embed/ts-embed.d.ts +1 -1
  83. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  84. package/lib/src/embed/ts-embed.js +9 -9
  85. package/lib/src/embed/ts-embed.js.map +1 -1
  86. package/lib/src/embed/ts-embed.spec.js +8 -14
  87. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  88. package/lib/src/index.d.ts +4 -3
  89. package/lib/src/index.d.ts.map +1 -1
  90. package/lib/src/index.js +2 -3
  91. package/lib/src/index.js.map +1 -1
  92. package/lib/src/mixpanel-service.d.ts +1 -0
  93. package/lib/src/mixpanel-service.d.ts.map +1 -1
  94. package/lib/src/mixpanel-service.js +1 -0
  95. package/lib/src/mixpanel-service.js.map +1 -1
  96. package/lib/src/react/all-types-export.d.ts +1 -1
  97. package/lib/src/react/all-types-export.d.ts.map +1 -1
  98. package/lib/src/react/all-types-export.js +1 -1
  99. package/lib/src/react/all-types-export.js.map +1 -1
  100. package/lib/src/react/index.spec.js +0 -12
  101. package/lib/src/react/index.spec.js.map +1 -1
  102. package/lib/src/types.d.ts +6 -2
  103. package/lib/src/types.d.ts.map +1 -1
  104. package/lib/src/types.js +3 -2
  105. package/lib/src/types.js.map +1 -1
  106. package/lib/src/utils/authService/authService.spec.js +1 -1
  107. package/lib/src/utils/authService/authService.spec.js.map +1 -1
  108. package/lib/src/utils/graphql/answerService/answerService.d.ts +56 -2
  109. package/lib/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  110. package/lib/src/utils/graphql/answerService/answerService.js +55 -0
  111. package/lib/src/utils/graphql/answerService/answerService.js.map +1 -1
  112. package/lib/src/visual-embed-sdk.d.ts +102 -14
  113. package/package.json +1 -1
  114. package/src/auth.ts +6 -6
  115. package/src/embed/base.spec.ts +3 -3
  116. package/src/embed/base.ts +12 -12
  117. package/src/embed/search.ts +6 -11
  118. package/src/embed/ts-embed.spec.ts +19 -25
  119. package/src/embed/ts-embed.ts +37 -34
  120. package/src/index.ts +10 -1
  121. package/src/mixpanel-service.ts +1 -0
  122. package/src/react/all-types-export.ts +1 -0
  123. package/src/react/index.spec.tsx +0 -29
  124. package/src/types.ts +16 -13
  125. package/src/utils/authService/authService.spec.ts +4 -4
  126. package/src/utils/graphql/answerService/answerService.ts +56 -1
package/dist/tsembed.js CHANGED
@@ -443,7 +443,8 @@
443
443
  * A custom action has been triggered.
444
444
  *
445
445
  * @returns actionId - ID of the custom action
446
- * @returns data - Response payload with the Answer or Liveboard data
446
+ * @returns payload {@link CustomActionPayload} - Response payload with the
447
+ * Answer or Liveboard data
447
448
  * @example
448
449
  * ```js
449
450
  * appEmbed.on(EmbedEvent.customAction, payload => {
@@ -463,7 +464,7 @@
463
464
  * @example
464
465
  * ```js
465
466
  * livebaordEmbed.on(EmbedEvent.VizPointDoubleClick, payload => {
466
- * console.log('VizPointDoubleClick', payload)
467
+ * console.log('VizPointDoubleClick', payload);
467
468
  * })
468
469
  * ```
469
470
  */
@@ -5571,8 +5572,6 @@
5571
5572
 
5572
5573
  var isEqual_1 = isEqual;
5573
5574
 
5574
- var name="@thoughtspot/visual-embed-sdk";var version="1.27.8";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:"44 kB"}],scripts:scripts,peerDependencies:peerDependencies,dependencies:dependencies,devDependencies:devDependencies,author:author,email:email,license:license,directories:directories,repository:repository,publishConfig:publishConfig,keywords:keywords,bugs:bugs,homepage:homepage,globals:globals};
5575
-
5576
5575
  const EndPoints = {
5577
5576
  AUTH_VERIFICATION: '/callosum/v1/session/info',
5578
5577
  SAML_LOGIN_TEMPLATE: (targetUrl) => `/callosum/v1/saml/login?targetURLPath=${targetUrl}`,
@@ -5735,535 +5734,1079 @@
5735
5734
  cachedAuthToken = null;
5736
5735
  };
5737
5736
 
5738
- var Config = {
5739
- DEBUG: false,
5740
- LIB_VERSION: '2.45.0'
5741
- };
5742
-
5743
- // since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
5744
- var window$1;
5745
- if (typeof(window) === 'undefined') {
5746
- var loc = {
5747
- hostname: ''
5748
- };
5749
- window$1 = {
5750
- navigator: { userAgent: '' },
5751
- document: {
5752
- location: loc,
5753
- referrer: ''
5754
- },
5755
- screen: { width: 0, height: 0 },
5756
- location: loc
5757
- };
5758
- } else {
5759
- window$1 = window;
5760
- }
5761
-
5762
- /*
5763
- * Saved references to long variable names, so that closure compiler can
5764
- * minimize file size.
5765
- */
5766
-
5767
- var ArrayProto = Array.prototype;
5768
- var FuncProto = Function.prototype;
5769
- var ObjProto = Object.prototype;
5770
- var slice = ArrayProto.slice;
5771
- var toString = ObjProto.toString;
5772
- var hasOwnProperty$9 = ObjProto.hasOwnProperty;
5773
- var windowConsole = window$1.console;
5774
- var navigator = window$1.navigator;
5775
- var document$1 = window$1.document;
5776
- var windowOpera = window$1.opera;
5777
- var screen = window$1.screen;
5778
- var userAgent = navigator.userAgent;
5779
- var nativeBind = FuncProto.bind;
5780
- var nativeForEach = ArrayProto.forEach;
5781
- var nativeIndexOf = ArrayProto.indexOf;
5782
- var nativeMap = ArrayProto.map;
5783
- var nativeIsArray = Array.isArray;
5784
- var breaker = {};
5785
- var _ = {
5786
- trim: function(str) {
5787
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim#Polyfill
5788
- return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
5789
- }
5737
+ let config = {};
5738
+ /**
5739
+ * Gets the configuration embed was initialized with.
5740
+ *
5741
+ * @returns {@link EmbedConfig} The configuration embed was initialized with.
5742
+ * @version SDK: 1.19.0 | ThoughtSpot: *
5743
+ * @group Global methods
5744
+ */
5745
+ const getEmbedConfig = () => config;
5746
+ /**
5747
+ * Sets the configuration embed was initialized with.
5748
+ * And returns the new configuration.
5749
+ *
5750
+ * @param newConfig The configuration to set.
5751
+ * @version SDK: 1.27.0 | ThoughtSpot: *
5752
+ * @group Global methods
5753
+ */
5754
+ const setEmbedConfig = (newConfig) => {
5755
+ config = newConfig;
5756
+ return newConfig;
5790
5757
  };
5791
5758
 
5792
- // Console override
5793
- var console$1 = {
5794
- /** @type {function(...*)} */
5795
- log: function() {
5796
- if (Config.DEBUG && !_.isUndefined(windowConsole) && windowConsole) {
5797
- try {
5798
- windowConsole.log.apply(windowConsole, arguments);
5799
- } catch (err) {
5800
- _.each(arguments, function(arg) {
5801
- windowConsole.log(arg);
5802
- });
5803
- }
5804
- }
5805
- },
5806
- /** @type {function(...*)} */
5807
- warn: function() {
5808
- if (Config.DEBUG && !_.isUndefined(windowConsole) && windowConsole) {
5809
- var args = ['Mixpanel warning:'].concat(_.toArray(arguments));
5810
- try {
5811
- windowConsole.warn.apply(windowConsole, args);
5812
- } catch (err) {
5813
- _.each(args, function(arg) {
5814
- windowConsole.warn(arg);
5815
- });
5816
- }
5817
- }
5818
- },
5819
- /** @type {function(...*)} */
5820
- error: function() {
5821
- if (Config.DEBUG && !_.isUndefined(windowConsole) && windowConsole) {
5822
- var args = ['Mixpanel error:'].concat(_.toArray(arguments));
5823
- try {
5824
- windowConsole.error.apply(windowConsole, args);
5825
- } catch (err) {
5826
- _.each(args, function(arg) {
5827
- windowConsole.error(arg);
5828
- });
5829
- }
5830
- }
5831
- },
5832
- /** @type {function(...*)} */
5833
- critical: function() {
5834
- if (!_.isUndefined(windowConsole) && windowConsole) {
5835
- var args = ['Mixpanel error:'].concat(_.toArray(arguments));
5836
- try {
5837
- windowConsole.error.apply(windowConsole, args);
5838
- } catch (err) {
5839
- _.each(args, function(arg) {
5840
- windowConsole.error(arg);
5841
- });
5842
- }
5843
- }
5844
- }
5759
+ const tokenizedFetch = async (input, init) => {
5760
+ const embedConfig = getEmbedConfig();
5761
+ if (embedConfig.authType !== exports.AuthType.TrustedAuthTokenCookieless) {
5762
+ return fetch(input, init);
5763
+ }
5764
+ const req = new Request(input, init);
5765
+ const authToken = await getAuthenticationToken(embedConfig);
5766
+ if (authToken) {
5767
+ req.headers.append('Authorization', `Bearer ${authToken}`);
5768
+ }
5769
+ return fetch(req);
5845
5770
  };
5846
5771
 
5847
- var log_func_with_prefix = function(func, prefix) {
5848
- return function() {
5849
- arguments[0] = '[' + prefix + '] ' + arguments[0];
5850
- return func.apply(console$1, arguments);
5851
- };
5852
- };
5853
- var console_with_prefix = function(prefix) {
5854
- return {
5855
- log: log_func_with_prefix(console$1.log, prefix),
5856
- error: log_func_with_prefix(console$1.error, prefix),
5857
- critical: log_func_with_prefix(console$1.critical, prefix)
5858
- };
5859
- };
5772
+ /**
5773
+ *
5774
+ * @param root0
5775
+ * @param root0.query
5776
+ * @param root0.variables
5777
+ * @param root0.thoughtSpotHost
5778
+ * @param root0.isCompositeQuery
5779
+ */
5780
+ async function graphqlQuery({ query, variables, thoughtSpotHost, isCompositeQuery = false, }) {
5781
+ const operationName = getOperationNameFromQuery(query);
5782
+ try {
5783
+ const response = await fetch(`${thoughtSpotHost}/prism/?op=${operationName}`, {
5784
+ method: 'POST',
5785
+ headers: {
5786
+ 'content-type': 'application/json;charset=UTF-8',
5787
+ 'x-requested-by': 'ThoughtSpot',
5788
+ accept: '*/*',
5789
+ 'accept-language': 'en-us',
5790
+ },
5791
+ body: JSON.stringify({
5792
+ operationName,
5793
+ query,
5794
+ variables,
5795
+ }),
5796
+ credentials: 'include',
5797
+ });
5798
+ const result = await response.json();
5799
+ const dataValues = Object.values(result.data);
5800
+ return (isCompositeQuery) ? result.data : dataValues[0];
5801
+ }
5802
+ catch (error) {
5803
+ return error;
5804
+ }
5805
+ }
5860
5806
 
5807
+ const getSourceDetailQuery = `
5808
+ query GetSourceDetail($ids: [GUID!]!) {
5809
+ getSourceDetailById(ids: $ids, type: LOGICAL_TABLE) {
5810
+ id
5811
+ name
5812
+ description
5813
+ authorName
5814
+ authorDisplayName
5815
+ isExternal
5816
+ type
5817
+ created
5818
+ modified
5819
+ columns {
5820
+ id
5821
+ name
5822
+ author
5823
+ authorDisplayName
5824
+ description
5825
+ dataType
5826
+ type
5827
+ modified
5828
+ ownerName
5829
+ owner
5830
+ dataRecency
5831
+ sources {
5832
+ tableId
5833
+ tableName
5834
+ columnId
5835
+ columnName
5836
+ __typename
5837
+ }
5838
+ synonyms
5839
+ cohortAnswerId
5840
+ __typename
5841
+ }
5842
+ relationships
5843
+ destinationRelationships
5844
+ dataSourceId
5845
+ __typename
5846
+ }
5847
+ }
5848
+ `;
5849
+ const sourceDetailCache = new Map();
5850
+ /**
5851
+ *
5852
+ * @param thoughtSpotHost
5853
+ * @param sourceId
5854
+ */
5855
+ async function getSourceDetail(thoughtSpotHost, sourceId) {
5856
+ if (sourceDetailCache.get(sourceId)) {
5857
+ return sourceDetailCache.get(sourceId);
5858
+ }
5859
+ const details = await graphqlQuery({
5860
+ query: getSourceDetailQuery,
5861
+ variables: {
5862
+ ids: [sourceId],
5863
+ },
5864
+ thoughtSpotHost,
5865
+ });
5866
+ const souceDetails = details[0];
5867
+ if (souceDetails) {
5868
+ sourceDetailCache.set(sourceId, souceDetails);
5869
+ }
5870
+ return souceDetails;
5871
+ }
5861
5872
 
5862
- // UNDERSCORE
5863
- // Embed part of the Underscore Library
5864
- _.bind = function(func, context) {
5865
- var args, bound;
5866
- if (nativeBind && func.bind === nativeBind) {
5867
- return nativeBind.apply(func, slice.call(arguments, 1));
5868
- }
5869
- if (!_.isFunction(func)) {
5870
- throw new TypeError();
5871
- }
5872
- args = slice.call(arguments, 2);
5873
- bound = function() {
5874
- if (!(this instanceof bound)) {
5875
- return func.apply(context, args.concat(slice.call(arguments)));
5876
- }
5877
- var ctor = {};
5878
- ctor.prototype = func.prototype;
5879
- var self = new ctor();
5880
- ctor.prototype = null;
5881
- var result = func.apply(self, args.concat(slice.call(arguments)));
5882
- if (Object(result) === result) {
5883
- return result;
5884
- }
5885
- return self;
5886
- };
5887
- return bound;
5888
- };
5889
-
5890
- /**
5891
- * @param {*=} obj
5892
- * @param {function(...*)=} iterator
5893
- * @param {Object=} context
5894
- */
5895
- _.each = function(obj, iterator, context) {
5896
- if (obj === null || obj === undefined) {
5897
- return;
5898
- }
5899
- if (nativeForEach && obj.forEach === nativeForEach) {
5900
- obj.forEach(iterator, context);
5901
- } else if (obj.length === +obj.length) {
5902
- for (var i = 0, l = obj.length; i < l; i++) {
5903
- if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) {
5904
- return;
5905
- }
5906
- }
5907
- } else {
5908
- for (var key in obj) {
5909
- if (hasOwnProperty$9.call(obj, key)) {
5910
- if (iterator.call(context, obj[key], key, obj) === breaker) {
5911
- return;
5912
- }
5913
- }
5914
- }
5915
- }
5916
- };
5917
-
5918
- _.extend = function(obj) {
5919
- _.each(slice.call(arguments, 1), function(source) {
5920
- for (var prop in source) {
5921
- if (source[prop] !== void 0) {
5922
- obj[prop] = source[prop];
5923
- }
5924
- }
5925
- });
5926
- return obj;
5927
- };
5928
-
5929
- _.isArray = nativeIsArray || function(obj) {
5930
- return toString.call(obj) === '[object Array]';
5931
- };
5932
-
5933
- // from a comment on http://dbj.org/dbj/?p=286
5934
- // fails on only one very rare and deliberate custom object:
5935
- // var bomb = { toString : undefined, valueOf: function(o) { return "function BOMBA!"; }};
5936
- _.isFunction = function(f) {
5937
- try {
5938
- return /^\s*\bfunction\b/.test(f);
5939
- } catch (x) {
5940
- return false;
5941
- }
5942
- };
5943
-
5944
- _.isArguments = function(obj) {
5945
- return !!(obj && hasOwnProperty$9.call(obj, 'callee'));
5946
- };
5947
-
5948
- _.toArray = function(iterable) {
5949
- if (!iterable) {
5950
- return [];
5951
- }
5952
- if (iterable.toArray) {
5953
- return iterable.toArray();
5954
- }
5955
- if (_.isArray(iterable)) {
5956
- return slice.call(iterable);
5957
- }
5958
- if (_.isArguments(iterable)) {
5959
- return slice.call(iterable);
5960
- }
5961
- return _.values(iterable);
5962
- };
5963
-
5964
- _.map = function(arr, callback, context) {
5965
- if (nativeMap && arr.map === nativeMap) {
5966
- return arr.map(callback, context);
5967
- } else {
5968
- var results = [];
5969
- _.each(arr, function(item) {
5970
- results.push(callback.call(context, item));
5971
- });
5972
- return results;
5973
- }
5974
- };
5975
-
5976
- _.keys = function(obj) {
5977
- var results = [];
5978
- if (obj === null) {
5979
- return results;
5980
- }
5981
- _.each(obj, function(value, key) {
5982
- results[results.length] = key;
5983
- });
5984
- return results;
5985
- };
5986
-
5987
- _.values = function(obj) {
5988
- var results = [];
5989
- if (obj === null) {
5990
- return results;
5991
- }
5992
- _.each(obj, function(value) {
5993
- results[results.length] = value;
5994
- });
5995
- return results;
5996
- };
5997
-
5998
- _.include = function(obj, target) {
5999
- var found = false;
6000
- if (obj === null) {
6001
- return found;
6002
- }
6003
- if (nativeIndexOf && obj.indexOf === nativeIndexOf) {
6004
- return obj.indexOf(target) != -1;
6005
- }
6006
- _.each(obj, function(value) {
6007
- if (found || (found = (value === target))) {
6008
- return breaker;
6009
- }
6010
- });
6011
- return found;
6012
- };
6013
-
6014
- _.includes = function(str, needle) {
6015
- return str.indexOf(needle) !== -1;
6016
- };
6017
-
6018
- // Underscore Addons
6019
- _.inherit = function(subclass, superclass) {
6020
- subclass.prototype = new superclass();
6021
- subclass.prototype.constructor = subclass;
6022
- subclass.superclass = superclass.prototype;
6023
- return subclass;
6024
- };
6025
-
6026
- _.isObject = function(obj) {
6027
- return (obj === Object(obj) && !_.isArray(obj));
6028
- };
6029
-
6030
- _.isEmptyObject = function(obj) {
6031
- if (_.isObject(obj)) {
6032
- for (var key in obj) {
6033
- if (hasOwnProperty$9.call(obj, key)) {
6034
- return false;
6035
- }
6036
- }
6037
- return true;
6038
- }
6039
- return false;
6040
- };
6041
-
6042
- _.isUndefined = function(obj) {
6043
- return obj === void 0;
6044
- };
6045
-
6046
- _.isString = function(obj) {
6047
- return toString.call(obj) == '[object String]';
6048
- };
5873
+ const bachSessionId = `
5874
+ id {
5875
+ sessionId
5876
+ genNo
5877
+ acSession {
5878
+ sessionId
5879
+ genNo
5880
+ }
5881
+ }
5882
+ `;
5883
+ const getUnaggregatedAnswerSession = `
5884
+ mutation GetUnAggregatedAnswerSession($session: BachSessionIdInput!, $columns: [UserPointSelectionInput!]!) {
5885
+ Answer__getUnaggregatedAnswer(session: $session, columns: $columns) {
5886
+ ${bachSessionId}
5887
+ answer {
5888
+ visualizations {
5889
+ ... on TableViz {
5890
+ columns {
5891
+ column {
5892
+ id
5893
+ name
5894
+ referencedColumns {
5895
+ guid
5896
+ displayName
5897
+ }
5898
+ }
5899
+ }
5900
+ }
5901
+ }
5902
+ }
5903
+ }
5904
+ }
5905
+ `;
5906
+ const removeColumns = `
5907
+ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!], $columnIds: [GUID!]) {
5908
+ Answer__removeColumns(
5909
+ session: $session
5910
+ logicalColumnIds: $logicalColumnIds
5911
+ columnIds: $columnIds
5912
+ ) {
5913
+ ${bachSessionId}
5914
+ }
5915
+ }
5916
+ `;
5917
+ const addColumns = `
5918
+ mutation AddColumns($session: BachSessionIdInput!, $columns: [AnswerColumnInfo!]!) {
5919
+ Answer__addColumn(session: $session, columns: $columns) {
5920
+ ${bachSessionId}
5921
+ }
5922
+ }
5923
+ `;
5924
+ const getAnswerData = `
5925
+ query GetTableWithHeadlineData($session: BachSessionIdInput!, $deadline: Int!, $dataPaginationParams: DataPaginationParamsInput!) {
5926
+ getAnswer(session: $session) {
5927
+ ${bachSessionId}
5928
+ answer {
5929
+ id
5930
+ visualizations {
5931
+ id
5932
+ ... on TableViz {
5933
+ columns {
5934
+ column {
5935
+ id
5936
+ name
5937
+ type
5938
+ aggregationType
5939
+ dataType
5940
+ }
5941
+ }
5942
+ data(deadline: $deadline, pagination: $dataPaginationParams)
5943
+ }
5944
+ }
5945
+ }
5946
+ }
5947
+ }
5948
+ `;
6049
5949
 
6050
- _.isDate = function(obj) {
6051
- return toString.call(obj) == '[object Date]';
6052
- };
6053
-
6054
- _.isNumber = function(obj) {
6055
- return toString.call(obj) == '[object Number]';
6056
- };
5950
+ // eslint-disable-next-line no-shadow
5951
+ var OperationType;
5952
+ (function (OperationType) {
5953
+ OperationType["GetChartWithData"] = "GetChartWithData";
5954
+ OperationType["GetTableWithHeadlineData"] = "GetTableWithHeadlineData";
5955
+ })(OperationType || (OperationType = {}));
5956
+ /**
5957
+ * Class representing the answer service provided with the
5958
+ * custom action payload. This service could be used to run
5959
+ * graphql queries in the context of the answer on which the
5960
+ * custom action was triggered.
5961
+ *
5962
+ * @example
5963
+ * ```js
5964
+ * embed.on(EmbedEvent.CustomAction, e => {
5965
+ * const underlying = await e.answerService.getUnderlyingDataForPoint([
5966
+ * 'col name 1'
5967
+ * ]);
5968
+ * const data = await underlying.fetchData(0, 100);
5969
+ * })
5970
+ * ```
5971
+ * @version SDK: 1.25.0| ThoughtSpot: 9.10.0.cl
5972
+ * @group Events
5973
+ */
5974
+ class AnswerService {
5975
+ /**
5976
+ * Should not need to be called directly.
5977
+ *
5978
+ * @param session
5979
+ * @param answer
5980
+ * @param thoughtSpotHost
5981
+ * @param selectedPoints
5982
+ */
5983
+ constructor(session, answer, thoughtSpotHost, selectedPoints) {
5984
+ this.session = session;
5985
+ this.answer = answer;
5986
+ this.thoughtSpotHost = thoughtSpotHost;
5987
+ this.selectedPoints = selectedPoints;
5988
+ this.session = removeTypename(session);
5989
+ }
5990
+ /**
5991
+ * Get the details about the source used in the answer.
5992
+ * This can be used to get the list of all columns in the data source for example.
5993
+ */
5994
+ async getSourceDetail() {
5995
+ const sourceId = this.answer.sources[0].header.guid;
5996
+ return getSourceDetail(this.thoughtSpotHost, sourceId);
5997
+ }
5998
+ /**
5999
+ * Remove columnIds and return updated answer session.
6000
+ *
6001
+ * @param columnIds
6002
+ * @returns
6003
+ */
6004
+ async removeColumns(columnIds) {
6005
+ return this.executeQuery(removeColumns, {
6006
+ logicalColumnIds: columnIds,
6007
+ });
6008
+ }
6009
+ /**
6010
+ * Add columnIds and return updated answer session.
6011
+ *
6012
+ * @param columnIds
6013
+ * @returns
6014
+ */
6015
+ async addColumns(columnIds) {
6016
+ return this.executeQuery(addColumns, {
6017
+ columns: columnIds.map((colId) => ({ logicalColumnId: colId })),
6018
+ });
6019
+ }
6020
+ /**
6021
+ * Fetch data from the answer.
6022
+ *
6023
+ * @param offset
6024
+ * @param size
6025
+ * @returns
6026
+ */
6027
+ async fetchData(offset = 0, size = 1000) {
6028
+ const { answer } = await this.executeQuery(getAnswerData, {
6029
+ deadline: 0,
6030
+ dataPaginationParams: {
6031
+ isClientPaginated: true,
6032
+ offset,
6033
+ size,
6034
+ },
6035
+ });
6036
+ const { columns, data } = answer.visualizations.find((viz) => !!viz.data) || {};
6037
+ return {
6038
+ columns,
6039
+ data,
6040
+ };
6041
+ }
6042
+ /**
6043
+ * Fetch the data for the answer as a CSV blob. This might be
6044
+ * quicker for larger data.
6045
+ *
6046
+ * @param userLocale
6047
+ * @param includeInfo Include the CSV header in the output
6048
+ * @returns Response
6049
+ */
6050
+ async fetchCSVBlob(userLocale = 'en-us', includeInfo = false) {
6051
+ const fetchUrl = this.getFetchCSVBlobUrl(userLocale, includeInfo);
6052
+ return tokenizedFetch(fetchUrl, {
6053
+ credentials: 'include',
6054
+ });
6055
+ }
6056
+ /**
6057
+ * Just get the internal URL for this answer's data
6058
+ * as a CSV blob.
6059
+ *
6060
+ * @param userLocale
6061
+ * @param includeInfo
6062
+ * @returns
6063
+ */
6064
+ getFetchCSVBlobUrl(userLocale = 'en-us', includeInfo = false) {
6065
+ return `${this.thoughtSpotHost}/prism/download/answer/csv?sessionId=${this.session.sessionId}&genNo=${this.session.genNo}&userLocale=${userLocale}&exportFileName=data&hideCsvHeader=${!includeInfo}`;
6066
+ }
6067
+ /**
6068
+ * Get underlying data given a point and the output column names.
6069
+ * In case of a context menu action, the selectedPoints are
6070
+ * automatically passed.
6071
+ *
6072
+ * @param outputColumnNames
6073
+ * @param selectedPoints
6074
+ * @example
6075
+ * ```js
6076
+ * embed.on(EmbedEvent.CustomAction, e => {
6077
+ * const underlying = await e.answerService.getUnderlyingDataForPoint([
6078
+ * 'col name 1' // The column should exist in the data source.
6079
+ * ]);
6080
+ * const data = await underlying.fetchData(0, 100);
6081
+ * })
6082
+ * ```
6083
+ * @version SDK: 1.25.0| ThoughtSpot: 9.10.0.cl
6084
+ */
6085
+ async getUnderlyingDataForPoint(outputColumnNames, selectedPoints) {
6086
+ if (!selectedPoints && !this.selectedPoints) {
6087
+ throw new Error('Needs to be triggered in context of a point');
6088
+ }
6089
+ if (!selectedPoints) {
6090
+ selectedPoints = getSelectedPointsForUnderlyingDataQuery(this.selectedPoints);
6091
+ }
6092
+ const sourceDetail = await this.getSourceDetail();
6093
+ const ouputColumnGuids = getGuidsFromColumnNames(sourceDetail, outputColumnNames);
6094
+ const unAggAnswer = await graphqlQuery({
6095
+ query: getUnaggregatedAnswerSession,
6096
+ variables: {
6097
+ session: this.session,
6098
+ columns: selectedPoints,
6099
+ },
6100
+ thoughtSpotHost: this.thoughtSpotHost,
6101
+ });
6102
+ const unaggAnswerSession = new AnswerService(unAggAnswer.id, unAggAnswer.answer, this.thoughtSpotHost);
6103
+ const currentColumns = new Set(unAggAnswer.answer.visualizations[0].columns
6104
+ .map((c) => c.column.referencedColumns[0].guid));
6105
+ const columnsToAdd = [...ouputColumnGuids].filter((col) => !currentColumns.has(col));
6106
+ if (columnsToAdd.length) {
6107
+ await unaggAnswerSession.addColumns(columnsToAdd);
6108
+ }
6109
+ const columnsToRemove = [...currentColumns].filter((col) => !ouputColumnGuids.has(col));
6110
+ if (columnsToRemove.length) {
6111
+ await unaggAnswerSession.removeColumns(columnsToRemove);
6112
+ }
6113
+ return unaggAnswerSession;
6114
+ }
6115
+ /**
6116
+ * Execute a custom graphql query in the context of the answer.
6117
+ *
6118
+ * @param query graphql query
6119
+ * @param variables graphql variables
6120
+ * @returns
6121
+ */
6122
+ async executeQuery(query, variables) {
6123
+ const data = await graphqlQuery({
6124
+ query,
6125
+ variables: {
6126
+ session: this.session,
6127
+ ...variables,
6128
+ },
6129
+ thoughtSpotHost: this.thoughtSpotHost,
6130
+ isCompositeQuery: false,
6131
+ });
6132
+ this.session = deepMerge(this.session, (data === null || data === void 0 ? void 0 : data.id) || {});
6133
+ return data;
6134
+ }
6135
+ /**
6136
+ * Get the internal session details for the answer.
6137
+ *
6138
+ * @returns
6139
+ */
6140
+ getSession() {
6141
+ return this.session;
6142
+ }
6143
+ }
6144
+ /**
6145
+ *
6146
+ * @param sourceDetail
6147
+ * @param colNames
6148
+ */
6149
+ function getGuidsFromColumnNames(sourceDetail, colNames) {
6150
+ const cols = sourceDetail.columns.reduce((colSet, col) => {
6151
+ colSet[col.name] = col;
6152
+ return colSet;
6153
+ }, {});
6154
+ return new Set(colNames.map((colName) => {
6155
+ const col = cols[colName];
6156
+ return col.id;
6157
+ }));
6158
+ }
6159
+ /**
6160
+ *
6161
+ * @param selectedPoints
6162
+ */
6163
+ function getSelectedPointsForUnderlyingDataQuery(selectedPoints) {
6164
+ const underlyingDataPoint = [];
6165
+ /**
6166
+ *
6167
+ * @param colVal
6168
+ */
6169
+ function addPointFromColVal(colVal) {
6170
+ var _a;
6171
+ const dataType = colVal.column.dataType;
6172
+ const id = colVal.column.id;
6173
+ let dataValue;
6174
+ if (dataType === 'DATE') {
6175
+ if (Number.isFinite(colVal.value)) {
6176
+ dataValue = [{
6177
+ epochRange: {
6178
+ startEpoch: colVal.value,
6179
+ },
6180
+ }];
6181
+ // Case for custom calendar.
6182
+ }
6183
+ else if ((_a = colVal.value) === null || _a === void 0 ? void 0 : _a.v) {
6184
+ dataValue = [{
6185
+ epochRange: {
6186
+ startEpoch: colVal.value.v.s,
6187
+ endEpoch: colVal.value.v.e,
6188
+ },
6189
+ }];
6190
+ }
6191
+ }
6192
+ else {
6193
+ dataValue = [{ value: colVal.value }];
6194
+ }
6195
+ underlyingDataPoint.push({
6196
+ columnId: colVal.column.id,
6197
+ dataValue,
6198
+ });
6199
+ }
6200
+ selectedPoints.forEach((p) => {
6201
+ p.selectedAttributes.forEach(addPointFromColVal);
6202
+ });
6203
+ return underlyingDataPoint;
6204
+ }
6057
6205
 
6058
- _.isElement = function(obj) {
6059
- return !!(obj && obj.nodeType === 1);
6206
+ const ERROR_MESSAGE = {
6207
+ INVALID_THOUGHTSPOT_HOST: 'Error parsing ThoughtSpot host. Please provide a valid URL.',
6208
+ LIVEBOARD_VIZ_ID_VALIDATION: 'Please provide either liveboardId or pinboardId',
6209
+ TRIGGER_TIMED_OUT: 'Trigger timedout in getting response',
6210
+ SEARCHEMBED_BETA_WRANING_MESSAGE: 'Search Embed is in Beta in this release.',
6211
+ SAGE_EMBED_BETA_WARNING_MESSAGE: 'Sage Embed is in Beta in this release.',
6060
6212
  };
6061
6213
 
6062
- _.encodeDates = function(obj) {
6063
- _.each(obj, function(v, k) {
6064
- if (_.isDate(v)) {
6065
- obj[k] = _.formatDate(v);
6066
- } else if (_.isObject(v)) {
6067
- obj[k] = _.encodeDates(v); // recurse
6068
- }
6069
- });
6070
- return obj;
6071
- };
6072
-
6073
- _.timestamp = function() {
6074
- Date.now = Date.now || function() {
6075
- return +new Date;
6076
- };
6077
- return Date.now();
6078
- };
6214
+ /**
6215
+ * Copyright (c) 2023
6216
+ *
6217
+ * Utilities related to reading configuration objects
6218
+ *
6219
+ * @summary Config-related utils
6220
+ * @author Ayon Ghosh <ayon.ghosh@thoughtspot.com>
6221
+ */
6222
+ const urlRegex = new RegExp([
6223
+ '(^(https?:)//)?',
6224
+ '(([^:/?#]*)(?::([0-9]+))?)',
6225
+ '(/{0,1}[^?#]*)',
6226
+ '(\\?[^#]*|)',
6227
+ '(#.*|)$', // hash
6228
+ ].join(''));
6229
+ /**
6230
+ * Parse and construct the ThoughtSpot hostname or IP address
6231
+ * from the embed configuration object.
6232
+ *
6233
+ * @param config
6234
+ */
6235
+ const getThoughtSpotHost = (config) => {
6236
+ if (!config.thoughtSpotHost) {
6237
+ throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
6238
+ }
6239
+ const urlParts = config.thoughtSpotHost.match(urlRegex);
6240
+ if (!urlParts) {
6241
+ throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
6242
+ }
6243
+ const protocol = urlParts[2] || window.location.protocol;
6244
+ const host = urlParts[3];
6245
+ let path = urlParts[6];
6246
+ // Lose the trailing / if any
6247
+ if (path.charAt(path.length - 1) === '/') {
6248
+ path = path.substring(0, path.length - 1);
6249
+ }
6250
+ // const urlParams = urlParts[7];
6251
+ // const hash = urlParts[8];
6252
+ return `${protocol}//${host}${path}`;
6253
+ };
6254
+ const getV2BasePath = (config) => {
6255
+ if (config.basepath) {
6256
+ return config.basepath;
6257
+ }
6258
+ const tsHost = getThoughtSpotHost(config);
6259
+ // This is to handle when e2e's. Search is run on pods for
6260
+ // comp-blink-test-pipeline with baseUrl=https://localhost:8443.
6261
+ // This is to handle when the developer is developing in their local
6262
+ // environment.
6263
+ if (tsHost.includes('://localhost') && !tsHost.includes(':8443')) {
6264
+ return '';
6265
+ }
6266
+ return 'v2';
6267
+ };
6268
+ /**
6269
+ * It is a good idea to keep URLs under 2000 chars.
6270
+ * If this is ever breached, since we pass view configuration through
6271
+ * URL params, we would like to log a warning.
6272
+ * Reference: https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
6273
+ */
6274
+ const URL_MAX_LENGTH = 2000;
6275
+ /**
6276
+ * The default CSS dimensions of the embedded app
6277
+ */
6278
+ const DEFAULT_EMBED_WIDTH = '100%';
6279
+ const DEFAULT_EMBED_HEIGHT = '100%';
6079
6280
 
6080
- _.formatDate = function(d) {
6081
- // YYYY-MM-DDTHH:MM:SS in UTC
6082
- function pad(n) {
6083
- return n < 10 ? '0' + n : n;
6084
- }
6085
- return d.getUTCFullYear() + '-' +
6086
- pad(d.getUTCMonth() + 1) + '-' +
6087
- pad(d.getUTCDate()) + 'T' +
6088
- pad(d.getUTCHours()) + ':' +
6089
- pad(d.getUTCMinutes()) + ':' +
6090
- pad(d.getUTCSeconds());
6281
+ var Config = {
6282
+ DEBUG: false,
6283
+ LIB_VERSION: '2.45.0'
6091
6284
  };
6092
6285
 
6093
- _.strip_empty_properties = function(p) {
6094
- var ret = {};
6095
- _.each(p, function(v, k) {
6096
- if (_.isString(v) && v.length > 0) {
6097
- ret[k] = v;
6098
- }
6099
- });
6100
- return ret;
6101
- };
6286
+ // since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
6287
+ var window$1;
6288
+ if (typeof(window) === 'undefined') {
6289
+ var loc = {
6290
+ hostname: ''
6291
+ };
6292
+ window$1 = {
6293
+ navigator: { userAgent: '' },
6294
+ document: {
6295
+ location: loc,
6296
+ referrer: ''
6297
+ },
6298
+ screen: { width: 0, height: 0 },
6299
+ location: loc
6300
+ };
6301
+ } else {
6302
+ window$1 = window;
6303
+ }
6102
6304
 
6103
6305
  /*
6104
- * this function returns a copy of object after truncating it. If
6105
- * passed an Array or Object it will iterate through obj and
6106
- * truncate all the values recursively.
6306
+ * Saved references to long variable names, so that closure compiler can
6307
+ * minimize file size.
6107
6308
  */
6108
- _.truncate = function(obj, length) {
6109
- var ret;
6110
6309
 
6111
- if (typeof(obj) === 'string') {
6112
- ret = obj.slice(0, length);
6113
- } else if (_.isArray(obj)) {
6114
- ret = [];
6115
- _.each(obj, function(val) {
6116
- ret.push(_.truncate(val, length));
6117
- });
6118
- } else if (_.isObject(obj)) {
6119
- ret = {};
6120
- _.each(obj, function(val, key) {
6121
- ret[key] = _.truncate(val, length);
6122
- });
6123
- } else {
6124
- ret = obj;
6310
+ var ArrayProto = Array.prototype;
6311
+ var FuncProto = Function.prototype;
6312
+ var ObjProto = Object.prototype;
6313
+ var slice = ArrayProto.slice;
6314
+ var toString = ObjProto.toString;
6315
+ var hasOwnProperty$9 = ObjProto.hasOwnProperty;
6316
+ var windowConsole = window$1.console;
6317
+ var navigator = window$1.navigator;
6318
+ var document$1 = window$1.document;
6319
+ var windowOpera = window$1.opera;
6320
+ var screen = window$1.screen;
6321
+ var userAgent = navigator.userAgent;
6322
+ var nativeBind = FuncProto.bind;
6323
+ var nativeForEach = ArrayProto.forEach;
6324
+ var nativeIndexOf = ArrayProto.indexOf;
6325
+ var nativeMap = ArrayProto.map;
6326
+ var nativeIsArray = Array.isArray;
6327
+ var breaker = {};
6328
+ var _ = {
6329
+ trim: function(str) {
6330
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim#Polyfill
6331
+ return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
6125
6332
  }
6333
+ };
6126
6334
 
6127
- return ret;
6335
+ // Console override
6336
+ var console$1 = {
6337
+ /** @type {function(...*)} */
6338
+ log: function() {
6339
+ if (Config.DEBUG && !_.isUndefined(windowConsole) && windowConsole) {
6340
+ try {
6341
+ windowConsole.log.apply(windowConsole, arguments);
6342
+ } catch (err) {
6343
+ _.each(arguments, function(arg) {
6344
+ windowConsole.log(arg);
6345
+ });
6346
+ }
6347
+ }
6348
+ },
6349
+ /** @type {function(...*)} */
6350
+ warn: function() {
6351
+ if (Config.DEBUG && !_.isUndefined(windowConsole) && windowConsole) {
6352
+ var args = ['Mixpanel warning:'].concat(_.toArray(arguments));
6353
+ try {
6354
+ windowConsole.warn.apply(windowConsole, args);
6355
+ } catch (err) {
6356
+ _.each(args, function(arg) {
6357
+ windowConsole.warn(arg);
6358
+ });
6359
+ }
6360
+ }
6361
+ },
6362
+ /** @type {function(...*)} */
6363
+ error: function() {
6364
+ if (Config.DEBUG && !_.isUndefined(windowConsole) && windowConsole) {
6365
+ var args = ['Mixpanel error:'].concat(_.toArray(arguments));
6366
+ try {
6367
+ windowConsole.error.apply(windowConsole, args);
6368
+ } catch (err) {
6369
+ _.each(args, function(arg) {
6370
+ windowConsole.error(arg);
6371
+ });
6372
+ }
6373
+ }
6374
+ },
6375
+ /** @type {function(...*)} */
6376
+ critical: function() {
6377
+ if (!_.isUndefined(windowConsole) && windowConsole) {
6378
+ var args = ['Mixpanel error:'].concat(_.toArray(arguments));
6379
+ try {
6380
+ windowConsole.error.apply(windowConsole, args);
6381
+ } catch (err) {
6382
+ _.each(args, function(arg) {
6383
+ windowConsole.error(arg);
6384
+ });
6385
+ }
6386
+ }
6387
+ }
6128
6388
  };
6129
6389
 
6130
- _.JSONEncode = (function() {
6131
- return function(mixed_val) {
6132
- var value = mixed_val;
6133
- var quote = function(string) {
6134
- var escapable = /[\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; // eslint-disable-line no-control-regex
6135
- var meta = { // table of character substitutions
6136
- '\b': '\\b',
6137
- '\t': '\\t',
6138
- '\n': '\\n',
6139
- '\f': '\\f',
6140
- '\r': '\\r',
6141
- '"': '\\"',
6142
- '\\': '\\\\'
6143
- };
6390
+ var log_func_with_prefix = function(func, prefix) {
6391
+ return function() {
6392
+ arguments[0] = '[' + prefix + '] ' + arguments[0];
6393
+ return func.apply(console$1, arguments);
6394
+ };
6395
+ };
6396
+ var console_with_prefix = function(prefix) {
6397
+ return {
6398
+ log: log_func_with_prefix(console$1.log, prefix),
6399
+ error: log_func_with_prefix(console$1.error, prefix),
6400
+ critical: log_func_with_prefix(console$1.critical, prefix)
6401
+ };
6402
+ };
6144
6403
 
6145
- escapable.lastIndex = 0;
6146
- return escapable.test(string) ?
6147
- '"' + string.replace(escapable, function(a) {
6148
- var c = meta[a];
6149
- return typeof c === 'string' ? c :
6150
- '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
6151
- }) + '"' :
6152
- '"' + string + '"';
6153
- };
6154
6404
 
6155
- var str = function(key, holder) {
6156
- var gap = '';
6157
- var indent = ' ';
6158
- var i = 0; // The loop counter.
6159
- var k = ''; // The member key.
6160
- var v = ''; // The member value.
6161
- var length = 0;
6162
- var mind = gap;
6163
- var partial = [];
6164
- var value = holder[key];
6405
+ // UNDERSCORE
6406
+ // Embed part of the Underscore Library
6407
+ _.bind = function(func, context) {
6408
+ var args, bound;
6409
+ if (nativeBind && func.bind === nativeBind) {
6410
+ return nativeBind.apply(func, slice.call(arguments, 1));
6411
+ }
6412
+ if (!_.isFunction(func)) {
6413
+ throw new TypeError();
6414
+ }
6415
+ args = slice.call(arguments, 2);
6416
+ bound = function() {
6417
+ if (!(this instanceof bound)) {
6418
+ return func.apply(context, args.concat(slice.call(arguments)));
6419
+ }
6420
+ var ctor = {};
6421
+ ctor.prototype = func.prototype;
6422
+ var self = new ctor();
6423
+ ctor.prototype = null;
6424
+ var result = func.apply(self, args.concat(slice.call(arguments)));
6425
+ if (Object(result) === result) {
6426
+ return result;
6427
+ }
6428
+ return self;
6429
+ };
6430
+ return bound;
6431
+ };
6165
6432
 
6166
- // If the value has a toJSON method, call it to obtain a replacement value.
6167
- if (value && typeof value === 'object' &&
6168
- typeof value.toJSON === 'function') {
6169
- value = value.toJSON(key);
6433
+ /**
6434
+ * @param {*=} obj
6435
+ * @param {function(...*)=} iterator
6436
+ * @param {Object=} context
6437
+ */
6438
+ _.each = function(obj, iterator, context) {
6439
+ if (obj === null || obj === undefined) {
6440
+ return;
6441
+ }
6442
+ if (nativeForEach && obj.forEach === nativeForEach) {
6443
+ obj.forEach(iterator, context);
6444
+ } else if (obj.length === +obj.length) {
6445
+ for (var i = 0, l = obj.length; i < l; i++) {
6446
+ if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) {
6447
+ return;
6170
6448
  }
6449
+ }
6450
+ } else {
6451
+ for (var key in obj) {
6452
+ if (hasOwnProperty$9.call(obj, key)) {
6453
+ if (iterator.call(context, obj[key], key, obj) === breaker) {
6454
+ return;
6455
+ }
6456
+ }
6457
+ }
6458
+ }
6459
+ };
6171
6460
 
6172
- // What happens next depends on the value's type.
6173
- switch (typeof value) {
6174
- case 'string':
6175
- return quote(value);
6461
+ _.extend = function(obj) {
6462
+ _.each(slice.call(arguments, 1), function(source) {
6463
+ for (var prop in source) {
6464
+ if (source[prop] !== void 0) {
6465
+ obj[prop] = source[prop];
6466
+ }
6467
+ }
6468
+ });
6469
+ return obj;
6470
+ };
6176
6471
 
6177
- case 'number':
6178
- // JSON numbers must be finite. Encode non-finite numbers as null.
6179
- return isFinite(value) ? String(value) : 'null';
6472
+ _.isArray = nativeIsArray || function(obj) {
6473
+ return toString.call(obj) === '[object Array]';
6474
+ };
6180
6475
 
6181
- case 'boolean':
6182
- case 'null':
6183
- // If the value is a boolean or null, convert it to a string. Note:
6184
- // typeof null does not produce 'null'. The case is included here in
6185
- // the remote chance that this gets fixed someday.
6476
+ // from a comment on http://dbj.org/dbj/?p=286
6477
+ // fails on only one very rare and deliberate custom object:
6478
+ // var bomb = { toString : undefined, valueOf: function(o) { return "function BOMBA!"; }};
6479
+ _.isFunction = function(f) {
6480
+ try {
6481
+ return /^\s*\bfunction\b/.test(f);
6482
+ } catch (x) {
6483
+ return false;
6484
+ }
6485
+ };
6186
6486
 
6187
- return String(value);
6487
+ _.isArguments = function(obj) {
6488
+ return !!(obj && hasOwnProperty$9.call(obj, 'callee'));
6489
+ };
6188
6490
 
6189
- case 'object':
6190
- // If the type is 'object', we might be dealing with an object or an array or
6191
- // null.
6192
- // Due to a specification blunder in ECMAScript, typeof null is 'object',
6193
- // so watch out for that case.
6194
- if (!value) {
6195
- return 'null';
6196
- }
6491
+ _.toArray = function(iterable) {
6492
+ if (!iterable) {
6493
+ return [];
6494
+ }
6495
+ if (iterable.toArray) {
6496
+ return iterable.toArray();
6497
+ }
6498
+ if (_.isArray(iterable)) {
6499
+ return slice.call(iterable);
6500
+ }
6501
+ if (_.isArguments(iterable)) {
6502
+ return slice.call(iterable);
6503
+ }
6504
+ return _.values(iterable);
6505
+ };
6197
6506
 
6198
- // Make an array to hold the partial results of stringifying this object value.
6199
- gap += indent;
6200
- partial = [];
6507
+ _.map = function(arr, callback, context) {
6508
+ if (nativeMap && arr.map === nativeMap) {
6509
+ return arr.map(callback, context);
6510
+ } else {
6511
+ var results = [];
6512
+ _.each(arr, function(item) {
6513
+ results.push(callback.call(context, item));
6514
+ });
6515
+ return results;
6516
+ }
6517
+ };
6201
6518
 
6202
- // Is the value an array?
6203
- if (toString.apply(value) === '[object Array]') {
6204
- // The value is an array. Stringify every element. Use null as a placeholder
6205
- // for non-JSON values.
6519
+ _.keys = function(obj) {
6520
+ var results = [];
6521
+ if (obj === null) {
6522
+ return results;
6523
+ }
6524
+ _.each(obj, function(value, key) {
6525
+ results[results.length] = key;
6526
+ });
6527
+ return results;
6528
+ };
6206
6529
 
6207
- length = value.length;
6208
- for (i = 0; i < length; i += 1) {
6209
- partial[i] = str(i, value) || 'null';
6210
- }
6530
+ _.values = function(obj) {
6531
+ var results = [];
6532
+ if (obj === null) {
6533
+ return results;
6534
+ }
6535
+ _.each(obj, function(value) {
6536
+ results[results.length] = value;
6537
+ });
6538
+ return results;
6539
+ };
6211
6540
 
6212
- // Join all of the elements together, separated with commas, and wrap them in
6213
- // brackets.
6214
- v = partial.length === 0 ? '[]' :
6215
- gap ? '[\n' + gap +
6216
- partial.join(',\n' + gap) + '\n' +
6217
- mind + ']' :
6218
- '[' + partial.join(',') + ']';
6219
- gap = mind;
6220
- return v;
6221
- }
6541
+ _.include = function(obj, target) {
6542
+ var found = false;
6543
+ if (obj === null) {
6544
+ return found;
6545
+ }
6546
+ if (nativeIndexOf && obj.indexOf === nativeIndexOf) {
6547
+ return obj.indexOf(target) != -1;
6548
+ }
6549
+ _.each(obj, function(value) {
6550
+ if (found || (found = (value === target))) {
6551
+ return breaker;
6552
+ }
6553
+ });
6554
+ return found;
6555
+ };
6222
6556
 
6223
- // Iterate through all of the keys in the object.
6224
- for (k in value) {
6225
- if (hasOwnProperty$9.call(value, k)) {
6226
- v = str(k, value);
6227
- if (v) {
6228
- partial.push(quote(k) + (gap ? ': ' : ':') + v);
6229
- }
6230
- }
6231
- }
6557
+ _.includes = function(str, needle) {
6558
+ return str.indexOf(needle) !== -1;
6559
+ };
6232
6560
 
6233
- // Join all of the member texts together, separated with commas,
6234
- // and wrap them in braces.
6235
- v = partial.length === 0 ? '{}' :
6236
- gap ? '{' + partial.join(',') + '' +
6237
- mind + '}' : '{' + partial.join(',') + '}';
6238
- gap = mind;
6239
- return v;
6561
+ // Underscore Addons
6562
+ _.inherit = function(subclass, superclass) {
6563
+ subclass.prototype = new superclass();
6564
+ subclass.prototype.constructor = subclass;
6565
+ subclass.superclass = superclass.prototype;
6566
+ return subclass;
6567
+ };
6568
+
6569
+ _.isObject = function(obj) {
6570
+ return (obj === Object(obj) && !_.isArray(obj));
6571
+ };
6572
+
6573
+ _.isEmptyObject = function(obj) {
6574
+ if (_.isObject(obj)) {
6575
+ for (var key in obj) {
6576
+ if (hasOwnProperty$9.call(obj, key)) {
6577
+ return false;
6240
6578
  }
6241
- };
6579
+ }
6580
+ return true;
6581
+ }
6582
+ return false;
6583
+ };
6242
6584
 
6243
- // Make a fake root object containing our value under the key of ''.
6244
- // Return the result of stringifying the value.
6245
- return str('', {
6246
- '': value
6247
- });
6248
- };
6249
- })();
6585
+ _.isUndefined = function(obj) {
6586
+ return obj === void 0;
6587
+ };
6250
6588
 
6251
- /**
6252
- * From https://github.com/douglascrockford/JSON-js/blob/master/json_parse.js
6253
- * Slightly modified to throw a real Error rather than a POJO
6254
- */
6255
- _.JSONDecode = (function() {
6256
- var at, // The index of the current character
6257
- ch, // The current character
6258
- escapee = {
6259
- '"': '"',
6260
- '\\': '\\',
6261
- '/': '/',
6262
- 'b': '\b',
6263
- 'f': '\f',
6264
- 'n': '\n',
6265
- 'r': '\r',
6266
- 't': '\t'
6589
+ _.isString = function(obj) {
6590
+ return toString.call(obj) == '[object String]';
6591
+ };
6592
+
6593
+ _.isDate = function(obj) {
6594
+ return toString.call(obj) == '[object Date]';
6595
+ };
6596
+
6597
+ _.isNumber = function(obj) {
6598
+ return toString.call(obj) == '[object Number]';
6599
+ };
6600
+
6601
+ _.isElement = function(obj) {
6602
+ return !!(obj && obj.nodeType === 1);
6603
+ };
6604
+
6605
+ _.encodeDates = function(obj) {
6606
+ _.each(obj, function(v, k) {
6607
+ if (_.isDate(v)) {
6608
+ obj[k] = _.formatDate(v);
6609
+ } else if (_.isObject(v)) {
6610
+ obj[k] = _.encodeDates(v); // recurse
6611
+ }
6612
+ });
6613
+ return obj;
6614
+ };
6615
+
6616
+ _.timestamp = function() {
6617
+ Date.now = Date.now || function() {
6618
+ return +new Date;
6619
+ };
6620
+ return Date.now();
6621
+ };
6622
+
6623
+ _.formatDate = function(d) {
6624
+ // YYYY-MM-DDTHH:MM:SS in UTC
6625
+ function pad(n) {
6626
+ return n < 10 ? '0' + n : n;
6627
+ }
6628
+ return d.getUTCFullYear() + '-' +
6629
+ pad(d.getUTCMonth() + 1) + '-' +
6630
+ pad(d.getUTCDate()) + 'T' +
6631
+ pad(d.getUTCHours()) + ':' +
6632
+ pad(d.getUTCMinutes()) + ':' +
6633
+ pad(d.getUTCSeconds());
6634
+ };
6635
+
6636
+ _.strip_empty_properties = function(p) {
6637
+ var ret = {};
6638
+ _.each(p, function(v, k) {
6639
+ if (_.isString(v) && v.length > 0) {
6640
+ ret[k] = v;
6641
+ }
6642
+ });
6643
+ return ret;
6644
+ };
6645
+
6646
+ /*
6647
+ * this function returns a copy of object after truncating it. If
6648
+ * passed an Array or Object it will iterate through obj and
6649
+ * truncate all the values recursively.
6650
+ */
6651
+ _.truncate = function(obj, length) {
6652
+ var ret;
6653
+
6654
+ if (typeof(obj) === 'string') {
6655
+ ret = obj.slice(0, length);
6656
+ } else if (_.isArray(obj)) {
6657
+ ret = [];
6658
+ _.each(obj, function(val) {
6659
+ ret.push(_.truncate(val, length));
6660
+ });
6661
+ } else if (_.isObject(obj)) {
6662
+ ret = {};
6663
+ _.each(obj, function(val, key) {
6664
+ ret[key] = _.truncate(val, length);
6665
+ });
6666
+ } else {
6667
+ ret = obj;
6668
+ }
6669
+
6670
+ return ret;
6671
+ };
6672
+
6673
+ _.JSONEncode = (function() {
6674
+ return function(mixed_val) {
6675
+ var value = mixed_val;
6676
+ var quote = function(string) {
6677
+ var escapable = /[\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; // eslint-disable-line no-control-regex
6678
+ var meta = { // table of character substitutions
6679
+ '\b': '\\b',
6680
+ '\t': '\\t',
6681
+ '\n': '\\n',
6682
+ '\f': '\\f',
6683
+ '\r': '\\r',
6684
+ '"': '\\"',
6685
+ '\\': '\\\\'
6686
+ };
6687
+
6688
+ escapable.lastIndex = 0;
6689
+ return escapable.test(string) ?
6690
+ '"' + string.replace(escapable, function(a) {
6691
+ var c = meta[a];
6692
+ return typeof c === 'string' ? c :
6693
+ '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
6694
+ }) + '"' :
6695
+ '"' + string + '"';
6696
+ };
6697
+
6698
+ var str = function(key, holder) {
6699
+ var gap = '';
6700
+ var indent = ' ';
6701
+ var i = 0; // The loop counter.
6702
+ var k = ''; // The member key.
6703
+ var v = ''; // The member value.
6704
+ var length = 0;
6705
+ var mind = gap;
6706
+ var partial = [];
6707
+ var value = holder[key];
6708
+
6709
+ // If the value has a toJSON method, call it to obtain a replacement value.
6710
+ if (value && typeof value === 'object' &&
6711
+ typeof value.toJSON === 'function') {
6712
+ value = value.toJSON(key);
6713
+ }
6714
+
6715
+ // What happens next depends on the value's type.
6716
+ switch (typeof value) {
6717
+ case 'string':
6718
+ return quote(value);
6719
+
6720
+ case 'number':
6721
+ // JSON numbers must be finite. Encode non-finite numbers as null.
6722
+ return isFinite(value) ? String(value) : 'null';
6723
+
6724
+ case 'boolean':
6725
+ case 'null':
6726
+ // If the value is a boolean or null, convert it to a string. Note:
6727
+ // typeof null does not produce 'null'. The case is included here in
6728
+ // the remote chance that this gets fixed someday.
6729
+
6730
+ return String(value);
6731
+
6732
+ case 'object':
6733
+ // If the type is 'object', we might be dealing with an object or an array or
6734
+ // null.
6735
+ // Due to a specification blunder in ECMAScript, typeof null is 'object',
6736
+ // so watch out for that case.
6737
+ if (!value) {
6738
+ return 'null';
6739
+ }
6740
+
6741
+ // Make an array to hold the partial results of stringifying this object value.
6742
+ gap += indent;
6743
+ partial = [];
6744
+
6745
+ // Is the value an array?
6746
+ if (toString.apply(value) === '[object Array]') {
6747
+ // The value is an array. Stringify every element. Use null as a placeholder
6748
+ // for non-JSON values.
6749
+
6750
+ length = value.length;
6751
+ for (i = 0; i < length; i += 1) {
6752
+ partial[i] = str(i, value) || 'null';
6753
+ }
6754
+
6755
+ // Join all of the elements together, separated with commas, and wrap them in
6756
+ // brackets.
6757
+ v = partial.length === 0 ? '[]' :
6758
+ gap ? '[\n' + gap +
6759
+ partial.join(',\n' + gap) + '\n' +
6760
+ mind + ']' :
6761
+ '[' + partial.join(',') + ']';
6762
+ gap = mind;
6763
+ return v;
6764
+ }
6765
+
6766
+ // Iterate through all of the keys in the object.
6767
+ for (k in value) {
6768
+ if (hasOwnProperty$9.call(value, k)) {
6769
+ v = str(k, value);
6770
+ if (v) {
6771
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
6772
+ }
6773
+ }
6774
+ }
6775
+
6776
+ // Join all of the member texts together, separated with commas,
6777
+ // and wrap them in braces.
6778
+ v = partial.length === 0 ? '{}' :
6779
+ gap ? '{' + partial.join(',') + '' +
6780
+ mind + '}' : '{' + partial.join(',') + '}';
6781
+ gap = mind;
6782
+ return v;
6783
+ }
6784
+ };
6785
+
6786
+ // Make a fake root object containing our value under the key of ''.
6787
+ // Return the result of stringifying the value.
6788
+ return str('', {
6789
+ '': value
6790
+ });
6791
+ };
6792
+ })();
6793
+
6794
+ /**
6795
+ * From https://github.com/douglascrockford/JSON-js/blob/master/json_parse.js
6796
+ * Slightly modified to throw a real Error rather than a POJO
6797
+ */
6798
+ _.JSONDecode = (function() {
6799
+ var at, // The index of the current character
6800
+ ch, // The current character
6801
+ escapee = {
6802
+ '"': '"',
6803
+ '\\': '\\',
6804
+ '/': '/',
6805
+ 'b': '\b',
6806
+ 'f': '\f',
6807
+ 'n': '\n',
6808
+ 'r': '\r',
6809
+ 't': '\t'
6267
6810
  },
6268
6811
  text,
6269
6812
  error = function(m) {
@@ -11299,1405 +11842,497 @@
11299
11842
 
11300
11843
  // perform some housekeeping around GDPR opt-in/out state
11301
11844
  MixpanelLib.prototype._gdpr_init = function() {
11302
- var is_localStorage_requested = this.get_config('opt_out_tracking_persistence_type') === 'localStorage';
11303
-
11304
- // try to convert opt-in/out cookies to localStorage if possible
11305
- if (is_localStorage_requested && _.localStorage.is_supported()) {
11306
- if (!this.has_opted_in_tracking() && this.has_opted_in_tracking({'persistence_type': 'cookie'})) {
11307
- this.opt_in_tracking({'enable_persistence': false});
11308
- }
11309
- if (!this.has_opted_out_tracking() && this.has_opted_out_tracking({'persistence_type': 'cookie'})) {
11310
- this.opt_out_tracking({'clear_persistence': false});
11311
- }
11312
- this.clear_opt_in_out_tracking({
11313
- 'persistence_type': 'cookie',
11314
- 'enable_persistence': false
11315
- });
11316
- }
11317
-
11318
- // check whether the user has already opted out - if so, clear & disable persistence
11319
- if (this.has_opted_out_tracking()) {
11320
- this._gdpr_update_persistence({'clear_persistence': true});
11321
-
11322
- // check whether we should opt out by default
11323
- // note: we don't clear persistence here by default since opt-out default state is often
11324
- // used as an initial state while GDPR information is being collected
11325
- } else if (!this.has_opted_in_tracking() && (
11326
- this.get_config('opt_out_tracking_by_default') || _.cookie.get('mp_optout')
11327
- )) {
11328
- _.cookie.remove('mp_optout');
11329
- this.opt_out_tracking({
11330
- 'clear_persistence': this.get_config('opt_out_persistence_by_default')
11331
- });
11332
- }
11333
- };
11334
-
11335
- /**
11336
- * Enable or disable persistence based on options
11337
- * only enable/disable if persistence is not already in this state
11338
- * @param {boolean} [options.clear_persistence] If true, will delete all data stored by the sdk in persistence and disable it
11339
- * @param {boolean} [options.enable_persistence] If true, will re-enable sdk persistence
11340
- */
11341
- MixpanelLib.prototype._gdpr_update_persistence = function(options) {
11342
- var disabled;
11343
- if (options && options['clear_persistence']) {
11344
- disabled = true;
11345
- } else if (options && options['enable_persistence']) {
11346
- disabled = false;
11347
- } else {
11348
- return;
11349
- }
11350
-
11351
- if (!this.get_config('disable_persistence') && this['persistence'].disabled !== disabled) {
11352
- this['persistence'].set_disabled(disabled);
11353
- }
11354
-
11355
- if (disabled) {
11356
- _.each(this.request_batchers, function(batcher) {
11357
- batcher.clear();
11358
- });
11359
- }
11360
- };
11361
-
11362
- // call a base gdpr function after constructing the appropriate token and options args
11363
- MixpanelLib.prototype._gdpr_call_func = function(func, options) {
11364
- options = _.extend({
11365
- 'track': _.bind(this.track, this),
11366
- 'persistence_type': this.get_config('opt_out_tracking_persistence_type'),
11367
- 'cookie_prefix': this.get_config('opt_out_tracking_cookie_prefix'),
11368
- 'cookie_expiration': this.get_config('cookie_expiration'),
11369
- 'cross_site_cookie': this.get_config('cross_site_cookie'),
11370
- 'cross_subdomain_cookie': this.get_config('cross_subdomain_cookie'),
11371
- 'cookie_domain': this.get_config('cookie_domain'),
11372
- 'secure_cookie': this.get_config('secure_cookie'),
11373
- 'ignore_dnt': this.get_config('ignore_dnt')
11374
- }, options);
11375
-
11376
- // check if localStorage can be used for recording opt out status, fall back to cookie if not
11377
- if (!_.localStorage.is_supported()) {
11378
- options['persistence_type'] = 'cookie';
11379
- }
11380
-
11381
- return func(this.get_config('token'), {
11382
- track: options['track'],
11383
- trackEventName: options['track_event_name'],
11384
- trackProperties: options['track_properties'],
11385
- persistenceType: options['persistence_type'],
11386
- persistencePrefix: options['cookie_prefix'],
11387
- cookieDomain: options['cookie_domain'],
11388
- cookieExpiration: options['cookie_expiration'],
11389
- crossSiteCookie: options['cross_site_cookie'],
11390
- crossSubdomainCookie: options['cross_subdomain_cookie'],
11391
- secureCookie: options['secure_cookie'],
11392
- ignoreDnt: options['ignore_dnt']
11393
- });
11394
- };
11395
-
11396
- /**
11397
- * Opt the user in to data tracking and cookies/localstorage for this Mixpanel instance
11398
- *
11399
- * ### Usage
11400
- *
11401
- * // opt user in
11402
- * mixpanel.opt_in_tracking();
11403
- *
11404
- * // opt user in with specific event name, properties, cookie configuration
11405
- * mixpanel.opt_in_tracking({
11406
- * track_event_name: 'User opted in',
11407
- * track_event_properties: {
11408
- * 'Email': 'jdoe@example.com'
11409
- * },
11410
- * cookie_expiration: 30,
11411
- * secure_cookie: true
11412
- * });
11413
- *
11414
- * @param {Object} [options] A dictionary of config options to override
11415
- * @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)
11416
- * @param {string} [options.track_event_name=$opt_in] Event name to be used for tracking the opt-in action
11417
- * @param {Object} [options.track_properties] Set of properties to be tracked along with the opt-in action
11418
- * @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence
11419
- * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11420
- * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11421
- * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
11422
- * @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
11423
- * @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)
11424
- * @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)
11425
- * @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)
11426
- */
11427
- MixpanelLib.prototype.opt_in_tracking = function(options) {
11428
- options = _.extend({
11429
- 'enable_persistence': true
11430
- }, options);
11431
-
11432
- this._gdpr_call_func(optIn, options);
11433
- this._gdpr_update_persistence(options);
11434
- };
11435
-
11436
- /**
11437
- * Opt the user out of data tracking and cookies/localstorage for this Mixpanel instance
11438
- *
11439
- * ### Usage
11440
- *
11441
- * // opt user out
11442
- * mixpanel.opt_out_tracking();
11443
- *
11444
- * // opt user out with different cookie configuration from Mixpanel instance
11445
- * mixpanel.opt_out_tracking({
11446
- * cookie_expiration: 30,
11447
- * secure_cookie: true
11448
- * });
11449
- *
11450
- * @param {Object} [options] A dictionary of config options to override
11451
- * @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
11452
- * @param {boolean} [options.clear_persistence=true] If true, will delete all data stored by the sdk in persistence
11453
- * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11454
- * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11455
- * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
11456
- * @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
11457
- * @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)
11458
- * @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)
11459
- * @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)
11460
- */
11461
- MixpanelLib.prototype.opt_out_tracking = function(options) {
11462
- options = _.extend({
11463
- 'clear_persistence': true,
11464
- 'delete_user': true
11465
- }, options);
11466
-
11467
- // delete user and clear charges since these methods may be disabled by opt-out
11468
- if (options['delete_user'] && this['people'] && this['people']._identify_called()) {
11469
- this['people'].delete_user();
11470
- this['people'].clear_charges();
11471
- }
11472
-
11473
- this._gdpr_call_func(optOut, options);
11474
- this._gdpr_update_persistence(options);
11475
- };
11476
-
11477
- /**
11478
- * Check whether the user has opted in to data tracking and cookies/localstorage for this Mixpanel instance
11479
- *
11480
- * ### Usage
11481
- *
11482
- * var has_opted_in = mixpanel.has_opted_in_tracking();
11483
- * // use has_opted_in value
11484
- *
11485
- * @param {Object} [options] A dictionary of config options to override
11486
- * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11487
- * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11488
- * @returns {boolean} current opt-in status
11489
- */
11490
- MixpanelLib.prototype.has_opted_in_tracking = function(options) {
11491
- return this._gdpr_call_func(hasOptedIn, options);
11492
- };
11493
-
11494
- /**
11495
- * Check whether the user has opted out of data tracking and cookies/localstorage for this Mixpanel instance
11496
- *
11497
- * ### Usage
11498
- *
11499
- * var has_opted_out = mixpanel.has_opted_out_tracking();
11500
- * // use has_opted_out value
11501
- *
11502
- * @param {Object} [options] A dictionary of config options to override
11503
- * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11504
- * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11505
- * @returns {boolean} current opt-out status
11506
- */
11507
- MixpanelLib.prototype.has_opted_out_tracking = function(options) {
11508
- return this._gdpr_call_func(hasOptedOut, options);
11509
- };
11510
-
11511
- /**
11512
- * Clear the user's opt in/out status of data tracking and cookies/localstorage for this Mixpanel instance
11513
- *
11514
- * ### Usage
11515
- *
11516
- * // clear user's opt-in/out status
11517
- * mixpanel.clear_opt_in_out_tracking();
11518
- *
11519
- * // clear user's opt-in/out status with specific cookie configuration - should match
11520
- * // configuration used when opt_in_tracking/opt_out_tracking methods were called.
11521
- * mixpanel.clear_opt_in_out_tracking({
11522
- * cookie_expiration: 30,
11523
- * secure_cookie: true
11524
- * });
11525
- *
11526
- * @param {Object} [options] A dictionary of config options to override
11527
- * @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence
11528
- * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11529
- * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11530
- * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
11531
- * @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
11532
- * @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)
11533
- * @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)
11534
- * @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)
11535
- */
11536
- MixpanelLib.prototype.clear_opt_in_out_tracking = function(options) {
11537
- options = _.extend({
11538
- 'enable_persistence': true
11539
- }, options);
11540
-
11541
- this._gdpr_call_func(clearOptInOut, options);
11542
- this._gdpr_update_persistence(options);
11543
- };
11544
-
11545
- MixpanelLib.prototype.report_error = function(msg, err) {
11546
- console$1.error.apply(console$1.error, arguments);
11547
- try {
11548
- if (!err && !(msg instanceof Error)) {
11549
- msg = new Error(msg);
11550
- }
11551
- this.get_config('error_reporter')(msg, err);
11552
- } catch(err) {
11553
- console$1.error(err);
11554
- }
11555
- };
11556
-
11557
- // EXPORTS (for closure compiler)
11558
-
11559
- // MixpanelLib Exports
11560
- MixpanelLib.prototype['init'] = MixpanelLib.prototype.init;
11561
- MixpanelLib.prototype['reset'] = MixpanelLib.prototype.reset;
11562
- MixpanelLib.prototype['disable'] = MixpanelLib.prototype.disable;
11563
- MixpanelLib.prototype['time_event'] = MixpanelLib.prototype.time_event;
11564
- MixpanelLib.prototype['track'] = MixpanelLib.prototype.track;
11565
- MixpanelLib.prototype['track_links'] = MixpanelLib.prototype.track_links;
11566
- MixpanelLib.prototype['track_forms'] = MixpanelLib.prototype.track_forms;
11567
- MixpanelLib.prototype['track_pageview'] = MixpanelLib.prototype.track_pageview;
11568
- MixpanelLib.prototype['register'] = MixpanelLib.prototype.register;
11569
- MixpanelLib.prototype['register_once'] = MixpanelLib.prototype.register_once;
11570
- MixpanelLib.prototype['unregister'] = MixpanelLib.prototype.unregister;
11571
- MixpanelLib.prototype['identify'] = MixpanelLib.prototype.identify;
11572
- MixpanelLib.prototype['alias'] = MixpanelLib.prototype.alias;
11573
- MixpanelLib.prototype['name_tag'] = MixpanelLib.prototype.name_tag;
11574
- MixpanelLib.prototype['set_config'] = MixpanelLib.prototype.set_config;
11575
- MixpanelLib.prototype['get_config'] = MixpanelLib.prototype.get_config;
11576
- MixpanelLib.prototype['get_property'] = MixpanelLib.prototype.get_property;
11577
- MixpanelLib.prototype['get_distinct_id'] = MixpanelLib.prototype.get_distinct_id;
11578
- MixpanelLib.prototype['toString'] = MixpanelLib.prototype.toString;
11579
- MixpanelLib.prototype['opt_out_tracking'] = MixpanelLib.prototype.opt_out_tracking;
11580
- MixpanelLib.prototype['opt_in_tracking'] = MixpanelLib.prototype.opt_in_tracking;
11581
- MixpanelLib.prototype['has_opted_out_tracking'] = MixpanelLib.prototype.has_opted_out_tracking;
11582
- MixpanelLib.prototype['has_opted_in_tracking'] = MixpanelLib.prototype.has_opted_in_tracking;
11583
- MixpanelLib.prototype['clear_opt_in_out_tracking'] = MixpanelLib.prototype.clear_opt_in_out_tracking;
11584
- MixpanelLib.prototype['get_group'] = MixpanelLib.prototype.get_group;
11585
- MixpanelLib.prototype['set_group'] = MixpanelLib.prototype.set_group;
11586
- MixpanelLib.prototype['add_group'] = MixpanelLib.prototype.add_group;
11587
- MixpanelLib.prototype['remove_group'] = MixpanelLib.prototype.remove_group;
11588
- MixpanelLib.prototype['track_with_groups'] = MixpanelLib.prototype.track_with_groups;
11589
- MixpanelLib.prototype['start_batch_senders'] = MixpanelLib.prototype.start_batch_senders;
11590
- MixpanelLib.prototype['stop_batch_senders'] = MixpanelLib.prototype.stop_batch_senders;
11591
-
11592
- // MixpanelPersistence Exports
11593
- MixpanelPersistence.prototype['properties'] = MixpanelPersistence.prototype.properties;
11594
- MixpanelPersistence.prototype['update_search_keyword'] = MixpanelPersistence.prototype.update_search_keyword;
11595
- MixpanelPersistence.prototype['update_referrer_info'] = MixpanelPersistence.prototype.update_referrer_info;
11596
- MixpanelPersistence.prototype['get_cross_subdomain'] = MixpanelPersistence.prototype.get_cross_subdomain;
11597
- MixpanelPersistence.prototype['clear'] = MixpanelPersistence.prototype.clear;
11598
-
11599
-
11600
- var instances = {};
11601
- var extend_mp = function() {
11602
- // add all the sub mixpanel instances
11603
- _.each(instances, function(instance, name) {
11604
- if (name !== PRIMARY_INSTANCE_NAME) { mixpanel_master[name] = instance; }
11605
- });
11606
-
11607
- // add private functions as _
11608
- mixpanel_master['_'] = _;
11609
- };
11610
-
11611
- var override_mp_init_func = function() {
11612
- // we override the snippets init function to handle the case where a
11613
- // user initializes the mixpanel library after the script loads & runs
11614
- mixpanel_master['init'] = function(token, config, name) {
11615
- if (name) {
11616
- // initialize a sub library
11617
- if (!mixpanel_master[name]) {
11618
- mixpanel_master[name] = instances[name] = create_mplib(token, config, name);
11619
- mixpanel_master[name]._loaded();
11620
- }
11621
- return mixpanel_master[name];
11622
- } else {
11623
- var instance = mixpanel_master;
11624
-
11625
- if (instances[PRIMARY_INSTANCE_NAME]) {
11626
- // main mixpanel lib already initialized
11627
- instance = instances[PRIMARY_INSTANCE_NAME];
11628
- } else if (token) {
11629
- // intialize the main mixpanel lib
11630
- instance = create_mplib(token, config, PRIMARY_INSTANCE_NAME);
11631
- instance._loaded();
11632
- instances[PRIMARY_INSTANCE_NAME] = instance;
11633
- }
11634
-
11635
- mixpanel_master = instance;
11636
- if (init_type === INIT_SNIPPET) {
11637
- window$1[PRIMARY_INSTANCE_NAME] = mixpanel_master;
11638
- }
11639
- extend_mp();
11640
- }
11641
- };
11642
- };
11643
-
11644
- var add_dom_loaded_handler = function() {
11645
- // Cross browser DOM Loaded support
11646
- function dom_loaded_handler() {
11647
- // function flag since we only want to execute this once
11648
- if (dom_loaded_handler.done) { return; }
11649
- dom_loaded_handler.done = true;
11650
-
11651
- DOM_LOADED = true;
11652
- ENQUEUE_REQUESTS = false;
11653
-
11654
- _.each(instances, function(inst) {
11655
- inst._dom_loaded();
11656
- });
11657
- }
11658
-
11659
- function do_scroll_check() {
11660
- try {
11661
- document$1.documentElement.doScroll('left');
11662
- } catch(e) {
11663
- setTimeout(do_scroll_check, 1);
11664
- return;
11665
- }
11666
-
11667
- dom_loaded_handler();
11668
- }
11669
-
11670
- if (document$1.addEventListener) {
11671
- if (document$1.readyState === 'complete') {
11672
- // safari 4 can fire the DOMContentLoaded event before loading all
11673
- // external JS (including this file). you will see some copypasta
11674
- // on the internet that checks for 'complete' and 'loaded', but
11675
- // 'loaded' is an IE thing
11676
- dom_loaded_handler();
11677
- } else {
11678
- document$1.addEventListener('DOMContentLoaded', dom_loaded_handler, false);
11679
- }
11680
- } else if (document$1.attachEvent) {
11681
- // IE
11682
- document$1.attachEvent('onreadystatechange', dom_loaded_handler);
11683
-
11684
- // check to make sure we arn't in a frame
11685
- var toplevel = false;
11686
- try {
11687
- toplevel = window$1.frameElement === null;
11688
- } catch(e) {
11689
- // noop
11690
- }
11691
-
11692
- if (document$1.documentElement.doScroll && toplevel) {
11693
- do_scroll_check();
11694
- }
11695
- }
11696
-
11697
- // fallback handler, always will work
11698
- _.register_event(window$1, 'load', dom_loaded_handler, true);
11699
- };
11700
-
11701
- function init_as_module() {
11702
- init_type = INIT_MODULE;
11703
- mixpanel_master = new MixpanelLib();
11704
-
11705
- override_mp_init_func();
11706
- mixpanel_master['init']();
11707
- add_dom_loaded_handler();
11708
-
11709
- return mixpanel_master;
11710
- }
11711
-
11712
- var mixpanel = init_as_module();
11713
-
11714
- var mixpanel_cjs = mixpanel;
11715
-
11716
- var mixpanel$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), mixpanel_cjs, {
11717
- 'default': mixpanel_cjs
11718
- }));
11719
-
11720
- // Needed to avoid error in CJS builds on some bundlers.
11721
- const mixpanelLib = mixpanel_cjs || mixpanel$1;
11722
- let mixpanelInstance;
11723
- const MIXPANEL_EVENT = {
11724
- VISUAL_SDK_RENDER_START: 'visual-sdk-render-start',
11725
- VISUAL_SDK_CALLED_INIT: 'visual-sdk-called-init',
11726
- VISUAL_SDK_RENDER_COMPLETE: 'visual-sdk-render-complete',
11727
- VISUAL_SDK_RENDER_FAILED: 'visual-sdk-render-failed',
11728
- VISUAL_SDK_TRIGGER: 'visual-sdk-trigger',
11729
- VISUAL_SDK_ON: 'visual-sdk-on',
11730
- VISUAL_SDK_IFRAME_LOAD_PERFORMANCE: 'visual-sdk-iframe-load-performance',
11731
- VISUAL_SDK_EMBED_CREATE: 'visual-sdk-embed-create',
11732
- };
11733
- let isMixpanelInitialized = false;
11734
- let eventQueue = [];
11735
- /**
11736
- * Pushes the event with its Property key-value map to mixpanel.
11737
- *
11738
- * @param eventId
11739
- * @param eventProps
11740
- */
11741
- function uploadMixpanelEvent(eventId, eventProps = {}) {
11742
- if (!isMixpanelInitialized) {
11743
- eventQueue.push({ eventId, eventProps });
11744
- return;
11745
- }
11746
- mixpanelInstance.track(eventId, eventProps);
11747
- }
11748
- /**
11749
- *
11750
- */
11751
- function emptyQueue() {
11752
- if (!isMixpanelInitialized) {
11753
- return;
11754
- }
11755
- eventQueue.forEach((event) => {
11756
- uploadMixpanelEvent(event.eventId, event.eventProps);
11757
- });
11758
- eventQueue = [];
11759
- }
11760
- /**
11761
- *
11762
- * @param sessionInfo
11763
- */
11764
- function initMixpanel(sessionInfo) {
11765
- var _a;
11766
- if (!sessionInfo || !sessionInfo.mixpanelToken) {
11767
- return;
11768
- }
11769
- // On a public cluster the user is anonymous, so don't set the identify to
11770
- // userGUID
11771
- const isPublicCluster = !!sessionInfo.isPublicUser;
11772
- const token = sessionInfo.mixpanelToken;
11773
- try {
11774
- if (token) {
11775
- mixpanelInstance = mixpanelLib.init(token, undefined, 'tsEmbed');
11776
- if (!isPublicCluster) {
11777
- mixpanelInstance.identify(sessionInfo.userGUID);
11778
- }
11779
- mixpanelInstance.register_once({
11780
- clusterId: sessionInfo.clusterId,
11781
- clusterName: sessionInfo.clusterName,
11782
- releaseVersion: sessionInfo.releaseVersion,
11783
- hostAppUrl: ((_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.host) || '',
11784
- });
11785
- isMixpanelInitialized = true;
11786
- emptyQueue();
11787
- }
11788
- }
11789
- catch (e) {
11790
- logger.error('Error initializing mixpanel', e);
11791
- }
11792
- }
11793
-
11794
- let config = {};
11795
- /**
11796
- * Gets the configuration embed was initialized with.
11797
- *
11798
- * @returns {@link EmbedConfig} The configuration embed was initialized with.
11799
- * @version SDK: 1.19.0 | ThoughtSpot: *
11800
- * @group Global methods
11801
- */
11802
- const getEmbedConfig = () => config;
11803
- /**
11804
- * Sets the configuration embed was initialized with.
11805
- * And returns the new configuration.
11806
- *
11807
- * @param newConfig The configuration to set.
11808
- * @version SDK: 1.27.0 | ThoughtSpot: *
11809
- * @group Global methods
11810
- */
11811
- const setEmbedConfig = (newConfig) => {
11812
- config = newConfig;
11813
- return newConfig;
11814
- };
11815
-
11816
- const tokenizedFetch = async (input, init) => {
11817
- const embedConfig = getEmbedConfig();
11818
- if (embedConfig.authType !== exports.AuthType.TrustedAuthTokenCookieless) {
11819
- return fetch(input, init);
11820
- }
11821
- const req = new Request(input, init);
11822
- const authToken = await getAuthenticationToken(embedConfig);
11823
- if (authToken) {
11824
- req.headers.append('Authorization', `Bearer ${authToken}`);
11825
- }
11826
- return fetch(req);
11827
- };
11828
-
11829
- /**
11830
- *
11831
- * @param url
11832
- * @param options
11833
- */
11834
- function tokenisedFailureLoggedFetch(url, options = {}) {
11835
- return tokenizedFetch(url, options).then(async (r) => {
11836
- var _a;
11837
- if (!r.ok && r.type !== 'opaqueredirect' && r.type !== 'opaque') {
11838
- logger.error('Failure', await ((_a = r.text) === null || _a === void 0 ? void 0 : _a.call(r)));
11839
- }
11840
- return r;
11841
- });
11842
- }
11843
- /**
11844
- *
11845
- * @param authVerificationUrl
11846
- */
11847
- function fetchSessionInfoService(authVerificationUrl) {
11848
- return tokenisedFailureLoggedFetch(authVerificationUrl, {
11849
- credentials: 'include',
11850
- });
11851
- }
11852
- /**
11853
- *
11854
- * @param thoughtSpotHost
11855
- */
11856
- async function fetchLogoutService(thoughtSpotHost) {
11857
- return tokenisedFailureLoggedFetch(`${thoughtSpotHost}${EndPoints.LOGOUT}`, {
11858
- credentials: 'include',
11859
- method: 'POST',
11860
- headers: {
11861
- 'x-requested-by': 'ThoughtSpot',
11862
- },
11863
- });
11864
- }
11865
-
11866
- // eslint-disable-next-line import/no-mutable-exports
11867
- let loggedInStatus = false;
11868
- // eslint-disable-next-line import/no-mutable-exports
11869
- let samlAuthWindow = null;
11870
- // eslint-disable-next-line import/no-mutable-exports
11871
- let samlCompletionPromise = null;
11872
- let sessionInfo = null;
11873
- let sessionInfoResolver = null;
11874
- const sessionInfoPromise = new Promise((resolve) => {
11875
- sessionInfoResolver = resolve;
11876
- });
11877
- let releaseVersion = '';
11878
- const SSO_REDIRECTION_MARKER_GUID = '5e16222e-ef02-43e9-9fbd-24226bf3ce5b';
11879
- (function (AuthFailureType) {
11880
- AuthFailureType["SDK"] = "SDK";
11881
- AuthFailureType["NO_COOKIE_ACCESS"] = "NO_COOKIE_ACCESS";
11882
- AuthFailureType["EXPIRY"] = "EXPIRY";
11883
- AuthFailureType["OTHER"] = "OTHER";
11884
- })(exports.AuthFailureType || (exports.AuthFailureType = {}));
11885
- (function (AuthStatus) {
11886
- /**
11887
- * Emits when the SDK fails to authenticate
11888
- */
11889
- AuthStatus["FAILURE"] = "FAILURE";
11890
- /**
11891
- * Emits when the SDK authenticates successfully
11892
- */
11893
- AuthStatus["SDK_SUCCESS"] = "SDK_SUCCESS";
11894
- /**
11895
- * Emits when the app sends an authentication success message
11896
- */
11897
- AuthStatus["SUCCESS"] = "SUCCESS";
11898
- /**
11899
- * Emits when a user logs out
11900
- */
11901
- AuthStatus["LOGOUT"] = "LOGOUT";
11902
- /**
11903
- * Emitted when inPopup is true in the SAMLRedirect flow and the
11904
- * popup is waiting to be triggered either programmatically
11905
- * or by the trigger button.
11906
- *
11907
- * @version SDK: 1.19.0
11908
- */
11909
- AuthStatus["WAITING_FOR_POPUP"] = "WAITING_FOR_POPUP";
11910
- })(exports.AuthStatus || (exports.AuthStatus = {}));
11911
- (function (AuthEvent) {
11912
- /**
11913
- * Manually trigger the SSO popup. This is useful when
11914
- * authStatus is SAMLRedirect/OIDCRedirect and inPopup is set to true
11915
- */
11916
- AuthEvent["TRIGGER_SSO_POPUP"] = "TRIGGER_SSO_POPUP";
11917
- })(exports.AuthEvent || (exports.AuthEvent = {}));
11918
- let authEE;
11919
- /**
11920
- *
11921
- * @param eventEmitter
11922
- */
11923
- function setAuthEE(eventEmitter) {
11924
- authEE = eventEmitter;
11925
- }
11926
- /**
11927
- *
11928
- */
11929
- function notifyAuthSDKSuccess() {
11930
- if (!authEE) {
11931
- logger.error('SDK not initialized');
11932
- return;
11933
- }
11934
- authEE.emit(exports.AuthStatus.SDK_SUCCESS);
11935
- }
11936
- /**
11937
- *
11938
- */
11939
- function notifyAuthSuccess() {
11940
- if (!authEE) {
11941
- logger.error('SDK not initialized');
11942
- return;
11943
- }
11944
- authEE.emit(exports.AuthStatus.SUCCESS, sessionInfo);
11945
- }
11946
- /**
11947
- *
11948
- * @param failureType
11949
- */
11950
- function notifyAuthFailure(failureType) {
11951
- if (!authEE) {
11952
- logger.error('SDK not initialized');
11953
- return;
11954
- }
11955
- authEE.emit(exports.AuthStatus.FAILURE, failureType);
11956
- }
11957
- /**
11958
- *
11959
- */
11960
- function notifyLogout() {
11961
- if (!authEE) {
11962
- logger.error('SDK not initialized');
11963
- return;
11964
- }
11965
- authEE.emit(exports.AuthStatus.LOGOUT);
11966
- }
11967
- const initSession = (sessionDetails) => {
11968
- if (sessionInfo == null) {
11969
- sessionInfo = sessionDetails;
11970
- initMixpanel(sessionInfo);
11971
- sessionInfoResolver(sessionInfo);
11972
- }
11973
- };
11974
- const getSessionDetails = (sessionInfoResp) => {
11975
- const devMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.devSdkKey;
11976
- const prodMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.prodSdkKey;
11977
- const mixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.production
11978
- ? prodMixpanelToken
11979
- : devMixpanelToken;
11980
- return {
11981
- userGUID: sessionInfoResp.userGUID,
11982
- mixpanelToken,
11983
- isPublicUser: sessionInfoResp.configInfo.isPublicUser,
11984
- releaseVersion: sessionInfoResp.releaseVersion,
11985
- clusterId: sessionInfoResp.configInfo.selfClusterId,
11986
- clusterName: sessionInfoResp.configInfo.selfClusterName,
11987
- ...sessionInfoResp,
11988
- };
11989
- };
11990
- /**
11991
- * Check if we are logged into the ThoughtSpot cluster
11992
- *
11993
- * @param thoughtSpotHost The ThoughtSpot cluster hostname or IP
11994
- */
11995
- async function isLoggedIn(thoughtSpotHost) {
11996
- const authVerificationUrl = `${thoughtSpotHost}${EndPoints.AUTH_VERIFICATION}`;
11997
- let response = null;
11998
- try {
11999
- response = await fetchSessionInfoService(authVerificationUrl);
12000
- const sessionInfoResp = await response.json();
12001
- const sessionDetails = getSessionDetails(sessionInfoResp);
12002
- // Store user session details from session info
12003
- initSession(sessionDetails);
12004
- releaseVersion = sessionInfoResp.releaseVersion;
12005
- }
12006
- catch (e) {
12007
- return false;
12008
- }
12009
- return response.status === 200;
12010
- }
12011
- /**
12012
- * Return releaseVersion if available
12013
- */
12014
- function getReleaseVersion() {
12015
- return releaseVersion;
12016
- }
12017
- /**
12018
- * Return a promise that resolves with the session information when
12019
- * authentication is successful. And info is available.
12020
- *
12021
- * @group Global methods
12022
- */
12023
- function getSessionInfo() {
12024
- return sessionInfoPromise;
12025
- }
12026
- /**
12027
- * Check if we are stuck at the SSO redirect URL
12028
- */
12029
- function isAtSSORedirectUrl() {
12030
- return window.location.href.indexOf(SSO_REDIRECTION_MARKER_GUID) >= 0;
12031
- }
12032
- /**
12033
- * Remove the SSO redirect URL marker
12034
- */
12035
- function removeSSORedirectUrlMarker() {
12036
- // Note (sunny): This will leave a # around even if it was not in the URL
12037
- // to begin with. Trying to remove the hash by changing window.location will
12038
- // reload the page which we don't want. We'll live with adding an
12039
- // unnecessary hash to the parent page URL until we find any use case where
12040
- // that creates an issue.
12041
- window.location.hash = window.location.hash.replace(SSO_REDIRECTION_MARKER_GUID, '');
12042
- }
12043
- /**
12044
- * Perform token based authentication
12045
- *
12046
- * @param embedConfig The embed configuration
12047
- */
12048
- const doTokenAuth = async (embedConfig) => {
12049
- const { thoughtSpotHost, username, authEndpoint, getAuthToken, } = embedConfig;
12050
- if (!authEndpoint && !getAuthToken) {
12051
- throw new Error('Either auth endpoint or getAuthToken function must be provided');
12052
- }
12053
- loggedInStatus = await isLoggedIn(thoughtSpotHost);
12054
- if (!loggedInStatus) {
12055
- const authToken = await getAuthenticationToken(embedConfig);
12056
- let resp;
12057
- try {
12058
- resp = await fetchAuthPostService(thoughtSpotHost, username, authToken);
12059
- }
12060
- catch (e) {
12061
- resp = await fetchAuthService(thoughtSpotHost, username, authToken);
12062
- }
12063
- // token login issues a 302 when successful
12064
- loggedInStatus = resp.ok || resp.type === 'opaqueredirect';
12065
- if (loggedInStatus && embedConfig.detectCookieAccessSlow) {
12066
- // When 3rd party cookie access is blocked, this will fail because
12067
- // cookies will not be sent with the call.
12068
- loggedInStatus = await isLoggedIn(thoughtSpotHost);
12069
- }
12070
- }
12071
- return loggedInStatus;
12072
- };
12073
- /**
12074
- * Validate embedConfig parameters required for cookielessTokenAuth
12075
- *
12076
- * @param embedConfig The embed configuration
12077
- */
12078
- const doCookielessTokenAuth = async (embedConfig) => {
12079
- const { authEndpoint, getAuthToken } = embedConfig;
12080
- if (!authEndpoint && !getAuthToken) {
12081
- throw new Error('Either auth endpoint or getAuthToken function must be provided');
12082
- }
12083
- let authSuccess = false;
12084
- try {
12085
- const authToken = await getAuthenticationToken(embedConfig);
12086
- if (authToken) {
12087
- authSuccess = true;
12088
- }
12089
- }
12090
- catch {
12091
- authSuccess = false;
12092
- }
12093
- return authSuccess;
12094
- };
12095
- /**
12096
- * Perform basic authentication to the ThoughtSpot cluster using the cluster
12097
- * credentials.
12098
- *
12099
- * Warning: This feature is primarily intended for developer testing. It is
12100
- * strongly advised not to use this authentication method in production.
12101
- *
12102
- * @param embedConfig The embed configuration
12103
- */
12104
- const doBasicAuth = async (embedConfig) => {
12105
- const { thoughtSpotHost, username, password } = embedConfig;
12106
- const loggedIn = await isLoggedIn(thoughtSpotHost);
12107
- if (!loggedIn) {
12108
- const response = await fetchBasicAuthService(thoughtSpotHost, username, password);
12109
- loggedInStatus = response.ok;
12110
- if (embedConfig.detectCookieAccessSlow) {
12111
- loggedInStatus = await isLoggedIn(thoughtSpotHost);
12112
- }
12113
- }
12114
- else {
12115
- loggedInStatus = true;
12116
- }
12117
- return loggedInStatus;
12118
- };
12119
- /**
12120
- *
12121
- * @param ssoURL
12122
- * @param triggerContainer
12123
- * @param triggerText
12124
- */
12125
- async function samlPopupFlow(ssoURL, triggerContainer, triggerText) {
12126
- const openPopup = () => {
12127
- if (samlAuthWindow === null || samlAuthWindow.closed) {
12128
- samlAuthWindow = window.open(ssoURL, '_blank', 'location=no,height=570,width=520,scrollbars=yes,status=yes');
12129
- }
12130
- else {
12131
- samlAuthWindow.focus();
12132
- }
12133
- };
12134
- authEE === null || authEE === void 0 ? void 0 : authEE.emit(exports.AuthStatus.WAITING_FOR_POPUP);
12135
- const containerEl = getDOMNode(triggerContainer);
12136
- if (containerEl) {
12137
- containerEl.innerHTML = '<button id="ts-auth-btn" class="ts-auth-btn" style="margin: auto;"></button>';
12138
- const authElem = document.getElementById('ts-auth-btn');
12139
- authElem.textContent = triggerText;
12140
- authElem.addEventListener('click', openPopup, { once: true });
12141
- }
12142
- samlCompletionPromise = samlCompletionPromise
12143
- || new Promise((resolve, reject) => {
12144
- window.addEventListener('message', (e) => {
12145
- if (e.data.type === exports.EmbedEvent.SAMLComplete) {
12146
- e.source.close();
12147
- resolve();
12148
- }
12149
- });
12150
- });
12151
- authEE === null || authEE === void 0 ? void 0 : authEE.once(exports.AuthEvent.TRIGGER_SSO_POPUP, openPopup);
12152
- return samlCompletionPromise;
12153
- }
12154
- /**
12155
- * Perform SAML authentication
12156
- *
12157
- * @param embedConfig The embed configuration
12158
- * @param ssoEndPoint
12159
- */
12160
- const doSSOAuth = async (embedConfig, ssoEndPoint) => {
12161
- const { thoughtSpotHost } = embedConfig;
12162
- const loggedIn = await isLoggedIn(thoughtSpotHost);
12163
- if (loggedIn) {
12164
- if (isAtSSORedirectUrl()) {
12165
- removeSSORedirectUrlMarker();
12166
- }
12167
- loggedInStatus = true;
12168
- return;
12169
- }
12170
- // we have already tried authentication and it did not succeed, restore
12171
- // the current URL to the original one and invoke the callback.
12172
- if (isAtSSORedirectUrl()) {
12173
- removeSSORedirectUrlMarker();
12174
- loggedInStatus = false;
12175
- return;
12176
- }
12177
- const ssoURL = `${thoughtSpotHost}${ssoEndPoint}`;
12178
- if (embedConfig.inPopup) {
12179
- await samlPopupFlow(ssoURL, embedConfig.authTriggerContainer, embedConfig.authTriggerText);
12180
- loggedInStatus = await isLoggedIn(thoughtSpotHost);
12181
- return;
12182
- }
12183
- window.location.href = ssoURL;
12184
- };
12185
- const doSamlAuth = async (embedConfig) => {
12186
- const { thoughtSpotHost } = embedConfig;
12187
- // redirect for SSO, when the SSO authentication is done, this page will be
12188
- // loaded again and the same JS will execute again.
12189
- const ssoRedirectUrl = embedConfig.inPopup
12190
- ? `${thoughtSpotHost}/v2/#/embed/saml-complete`
12191
- : getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
12192
- // bring back the page to the same URL
12193
- const ssoEndPoint = `${EndPoints.SAML_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
12194
- await doSSOAuth(embedConfig, ssoEndPoint);
12195
- return loggedInStatus;
12196
- };
12197
- const doOIDCAuth = async (embedConfig) => {
12198
- const { thoughtSpotHost } = embedConfig;
12199
- // redirect for SSO, when the SSO authentication is done, this page will be
12200
- // loaded again and the same JS will execute again.
12201
- const ssoRedirectUrl = embedConfig.noRedirect || embedConfig.inPopup
12202
- ? `${thoughtSpotHost}/v2/#/embed/saml-complete`
12203
- : getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
12204
- // bring back the page to the same URL
12205
- const ssoEndPoint = `${EndPoints.OIDC_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
12206
- await doSSOAuth(embedConfig, ssoEndPoint);
12207
- return loggedInStatus;
12208
- };
12209
- const logout = async (embedConfig) => {
12210
- const { thoughtSpotHost } = embedConfig;
12211
- await fetchLogoutService(thoughtSpotHost);
12212
- resetCachedAuthToken();
12213
- const thoughtspotIframes = document.querySelectorAll("[data-ts-iframe='true']");
12214
- if (thoughtspotIframes === null || thoughtspotIframes === void 0 ? void 0 : thoughtspotIframes.length) {
12215
- thoughtspotIframes.forEach((el) => {
12216
- el.parentElement.innerHTML = embedConfig.loginFailedMessage;
12217
- });
12218
- }
12219
- loggedInStatus = false;
12220
- return loggedInStatus;
12221
- };
12222
- /**
12223
- * Perform authentication on the ThoughtSpot cluster
12224
- *
12225
- * @param embedConfig The embed configuration
12226
- */
12227
- const authenticate = async (embedConfig) => {
12228
- const { authType } = embedConfig;
12229
- switch (authType) {
12230
- case exports.AuthType.SSO:
12231
- case exports.AuthType.SAMLRedirect:
12232
- case exports.AuthType.SAML:
12233
- return doSamlAuth(embedConfig);
12234
- case exports.AuthType.OIDC:
12235
- case exports.AuthType.OIDCRedirect:
12236
- return doOIDCAuth(embedConfig);
12237
- case exports.AuthType.AuthServer:
12238
- case exports.AuthType.TrustedAuthToken:
12239
- return doTokenAuth(embedConfig);
12240
- case exports.AuthType.TrustedAuthTokenCookieless:
12241
- return doCookielessTokenAuth(embedConfig);
12242
- case exports.AuthType.Basic:
12243
- return doBasicAuth(embedConfig);
12244
- default:
12245
- return Promise.resolve(true);
12246
- }
11845
+ var is_localStorage_requested = this.get_config('opt_out_tracking_persistence_type') === 'localStorage';
11846
+
11847
+ // try to convert opt-in/out cookies to localStorage if possible
11848
+ if (is_localStorage_requested && _.localStorage.is_supported()) {
11849
+ if (!this.has_opted_in_tracking() && this.has_opted_in_tracking({'persistence_type': 'cookie'})) {
11850
+ this.opt_in_tracking({'enable_persistence': false});
11851
+ }
11852
+ if (!this.has_opted_out_tracking() && this.has_opted_out_tracking({'persistence_type': 'cookie'})) {
11853
+ this.opt_out_tracking({'clear_persistence': false});
11854
+ }
11855
+ this.clear_opt_in_out_tracking({
11856
+ 'persistence_type': 'cookie',
11857
+ 'enable_persistence': false
11858
+ });
11859
+ }
11860
+
11861
+ // check whether the user has already opted out - if so, clear & disable persistence
11862
+ if (this.has_opted_out_tracking()) {
11863
+ this._gdpr_update_persistence({'clear_persistence': true});
11864
+
11865
+ // check whether we should opt out by default
11866
+ // note: we don't clear persistence here by default since opt-out default state is often
11867
+ // used as an initial state while GDPR information is being collected
11868
+ } else if (!this.has_opted_in_tracking() && (
11869
+ this.get_config('opt_out_tracking_by_default') || _.cookie.get('mp_optout')
11870
+ )) {
11871
+ _.cookie.remove('mp_optout');
11872
+ this.opt_out_tracking({
11873
+ 'clear_persistence': this.get_config('opt_out_persistence_by_default')
11874
+ });
11875
+ }
11876
+ };
11877
+
11878
+ /**
11879
+ * Enable or disable persistence based on options
11880
+ * only enable/disable if persistence is not already in this state
11881
+ * @param {boolean} [options.clear_persistence] If true, will delete all data stored by the sdk in persistence and disable it
11882
+ * @param {boolean} [options.enable_persistence] If true, will re-enable sdk persistence
11883
+ */
11884
+ MixpanelLib.prototype._gdpr_update_persistence = function(options) {
11885
+ var disabled;
11886
+ if (options && options['clear_persistence']) {
11887
+ disabled = true;
11888
+ } else if (options && options['enable_persistence']) {
11889
+ disabled = false;
11890
+ } else {
11891
+ return;
11892
+ }
11893
+
11894
+ if (!this.get_config('disable_persistence') && this['persistence'].disabled !== disabled) {
11895
+ this['persistence'].set_disabled(disabled);
11896
+ }
11897
+
11898
+ if (disabled) {
11899
+ _.each(this.request_batchers, function(batcher) {
11900
+ batcher.clear();
11901
+ });
11902
+ }
11903
+ };
11904
+
11905
+ // call a base gdpr function after constructing the appropriate token and options args
11906
+ MixpanelLib.prototype._gdpr_call_func = function(func, options) {
11907
+ options = _.extend({
11908
+ 'track': _.bind(this.track, this),
11909
+ 'persistence_type': this.get_config('opt_out_tracking_persistence_type'),
11910
+ 'cookie_prefix': this.get_config('opt_out_tracking_cookie_prefix'),
11911
+ 'cookie_expiration': this.get_config('cookie_expiration'),
11912
+ 'cross_site_cookie': this.get_config('cross_site_cookie'),
11913
+ 'cross_subdomain_cookie': this.get_config('cross_subdomain_cookie'),
11914
+ 'cookie_domain': this.get_config('cookie_domain'),
11915
+ 'secure_cookie': this.get_config('secure_cookie'),
11916
+ 'ignore_dnt': this.get_config('ignore_dnt')
11917
+ }, options);
11918
+
11919
+ // check if localStorage can be used for recording opt out status, fall back to cookie if not
11920
+ if (!_.localStorage.is_supported()) {
11921
+ options['persistence_type'] = 'cookie';
11922
+ }
11923
+
11924
+ return func(this.get_config('token'), {
11925
+ track: options['track'],
11926
+ trackEventName: options['track_event_name'],
11927
+ trackProperties: options['track_properties'],
11928
+ persistenceType: options['persistence_type'],
11929
+ persistencePrefix: options['cookie_prefix'],
11930
+ cookieDomain: options['cookie_domain'],
11931
+ cookieExpiration: options['cookie_expiration'],
11932
+ crossSiteCookie: options['cross_site_cookie'],
11933
+ crossSubdomainCookie: options['cross_subdomain_cookie'],
11934
+ secureCookie: options['secure_cookie'],
11935
+ ignoreDnt: options['ignore_dnt']
11936
+ });
11937
+ };
11938
+
11939
+ /**
11940
+ * Opt the user in to data tracking and cookies/localstorage for this Mixpanel instance
11941
+ *
11942
+ * ### Usage
11943
+ *
11944
+ * // opt user in
11945
+ * mixpanel.opt_in_tracking();
11946
+ *
11947
+ * // opt user in with specific event name, properties, cookie configuration
11948
+ * mixpanel.opt_in_tracking({
11949
+ * track_event_name: 'User opted in',
11950
+ * track_event_properties: {
11951
+ * 'Email': 'jdoe@example.com'
11952
+ * },
11953
+ * cookie_expiration: 30,
11954
+ * secure_cookie: true
11955
+ * });
11956
+ *
11957
+ * @param {Object} [options] A dictionary of config options to override
11958
+ * @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)
11959
+ * @param {string} [options.track_event_name=$opt_in] Event name to be used for tracking the opt-in action
11960
+ * @param {Object} [options.track_properties] Set of properties to be tracked along with the opt-in action
11961
+ * @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence
11962
+ * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11963
+ * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11964
+ * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
11965
+ * @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
11966
+ * @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)
11967
+ * @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)
11968
+ * @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)
11969
+ */
11970
+ MixpanelLib.prototype.opt_in_tracking = function(options) {
11971
+ options = _.extend({
11972
+ 'enable_persistence': true
11973
+ }, options);
11974
+
11975
+ this._gdpr_call_func(optIn, options);
11976
+ this._gdpr_update_persistence(options);
11977
+ };
11978
+
11979
+ /**
11980
+ * Opt the user out of data tracking and cookies/localstorage for this Mixpanel instance
11981
+ *
11982
+ * ### Usage
11983
+ *
11984
+ * // opt user out
11985
+ * mixpanel.opt_out_tracking();
11986
+ *
11987
+ * // opt user out with different cookie configuration from Mixpanel instance
11988
+ * mixpanel.opt_out_tracking({
11989
+ * cookie_expiration: 30,
11990
+ * secure_cookie: true
11991
+ * });
11992
+ *
11993
+ * @param {Object} [options] A dictionary of config options to override
11994
+ * @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
11995
+ * @param {boolean} [options.clear_persistence=true] If true, will delete all data stored by the sdk in persistence
11996
+ * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11997
+ * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11998
+ * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
11999
+ * @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
12000
+ * @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)
12001
+ * @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)
12002
+ * @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)
12003
+ */
12004
+ MixpanelLib.prototype.opt_out_tracking = function(options) {
12005
+ options = _.extend({
12006
+ 'clear_persistence': true,
12007
+ 'delete_user': true
12008
+ }, options);
12009
+
12010
+ // delete user and clear charges since these methods may be disabled by opt-out
12011
+ if (options['delete_user'] && this['people'] && this['people']._identify_called()) {
12012
+ this['people'].delete_user();
12013
+ this['people'].clear_charges();
12014
+ }
12015
+
12016
+ this._gdpr_call_func(optOut, options);
12017
+ this._gdpr_update_persistence(options);
12018
+ };
12019
+
12020
+ /**
12021
+ * Check whether the user has opted in to data tracking and cookies/localstorage for this Mixpanel instance
12022
+ *
12023
+ * ### Usage
12024
+ *
12025
+ * var has_opted_in = mixpanel.has_opted_in_tracking();
12026
+ * // use has_opted_in value
12027
+ *
12028
+ * @param {Object} [options] A dictionary of config options to override
12029
+ * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
12030
+ * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
12031
+ * @returns {boolean} current opt-in status
12032
+ */
12033
+ MixpanelLib.prototype.has_opted_in_tracking = function(options) {
12034
+ return this._gdpr_call_func(hasOptedIn, options);
12035
+ };
12036
+
12037
+ /**
12038
+ * Check whether the user has opted out of data tracking and cookies/localstorage for this Mixpanel instance
12039
+ *
12040
+ * ### Usage
12041
+ *
12042
+ * var has_opted_out = mixpanel.has_opted_out_tracking();
12043
+ * // use has_opted_out value
12044
+ *
12045
+ * @param {Object} [options] A dictionary of config options to override
12046
+ * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
12047
+ * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
12048
+ * @returns {boolean} current opt-out status
12049
+ */
12050
+ MixpanelLib.prototype.has_opted_out_tracking = function(options) {
12051
+ return this._gdpr_call_func(hasOptedOut, options);
12052
+ };
12053
+
12054
+ /**
12055
+ * Clear the user's opt in/out status of data tracking and cookies/localstorage for this Mixpanel instance
12056
+ *
12057
+ * ### Usage
12058
+ *
12059
+ * // clear user's opt-in/out status
12060
+ * mixpanel.clear_opt_in_out_tracking();
12061
+ *
12062
+ * // clear user's opt-in/out status with specific cookie configuration - should match
12063
+ * // configuration used when opt_in_tracking/opt_out_tracking methods were called.
12064
+ * mixpanel.clear_opt_in_out_tracking({
12065
+ * cookie_expiration: 30,
12066
+ * secure_cookie: true
12067
+ * });
12068
+ *
12069
+ * @param {Object} [options] A dictionary of config options to override
12070
+ * @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence
12071
+ * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
12072
+ * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
12073
+ * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
12074
+ * @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
12075
+ * @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)
12076
+ * @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)
12077
+ * @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)
12078
+ */
12079
+ MixpanelLib.prototype.clear_opt_in_out_tracking = function(options) {
12080
+ options = _.extend({
12081
+ 'enable_persistence': true
12082
+ }, options);
12083
+
12084
+ this._gdpr_call_func(clearOptInOut, options);
12085
+ this._gdpr_update_persistence(options);
12086
+ };
12087
+
12088
+ MixpanelLib.prototype.report_error = function(msg, err) {
12089
+ console$1.error.apply(console$1.error, arguments);
12090
+ try {
12091
+ if (!err && !(msg instanceof Error)) {
12092
+ msg = new Error(msg);
12093
+ }
12094
+ this.get_config('error_reporter')(msg, err);
12095
+ } catch(err) {
12096
+ console$1.error(err);
12097
+ }
12247
12098
  };
12248
12099
 
12249
- const ERROR_MESSAGE = {
12250
- INVALID_THOUGHTSPOT_HOST: 'Error parsing ThoughtSpot host. Please provide a valid URL.',
12251
- LIVEBOARD_VIZ_ID_VALIDATION: 'Please provide either liveboardId or pinboardId',
12252
- TRIGGER_TIMED_OUT: 'Trigger timedout in getting response',
12253
- SEARCHEMBED_BETA_WRANING_MESSAGE: 'Search Embed is in Beta in this release.',
12254
- SAGE_EMBED_BETA_WARNING_MESSAGE: 'Sage Embed is in Beta in this release.',
12100
+ // EXPORTS (for closure compiler)
12101
+
12102
+ // MixpanelLib Exports
12103
+ MixpanelLib.prototype['init'] = MixpanelLib.prototype.init;
12104
+ MixpanelLib.prototype['reset'] = MixpanelLib.prototype.reset;
12105
+ MixpanelLib.prototype['disable'] = MixpanelLib.prototype.disable;
12106
+ MixpanelLib.prototype['time_event'] = MixpanelLib.prototype.time_event;
12107
+ MixpanelLib.prototype['track'] = MixpanelLib.prototype.track;
12108
+ MixpanelLib.prototype['track_links'] = MixpanelLib.prototype.track_links;
12109
+ MixpanelLib.prototype['track_forms'] = MixpanelLib.prototype.track_forms;
12110
+ MixpanelLib.prototype['track_pageview'] = MixpanelLib.prototype.track_pageview;
12111
+ MixpanelLib.prototype['register'] = MixpanelLib.prototype.register;
12112
+ MixpanelLib.prototype['register_once'] = MixpanelLib.prototype.register_once;
12113
+ MixpanelLib.prototype['unregister'] = MixpanelLib.prototype.unregister;
12114
+ MixpanelLib.prototype['identify'] = MixpanelLib.prototype.identify;
12115
+ MixpanelLib.prototype['alias'] = MixpanelLib.prototype.alias;
12116
+ MixpanelLib.prototype['name_tag'] = MixpanelLib.prototype.name_tag;
12117
+ MixpanelLib.prototype['set_config'] = MixpanelLib.prototype.set_config;
12118
+ MixpanelLib.prototype['get_config'] = MixpanelLib.prototype.get_config;
12119
+ MixpanelLib.prototype['get_property'] = MixpanelLib.prototype.get_property;
12120
+ MixpanelLib.prototype['get_distinct_id'] = MixpanelLib.prototype.get_distinct_id;
12121
+ MixpanelLib.prototype['toString'] = MixpanelLib.prototype.toString;
12122
+ MixpanelLib.prototype['opt_out_tracking'] = MixpanelLib.prototype.opt_out_tracking;
12123
+ MixpanelLib.prototype['opt_in_tracking'] = MixpanelLib.prototype.opt_in_tracking;
12124
+ MixpanelLib.prototype['has_opted_out_tracking'] = MixpanelLib.prototype.has_opted_out_tracking;
12125
+ MixpanelLib.prototype['has_opted_in_tracking'] = MixpanelLib.prototype.has_opted_in_tracking;
12126
+ MixpanelLib.prototype['clear_opt_in_out_tracking'] = MixpanelLib.prototype.clear_opt_in_out_tracking;
12127
+ MixpanelLib.prototype['get_group'] = MixpanelLib.prototype.get_group;
12128
+ MixpanelLib.prototype['set_group'] = MixpanelLib.prototype.set_group;
12129
+ MixpanelLib.prototype['add_group'] = MixpanelLib.prototype.add_group;
12130
+ MixpanelLib.prototype['remove_group'] = MixpanelLib.prototype.remove_group;
12131
+ MixpanelLib.prototype['track_with_groups'] = MixpanelLib.prototype.track_with_groups;
12132
+ MixpanelLib.prototype['start_batch_senders'] = MixpanelLib.prototype.start_batch_senders;
12133
+ MixpanelLib.prototype['stop_batch_senders'] = MixpanelLib.prototype.stop_batch_senders;
12134
+
12135
+ // MixpanelPersistence Exports
12136
+ MixpanelPersistence.prototype['properties'] = MixpanelPersistence.prototype.properties;
12137
+ MixpanelPersistence.prototype['update_search_keyword'] = MixpanelPersistence.prototype.update_search_keyword;
12138
+ MixpanelPersistence.prototype['update_referrer_info'] = MixpanelPersistence.prototype.update_referrer_info;
12139
+ MixpanelPersistence.prototype['get_cross_subdomain'] = MixpanelPersistence.prototype.get_cross_subdomain;
12140
+ MixpanelPersistence.prototype['clear'] = MixpanelPersistence.prototype.clear;
12141
+
12142
+
12143
+ var instances = {};
12144
+ var extend_mp = function() {
12145
+ // add all the sub mixpanel instances
12146
+ _.each(instances, function(instance, name) {
12147
+ if (name !== PRIMARY_INSTANCE_NAME) { mixpanel_master[name] = instance; }
12148
+ });
12149
+
12150
+ // add private functions as _
12151
+ mixpanel_master['_'] = _;
12255
12152
  };
12256
12153
 
12257
- /**
12258
- * Copyright (c) 2023
12259
- *
12260
- * Utilities related to reading configuration objects
12261
- *
12262
- * @summary Config-related utils
12263
- * @author Ayon Ghosh <ayon.ghosh@thoughtspot.com>
12264
- */
12265
- const urlRegex = new RegExp([
12266
- '(^(https?:)//)?',
12267
- '(([^:/?#]*)(?::([0-9]+))?)',
12268
- '(/{0,1}[^?#]*)',
12269
- '(\\?[^#]*|)',
12270
- '(#.*|)$', // hash
12271
- ].join(''));
12272
- /**
12273
- * Parse and construct the ThoughtSpot hostname or IP address
12274
- * from the embed configuration object.
12275
- *
12276
- * @param config
12277
- */
12278
- const getThoughtSpotHost = (config) => {
12279
- if (!config.thoughtSpotHost) {
12280
- throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
12281
- }
12282
- const urlParts = config.thoughtSpotHost.match(urlRegex);
12283
- if (!urlParts) {
12284
- throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
12285
- }
12286
- const protocol = urlParts[2] || window.location.protocol;
12287
- const host = urlParts[3];
12288
- let path = urlParts[6];
12289
- // Lose the trailing / if any
12290
- if (path.charAt(path.length - 1) === '/') {
12291
- path = path.substring(0, path.length - 1);
12292
- }
12293
- // const urlParams = urlParts[7];
12294
- // const hash = urlParts[8];
12295
- return `${protocol}//${host}${path}`;
12296
- };
12297
- const getV2BasePath = (config) => {
12298
- if (config.basepath) {
12299
- return config.basepath;
12300
- }
12301
- const tsHost = getThoughtSpotHost(config);
12302
- // This is to handle when e2e's. Search is run on pods for
12303
- // comp-blink-test-pipeline with baseUrl=https://localhost:8443.
12304
- // This is to handle when the developer is developing in their local
12305
- // environment.
12306
- if (tsHost.includes('://localhost') && !tsHost.includes(':8443')) {
12307
- return '';
12308
- }
12309
- return 'v2';
12310
- };
12311
- /**
12312
- * It is a good idea to keep URLs under 2000 chars.
12313
- * If this is ever breached, since we pass view configuration through
12314
- * URL params, we would like to log a warning.
12315
- * Reference: https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
12316
- */
12317
- const URL_MAX_LENGTH = 2000;
12318
- /**
12319
- * The default CSS dimensions of the embedded app
12320
- */
12321
- const DEFAULT_EMBED_WIDTH = '100%';
12322
- const DEFAULT_EMBED_HEIGHT = '100%';
12154
+ var override_mp_init_func = function() {
12155
+ // we override the snippets init function to handle the case where a
12156
+ // user initializes the mixpanel library after the script loads & runs
12157
+ mixpanel_master['init'] = function(token, config, name) {
12158
+ if (name) {
12159
+ // initialize a sub library
12160
+ if (!mixpanel_master[name]) {
12161
+ mixpanel_master[name] = instances[name] = create_mplib(token, config, name);
12162
+ mixpanel_master[name]._loaded();
12163
+ }
12164
+ return mixpanel_master[name];
12165
+ } else {
12166
+ var instance = mixpanel_master;
12323
12167
 
12324
- /**
12325
- *
12326
- * @param root0
12327
- * @param root0.query
12328
- * @param root0.variables
12329
- * @param root0.thoughtSpotHost
12330
- * @param root0.isCompositeQuery
12331
- */
12332
- async function graphqlQuery({ query, variables, thoughtSpotHost, isCompositeQuery = false, }) {
12333
- const operationName = getOperationNameFromQuery(query);
12334
- try {
12335
- const response = await fetch(`${thoughtSpotHost}/prism/?op=${operationName}`, {
12336
- method: 'POST',
12337
- headers: {
12338
- 'content-type': 'application/json;charset=UTF-8',
12339
- 'x-requested-by': 'ThoughtSpot',
12340
- accept: '*/*',
12341
- 'accept-language': 'en-us',
12342
- },
12343
- body: JSON.stringify({
12344
- operationName,
12345
- query,
12346
- variables,
12347
- }),
12348
- credentials: 'include',
12349
- });
12350
- const result = await response.json();
12351
- const dataValues = Object.values(result.data);
12352
- return (isCompositeQuery) ? result.data : dataValues[0];
12353
- }
12354
- catch (error) {
12355
- return error;
12356
- }
12357
- }
12168
+ if (instances[PRIMARY_INSTANCE_NAME]) {
12169
+ // main mixpanel lib already initialized
12170
+ instance = instances[PRIMARY_INSTANCE_NAME];
12171
+ } else if (token) {
12172
+ // intialize the main mixpanel lib
12173
+ instance = create_mplib(token, config, PRIMARY_INSTANCE_NAME);
12174
+ instance._loaded();
12175
+ instances[PRIMARY_INSTANCE_NAME] = instance;
12176
+ }
12358
12177
 
12359
- const getSourceDetailQuery = `
12360
- query GetSourceDetail($ids: [GUID!]!) {
12361
- getSourceDetailById(ids: $ids, type: LOGICAL_TABLE) {
12362
- id
12363
- name
12364
- description
12365
- authorName
12366
- authorDisplayName
12367
- isExternal
12368
- type
12369
- created
12370
- modified
12371
- columns {
12372
- id
12373
- name
12374
- author
12375
- authorDisplayName
12376
- description
12377
- dataType
12378
- type
12379
- modified
12380
- ownerName
12381
- owner
12382
- dataRecency
12383
- sources {
12384
- tableId
12385
- tableName
12386
- columnId
12387
- columnName
12388
- __typename
12389
- }
12390
- synonyms
12391
- cohortAnswerId
12392
- __typename
12393
- }
12394
- relationships
12395
- destinationRelationships
12396
- dataSourceId
12397
- __typename
12398
- }
12399
- }
12400
- `;
12401
- const sourceDetailCache = new Map();
12402
- /**
12403
- *
12404
- * @param thoughtSpotHost
12405
- * @param sourceId
12406
- */
12407
- async function getSourceDetail(thoughtSpotHost, sourceId) {
12408
- if (sourceDetailCache.get(sourceId)) {
12409
- return sourceDetailCache.get(sourceId);
12410
- }
12411
- const details = await graphqlQuery({
12412
- query: getSourceDetailQuery,
12413
- variables: {
12414
- ids: [sourceId],
12415
- },
12416
- thoughtSpotHost,
12417
- });
12418
- const souceDetails = details[0];
12419
- if (souceDetails) {
12420
- sourceDetailCache.set(sourceId, souceDetails);
12421
- }
12422
- return souceDetails;
12423
- }
12178
+ mixpanel_master = instance;
12179
+ if (init_type === INIT_SNIPPET) {
12180
+ window$1[PRIMARY_INSTANCE_NAME] = mixpanel_master;
12181
+ }
12182
+ extend_mp();
12183
+ }
12184
+ };
12185
+ };
12186
+
12187
+ var add_dom_loaded_handler = function() {
12188
+ // Cross browser DOM Loaded support
12189
+ function dom_loaded_handler() {
12190
+ // function flag since we only want to execute this once
12191
+ if (dom_loaded_handler.done) { return; }
12192
+ dom_loaded_handler.done = true;
12424
12193
 
12425
- const bachSessionId = `
12426
- id {
12427
- sessionId
12428
- genNo
12429
- acSession {
12430
- sessionId
12431
- genNo
12432
- }
12433
- }
12434
- `;
12435
- const getUnaggregatedAnswerSession = `
12436
- mutation GetUnAggregatedAnswerSession($session: BachSessionIdInput!, $columns: [UserPointSelectionInput!]!) {
12437
- Answer__getUnaggregatedAnswer(session: $session, columns: $columns) {
12438
- ${bachSessionId}
12439
- answer {
12440
- visualizations {
12441
- ... on TableViz {
12442
- columns {
12443
- column {
12444
- id
12445
- name
12446
- referencedColumns {
12447
- guid
12448
- displayName
12449
- }
12450
- }
12451
- }
12452
- }
12453
- }
12454
- }
12455
- }
12456
- }
12457
- `;
12458
- const removeColumns = `
12459
- mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!], $columnIds: [GUID!]) {
12460
- Answer__removeColumns(
12461
- session: $session
12462
- logicalColumnIds: $logicalColumnIds
12463
- columnIds: $columnIds
12464
- ) {
12465
- ${bachSessionId}
12466
- }
12467
- }
12468
- `;
12469
- const addColumns = `
12470
- mutation AddColumns($session: BachSessionIdInput!, $columns: [AnswerColumnInfo!]!) {
12471
- Answer__addColumn(session: $session, columns: $columns) {
12472
- ${bachSessionId}
12473
- }
12474
- }
12475
- `;
12476
- const getAnswerData = `
12477
- query GetTableWithHeadlineData($session: BachSessionIdInput!, $deadline: Int!, $dataPaginationParams: DataPaginationParamsInput!) {
12478
- getAnswer(session: $session) {
12479
- ${bachSessionId}
12480
- answer {
12481
- id
12482
- visualizations {
12483
- id
12484
- ... on TableViz {
12485
- columns {
12486
- column {
12487
- id
12488
- name
12489
- type
12490
- aggregationType
12491
- dataType
12492
- }
12493
- }
12494
- data(deadline: $deadline, pagination: $dataPaginationParams)
12495
- }
12496
- }
12497
- }
12498
- }
12499
- }
12500
- `;
12194
+ DOM_LOADED = true;
12195
+ ENQUEUE_REQUESTS = false;
12501
12196
 
12502
- // eslint-disable-next-line no-shadow
12503
- var OperationType;
12504
- (function (OperationType) {
12505
- OperationType["GetChartWithData"] = "GetChartWithData";
12506
- OperationType["GetTableWithHeadlineData"] = "GetTableWithHeadlineData";
12507
- })(OperationType || (OperationType = {}));
12508
- /**
12509
- * Class representing the answer service provided with the
12510
- * custom action payload. This service could be used to run
12511
- * graphql queries in the context of the answer on which the
12512
- * custom action was triggered.
12513
- *
12514
- * @example
12515
- * ```js
12516
- * embed.on(EmbedEvent.CustomAction, e => {
12517
- * const underlying = await e.answerService.getUnderlyingDataForPoint([
12518
- * 'col name 1'
12519
- * ]);
12520
- * const data = await underlying.fetchData(0, 100);
12521
- * })
12522
- * ```
12523
- * @version SDK: 1.25.0| ThoughtSpot: 9.10.0.cl
12524
- * @group Events
12525
- */
12526
- class AnswerService {
12527
- constructor(session, answer, thoughtSpotHost, selectedPoints) {
12528
- this.session = session;
12529
- this.answer = answer;
12530
- this.thoughtSpotHost = thoughtSpotHost;
12531
- this.selectedPoints = selectedPoints;
12532
- this.session = removeTypename(session);
12533
- }
12534
- async getSourceDetail() {
12535
- const sourceId = this.answer.sources[0].header.guid;
12536
- return getSourceDetail(this.thoughtSpotHost, sourceId);
12537
- }
12538
- async removeColumns(columnIds) {
12539
- return this.executeQuery(removeColumns, {
12540
- logicalColumnIds: columnIds,
12541
- });
12542
- }
12543
- async addColumns(columnIds) {
12544
- return this.executeQuery(addColumns, {
12545
- columns: columnIds.map((colId) => ({ logicalColumnId: colId })),
12546
- });
12547
- }
12548
- async fetchData(offset = 0, size = 1000) {
12549
- const { answer } = await this.executeQuery(getAnswerData, {
12550
- deadline: 0,
12551
- dataPaginationParams: {
12552
- isClientPaginated: true,
12553
- offset,
12554
- size,
12555
- },
12556
- });
12557
- const { columns, data } = answer.visualizations.find((viz) => !!viz.data) || {};
12558
- return {
12559
- columns,
12560
- data,
12561
- };
12562
- }
12563
- /**
12564
- *
12565
- * @param userLocale
12566
- * @param includeInfo Include the CSV header in the output
12567
- * @returns Response
12568
- */
12569
- async fetchCSVBlob(userLocale = 'en-us', includeInfo = false) {
12570
- const fetchUrl = this.getFetchCSVBlobUrl(userLocale, includeInfo);
12571
- return tokenizedFetch(fetchUrl, {
12572
- credentials: 'include',
12573
- });
12574
- }
12575
- getFetchCSVBlobUrl(userLocale = 'en-us', includeInfo = false) {
12576
- return `${this.thoughtSpotHost}/prism/download/answer/csv?sessionId=${this.session.sessionId}&genNo=${this.session.genNo}&userLocale=${userLocale}&exportFileName=data&hideCsvHeader=${!includeInfo}`;
12577
- }
12578
- /**
12579
- * Get underlying data given a point and the output column names.
12580
- *
12581
- * @param outputColumnNames
12582
- * @param selectedPoints
12583
- * @example
12584
- * ```js
12585
- * embed.on(EmbedEvent.CustomAction, e => {
12586
- * const underlying = await e.answerService.getUnderlyingDataForPoint([
12587
- * 'col name 1' // The column should exist in the data source.
12588
- * ]);
12589
- * const data = await underlying.fetchData(0, 100);
12590
- * })
12591
- * ```
12592
- * @version SDK: 1.25.0| ThoughtSpot: 9.10.0.cl
12593
- */
12594
- async getUnderlyingDataForPoint(outputColumnNames, selectedPoints) {
12595
- if (!selectedPoints && !this.selectedPoints) {
12596
- throw new Error('Needs to be triggered in context of a point');
12597
- }
12598
- if (!selectedPoints) {
12599
- selectedPoints = getSelectedPointsForUnderlyingDataQuery(this.selectedPoints);
12600
- }
12601
- const sourceDetail = await this.getSourceDetail();
12602
- const ouputColumnGuids = getGuidsFromColumnNames(sourceDetail, outputColumnNames);
12603
- const unAggAnswer = await graphqlQuery({
12604
- query: getUnaggregatedAnswerSession,
12605
- variables: {
12606
- session: this.session,
12607
- columns: selectedPoints,
12608
- },
12609
- thoughtSpotHost: this.thoughtSpotHost,
12610
- });
12611
- const unaggAnswerSession = new AnswerService(unAggAnswer.id, unAggAnswer.answer, this.thoughtSpotHost);
12612
- const currentColumns = new Set(unAggAnswer.answer.visualizations[0].columns
12613
- .map((c) => c.column.referencedColumns[0].guid));
12614
- const columnsToAdd = [...ouputColumnGuids].filter((col) => !currentColumns.has(col));
12615
- if (columnsToAdd.length) {
12616
- await unaggAnswerSession.addColumns(columnsToAdd);
12617
- }
12618
- const columnsToRemove = [...currentColumns].filter((col) => !ouputColumnGuids.has(col));
12619
- if (columnsToRemove.length) {
12620
- await unaggAnswerSession.removeColumns(columnsToRemove);
12621
- }
12622
- return unaggAnswerSession;
12623
- }
12624
- async executeQuery(query, variables) {
12625
- const data = await graphqlQuery({
12626
- query,
12627
- variables: {
12628
- session: this.session,
12629
- ...variables,
12630
- },
12631
- thoughtSpotHost: this.thoughtSpotHost,
12632
- isCompositeQuery: false,
12633
- });
12634
- this.session = deepMerge(this.session, (data === null || data === void 0 ? void 0 : data.id) || {});
12635
- return data;
12636
- }
12637
- getSession() {
12638
- return this.session;
12197
+ _.each(instances, function(inst) {
12198
+ inst._dom_loaded();
12199
+ });
12200
+ }
12201
+
12202
+ function do_scroll_check() {
12203
+ try {
12204
+ document$1.documentElement.doScroll('left');
12205
+ } catch(e) {
12206
+ setTimeout(do_scroll_check, 1);
12207
+ return;
12208
+ }
12209
+
12210
+ dom_loaded_handler();
12211
+ }
12212
+
12213
+ if (document$1.addEventListener) {
12214
+ if (document$1.readyState === 'complete') {
12215
+ // safari 4 can fire the DOMContentLoaded event before loading all
12216
+ // external JS (including this file). you will see some copypasta
12217
+ // on the internet that checks for 'complete' and 'loaded', but
12218
+ // 'loaded' is an IE thing
12219
+ dom_loaded_handler();
12220
+ } else {
12221
+ document$1.addEventListener('DOMContentLoaded', dom_loaded_handler, false);
12222
+ }
12223
+ } else if (document$1.attachEvent) {
12224
+ // IE
12225
+ document$1.attachEvent('onreadystatechange', dom_loaded_handler);
12226
+
12227
+ // check to make sure we arn't in a frame
12228
+ var toplevel = false;
12229
+ try {
12230
+ toplevel = window$1.frameElement === null;
12231
+ } catch(e) {
12232
+ // noop
12233
+ }
12234
+
12235
+ if (document$1.documentElement.doScroll && toplevel) {
12236
+ do_scroll_check();
12237
+ }
12238
+ }
12239
+
12240
+ // fallback handler, always will work
12241
+ _.register_event(window$1, 'load', dom_loaded_handler, true);
12242
+ };
12243
+
12244
+ function init_as_module() {
12245
+ init_type = INIT_MODULE;
12246
+ mixpanel_master = new MixpanelLib();
12247
+
12248
+ override_mp_init_func();
12249
+ mixpanel_master['init']();
12250
+ add_dom_loaded_handler();
12251
+
12252
+ return mixpanel_master;
12253
+ }
12254
+
12255
+ var mixpanel = init_as_module();
12256
+
12257
+ var mixpanel_cjs = mixpanel;
12258
+
12259
+ var mixpanel$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), mixpanel_cjs, {
12260
+ 'default': mixpanel_cjs
12261
+ }));
12262
+
12263
+ // Needed to avoid error in CJS builds on some bundlers.
12264
+ const mixpanelLib = mixpanel_cjs || mixpanel$1;
12265
+ let mixpanelInstance;
12266
+ const MIXPANEL_EVENT = {
12267
+ VISUAL_SDK_RENDER_START: 'visual-sdk-render-start',
12268
+ VISUAL_SDK_CALLED_INIT: 'visual-sdk-called-init',
12269
+ VISUAL_SDK_RENDER_COMPLETE: 'visual-sdk-render-complete',
12270
+ VISUAL_SDK_RENDER_FAILED: 'visual-sdk-render-failed',
12271
+ VISUAL_SDK_TRIGGER: 'visual-sdk-trigger',
12272
+ VISUAL_SDK_ON: 'visual-sdk-on',
12273
+ VISUAL_SDK_IFRAME_LOAD_PERFORMANCE: 'visual-sdk-iframe-load-performance',
12274
+ VISUAL_SDK_EMBED_CREATE: 'visual-sdk-embed-create',
12275
+ VERCEL_INTEGRATION_COMPLETED: 'vercel-integration-completed',
12276
+ };
12277
+ let isMixpanelInitialized = false;
12278
+ let eventQueue = [];
12279
+ /**
12280
+ * Pushes the event with its Property key-value map to mixpanel.
12281
+ *
12282
+ * @param eventId
12283
+ * @param eventProps
12284
+ */
12285
+ function uploadMixpanelEvent(eventId, eventProps = {}) {
12286
+ if (!isMixpanelInitialized) {
12287
+ eventQueue.push({ eventId, eventProps });
12288
+ return;
12639
12289
  }
12290
+ mixpanelInstance.track(eventId, eventProps);
12640
12291
  }
12641
12292
  /**
12642
12293
  *
12643
- * @param sourceDetail
12644
- * @param colNames
12645
12294
  */
12646
- function getGuidsFromColumnNames(sourceDetail, colNames) {
12647
- const cols = sourceDetail.columns.reduce((colSet, col) => {
12648
- colSet[col.name] = col;
12649
- return colSet;
12650
- }, {});
12651
- return new Set(colNames.map((colName) => {
12652
- const col = cols[colName];
12653
- return col.id;
12654
- }));
12295
+ function emptyQueue() {
12296
+ if (!isMixpanelInitialized) {
12297
+ return;
12298
+ }
12299
+ eventQueue.forEach((event) => {
12300
+ uploadMixpanelEvent(event.eventId, event.eventProps);
12301
+ });
12302
+ eventQueue = [];
12655
12303
  }
12656
12304
  /**
12657
12305
  *
12658
- * @param selectedPoints
12306
+ * @param sessionInfo
12659
12307
  */
12660
- function getSelectedPointsForUnderlyingDataQuery(selectedPoints) {
12661
- const underlyingDataPoint = [];
12662
- /**
12663
- *
12664
- * @param colVal
12665
- */
12666
- function addPointFromColVal(colVal) {
12667
- var _a;
12668
- const dataType = colVal.column.dataType;
12669
- const id = colVal.column.id;
12670
- let dataValue;
12671
- if (dataType === 'DATE') {
12672
- if (Number.isFinite(colVal.value)) {
12673
- dataValue = [{
12674
- epochRange: {
12675
- startEpoch: colVal.value,
12676
- },
12677
- }];
12678
- // Case for custom calendar.
12679
- }
12680
- else if ((_a = colVal.value) === null || _a === void 0 ? void 0 : _a.v) {
12681
- dataValue = [{
12682
- epochRange: {
12683
- startEpoch: colVal.value.v.s,
12684
- endEpoch: colVal.value.v.e,
12685
- },
12686
- }];
12308
+ function initMixpanel(sessionInfo) {
12309
+ var _a;
12310
+ if (!sessionInfo || !sessionInfo.mixpanelToken) {
12311
+ return;
12312
+ }
12313
+ // On a public cluster the user is anonymous, so don't set the identify to
12314
+ // userGUID
12315
+ const isPublicCluster = !!sessionInfo.isPublicUser;
12316
+ const token = sessionInfo.mixpanelToken;
12317
+ try {
12318
+ if (token) {
12319
+ mixpanelInstance = mixpanelLib.init(token, undefined, 'tsEmbed');
12320
+ if (!isPublicCluster) {
12321
+ mixpanelInstance.identify(sessionInfo.userGUID);
12687
12322
  }
12323
+ mixpanelInstance.register_once({
12324
+ clusterId: sessionInfo.clusterId,
12325
+ clusterName: sessionInfo.clusterName,
12326
+ releaseVersion: sessionInfo.releaseVersion,
12327
+ hostAppUrl: ((_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.host) || '',
12328
+ });
12329
+ isMixpanelInitialized = true;
12330
+ emptyQueue();
12688
12331
  }
12689
- else {
12690
- dataValue = [{ value: colVal.value }];
12691
- }
12692
- underlyingDataPoint.push({
12693
- columnId: colVal.column.id,
12694
- dataValue,
12695
- });
12696
12332
  }
12697
- selectedPoints.forEach((p) => {
12698
- p.selectedAttributes.forEach(addPointFromColVal);
12699
- });
12700
- return underlyingDataPoint;
12333
+ catch (e) {
12334
+ logger.error('Error initializing mixpanel', e);
12335
+ }
12701
12336
  }
12702
12337
 
12703
12338
  var eventemitter3 = createCommonjsModule(function (module) {
@@ -13154,114 +12789,534 @@ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!]
13154
12789
  return false;
13155
12790
  }
13156
12791
 
13157
- var _arrayIncludesWith = arrayIncludesWith;
13158
-
13159
- /** Used as references for various `Number` constants. */
13160
- var INFINITY = 1 / 0;
13161
-
13162
- /**
13163
- * Creates a set object of `values`.
13164
- *
13165
- * @private
13166
- * @param {Array} values The values to add to the set.
13167
- * @returns {Object} Returns the new set.
13168
- */
13169
- var createSet = !(_Set && (1 / _setToArray(new _Set([,-0]))[1]) == INFINITY) ? noop_1 : function(values) {
13170
- return new _Set(values);
12792
+ var _arrayIncludesWith = arrayIncludesWith;
12793
+
12794
+ /** Used as references for various `Number` constants. */
12795
+ var INFINITY = 1 / 0;
12796
+
12797
+ /**
12798
+ * Creates a set object of `values`.
12799
+ *
12800
+ * @private
12801
+ * @param {Array} values The values to add to the set.
12802
+ * @returns {Object} Returns the new set.
12803
+ */
12804
+ var createSet = !(_Set && (1 / _setToArray(new _Set([,-0]))[1]) == INFINITY) ? noop_1 : function(values) {
12805
+ return new _Set(values);
12806
+ };
12807
+
12808
+ var _createSet = createSet;
12809
+
12810
+ /** Used as the size to enable large array optimizations. */
12811
+ var LARGE_ARRAY_SIZE$1 = 200;
12812
+
12813
+ /**
12814
+ * The base implementation of `_.uniqBy` without support for iteratee shorthands.
12815
+ *
12816
+ * @private
12817
+ * @param {Array} array The array to inspect.
12818
+ * @param {Function} [iteratee] The iteratee invoked per element.
12819
+ * @param {Function} [comparator] The comparator invoked per element.
12820
+ * @returns {Array} Returns the new duplicate free array.
12821
+ */
12822
+ function baseUniq(array, iteratee, comparator) {
12823
+ var index = -1,
12824
+ includes = _arrayIncludes,
12825
+ length = array.length,
12826
+ isCommon = true,
12827
+ result = [],
12828
+ seen = result;
12829
+
12830
+ if (comparator) {
12831
+ isCommon = false;
12832
+ includes = _arrayIncludesWith;
12833
+ }
12834
+ else if (length >= LARGE_ARRAY_SIZE$1) {
12835
+ var set = iteratee ? null : _createSet(array);
12836
+ if (set) {
12837
+ return _setToArray(set);
12838
+ }
12839
+ isCommon = false;
12840
+ includes = _cacheHas;
12841
+ seen = new _SetCache;
12842
+ }
12843
+ else {
12844
+ seen = iteratee ? [] : result;
12845
+ }
12846
+ outer:
12847
+ while (++index < length) {
12848
+ var value = array[index],
12849
+ computed = iteratee ? iteratee(value) : value;
12850
+
12851
+ value = (comparator || value !== 0) ? value : 0;
12852
+ if (isCommon && computed === computed) {
12853
+ var seenIndex = seen.length;
12854
+ while (seenIndex--) {
12855
+ if (seen[seenIndex] === computed) {
12856
+ continue outer;
12857
+ }
12858
+ }
12859
+ if (iteratee) {
12860
+ seen.push(computed);
12861
+ }
12862
+ result.push(value);
12863
+ }
12864
+ else if (!includes(seen, computed, comparator)) {
12865
+ if (seen !== result) {
12866
+ seen.push(computed);
12867
+ }
12868
+ result.push(value);
12869
+ }
12870
+ }
12871
+ return result;
12872
+ }
12873
+
12874
+ var _baseUniq = baseUniq;
12875
+
12876
+ /**
12877
+ * Creates a duplicate-free version of an array, using
12878
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
12879
+ * for equality comparisons, in which only the first occurrence of each element
12880
+ * is kept. The order of result values is determined by the order they occur
12881
+ * in the array.
12882
+ *
12883
+ * @static
12884
+ * @memberOf _
12885
+ * @since 0.1.0
12886
+ * @category Array
12887
+ * @param {Array} array The array to inspect.
12888
+ * @returns {Array} Returns the new duplicate free array.
12889
+ * @example
12890
+ *
12891
+ * _.uniq([2, 1, 2]);
12892
+ * // => [2, 1]
12893
+ */
12894
+ function uniq(array) {
12895
+ return (array && array.length) ? _baseUniq(array) : [];
12896
+ }
12897
+
12898
+ var uniq_1 = uniq;
12899
+
12900
+ /**
12901
+ *
12902
+ * @param url
12903
+ * @param options
12904
+ */
12905
+ function tokenisedFailureLoggedFetch(url, options = {}) {
12906
+ return tokenizedFetch(url, options).then(async (r) => {
12907
+ var _a;
12908
+ if (!r.ok && r.type !== 'opaqueredirect' && r.type !== 'opaque') {
12909
+ logger.error('Failure', await ((_a = r.text) === null || _a === void 0 ? void 0 : _a.call(r)));
12910
+ }
12911
+ return r;
12912
+ });
12913
+ }
12914
+ /**
12915
+ *
12916
+ * @param authVerificationUrl
12917
+ */
12918
+ function fetchSessionInfoService(authVerificationUrl) {
12919
+ return tokenisedFailureLoggedFetch(authVerificationUrl, {
12920
+ credentials: 'include',
12921
+ });
12922
+ }
12923
+ /**
12924
+ *
12925
+ * @param thoughtSpotHost
12926
+ */
12927
+ async function fetchLogoutService(thoughtSpotHost) {
12928
+ return tokenisedFailureLoggedFetch(`${thoughtSpotHost}${EndPoints.LOGOUT}`, {
12929
+ credentials: 'include',
12930
+ method: 'POST',
12931
+ headers: {
12932
+ 'x-requested-by': 'ThoughtSpot',
12933
+ },
12934
+ });
12935
+ }
12936
+
12937
+ // eslint-disable-next-line import/no-mutable-exports
12938
+ let loggedInStatus = false;
12939
+ // eslint-disable-next-line import/no-mutable-exports
12940
+ let samlAuthWindow = null;
12941
+ // eslint-disable-next-line import/no-mutable-exports
12942
+ let samlCompletionPromise = null;
12943
+ let sessionInfo = null;
12944
+ let sessionInfoResolver = null;
12945
+ const sessionInfoPromise = new Promise((resolve) => {
12946
+ sessionInfoResolver = resolve;
12947
+ });
12948
+ let releaseVersion = '';
12949
+ const SSO_REDIRECTION_MARKER_GUID = '5e16222e-ef02-43e9-9fbd-24226bf3ce5b';
12950
+ (function (AuthFailureType) {
12951
+ AuthFailureType["SDK"] = "SDK";
12952
+ AuthFailureType["NO_COOKIE_ACCESS"] = "NO_COOKIE_ACCESS";
12953
+ AuthFailureType["EXPIRY"] = "EXPIRY";
12954
+ AuthFailureType["OTHER"] = "OTHER";
12955
+ })(exports.AuthFailureType || (exports.AuthFailureType = {}));
12956
+ (function (AuthStatus) {
12957
+ /**
12958
+ * Emits when the SDK fails to authenticate
12959
+ */
12960
+ AuthStatus["FAILURE"] = "FAILURE";
12961
+ /**
12962
+ * Emits when the SDK authenticates successfully
12963
+ */
12964
+ AuthStatus["SDK_SUCCESS"] = "SDK_SUCCESS";
12965
+ /**
12966
+ * Emits when the app sends an authentication success message
12967
+ */
12968
+ AuthStatus["SUCCESS"] = "SUCCESS";
12969
+ /**
12970
+ * Emits when a user logs out
12971
+ */
12972
+ AuthStatus["LOGOUT"] = "LOGOUT";
12973
+ /**
12974
+ * Emitted when inPopup is true in the SAMLRedirect flow and the
12975
+ * popup is waiting to be triggered either programmatically
12976
+ * or by the trigger button.
12977
+ *
12978
+ * @version SDK: 1.19.0
12979
+ */
12980
+ AuthStatus["WAITING_FOR_POPUP"] = "WAITING_FOR_POPUP";
12981
+ })(exports.AuthStatus || (exports.AuthStatus = {}));
12982
+ (function (AuthEvent) {
12983
+ /**
12984
+ * Manually trigger the SSO popup. This is useful when
12985
+ * authStatus is SAMLRedirect/OIDCRedirect and inPopup is set to true
12986
+ */
12987
+ AuthEvent["TRIGGER_SSO_POPUP"] = "TRIGGER_SSO_POPUP";
12988
+ })(exports.AuthEvent || (exports.AuthEvent = {}));
12989
+ let authEE;
12990
+ /**
12991
+ *
12992
+ * @param eventEmitter
12993
+ */
12994
+ function setAuthEE(eventEmitter) {
12995
+ authEE = eventEmitter;
12996
+ }
12997
+ /**
12998
+ *
12999
+ */
13000
+ function notifyAuthSDKSuccess() {
13001
+ if (!authEE) {
13002
+ logger.error('SDK not initialized');
13003
+ return;
13004
+ }
13005
+ authEE.emit(exports.AuthStatus.SDK_SUCCESS);
13006
+ }
13007
+ /**
13008
+ *
13009
+ */
13010
+ function notifyAuthSuccess() {
13011
+ if (!authEE) {
13012
+ logger.error('SDK not initialized');
13013
+ return;
13014
+ }
13015
+ authEE.emit(exports.AuthStatus.SUCCESS, sessionInfo);
13016
+ }
13017
+ /**
13018
+ *
13019
+ * @param failureType
13020
+ */
13021
+ function notifyAuthFailure(failureType) {
13022
+ if (!authEE) {
13023
+ logger.error('SDK not initialized');
13024
+ return;
13025
+ }
13026
+ authEE.emit(exports.AuthStatus.FAILURE, failureType);
13027
+ }
13028
+ /**
13029
+ *
13030
+ */
13031
+ function notifyLogout() {
13032
+ if (!authEE) {
13033
+ logger.error('SDK not initialized');
13034
+ return;
13035
+ }
13036
+ authEE.emit(exports.AuthStatus.LOGOUT);
13037
+ }
13038
+ const initSession = (sessionDetails) => {
13039
+ if (sessionInfo == null) {
13040
+ sessionInfo = sessionDetails;
13041
+ initMixpanel(sessionInfo);
13042
+ sessionInfoResolver(sessionInfo);
13043
+ }
13044
+ };
13045
+ const getSessionDetails = (sessionInfoResp) => {
13046
+ const devMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.devSdkKey;
13047
+ const prodMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.prodSdkKey;
13048
+ const mixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.production
13049
+ ? prodMixpanelToken
13050
+ : devMixpanelToken;
13051
+ return {
13052
+ userGUID: sessionInfoResp.userGUID,
13053
+ mixpanelToken,
13054
+ isPublicUser: sessionInfoResp.configInfo.isPublicUser,
13055
+ releaseVersion: sessionInfoResp.releaseVersion,
13056
+ clusterId: sessionInfoResp.configInfo.selfClusterId,
13057
+ clusterName: sessionInfoResp.configInfo.selfClusterName,
13058
+ ...sessionInfoResp,
13059
+ };
13060
+ };
13061
+ /**
13062
+ * Check if we are logged into the ThoughtSpot cluster
13063
+ *
13064
+ * @param thoughtSpotHost The ThoughtSpot cluster hostname or IP
13065
+ */
13066
+ async function isLoggedIn(thoughtSpotHost) {
13067
+ const authVerificationUrl = `${thoughtSpotHost}${EndPoints.AUTH_VERIFICATION}`;
13068
+ let response = null;
13069
+ try {
13070
+ response = await fetchSessionInfoService(authVerificationUrl);
13071
+ const sessionInfoResp = await response.json();
13072
+ const sessionDetails = getSessionDetails(sessionInfoResp);
13073
+ // Store user session details from session info
13074
+ initSession(sessionDetails);
13075
+ releaseVersion = sessionInfoResp.releaseVersion;
13076
+ }
13077
+ catch (e) {
13078
+ return false;
13079
+ }
13080
+ return response.status === 200;
13081
+ }
13082
+ /**
13083
+ * Return releaseVersion if available
13084
+ */
13085
+ function getReleaseVersion() {
13086
+ return releaseVersion;
13087
+ }
13088
+ /**
13089
+ * Return a promise that resolves with the session information when
13090
+ * authentication is successful. And info is available.
13091
+ *
13092
+ * @group Global methods
13093
+ */
13094
+ function getSessionInfo() {
13095
+ return sessionInfoPromise;
13096
+ }
13097
+ /**
13098
+ * Check if we are stuck at the SSO redirect URL
13099
+ */
13100
+ function isAtSSORedirectUrl() {
13101
+ return window.location.href.indexOf(SSO_REDIRECTION_MARKER_GUID) >= 0;
13102
+ }
13103
+ /**
13104
+ * Remove the SSO redirect URL marker
13105
+ */
13106
+ function removeSSORedirectUrlMarker() {
13107
+ // Note (sunny): This will leave a # around even if it was not in the URL
13108
+ // to begin with. Trying to remove the hash by changing window.location will
13109
+ // reload the page which we don't want. We'll live with adding an
13110
+ // unnecessary hash to the parent page URL until we find any use case where
13111
+ // that creates an issue.
13112
+ window.location.hash = window.location.hash.replace(SSO_REDIRECTION_MARKER_GUID, '');
13113
+ }
13114
+ /**
13115
+ * Perform token based authentication
13116
+ *
13117
+ * @param embedConfig The embed configuration
13118
+ */
13119
+ const doTokenAuth = async (embedConfig) => {
13120
+ const { thoughtSpotHost, username, authEndpoint, getAuthToken, } = embedConfig;
13121
+ if (!authEndpoint && !getAuthToken) {
13122
+ throw new Error('Either auth endpoint or getAuthToken function must be provided');
13123
+ }
13124
+ loggedInStatus = await isLoggedIn(thoughtSpotHost);
13125
+ if (!loggedInStatus) {
13126
+ const authToken = await getAuthenticationToken(embedConfig);
13127
+ let resp;
13128
+ try {
13129
+ resp = await fetchAuthPostService(thoughtSpotHost, username, authToken);
13130
+ }
13131
+ catch (e) {
13132
+ resp = await fetchAuthService(thoughtSpotHost, username, authToken);
13133
+ }
13134
+ // token login issues a 302 when successful
13135
+ loggedInStatus = resp.ok || resp.type === 'opaqueredirect';
13136
+ if (loggedInStatus && embedConfig.detectCookieAccessSlow) {
13137
+ // When 3rd party cookie access is blocked, this will fail because
13138
+ // cookies will not be sent with the call.
13139
+ loggedInStatus = await isLoggedIn(thoughtSpotHost);
13140
+ }
13141
+ }
13142
+ return loggedInStatus;
13143
+ };
13144
+ /**
13145
+ * Validate embedConfig parameters required for cookielessTokenAuth
13146
+ *
13147
+ * @param embedConfig The embed configuration
13148
+ */
13149
+ const doCookielessTokenAuth = async (embedConfig) => {
13150
+ const { authEndpoint, getAuthToken } = embedConfig;
13151
+ if (!authEndpoint && !getAuthToken) {
13152
+ throw new Error('Either auth endpoint or getAuthToken function must be provided');
13153
+ }
13154
+ let authSuccess = false;
13155
+ try {
13156
+ const authToken = await getAuthenticationToken(embedConfig);
13157
+ if (authToken) {
13158
+ authSuccess = true;
13159
+ }
13160
+ }
13161
+ catch {
13162
+ authSuccess = false;
13163
+ }
13164
+ return authSuccess;
13165
+ };
13166
+ /**
13167
+ * Perform basic authentication to the ThoughtSpot cluster using the cluster
13168
+ * credentials.
13169
+ *
13170
+ * Warning: This feature is primarily intended for developer testing. It is
13171
+ * strongly advised not to use this authentication method in production.
13172
+ *
13173
+ * @param embedConfig The embed configuration
13174
+ */
13175
+ const doBasicAuth = async (embedConfig) => {
13176
+ const { thoughtSpotHost, username, password } = embedConfig;
13177
+ const loggedIn = await isLoggedIn(thoughtSpotHost);
13178
+ if (!loggedIn) {
13179
+ const response = await fetchBasicAuthService(thoughtSpotHost, username, password);
13180
+ loggedInStatus = response.ok;
13181
+ if (embedConfig.detectCookieAccessSlow) {
13182
+ loggedInStatus = await isLoggedIn(thoughtSpotHost);
13183
+ }
13184
+ }
13185
+ else {
13186
+ loggedInStatus = true;
13187
+ }
13188
+ return loggedInStatus;
13189
+ };
13190
+ /**
13191
+ *
13192
+ * @param ssoURL
13193
+ * @param triggerContainer
13194
+ * @param triggerText
13195
+ */
13196
+ async function samlPopupFlow(ssoURL, triggerContainer, triggerText) {
13197
+ const openPopup = () => {
13198
+ if (samlAuthWindow === null || samlAuthWindow.closed) {
13199
+ samlAuthWindow = window.open(ssoURL, '_blank', 'location=no,height=570,width=520,scrollbars=yes,status=yes');
13200
+ }
13201
+ else {
13202
+ samlAuthWindow.focus();
13203
+ }
13204
+ };
13205
+ authEE === null || authEE === void 0 ? void 0 : authEE.emit(exports.AuthStatus.WAITING_FOR_POPUP);
13206
+ const containerEl = getDOMNode(triggerContainer);
13207
+ if (containerEl) {
13208
+ containerEl.innerHTML = '<button id="ts-auth-btn" class="ts-auth-btn" style="margin: auto;"></button>';
13209
+ const authElem = document.getElementById('ts-auth-btn');
13210
+ authElem.textContent = triggerText;
13211
+ authElem.addEventListener('click', openPopup, { once: true });
13212
+ }
13213
+ samlCompletionPromise = samlCompletionPromise
13214
+ || new Promise((resolve, reject) => {
13215
+ window.addEventListener('message', (e) => {
13216
+ if (e.data.type === exports.EmbedEvent.SAMLComplete) {
13217
+ e.source.close();
13218
+ resolve();
13219
+ }
13220
+ });
13221
+ });
13222
+ authEE === null || authEE === void 0 ? void 0 : authEE.once(exports.AuthEvent.TRIGGER_SSO_POPUP, openPopup);
13223
+ return samlCompletionPromise;
13224
+ }
13225
+ /**
13226
+ * Perform SAML authentication
13227
+ *
13228
+ * @param embedConfig The embed configuration
13229
+ * @param ssoEndPoint
13230
+ */
13231
+ const doSSOAuth = async (embedConfig, ssoEndPoint) => {
13232
+ const { thoughtSpotHost } = embedConfig;
13233
+ const loggedIn = await isLoggedIn(thoughtSpotHost);
13234
+ if (loggedIn) {
13235
+ if (isAtSSORedirectUrl()) {
13236
+ removeSSORedirectUrlMarker();
13237
+ }
13238
+ loggedInStatus = true;
13239
+ return;
13240
+ }
13241
+ // we have already tried authentication and it did not succeed, restore
13242
+ // the current URL to the original one and invoke the callback.
13243
+ if (isAtSSORedirectUrl()) {
13244
+ removeSSORedirectUrlMarker();
13245
+ loggedInStatus = false;
13246
+ return;
13247
+ }
13248
+ const ssoURL = `${thoughtSpotHost}${ssoEndPoint}`;
13249
+ if (embedConfig.inPopup) {
13250
+ await samlPopupFlow(ssoURL, embedConfig.authTriggerContainer, embedConfig.authTriggerText);
13251
+ loggedInStatus = await isLoggedIn(thoughtSpotHost);
13252
+ return;
13253
+ }
13254
+ window.location.href = ssoURL;
13255
+ };
13256
+ const doSamlAuth = async (embedConfig) => {
13257
+ const { thoughtSpotHost } = embedConfig;
13258
+ // redirect for SSO, when the SSO authentication is done, this page will be
13259
+ // loaded again and the same JS will execute again.
13260
+ const ssoRedirectUrl = embedConfig.inPopup
13261
+ ? `${thoughtSpotHost}/v2/#/embed/saml-complete`
13262
+ : getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
13263
+ // bring back the page to the same URL
13264
+ const ssoEndPoint = `${EndPoints.SAML_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
13265
+ await doSSOAuth(embedConfig, ssoEndPoint);
13266
+ return loggedInStatus;
13267
+ };
13268
+ const doOIDCAuth = async (embedConfig) => {
13269
+ const { thoughtSpotHost } = embedConfig;
13270
+ // redirect for SSO, when the SSO authentication is done, this page will be
13271
+ // loaded again and the same JS will execute again.
13272
+ const ssoRedirectUrl = embedConfig.noRedirect || embedConfig.inPopup
13273
+ ? `${thoughtSpotHost}/v2/#/embed/saml-complete`
13274
+ : getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
13275
+ // bring back the page to the same URL
13276
+ const ssoEndPoint = `${EndPoints.OIDC_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
13277
+ await doSSOAuth(embedConfig, ssoEndPoint);
13278
+ return loggedInStatus;
13279
+ };
13280
+ const logout = async (embedConfig) => {
13281
+ const { thoughtSpotHost } = embedConfig;
13282
+ await fetchLogoutService(thoughtSpotHost);
13283
+ resetCachedAuthToken();
13284
+ const thoughtspotIframes = document.querySelectorAll('[data-ts-iframe=\'true\']');
13285
+ if (thoughtspotIframes === null || thoughtspotIframes === void 0 ? void 0 : thoughtspotIframes.length) {
13286
+ thoughtspotIframes.forEach((el) => {
13287
+ el.parentElement.innerHTML = embedConfig.loginFailedMessage;
13288
+ });
13289
+ }
13290
+ loggedInStatus = false;
13291
+ return loggedInStatus;
13292
+ };
13293
+ /**
13294
+ * Perform authentication on the ThoughtSpot cluster
13295
+ *
13296
+ * @param embedConfig The embed configuration
13297
+ */
13298
+ const authenticate = async (embedConfig) => {
13299
+ const { authType } = embedConfig;
13300
+ switch (authType) {
13301
+ case exports.AuthType.SSO:
13302
+ case exports.AuthType.SAMLRedirect:
13303
+ case exports.AuthType.SAML:
13304
+ return doSamlAuth(embedConfig);
13305
+ case exports.AuthType.OIDC:
13306
+ case exports.AuthType.OIDCRedirect:
13307
+ return doOIDCAuth(embedConfig);
13308
+ case exports.AuthType.AuthServer:
13309
+ case exports.AuthType.TrustedAuthToken:
13310
+ return doTokenAuth(embedConfig);
13311
+ case exports.AuthType.TrustedAuthTokenCookieless:
13312
+ return doCookielessTokenAuth(embedConfig);
13313
+ case exports.AuthType.Basic:
13314
+ return doBasicAuth(embedConfig);
13315
+ default:
13316
+ return Promise.resolve(true);
13317
+ }
13171
13318
  };
13172
13319
 
13173
- var _createSet = createSet;
13174
-
13175
- /** Used as the size to enable large array optimizations. */
13176
- var LARGE_ARRAY_SIZE$1 = 200;
13177
-
13178
- /**
13179
- * The base implementation of `_.uniqBy` without support for iteratee shorthands.
13180
- *
13181
- * @private
13182
- * @param {Array} array The array to inspect.
13183
- * @param {Function} [iteratee] The iteratee invoked per element.
13184
- * @param {Function} [comparator] The comparator invoked per element.
13185
- * @returns {Array} Returns the new duplicate free array.
13186
- */
13187
- function baseUniq(array, iteratee, comparator) {
13188
- var index = -1,
13189
- includes = _arrayIncludes,
13190
- length = array.length,
13191
- isCommon = true,
13192
- result = [],
13193
- seen = result;
13194
-
13195
- if (comparator) {
13196
- isCommon = false;
13197
- includes = _arrayIncludesWith;
13198
- }
13199
- else if (length >= LARGE_ARRAY_SIZE$1) {
13200
- var set = iteratee ? null : _createSet(array);
13201
- if (set) {
13202
- return _setToArray(set);
13203
- }
13204
- isCommon = false;
13205
- includes = _cacheHas;
13206
- seen = new _SetCache;
13207
- }
13208
- else {
13209
- seen = iteratee ? [] : result;
13210
- }
13211
- outer:
13212
- while (++index < length) {
13213
- var value = array[index],
13214
- computed = iteratee ? iteratee(value) : value;
13215
-
13216
- value = (comparator || value !== 0) ? value : 0;
13217
- if (isCommon && computed === computed) {
13218
- var seenIndex = seen.length;
13219
- while (seenIndex--) {
13220
- if (seen[seenIndex] === computed) {
13221
- continue outer;
13222
- }
13223
- }
13224
- if (iteratee) {
13225
- seen.push(computed);
13226
- }
13227
- result.push(value);
13228
- }
13229
- else if (!includes(seen, computed, comparator)) {
13230
- if (seen !== result) {
13231
- seen.push(computed);
13232
- }
13233
- result.push(value);
13234
- }
13235
- }
13236
- return result;
13237
- }
13238
-
13239
- var _baseUniq = baseUniq;
13240
-
13241
- /**
13242
- * Creates a duplicate-free version of an array, using
13243
- * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
13244
- * for equality comparisons, in which only the first occurrence of each element
13245
- * is kept. The order of result values is determined by the order they occur
13246
- * in the array.
13247
- *
13248
- * @static
13249
- * @memberOf _
13250
- * @since 0.1.0
13251
- * @category Array
13252
- * @param {Array} array The array to inspect.
13253
- * @returns {Array} Returns the new duplicate free array.
13254
- * @example
13255
- *
13256
- * _.uniq([2, 1, 2]);
13257
- * // => [2, 1]
13258
- */
13259
- function uniq(array) {
13260
- return (array && array.length) ? _baseUniq(array) : [];
13261
- }
13262
-
13263
- var uniq_1 = uniq;
13264
-
13265
13320
  /* eslint-disable camelcase */
13266
13321
  const CONFIG_DEFAULTS = {
13267
13322
  loginFailedMessage: 'Not logged in',
@@ -13722,6 +13777,8 @@ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!]
13722
13777
  });
13723
13778
  }
13724
13779
 
13780
+ var name="@thoughtspot/visual-embed-sdk";var version="1.28.0-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:"44 kB"}],scripts:scripts,peerDependencies:peerDependencies,dependencies:dependencies,devDependencies:devDependencies,author:author,email:email,license:license,directories:directories,repository:repository,publishConfig:publishConfig,keywords:keywords,bugs:bugs,homepage:homepage,globals:globals};
13781
+
13725
13782
  /**
13726
13783
  * Copyright (c) 2022
13727
13784
  *
@@ -15221,7 +15278,7 @@ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!]
15221
15278
  }
15222
15279
  getEmbedParams() {
15223
15280
  var _a;
15224
- const { hideResults, expandAllDataSource, enableSearchAssist, forceTable, searchOptions, runtimeFilters, dataSource, dataSources, excludeRuntimeFiltersfromURL, hideSearchBar, dataPanelV2 = false, useLastSelectedSources = false, runtimeParameters, } = this.viewConfig;
15281
+ const { hideResults, enableSearchAssist, forceTable, searchOptions, runtimeFilters, dataSource, dataSources, excludeRuntimeFiltersfromURL, hideSearchBar, dataPanelV2 = false, useLastSelectedSources = false, runtimeParameters, } = this.viewConfig;
15225
15282
  const queryParams = this.getBaseQueryParams();
15226
15283
  queryParams[Param.HideActions] = [
15227
15284
  ...((_a = queryParams[Param.HideActions]) !== null && _a !== void 0 ? _a : []),
@@ -15463,6 +15520,7 @@ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!]
15463
15520
  exports.AnswerService = AnswerService;
15464
15521
  exports.AppEmbed = AppEmbed;
15465
15522
  exports.LiveboardEmbed = LiveboardEmbed;
15523
+ exports.MIXPANEL_EVENT = MIXPANEL_EVENT;
15466
15524
  exports.PinboardEmbed = PinboardEmbed;
15467
15525
  exports.SageEmbed = SageEmbed;
15468
15526
  exports.SearchBarEmbed = SearchBarEmbed;
@@ -15474,6 +15532,7 @@ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!]
15474
15532
  exports.init = init;
15475
15533
  exports.logout = logout$1;
15476
15534
  exports.prefetch = prefetch;
15535
+ exports.uploadMixpanelEvent = uploadMixpanelEvent;
15477
15536
 
15478
15537
  Object.defineProperty(exports, '__esModule', { value: true });
15479
15538