@thoughtspot/visual-embed-sdk 1.28.0-alpha.5 → 1.28.0

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 (125) hide show
  1. package/README.md +1 -1
  2. package/cjs/package.json +2 -2
  3. package/cjs/src/auth.d.ts.map +1 -1
  4. package/cjs/src/auth.js +2 -2
  5. package/cjs/src/auth.js.map +1 -1
  6. package/cjs/src/authToken.d.ts +0 -6
  7. package/cjs/src/authToken.d.ts.map +1 -1
  8. package/cjs/src/authToken.js +0 -6
  9. package/cjs/src/authToken.js.map +1 -1
  10. package/cjs/src/embed/app.d.ts +13 -20
  11. package/cjs/src/embed/app.d.ts.map +1 -1
  12. package/cjs/src/embed/app.js +2 -2
  13. package/cjs/src/embed/app.js.map +1 -1
  14. package/cjs/src/embed/base.d.ts +1 -1
  15. package/cjs/src/embed/base.d.ts.map +1 -1
  16. package/cjs/src/embed/base.js +5 -7
  17. package/cjs/src/embed/base.js.map +1 -1
  18. package/cjs/src/embed/base.spec.js +1 -1
  19. package/cjs/src/embed/base.spec.js.map +1 -1
  20. package/cjs/src/embed/liveboard.d.ts +2 -8
  21. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  22. package/cjs/src/embed/liveboard.js.map +1 -1
  23. package/cjs/src/embed/search.d.ts +5 -11
  24. package/cjs/src/embed/search.d.ts.map +1 -1
  25. package/cjs/src/embed/search.js +4 -4
  26. package/cjs/src/embed/search.js.map +1 -1
  27. package/cjs/src/embed/ts-embed.d.ts +1 -1
  28. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  29. package/cjs/src/embed/ts-embed.js +6 -6
  30. package/cjs/src/embed/ts-embed.js.map +1 -1
  31. package/cjs/src/embed/ts-embed.spec.js +18 -9
  32. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  33. package/cjs/src/index.d.ts +0 -1
  34. package/cjs/src/index.d.ts.map +1 -1
  35. package/cjs/src/index.js +1 -3
  36. package/cjs/src/index.js.map +1 -1
  37. package/cjs/src/react/index.spec.js +12 -0
  38. package/cjs/src/react/index.spec.js.map +1 -1
  39. package/cjs/src/types.d.ts +36 -29
  40. package/cjs/src/types.d.ts.map +1 -1
  41. package/cjs/src/types.js +23 -12
  42. package/cjs/src/types.js.map +1 -1
  43. package/dist/src/auth.d.ts.map +1 -1
  44. package/dist/src/authToken.d.ts +0 -6
  45. package/dist/src/authToken.d.ts.map +1 -1
  46. package/dist/src/embed/app.d.ts +13 -20
  47. package/dist/src/embed/app.d.ts.map +1 -1
  48. package/dist/src/embed/base.d.ts +1 -1
  49. package/dist/src/embed/base.d.ts.map +1 -1
  50. package/dist/src/embed/liveboard.d.ts +2 -8
  51. package/dist/src/embed/liveboard.d.ts.map +1 -1
  52. package/dist/src/embed/search.d.ts +5 -11
  53. package/dist/src/embed/search.d.ts.map +1 -1
  54. package/dist/src/embed/ts-embed.d.ts +1 -1
  55. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  56. package/dist/src/index.d.ts +0 -1
  57. package/dist/src/index.d.ts.map +1 -1
  58. package/dist/src/types.d.ts +36 -29
  59. package/dist/src/types.d.ts.map +1 -1
  60. package/dist/tsembed-react.es.js +1465 -1460
  61. package/dist/tsembed-react.js +2225 -2233
  62. package/dist/tsembed.es.js +1850 -1846
  63. package/dist/tsembed.js +15342 -15352
  64. package/dist/visual-embed-sdk-react-full.d.ts +54 -75
  65. package/dist/visual-embed-sdk-react.d.ts +54 -75
  66. package/dist/visual-embed-sdk.d.ts +54 -75
  67. package/lib/package.json +2 -2
  68. package/lib/src/auth.d.ts.map +1 -1
  69. package/lib/src/auth.js +3 -3
  70. package/lib/src/auth.js.map +1 -1
  71. package/lib/src/authToken.d.ts +0 -6
  72. package/lib/src/authToken.d.ts.map +1 -1
  73. package/lib/src/authToken.js +0 -6
  74. package/lib/src/authToken.js.map +1 -1
  75. package/lib/src/embed/app.d.ts +13 -20
  76. package/lib/src/embed/app.d.ts.map +1 -1
  77. package/lib/src/embed/app.js +2 -2
  78. package/lib/src/embed/app.js.map +1 -1
  79. package/lib/src/embed/base.d.ts +1 -1
  80. package/lib/src/embed/base.d.ts.map +1 -1
  81. package/lib/src/embed/base.js +5 -7
  82. package/lib/src/embed/base.js.map +1 -1
  83. package/lib/src/embed/base.spec.js +2 -2
  84. package/lib/src/embed/base.spec.js.map +1 -1
  85. package/lib/src/embed/liveboard.d.ts +2 -8
  86. package/lib/src/embed/liveboard.d.ts.map +1 -1
  87. package/lib/src/embed/liveboard.js +1 -1
  88. package/lib/src/embed/liveboard.js.map +1 -1
  89. package/lib/src/embed/search.d.ts +5 -11
  90. package/lib/src/embed/search.d.ts.map +1 -1
  91. package/lib/src/embed/search.js +5 -5
  92. package/lib/src/embed/search.js.map +1 -1
  93. package/lib/src/embed/ts-embed.d.ts +1 -1
  94. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  95. package/lib/src/embed/ts-embed.js +9 -9
  96. package/lib/src/embed/ts-embed.js.map +1 -1
  97. package/lib/src/embed/ts-embed.spec.js +18 -9
  98. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  99. package/lib/src/index.d.ts +0 -1
  100. package/lib/src/index.d.ts.map +1 -1
  101. package/lib/src/index.js +0 -1
  102. package/lib/src/index.js.map +1 -1
  103. package/lib/src/react/index.spec.js +12 -0
  104. package/lib/src/react/index.spec.js.map +1 -1
  105. package/lib/src/types.d.ts +36 -29
  106. package/lib/src/types.d.ts.map +1 -1
  107. package/lib/src/types.js +23 -12
  108. package/lib/src/types.js.map +1 -1
  109. package/lib/src/utils/authService/authService.spec.js +1 -1
  110. package/lib/src/utils/authService/authService.spec.js.map +1 -1
  111. package/lib/src/visual-embed-sdk.d.ts +58 -83
  112. package/package.json +2 -2
  113. package/src/auth.ts +6 -6
  114. package/src/authToken.ts +0 -6
  115. package/src/embed/app.ts +15 -27
  116. package/src/embed/base.spec.ts +3 -3
  117. package/src/embed/base.ts +12 -14
  118. package/src/embed/liveboard.ts +3 -16
  119. package/src/embed/search.ts +10 -19
  120. package/src/embed/ts-embed.spec.ts +34 -26
  121. package/src/embed/ts-embed.ts +39 -43
  122. package/src/index.ts +0 -2
  123. package/src/react/index.spec.tsx +29 -0
  124. package/src/types.ts +37 -29
  125. package/src/utils/authService/authService.spec.ts +4 -4
@@ -572,6 +572,7 @@
572
572
  * .then((data) => data.token);
573
573
  * }
574
574
  * });
575
+ * });
575
576
  * ```
576
577
  */
577
578
  AuthType["TrustedAuthToken"] = "AuthServer";
@@ -606,27 +607,27 @@
606
607
  })(AuthType || (AuthType = {}));
607
608
  (function (HomeLeftNavItem) {
608
609
  /**
609
- * @version SDK: 1.27.9| ThoughtSpot: 9.12.0.cl
610
+ * @version SDK: 1.28.0| ThoughtSpot: 9.12.5.cl
610
611
  */
611
612
  HomeLeftNavItem["SearchData"] = "search-data";
612
613
  /**
613
- * @version SDK: 1.27.9| ThoughtSpot: 9.12.0.cl
614
+ * @version SDK: 1.28.0| ThoughtSpot: 9.12.5.cl
614
615
  */
615
616
  HomeLeftNavItem["Home"] = "insights-home";
616
617
  /**
617
- * @version SDK: 1.27.9| ThoughtSpot: 9.12.0.cl
618
+ * @version SDK: 1.28.0| ThoughtSpot: 9.12.5.cl
618
619
  */
619
620
  HomeLeftNavItem["Liveboards"] = "liveboards";
620
621
  /**
621
- * @version SDK: 1.27.9| ThoughtSpot: 9.12.0.cl
622
+ * @version SDK: 1.28.0| ThoughtSpot: 9.12.5.cl
622
623
  */
623
624
  HomeLeftNavItem["Answers"] = "answers";
624
625
  /**
625
- * @version SDK: 1.27.9| ThoughtSpot: 9.12.0.cl
626
+ * @version SDK: 1.28.0| ThoughtSpot: 9.12.5.cl
626
627
  */
627
628
  HomeLeftNavItem["MonitorSubscription"] = "monitor-alerts";
628
629
  /**
629
- * @version SDK: 1.27.9| ThoughtSpot: 9.12.0.cl
630
+ * @version SDK: 1.28.0| ThoughtSpot: 9.12.5.cl
630
631
  */
631
632
  HomeLeftNavItem["SpotIQAnalysis"] = "spotiq-analysis";
632
633
  })(exports.HomeLeftNavItem || (exports.HomeLeftNavItem = {}));
@@ -707,10 +708,6 @@
707
708
  HomepageModule["MyLibrary"] = "MY_LIBRARY";
708
709
  /**
709
710
  * Trending list
710
- *
711
- * **Note**: This option does not apply to the classic homepage.
712
- * To access the updated modular homepage, set
713
- * `modularHomeExperience` to `true` (available in Early Access from 9.12.0.cl onwards).
714
711
  */
715
712
  HomepageModule["Trending"] = "TRENDING";
716
713
  /**
@@ -904,7 +901,8 @@
904
901
  *
905
902
  * API - API call failure error.
906
903
  *
907
- * FULLSCREEN - Error when presenting a Liveboard or visualization in full screen mode.
904
+ * FULLSCREEN - Error when presenting a Liveboard or visualization in full screen
905
+ * mode.
908
906
  *
909
907
  * SINGLE_VALUE_FILTER - Error due to multiple values in the single value filter.
910
908
  *
@@ -5713,6 +5711,8 @@
5713
5711
 
5714
5712
  var isEqual_1 = isEqual;
5715
5713
 
5714
+ var name="@thoughtspot/visual-embed-sdk";var version="1.28.0";var description="ThoughtSpot Embed SDK";var module="lib/src/index.js";var main="dist/tsembed.js";var types="lib/src/index.d.ts";var files=["dist/**","lib/**","src/**","cjs/**"];var exports$1={".":{"import":"./lib/src/index.js",require:"./cjs/src/index.js",types:"./lib/src/index.d.ts"},"./react":{"import":"./lib/src/react/all-types-export.js",require:"./cjs/src/react/all-types-export.js",types:"./lib/src/react/all-types-export.d.ts"},"./lib/src/react":{"import":"./lib/src/react/all-types-export.js",require:"./cjs/src/react/all-types-export.js",types:"./lib/src/react/all-types-export.d.ts"}};var typesVersions={"*":{react:["./lib/src/react/all-types-export.d.ts"]}};var scripts={lint:"eslint 'src/**'","lint:fix":"eslint 'src/**/*.*' --fix",tsc:"tsc -p . --incremental false; tsc -p . --incremental false --module commonjs --outDir cjs",start:"gatsby develop","build:gatsby":"npm run clean:gatsby && gatsby build --prefix-paths","build:gatsby:noprefix":"npm run clean:gatsby && gatsby build","serve:gatsby":"gatsby serve","clean:gatsby":"gatsby clean","build-and-publish":"npm run build:gatsby && npm run publish","bundle-dts-file":"dts-bundle --name @thoughtspot/visual-embed-sdk --out visual-embed-sdk.d.ts --main lib/src/index.d.ts","bundle-dts":"dts-bundle --name ../../dist/visual-embed-sdk --main lib/src/index.d.ts --outputAsModuleFolder=true","bundle-dts-react":"dts-bundle --name ../../../dist/visual-embed-sdk-react --main lib/src/react/index.d.ts --outputAsModuleFolder=true","bundle-dts-react-full":"dts-bundle --name ../../../dist/visual-embed-sdk-react-full --main lib/src/react/all-types-export.d.ts --outputAsModuleFolder=true",build:"rollup -c",watch:"rollup -cw","docs-cmd":"node scripts/gatsby-commands.js",docgen:"typedoc --tsconfig tsconfig.json --theme typedoc-theme","test-sdk":"jest -c jest.config.sdk.js --runInBand","test-docs":"jest -c jest.config.docs.js",test:"npm run test-sdk && npm run test-docs",posttest:"cat ./coverage/sdk/lcov.info | coveralls","is-publish-allowed":"node scripts/is-publish-allowed.js",prepublishOnly:"npm run is-publish-allowed && npm run test && npm run tsc && npm run bundle-dts-file && npm run bundle-dts && npm run bundle-dts-react && npm run bundle-dts-react-full && npm run build","check-size":"npm run build && size-limit","publish-dev":"npm publish --tag dev","publish-prod":"npm publish --tag latest"};var peerDependencies={react:"> 16.8.0","react-dom":"> 16.8.0"};var dependencies={algoliasearch:"^4.10.5",classnames:"^2.3.1",dompurify:"^2.3.4","eslint-plugin-comment-length":"^0.9.2","eslint-plugin-jsdoc":"^46.9.0",eventemitter3:"^4.0.7","gatsby-plugin-vercel":"^1.0.3","html-react-parser":"^1.4.12",lodash:"^4.17.21","mixpanel-browser":"^2.45.0","ts-deepmerge":"^6.0.2",tslib:"^2.5.3","use-deep-compare-effect":"^1.8.1"};var devDependencies={"@mdx-js/mdx":"^1.6.22","@mdx-js/react":"^1.6.22","@react-icons/all-files":"^4.1.0","@rollup/plugin-commonjs":"^18.0.0","@rollup/plugin-json":"^4.1.0","@rollup/plugin-node-resolve":"^11.2.1","@rollup/plugin-replace":"^5.0.2","@size-limit/preset-big-lib":"^8.2.6","@testing-library/dom":"^7.31.0","@testing-library/jest-dom":"^5.14.1","@testing-library/react":"^11.2.7","@testing-library/user-event":"^13.1.8","@types/jest":"^22.2.3","@types/mixpanel-browser":"^2.35.6","@types/react-test-renderer":"^17.0.1","@typescript-eslint/eslint-plugin":"^4.6.0","@typescript-eslint/parser":"^4.6.0",asciidoctor:"^2.2.1","babel-jest":"^26.6.3","babel-preset-gatsby":"^1.10.0","command-line-args":"^5.1.1",coveralls:"^3.1.0","current-git-branch":"^1.1.0","dts-bundle":"^0.7.3",eslint:"^7.12.1","eslint-config-airbnb-base":"^14.2.0","eslint-config-prettier":"^6.15.0","eslint-import-resolver-typescript":"^2.3.0","eslint-plugin-import":"^2.22.1","eslint-plugin-prettier":"^3.1.4","eslint-plugin-react-hooks":"^4.2.0","fs-extra":"^10.0.0",gatsby:"3.13.1","gatsby-plugin-algolia":"^0.22.2","gatsby-plugin-catch-links":"^3.1.0","gatsby-plugin-env-variables":"^2.1.0","gatsby-plugin-intl":"^0.3.3","gatsby-plugin-manifest":"^3.2.0","gatsby-plugin-output":"^0.1.3","gatsby-plugin-sass":"6.7.0","gatsby-plugin-sitemap":"^4.10.0","gatsby-source-filesystem":"3.1.0","gatsby-transformer-asciidoc":"2.1.0","gatsby-transformer-rehype":"2.0.0","gh-pages":"^3.1.0","highlight.js":"^10.6.0","html-to-text":"^8.0.0","identity-obj-proxy":"^3.0.0","istanbul-merge":"^1.1.1",jest:"^26.6.3","jest-fetch-mock":"^3.0.3",jsdom:"^17.0.0","node-sass":"^8.0.0",prettier:"2.1.2",react:"^16.14.0","react-dom":"^16.14.0","react-resizable":"^1.11.0","react-resize-detector":"^6.6.0","react-test-renderer":"^17.0.2","react-use-flexsearch":"^0.1.1",rollup:"2.30.0","rollup-plugin-typescript2":"0.27.3","ts-jest":"^26.5.5","ts-loader":"8.0.4",typedoc:"0.21.6","typedoc-plugin-toc-group":"thoughtspot/typedoc-plugin-toc-group",typescript:"^4.9.4","url-search-params-polyfill":"^8.1.0",util:"^0.12.4"};var author="ThoughtSpot";var email="support@thoughtspot.com";var license="ThoughtSpot Development Tools End User License Agreement";var directories={lib:"lib"};var repository={type:"git",url:"git+https://github.com/thoughtspot/visual-embed-sdk.git"};var publishConfig={registry:"https://registry.npmjs.org"};var keywords=["thoughtspot","everywhere","embed","sdk","analytics"];var bugs={url:"https://github.com/thoughtspot/visual-embed-sdk/issues"};var homepage="https://github.com/thoughtspot/visual-embed-sdk#readme";var globals={window:{}};var pkgInfo = {name:name,version:version,description:description,module:module,main:main,types:types,files:files,exports:exports$1,typesVersions:typesVersions,"size-limit":[{path:"dist/tsembed.js",limit:"45 kB"}],scripts:scripts,peerDependencies:peerDependencies,dependencies:dependencies,devDependencies:devDependencies,author:author,email:email,license:license,directories:directories,repository:repository,publishConfig:publishConfig,keywords:keywords,bugs:bugs,homepage:homepage,globals:globals};
5715
+
5716
5716
  /**
5717
5717
  * Checks if `value` is `undefined`.
5718
5718
  *
@@ -5985,585 +5985,38 @@
5985
5985
  throw new Error(INVALID_TOKEN_ERR);
5986
5986
  }
5987
5987
  };
5988
- /**
5989
- * Resets the auth token and a new token will be fetched on the next request.
5990
- *
5991
- * @version SDK: 1.28.0 | ThoughtSpot: *
5992
- * @group Authentication / Init
5993
- */
5994
5988
  const resetCachedAuthToken = () => {
5995
5989
  cachedAuthToken = null;
5996
5990
  };
5997
5991
 
5998
- let config = {};
5999
- /**
6000
- * Gets the configuration embed was initialized with.
6001
- *
6002
- * @returns {@link EmbedConfig} The configuration embed was initialized with.
6003
- * @version SDK: 1.19.0 | ThoughtSpot: *
6004
- * @group Global methods
6005
- */
6006
- const getEmbedConfig = () => config;
6007
-
6008
- /**
6009
- * Fetch wrapper that adds the authentication token to the request.
6010
- * Use this to call the ThoughtSpot APIs when using the visual embed sdk.
6011
- *
6012
- * @param input
6013
- * @param init
6014
- * @version SDK: 1.28.0
6015
- * @group Global methods
6016
- */
6017
- const tokenizedFetch = async (input, init) => {
6018
- const embedConfig = getEmbedConfig();
6019
- if (embedConfig.authType !== AuthType.TrustedAuthTokenCookieless) {
6020
- return fetch(input, init);
6021
- }
6022
- const req = new Request(input, init);
6023
- const authToken = await getAuthenticationToken(embedConfig);
6024
- if (authToken) {
6025
- req.headers.append('Authorization', `Bearer ${authToken}`);
6026
- }
6027
- return fetch(req);
5992
+ var Config = {
5993
+ DEBUG: false,
5994
+ LIB_VERSION: '2.45.0'
6028
5995
  };
6029
5996
 
6030
- /**
6031
- *
6032
- * @param root0
6033
- * @param root0.query
6034
- * @param root0.variables
6035
- * @param root0.thoughtSpotHost
6036
- * @param root0.isCompositeQuery
6037
- */
6038
- async function graphqlQuery({ query, variables, thoughtSpotHost, isCompositeQuery = false, }) {
6039
- const operationName = getOperationNameFromQuery(query);
6040
- try {
6041
- const response = await fetch(`${thoughtSpotHost}/prism/?op=${operationName}`, {
6042
- method: 'POST',
6043
- headers: {
6044
- 'content-type': 'application/json;charset=UTF-8',
6045
- 'x-requested-by': 'ThoughtSpot',
6046
- accept: '*/*',
6047
- 'accept-language': 'en-us',
6048
- },
6049
- body: JSON.stringify({
6050
- operationName,
6051
- query,
6052
- variables,
6053
- }),
6054
- credentials: 'include',
6055
- });
6056
- const result = await response.json();
6057
- const dataValues = Object.values(result.data);
6058
- return (isCompositeQuery) ? result.data : dataValues[0];
6059
- }
6060
- catch (error) {
6061
- return error;
6062
- }
6063
- }
6064
-
6065
- const getSourceDetailQuery = `
6066
- query GetSourceDetail($ids: [GUID!]!) {
6067
- getSourceDetailById(ids: $ids, type: LOGICAL_TABLE) {
6068
- id
6069
- name
6070
- description
6071
- authorName
6072
- authorDisplayName
6073
- isExternal
6074
- type
6075
- created
6076
- modified
6077
- columns {
6078
- id
6079
- name
6080
- author
6081
- authorDisplayName
6082
- description
6083
- dataType
6084
- type
6085
- modified
6086
- ownerName
6087
- owner
6088
- dataRecency
6089
- sources {
6090
- tableId
6091
- tableName
6092
- columnId
6093
- columnName
6094
- __typename
6095
- }
6096
- synonyms
6097
- cohortAnswerId
6098
- __typename
6099
- }
6100
- relationships
6101
- destinationRelationships
6102
- dataSourceId
6103
- __typename
6104
- }
6105
- }
6106
- `;
6107
- const sourceDetailCache = new Map();
6108
- /**
6109
- *
6110
- * @param thoughtSpotHost
6111
- * @param sourceId
6112
- */
6113
- async function getSourceDetail(thoughtSpotHost, sourceId) {
6114
- if (sourceDetailCache.get(sourceId)) {
6115
- return sourceDetailCache.get(sourceId);
6116
- }
6117
- const details = await graphqlQuery({
6118
- query: getSourceDetailQuery,
6119
- variables: {
6120
- ids: [sourceId],
6121
- },
6122
- thoughtSpotHost,
6123
- });
6124
- const souceDetails = details[0];
6125
- if (souceDetails) {
6126
- sourceDetailCache.set(sourceId, souceDetails);
6127
- }
6128
- return souceDetails;
5997
+ // since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
5998
+ var window$1;
5999
+ if (typeof(window) === 'undefined') {
6000
+ var loc = {
6001
+ hostname: ''
6002
+ };
6003
+ window$1 = {
6004
+ navigator: { userAgent: '' },
6005
+ document: {
6006
+ location: loc,
6007
+ referrer: ''
6008
+ },
6009
+ screen: { width: 0, height: 0 },
6010
+ location: loc
6011
+ };
6012
+ } else {
6013
+ window$1 = window;
6129
6014
  }
6130
6015
 
6131
- const bachSessionId = `
6132
- id {
6133
- sessionId
6134
- genNo
6135
- acSession {
6136
- sessionId
6137
- genNo
6138
- }
6139
- }
6140
- `;
6141
- const getUnaggregatedAnswerSession = `
6142
- mutation GetUnAggregatedAnswerSession($session: BachSessionIdInput!, $columns: [UserPointSelectionInput!]!) {
6143
- Answer__getUnaggregatedAnswer(session: $session, columns: $columns) {
6144
- ${bachSessionId}
6145
- answer {
6146
- visualizations {
6147
- ... on TableViz {
6148
- columns {
6149
- column {
6150
- id
6151
- name
6152
- referencedColumns {
6153
- guid
6154
- displayName
6155
- }
6156
- }
6157
- }
6158
- }
6159
- }
6160
- }
6161
- }
6162
- }
6163
- `;
6164
- const removeColumns = `
6165
- mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!], $columnIds: [GUID!]) {
6166
- Answer__removeColumns(
6167
- session: $session
6168
- logicalColumnIds: $logicalColumnIds
6169
- columnIds: $columnIds
6170
- ) {
6171
- ${bachSessionId}
6172
- }
6173
- }
6174
- `;
6175
- const addColumns = `
6176
- mutation AddColumns($session: BachSessionIdInput!, $columns: [AnswerColumnInfo!]!) {
6177
- Answer__addColumn(session: $session, columns: $columns) {
6178
- ${bachSessionId}
6179
- }
6180
- }
6181
- `;
6182
- const getAnswerData = `
6183
- query GetTableWithHeadlineData($session: BachSessionIdInput!, $deadline: Int!, $dataPaginationParams: DataPaginationParamsInput!) {
6184
- getAnswer(session: $session) {
6185
- ${bachSessionId}
6186
- answer {
6187
- id
6188
- visualizations {
6189
- id
6190
- ... on TableViz {
6191
- columns {
6192
- column {
6193
- id
6194
- name
6195
- type
6196
- aggregationType
6197
- dataType
6198
- }
6199
- }
6200
- data(deadline: $deadline, pagination: $dataPaginationParams)
6201
- }
6202
- }
6203
- }
6204
- }
6205
- }
6206
- `;
6207
-
6208
- // eslint-disable-next-line no-shadow
6209
- var OperationType;
6210
- (function (OperationType) {
6211
- OperationType["GetChartWithData"] = "GetChartWithData";
6212
- OperationType["GetTableWithHeadlineData"] = "GetTableWithHeadlineData";
6213
- })(OperationType || (OperationType = {}));
6214
- /**
6215
- * Class representing the answer service provided with the
6216
- * custom action payload. This service could be used to run
6217
- * graphql queries in the context of the answer on which the
6218
- * custom action was triggered.
6219
- *
6220
- * @example
6221
- * ```js
6222
- * embed.on(EmbedEvent.CustomAction, e => {
6223
- * const underlying = await e.answerService.getUnderlyingDataForPoint([
6224
- * 'col name 1'
6225
- * ]);
6226
- * const data = await underlying.fetchData(0, 100);
6227
- * })
6228
- * ```
6229
- * @version SDK: 1.25.0| ThoughtSpot: 9.10.0.cl
6230
- * @group Events
6231
- */
6232
- class AnswerService {
6233
- /**
6234
- * Should not need to be called directly.
6235
- *
6236
- * @param session
6237
- * @param answer
6238
- * @param thoughtSpotHost
6239
- * @param selectedPoints
6240
- */
6241
- constructor(session, answer, thoughtSpotHost, selectedPoints) {
6242
- this.session = session;
6243
- this.answer = answer;
6244
- this.thoughtSpotHost = thoughtSpotHost;
6245
- this.selectedPoints = selectedPoints;
6246
- this.session = removeTypename(session);
6247
- }
6248
- /**
6249
- * Get the details about the source used in the answer.
6250
- * This can be used to get the list of all columns in the data source for example.
6251
- */
6252
- async getSourceDetail() {
6253
- const sourceId = this.answer.sources[0].header.guid;
6254
- return getSourceDetail(this.thoughtSpotHost, sourceId);
6255
- }
6256
- /**
6257
- * Remove columnIds and return updated answer session.
6258
- *
6259
- * @param columnIds
6260
- * @returns
6261
- */
6262
- async removeColumns(columnIds) {
6263
- return this.executeQuery(removeColumns, {
6264
- logicalColumnIds: columnIds,
6265
- });
6266
- }
6267
- /**
6268
- * Add columnIds and return updated answer session.
6269
- *
6270
- * @param columnIds
6271
- * @returns
6272
- */
6273
- async addColumns(columnIds) {
6274
- return this.executeQuery(addColumns, {
6275
- columns: columnIds.map((colId) => ({ logicalColumnId: colId })),
6276
- });
6277
- }
6278
- /**
6279
- * Fetch data from the answer.
6280
- *
6281
- * @param offset
6282
- * @param size
6283
- * @returns
6284
- */
6285
- async fetchData(offset = 0, size = 1000) {
6286
- const { answer } = await this.executeQuery(getAnswerData, {
6287
- deadline: 0,
6288
- dataPaginationParams: {
6289
- isClientPaginated: true,
6290
- offset,
6291
- size,
6292
- },
6293
- });
6294
- const { columns, data } = answer.visualizations.find((viz) => !!viz.data) || {};
6295
- return {
6296
- columns,
6297
- data,
6298
- };
6299
- }
6300
- /**
6301
- * Fetch the data for the answer as a CSV blob. This might be
6302
- * quicker for larger data.
6303
- *
6304
- * @param userLocale
6305
- * @param includeInfo Include the CSV header in the output
6306
- * @returns Response
6307
- */
6308
- async fetchCSVBlob(userLocale = 'en-us', includeInfo = false) {
6309
- const fetchUrl = this.getFetchCSVBlobUrl(userLocale, includeInfo);
6310
- return tokenizedFetch(fetchUrl, {
6311
- credentials: 'include',
6312
- });
6313
- }
6314
- /**
6315
- * Just get the internal URL for this answer's data
6316
- * as a CSV blob.
6317
- *
6318
- * @param userLocale
6319
- * @param includeInfo
6320
- * @returns
6321
- */
6322
- getFetchCSVBlobUrl(userLocale = 'en-us', includeInfo = false) {
6323
- return `${this.thoughtSpotHost}/prism/download/answer/csv?sessionId=${this.session.sessionId}&genNo=${this.session.genNo}&userLocale=${userLocale}&exportFileName=data&hideCsvHeader=${!includeInfo}`;
6324
- }
6325
- /**
6326
- * Get underlying data given a point and the output column names.
6327
- * In case of a context menu action, the selectedPoints are
6328
- * automatically passed.
6329
- *
6330
- * @param outputColumnNames
6331
- * @param selectedPoints
6332
- * @example
6333
- * ```js
6334
- * embed.on(EmbedEvent.CustomAction, e => {
6335
- * const underlying = await e.answerService.getUnderlyingDataForPoint([
6336
- * 'col name 1' // The column should exist in the data source.
6337
- * ]);
6338
- * const data = await underlying.fetchData(0, 100);
6339
- * })
6340
- * ```
6341
- * @version SDK: 1.25.0| ThoughtSpot: 9.10.0.cl
6342
- */
6343
- async getUnderlyingDataForPoint(outputColumnNames, selectedPoints) {
6344
- if (!selectedPoints && !this.selectedPoints) {
6345
- throw new Error('Needs to be triggered in context of a point');
6346
- }
6347
- if (!selectedPoints) {
6348
- selectedPoints = getSelectedPointsForUnderlyingDataQuery(this.selectedPoints);
6349
- }
6350
- const sourceDetail = await this.getSourceDetail();
6351
- const ouputColumnGuids = getGuidsFromColumnNames(sourceDetail, outputColumnNames);
6352
- const unAggAnswer = await graphqlQuery({
6353
- query: getUnaggregatedAnswerSession,
6354
- variables: {
6355
- session: this.session,
6356
- columns: selectedPoints,
6357
- },
6358
- thoughtSpotHost: this.thoughtSpotHost,
6359
- });
6360
- const unaggAnswerSession = new AnswerService(unAggAnswer.id, unAggAnswer.answer, this.thoughtSpotHost);
6361
- const currentColumns = new Set(unAggAnswer.answer.visualizations[0].columns
6362
- .map((c) => c.column.referencedColumns[0].guid));
6363
- const columnsToAdd = [...ouputColumnGuids].filter((col) => !currentColumns.has(col));
6364
- if (columnsToAdd.length) {
6365
- await unaggAnswerSession.addColumns(columnsToAdd);
6366
- }
6367
- const columnsToRemove = [...currentColumns].filter((col) => !ouputColumnGuids.has(col));
6368
- if (columnsToRemove.length) {
6369
- await unaggAnswerSession.removeColumns(columnsToRemove);
6370
- }
6371
- return unaggAnswerSession;
6372
- }
6373
- /**
6374
- * Execute a custom graphql query in the context of the answer.
6375
- *
6376
- * @param query graphql query
6377
- * @param variables graphql variables
6378
- * @returns
6379
- */
6380
- async executeQuery(query, variables) {
6381
- const data = await graphqlQuery({
6382
- query,
6383
- variables: {
6384
- session: this.session,
6385
- ...variables,
6386
- },
6387
- thoughtSpotHost: this.thoughtSpotHost,
6388
- isCompositeQuery: false,
6389
- });
6390
- this.session = deepMerge(this.session, (data === null || data === void 0 ? void 0 : data.id) || {});
6391
- return data;
6392
- }
6393
- /**
6394
- * Get the internal session details for the answer.
6395
- *
6396
- * @returns
6397
- */
6398
- getSession() {
6399
- return this.session;
6400
- }
6401
- }
6402
- /**
6403
- *
6404
- * @param sourceDetail
6405
- * @param colNames
6406
- */
6407
- function getGuidsFromColumnNames(sourceDetail, colNames) {
6408
- const cols = sourceDetail.columns.reduce((colSet, col) => {
6409
- colSet[col.name] = col;
6410
- return colSet;
6411
- }, {});
6412
- return new Set(colNames.map((colName) => {
6413
- const col = cols[colName];
6414
- return col.id;
6415
- }));
6416
- }
6417
- /**
6418
- *
6419
- * @param selectedPoints
6420
- */
6421
- function getSelectedPointsForUnderlyingDataQuery(selectedPoints) {
6422
- const underlyingDataPoint = [];
6423
- /**
6424
- *
6425
- * @param colVal
6426
- */
6427
- function addPointFromColVal(colVal) {
6428
- var _a;
6429
- const dataType = colVal.column.dataType;
6430
- const id = colVal.column.id;
6431
- let dataValue;
6432
- if (dataType === 'DATE') {
6433
- if (Number.isFinite(colVal.value)) {
6434
- dataValue = [{
6435
- epochRange: {
6436
- startEpoch: colVal.value,
6437
- },
6438
- }];
6439
- // Case for custom calendar.
6440
- }
6441
- else if ((_a = colVal.value) === null || _a === void 0 ? void 0 : _a.v) {
6442
- dataValue = [{
6443
- epochRange: {
6444
- startEpoch: colVal.value.v.s,
6445
- endEpoch: colVal.value.v.e,
6446
- },
6447
- }];
6448
- }
6449
- }
6450
- else {
6451
- dataValue = [{ value: colVal.value }];
6452
- }
6453
- underlyingDataPoint.push({
6454
- columnId: colVal.column.id,
6455
- dataValue,
6456
- });
6457
- }
6458
- selectedPoints.forEach((p) => {
6459
- p.selectedAttributes.forEach(addPointFromColVal);
6460
- });
6461
- return underlyingDataPoint;
6462
- }
6463
-
6464
- const ERROR_MESSAGE = {
6465
- INVALID_THOUGHTSPOT_HOST: 'Error parsing ThoughtSpot host. Please provide a valid URL.',
6466
- LIVEBOARD_VIZ_ID_VALIDATION: 'Please provide either liveboardId or pinboardId',
6467
- TRIGGER_TIMED_OUT: 'Trigger timedout in getting response',
6468
- SEARCHEMBED_BETA_WRANING_MESSAGE: 'Search Embed is in Beta in this release.',
6469
- SAGE_EMBED_BETA_WARNING_MESSAGE: 'Sage Embed is in Beta in this release.',
6470
- };
6471
-
6472
- /**
6473
- * Copyright (c) 2023
6474
- *
6475
- * Utilities related to reading configuration objects
6476
- *
6477
- * @summary Config-related utils
6478
- * @author Ayon Ghosh <ayon.ghosh@thoughtspot.com>
6479
- */
6480
- const urlRegex = new RegExp([
6481
- '(^(https?:)//)?',
6482
- '(([^:/?#]*)(?::([0-9]+))?)',
6483
- '(/{0,1}[^?#]*)',
6484
- '(\\?[^#]*|)',
6485
- '(#.*|)$', // hash
6486
- ].join(''));
6487
- /**
6488
- * Parse and construct the ThoughtSpot hostname or IP address
6489
- * from the embed configuration object.
6490
- *
6491
- * @param config
6492
- */
6493
- const getThoughtSpotHost = (config) => {
6494
- if (!config.thoughtSpotHost) {
6495
- throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
6496
- }
6497
- const urlParts = config.thoughtSpotHost.match(urlRegex);
6498
- if (!urlParts) {
6499
- throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
6500
- }
6501
- const protocol = urlParts[2] || window.location.protocol;
6502
- const host = urlParts[3];
6503
- let path = urlParts[6];
6504
- // Lose the trailing / if any
6505
- if (path.charAt(path.length - 1) === '/') {
6506
- path = path.substring(0, path.length - 1);
6507
- }
6508
- // const urlParams = urlParts[7];
6509
- // const hash = urlParts[8];
6510
- return `${protocol}//${host}${path}`;
6511
- };
6512
- const getV2BasePath = (config) => {
6513
- if (config.basepath) {
6514
- return config.basepath;
6515
- }
6516
- const tsHost = getThoughtSpotHost(config);
6517
- // This is to handle when e2e's. Search is run on pods for
6518
- // comp-blink-test-pipeline with baseUrl=https://localhost:8443.
6519
- // This is to handle when the developer is developing in their local
6520
- // environment.
6521
- if (tsHost.includes('://localhost') && !tsHost.includes(':8443')) {
6522
- return '';
6523
- }
6524
- return 'v2';
6525
- };
6526
- /**
6527
- * It is a good idea to keep URLs under 2000 chars.
6528
- * If this is ever breached, since we pass view configuration through
6529
- * URL params, we would like to log a warning.
6530
- * Reference: https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
6531
- */
6532
- const URL_MAX_LENGTH = 2000;
6533
- /**
6534
- * The default CSS dimensions of the embedded app
6535
- */
6536
- const DEFAULT_EMBED_WIDTH = '100%';
6537
- const DEFAULT_EMBED_HEIGHT = '100%';
6538
-
6539
- var Config = {
6540
- DEBUG: false,
6541
- LIB_VERSION: '2.45.0'
6542
- };
6543
-
6544
- // since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
6545
- var window$1;
6546
- if (typeof(window) === 'undefined') {
6547
- var loc = {
6548
- hostname: ''
6549
- };
6550
- window$1 = {
6551
- navigator: { userAgent: '' },
6552
- document: {
6553
- location: loc,
6554
- referrer: ''
6555
- },
6556
- screen: { width: 0, height: 0 },
6557
- location: loc
6558
- };
6559
- } else {
6560
- window$1 = window;
6561
- }
6562
-
6563
- /*
6564
- * Saved references to long variable names, so that closure compiler can
6565
- * minimize file size.
6566
- */
6016
+ /*
6017
+ * Saved references to long variable names, so that closure compiler can
6018
+ * minimize file size.
6019
+ */
6567
6020
 
6568
6021
  var ArrayProto = Array.prototype;
6569
6022
  var FuncProto = Function.prototype;
@@ -11456,1886 +10909,2427 @@ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!]
11456
10909
  */
11457
10910
  MixpanelLib.prototype.track_with_groups = addOptOutCheckMixpanelLib(function(event_name, properties, groups, callback) {
11458
10911
  var tracking_props = _.extend({}, properties || {});
11459
- _.each(groups, function(v, k) {
11460
- if (v !== null && v !== undefined) {
11461
- tracking_props[k] = v;
11462
- }
11463
- });
11464
- return this.track(event_name, tracking_props, callback);
11465
- });
11466
-
11467
- MixpanelLib.prototype._create_map_key = function (group_key, group_id) {
11468
- return group_key + '_' + JSON.stringify(group_id);
11469
- };
11470
-
11471
- MixpanelLib.prototype._remove_group_from_cache = function (group_key, group_id) {
11472
- delete this._cached_groups[this._create_map_key(group_key, group_id)];
11473
- };
11474
-
11475
- /**
11476
- * Look up reference to a Mixpanel group
11477
- *
11478
- * ### Usage:
11479
- *
11480
- * mixpanel.get_group(group_key, group_id)
11481
- *
11482
- * @param {String} group_key Group key
11483
- * @param {Object} group_id A valid Mixpanel property type
11484
- * @returns {Object} A MixpanelGroup identifier
11485
- */
11486
- MixpanelLib.prototype.get_group = function (group_key, group_id) {
11487
- var map_key = this._create_map_key(group_key, group_id);
11488
- var group = this._cached_groups[map_key];
11489
- if (group === undefined || group._group_key !== group_key || group._group_id !== group_id) {
11490
- group = new MixpanelGroup();
11491
- group._init(this, group_key, group_id);
11492
- this._cached_groups[map_key] = group;
11493
- }
11494
- return group;
11495
- };
11496
-
11497
- /**
11498
- * Track mp_page_view event. This is now ignored by the server.
11499
- *
11500
- * @param {String} [page] The url of the page to record. If you don't include this, it defaults to the current url.
11501
- * @deprecated
11502
- */
11503
- MixpanelLib.prototype.track_pageview = function(page) {
11504
- if (_.isUndefined(page)) {
11505
- page = document$1.location.href;
11506
- }
11507
- this.track('mp_page_view', _.info.pageviewInfo(page));
11508
- };
11509
-
11510
- /**
11511
- * Track clicks on a set of document elements. Selector must be a
11512
- * valid query. Elements must exist on the page at the time track_links is called.
11513
- *
11514
- * ### Usage:
11515
- *
11516
- * // track click for link id #nav
11517
- * mixpanel.track_links('#nav', 'Clicked Nav Link');
11518
- *
11519
- * ### Notes:
11520
- *
11521
- * This function will wait up to 300 ms for the Mixpanel
11522
- * servers to respond. If they have not responded by that time
11523
- * it will head to the link without ensuring that your event
11524
- * has been tracked. To configure this timeout please see the
11525
- * set_config() documentation below.
11526
- *
11527
- * If you pass a function in as the properties argument, the
11528
- * function will receive the DOMElement that triggered the
11529
- * event as an argument. You are expected to return an object
11530
- * from the function; any properties defined on this object
11531
- * will be sent to mixpanel as event properties.
11532
- *
11533
- * @type {Function}
11534
- * @param {Object|String} query A valid DOM query, element or jQuery-esque list
11535
- * @param {String} event_name The name of the event to track
11536
- * @param {Object|Function} [properties] A properties object or function that returns a dictionary of properties when passed a DOMElement
11537
- */
11538
- MixpanelLib.prototype.track_links = function() {
11539
- return this._track_dom.call(this, LinkTracker, arguments);
11540
- };
11541
-
11542
- /**
11543
- * Track form submissions. Selector must be a valid query.
11544
- *
11545
- * ### Usage:
11546
- *
11547
- * // track submission for form id 'register'
11548
- * mixpanel.track_forms('#register', 'Created Account');
11549
- *
11550
- * ### Notes:
11551
- *
11552
- * This function will wait up to 300 ms for the mixpanel
11553
- * servers to respond, if they have not responded by that time
11554
- * it will head to the link without ensuring that your event
11555
- * has been tracked. To configure this timeout please see the
11556
- * set_config() documentation below.
11557
- *
11558
- * If you pass a function in as the properties argument, the
11559
- * function will receive the DOMElement that triggered the
11560
- * event as an argument. You are expected to return an object
11561
- * from the function; any properties defined on this object
11562
- * will be sent to mixpanel as event properties.
11563
- *
11564
- * @type {Function}
11565
- * @param {Object|String} query A valid DOM query, element or jQuery-esque list
11566
- * @param {String} event_name The name of the event to track
11567
- * @param {Object|Function} [properties] This can be a set of properties, or a function that returns a set of properties after being passed a DOMElement
11568
- */
11569
- MixpanelLib.prototype.track_forms = function() {
11570
- return this._track_dom.call(this, FormTracker, arguments);
11571
- };
11572
-
11573
- /**
11574
- * Time an event by including the time between this call and a
11575
- * later 'track' call for the same event in the properties sent
11576
- * with the event.
11577
- *
11578
- * ### Usage:
11579
- *
11580
- * // time an event named 'Registered'
11581
- * mixpanel.time_event('Registered');
11582
- * mixpanel.track('Registered', {'Gender': 'Male', 'Age': 21});
11583
- *
11584
- * When called for a particular event name, the next track call for that event
11585
- * name will include the elapsed time between the 'time_event' and 'track'
11586
- * calls. This value is stored as seconds in the '$duration' property.
11587
- *
11588
- * @param {String} event_name The name of the event.
11589
- */
11590
- MixpanelLib.prototype.time_event = function(event_name) {
11591
- if (_.isUndefined(event_name)) {
11592
- this.report_error('No event name provided to mixpanel.time_event');
11593
- return;
11594
- }
11595
-
11596
- if (this._event_is_disabled(event_name)) {
11597
- return;
11598
- }
11599
-
11600
- this['persistence'].set_event_timer(event_name, new Date().getTime());
11601
- };
11602
-
11603
- var REGISTER_DEFAULTS = {
11604
- 'persistent': true
11605
- };
11606
- /**
11607
- * Helper to parse options param for register methods, maintaining
11608
- * legacy support for plain "days" param instead of options object
11609
- * @param {Number|Object} [days_or_options] 'days' option (Number), or Options object for register methods
11610
- * @returns {Object} options object
11611
- */
11612
- var options_for_register = function(days_or_options) {
11613
- var options;
11614
- if (_.isObject(days_or_options)) {
11615
- options = days_or_options;
11616
- } else if (!_.isUndefined(days_or_options)) {
11617
- options = {'days': days_or_options};
11618
- } else {
11619
- options = {};
11620
- }
11621
- return _.extend({}, REGISTER_DEFAULTS, options);
11622
- };
11623
-
11624
- /**
11625
- * Register a set of super properties, which are included with all
11626
- * events. This will overwrite previous super property values.
11627
- *
11628
- * ### Usage:
11629
- *
11630
- * // register 'Gender' as a super property
11631
- * mixpanel.register({'Gender': 'Female'});
11632
- *
11633
- * // register several super properties when a user signs up
11634
- * mixpanel.register({
11635
- * 'Email': 'jdoe@example.com',
11636
- * 'Account Type': 'Free'
11637
- * });
11638
- *
11639
- * // register only for the current pageload
11640
- * mixpanel.register({'Name': 'Pat'}, {persistent: false});
11641
- *
11642
- * @param {Object} properties An associative array of properties to store about the user
11643
- * @param {Number|Object} [days_or_options] Options object or number of days since the user's last visit to store the super properties (only valid for persisted props)
11644
- * @param {boolean} [days_or_options.days] - number of days since the user's last visit to store the super properties (only valid for persisted props)
11645
- * @param {boolean} [days_or_options.persistent=true] - whether to put in persistent storage (cookie/localStorage)
11646
- */
11647
- MixpanelLib.prototype.register = function(props, days_or_options) {
11648
- var options = options_for_register(days_or_options);
11649
- if (options['persistent']) {
11650
- this['persistence'].register(props, options['days']);
11651
- } else {
11652
- _.extend(this.unpersisted_superprops, props);
11653
- }
11654
- };
11655
-
11656
- /**
11657
- * Register a set of super properties only once. This will not
11658
- * overwrite previous super property values, unlike register().
11659
- *
11660
- * ### Usage:
11661
- *
11662
- * // register a super property for the first time only
11663
- * mixpanel.register_once({
11664
- * 'First Login Date': new Date().toISOString()
11665
- * });
11666
- *
11667
- * // register once, only for the current pageload
11668
- * mixpanel.register_once({
11669
- * 'First interaction time': new Date().toISOString()
11670
- * }, 'None', {persistent: false});
11671
- *
11672
- * ### Notes:
11673
- *
11674
- * If default_value is specified, current super properties
11675
- * with that value will be overwritten.
11676
- *
11677
- * @param {Object} properties An associative array of properties to store about the user
11678
- * @param {*} [default_value] Value to override if already set in super properties (ex: 'False') Default: 'None'
11679
- * @param {Number|Object} [days_or_options] Options object or number of days since the user's last visit to store the super properties (only valid for persisted props)
11680
- * @param {boolean} [days_or_options.days] - number of days since the user's last visit to store the super properties (only valid for persisted props)
11681
- * @param {boolean} [days_or_options.persistent=true] - whether to put in persistent storage (cookie/localStorage)
11682
- */
11683
- MixpanelLib.prototype.register_once = function(props, default_value, days_or_options) {
11684
- var options = options_for_register(days_or_options);
11685
- if (options['persistent']) {
11686
- this['persistence'].register_once(props, default_value, options['days']);
11687
- } else {
11688
- if (typeof(default_value) === 'undefined') {
11689
- default_value = 'None';
11690
- }
11691
- _.each(props, function(val, prop) {
11692
- if (!this.unpersisted_superprops.hasOwnProperty(prop) || this.unpersisted_superprops[prop] === default_value) {
11693
- this.unpersisted_superprops[prop] = val;
11694
- }
11695
- }, this);
11696
- }
11697
- };
11698
-
11699
- /**
11700
- * Delete a super property stored with the current user.
11701
- *
11702
- * @param {String} property The name of the super property to remove
11703
- * @param {Object} [options]
11704
- * @param {boolean} [options.persistent=true] - whether to look in persistent storage (cookie/localStorage)
11705
- */
11706
- MixpanelLib.prototype.unregister = function(property, options) {
11707
- options = options_for_register(options);
11708
- if (options['persistent']) {
11709
- this['persistence'].unregister(property);
11710
- } else {
11711
- delete this.unpersisted_superprops[property];
11712
- }
10912
+ _.each(groups, function(v, k) {
10913
+ if (v !== null && v !== undefined) {
10914
+ tracking_props[k] = v;
10915
+ }
10916
+ });
10917
+ return this.track(event_name, tracking_props, callback);
10918
+ });
10919
+
10920
+ MixpanelLib.prototype._create_map_key = function (group_key, group_id) {
10921
+ return group_key + '_' + JSON.stringify(group_id);
11713
10922
  };
11714
10923
 
11715
- MixpanelLib.prototype._register_single = function(prop, value) {
11716
- var props = {};
11717
- props[prop] = value;
11718
- this.register(props);
10924
+ MixpanelLib.prototype._remove_group_from_cache = function (group_key, group_id) {
10925
+ delete this._cached_groups[this._create_map_key(group_key, group_id)];
11719
10926
  };
11720
10927
 
11721
10928
  /**
11722
- * Identify a user with a unique ID to track user activity across
11723
- * devices, tie a user to their events, and create a user profile.
11724
- * If you never call this method, unique visitors are tracked using
11725
- * a UUID generated the first time they visit the site.
11726
- *
11727
- * Call identify when you know the identity of the current user,
11728
- * typically after login or signup. We recommend against using
11729
- * identify for anonymous visitors to your site.
10929
+ * Look up reference to a Mixpanel group
11730
10930
  *
11731
- * ### Notes:
11732
- * If your project has
11733
- * <a href="https://help.mixpanel.com/hc/en-us/articles/360039133851">ID Merge</a>
11734
- * enabled, the identify method will connect pre- and
11735
- * post-authentication events when appropriate.
10931
+ * ### Usage:
11736
10932
  *
11737
- * If your project does not have ID Merge enabled, identify will
11738
- * change the user's local distinct_id to the unique ID you pass.
11739
- * Events tracked prior to authentication will not be connected
11740
- * to the same user identity. If ID Merge is disabled, alias can
11741
- * be used to connect pre- and post-registration events.
10933
+ * mixpanel.get_group(group_key, group_id)
11742
10934
  *
11743
- * @param {String} [unique_id] A string that uniquely identifies a user. If not provided, the distinct_id currently in the persistent store (cookie or localStorage) will be used.
10935
+ * @param {String} group_key Group key
10936
+ * @param {Object} group_id A valid Mixpanel property type
10937
+ * @returns {Object} A MixpanelGroup identifier
11744
10938
  */
11745
- MixpanelLib.prototype.identify = function(
11746
- new_distinct_id, _set_callback, _add_callback, _append_callback, _set_once_callback, _union_callback, _unset_callback, _remove_callback
11747
- ) {
11748
- // Optional Parameters
11749
- // _set_callback:function A callback to be run if and when the People set queue is flushed
11750
- // _add_callback:function A callback to be run if and when the People add queue is flushed
11751
- // _append_callback:function A callback to be run if and when the People append queue is flushed
11752
- // _set_once_callback:function A callback to be run if and when the People set_once queue is flushed
11753
- // _union_callback:function A callback to be run if and when the People union queue is flushed
11754
- // _unset_callback:function A callback to be run if and when the People unset queue is flushed
11755
-
11756
- var previous_distinct_id = this.get_distinct_id();
11757
- this.register({'$user_id': new_distinct_id});
11758
-
11759
- if (!this.get_property('$device_id')) {
11760
- // The persisted distinct id might not actually be a device id at all
11761
- // it might be a distinct id of the user from before
11762
- var device_id = previous_distinct_id;
11763
- this.register_once({
11764
- '$had_persisted_distinct_id': true,
11765
- '$device_id': device_id
11766
- }, '');
11767
- }
11768
-
11769
- // identify only changes the distinct id if it doesn't match either the existing or the alias;
11770
- // if it's new, blow away the alias as well.
11771
- if (new_distinct_id !== previous_distinct_id && new_distinct_id !== this.get_property(ALIAS_ID_KEY)) {
11772
- this.unregister(ALIAS_ID_KEY);
11773
- this.register({'distinct_id': new_distinct_id});
11774
- }
11775
- this._flags.identify_called = true;
11776
- // Flush any queued up people requests
11777
- this['people']._flush(_set_callback, _add_callback, _append_callback, _set_once_callback, _union_callback, _unset_callback, _remove_callback);
11778
-
11779
- // send an $identify event any time the distinct_id is changing - logic on the server
11780
- // will determine whether or not to do anything with it.
11781
- if (new_distinct_id !== previous_distinct_id) {
11782
- this.track('$identify', {
11783
- 'distinct_id': new_distinct_id,
11784
- '$anon_distinct_id': previous_distinct_id
11785
- }, {skip_hooks: true});
10939
+ MixpanelLib.prototype.get_group = function (group_key, group_id) {
10940
+ var map_key = this._create_map_key(group_key, group_id);
10941
+ var group = this._cached_groups[map_key];
10942
+ if (group === undefined || group._group_key !== group_key || group._group_id !== group_id) {
10943
+ group = new MixpanelGroup();
10944
+ group._init(this, group_key, group_id);
10945
+ this._cached_groups[map_key] = group;
11786
10946
  }
10947
+ return group;
11787
10948
  };
11788
10949
 
11789
10950
  /**
11790
- * Clears super properties and generates a new random distinct_id for this instance.
11791
- * Useful for clearing data when a user logs out.
10951
+ * Track mp_page_view event. This is now ignored by the server.
10952
+ *
10953
+ * @param {String} [page] The url of the page to record. If you don't include this, it defaults to the current url.
10954
+ * @deprecated
11792
10955
  */
11793
- MixpanelLib.prototype.reset = function() {
11794
- this['persistence'].clear();
11795
- this._flags.identify_called = false;
11796
- var uuid = _.UUID();
11797
- this.register_once({
11798
- 'distinct_id': uuid,
11799
- '$device_id': uuid
11800
- }, '');
10956
+ MixpanelLib.prototype.track_pageview = function(page) {
10957
+ if (_.isUndefined(page)) {
10958
+ page = document$1.location.href;
10959
+ }
10960
+ this.track('mp_page_view', _.info.pageviewInfo(page));
11801
10961
  };
11802
10962
 
11803
10963
  /**
11804
- * Returns the current distinct id of the user. This is either the id automatically
11805
- * generated by the library or the id that has been passed by a call to identify().
10964
+ * Track clicks on a set of document elements. Selector must be a
10965
+ * valid query. Elements must exist on the page at the time track_links is called.
10966
+ *
10967
+ * ### Usage:
10968
+ *
10969
+ * // track click for link id #nav
10970
+ * mixpanel.track_links('#nav', 'Clicked Nav Link');
11806
10971
  *
11807
10972
  * ### Notes:
11808
10973
  *
11809
- * get_distinct_id() can only be called after the Mixpanel library has finished loading.
11810
- * init() has a loaded function available to handle this automatically. For example:
10974
+ * This function will wait up to 300 ms for the Mixpanel
10975
+ * servers to respond. If they have not responded by that time
10976
+ * it will head to the link without ensuring that your event
10977
+ * has been tracked. To configure this timeout please see the
10978
+ * set_config() documentation below.
11811
10979
  *
11812
- * // set distinct_id after the mixpanel library has loaded
11813
- * mixpanel.init('YOUR PROJECT TOKEN', {
11814
- * loaded: function(mixpanel) {
11815
- * distinct_id = mixpanel.get_distinct_id();
11816
- * }
11817
- * });
10980
+ * If you pass a function in as the properties argument, the
10981
+ * function will receive the DOMElement that triggered the
10982
+ * event as an argument. You are expected to return an object
10983
+ * from the function; any properties defined on this object
10984
+ * will be sent to mixpanel as event properties.
10985
+ *
10986
+ * @type {Function}
10987
+ * @param {Object|String} query A valid DOM query, element or jQuery-esque list
10988
+ * @param {String} event_name The name of the event to track
10989
+ * @param {Object|Function} [properties] A properties object or function that returns a dictionary of properties when passed a DOMElement
11818
10990
  */
11819
- MixpanelLib.prototype.get_distinct_id = function() {
11820
- return this.get_property('distinct_id');
10991
+ MixpanelLib.prototype.track_links = function() {
10992
+ return this._track_dom.call(this, LinkTracker, arguments);
11821
10993
  };
11822
10994
 
11823
10995
  /**
11824
- * The alias method creates an alias which Mixpanel will use to
11825
- * remap one id to another. Multiple aliases can point to the
11826
- * same identifier.
10996
+ * Track form submissions. Selector must be a valid query.
11827
10997
  *
11828
- * The following is a valid use of alias:
10998
+ * ### Usage:
11829
10999
  *
11830
- * mixpanel.alias('new_id', 'existing_id');
11831
- * // You can add multiple id aliases to the existing ID
11832
- * mixpanel.alias('newer_id', 'existing_id');
11000
+ * // track submission for form id 'register'
11001
+ * mixpanel.track_forms('#register', 'Created Account');
11833
11002
  *
11834
- * Aliases can also be chained - the following is a valid example:
11003
+ * ### Notes:
11835
11004
  *
11836
- * mixpanel.alias('new_id', 'existing_id');
11837
- * // chain newer_id - new_id - existing_id
11838
- * mixpanel.alias('newer_id', 'new_id');
11005
+ * This function will wait up to 300 ms for the mixpanel
11006
+ * servers to respond, if they have not responded by that time
11007
+ * it will head to the link without ensuring that your event
11008
+ * has been tracked. To configure this timeout please see the
11009
+ * set_config() documentation below.
11839
11010
  *
11840
- * Aliases cannot point to multiple identifiers - the following
11841
- * example will not work:
11011
+ * If you pass a function in as the properties argument, the
11012
+ * function will receive the DOMElement that triggered the
11013
+ * event as an argument. You are expected to return an object
11014
+ * from the function; any properties defined on this object
11015
+ * will be sent to mixpanel as event properties.
11842
11016
  *
11843
- * mixpanel.alias('new_id', 'existing_id');
11844
- * // this is invalid as 'new_id' already points to 'existing_id'
11845
- * mixpanel.alias('new_id', 'newer_id');
11017
+ * @type {Function}
11018
+ * @param {Object|String} query A valid DOM query, element or jQuery-esque list
11019
+ * @param {String} event_name The name of the event to track
11020
+ * @param {Object|Function} [properties] This can be a set of properties, or a function that returns a set of properties after being passed a DOMElement
11021
+ */
11022
+ MixpanelLib.prototype.track_forms = function() {
11023
+ return this._track_dom.call(this, FormTracker, arguments);
11024
+ };
11025
+
11026
+ /**
11027
+ * Time an event by including the time between this call and a
11028
+ * later 'track' call for the same event in the properties sent
11029
+ * with the event.
11846
11030
  *
11847
- * ### Notes:
11031
+ * ### Usage:
11848
11032
  *
11849
- * If your project does not have
11850
- * <a href="https://help.mixpanel.com/hc/en-us/articles/360039133851">ID Merge</a>
11851
- * enabled, the best practice is to call alias once when a unique
11852
- * ID is first created for a user (e.g., when a user first registers
11853
- * for an account). Do not use alias multiple times for a single
11854
- * user without ID Merge enabled.
11033
+ * // time an event named 'Registered'
11034
+ * mixpanel.time_event('Registered');
11035
+ * mixpanel.track('Registered', {'Gender': 'Male', 'Age': 21});
11855
11036
  *
11856
- * @param {String} alias A unique identifier that you want to use for this user in the future.
11857
- * @param {String} [original] The current identifier being used for this user.
11037
+ * When called for a particular event name, the next track call for that event
11038
+ * name will include the elapsed time between the 'time_event' and 'track'
11039
+ * calls. This value is stored as seconds in the '$duration' property.
11040
+ *
11041
+ * @param {String} event_name The name of the event.
11858
11042
  */
11859
- MixpanelLib.prototype.alias = function(alias, original) {
11860
- // If the $people_distinct_id key exists in persistence, there has been a previous
11861
- // mixpanel.people.identify() call made for this user. It is VERY BAD to make an alias with
11862
- // this ID, as it will duplicate users.
11863
- if (alias === this.get_property(PEOPLE_DISTINCT_ID_KEY)) {
11864
- this.report_error('Attempting to create alias for existing People user - aborting.');
11865
- return -2;
11043
+ MixpanelLib.prototype.time_event = function(event_name) {
11044
+ if (_.isUndefined(event_name)) {
11045
+ this.report_error('No event name provided to mixpanel.time_event');
11046
+ return;
11866
11047
  }
11867
11048
 
11868
- var _this = this;
11869
- if (_.isUndefined(original)) {
11870
- original = this.get_distinct_id();
11049
+ if (this._event_is_disabled(event_name)) {
11050
+ return;
11871
11051
  }
11872
- if (alias !== original) {
11873
- this._register_single(ALIAS_ID_KEY, alias);
11874
- return this.track('$create_alias', {
11875
- 'alias': alias,
11876
- 'distinct_id': original
11877
- }, {
11878
- skip_hooks: true
11879
- }, function() {
11880
- // Flush the people queue
11881
- _this.identify(alias);
11882
- });
11052
+
11053
+ this['persistence'].set_event_timer(event_name, new Date().getTime());
11054
+ };
11055
+
11056
+ var REGISTER_DEFAULTS = {
11057
+ 'persistent': true
11058
+ };
11059
+ /**
11060
+ * Helper to parse options param for register methods, maintaining
11061
+ * legacy support for plain "days" param instead of options object
11062
+ * @param {Number|Object} [days_or_options] 'days' option (Number), or Options object for register methods
11063
+ * @returns {Object} options object
11064
+ */
11065
+ var options_for_register = function(days_or_options) {
11066
+ var options;
11067
+ if (_.isObject(days_or_options)) {
11068
+ options = days_or_options;
11069
+ } else if (!_.isUndefined(days_or_options)) {
11070
+ options = {'days': days_or_options};
11883
11071
  } else {
11884
- this.report_error('alias matches current distinct_id - skipping api call.');
11885
- this.identify(alias);
11886
- return -1;
11072
+ options = {};
11887
11073
  }
11074
+ return _.extend({}, REGISTER_DEFAULTS, options);
11888
11075
  };
11889
11076
 
11890
11077
  /**
11891
- * Provide a string to recognize the user by. The string passed to
11892
- * this method will appear in the Mixpanel Streams product rather
11893
- * than an automatically generated name. Name tags do not have to
11894
- * be unique.
11078
+ * Register a set of super properties, which are included with all
11079
+ * events. This will overwrite previous super property values.
11895
11080
  *
11896
- * This value will only be included in Streams data.
11081
+ * ### Usage:
11897
11082
  *
11898
- * @param {String} name_tag A human readable name for the user
11899
- * @deprecated
11083
+ * // register 'Gender' as a super property
11084
+ * mixpanel.register({'Gender': 'Female'});
11085
+ *
11086
+ * // register several super properties when a user signs up
11087
+ * mixpanel.register({
11088
+ * 'Email': 'jdoe@example.com',
11089
+ * 'Account Type': 'Free'
11090
+ * });
11091
+ *
11092
+ * // register only for the current pageload
11093
+ * mixpanel.register({'Name': 'Pat'}, {persistent: false});
11094
+ *
11095
+ * @param {Object} properties An associative array of properties to store about the user
11096
+ * @param {Number|Object} [days_or_options] Options object or number of days since the user's last visit to store the super properties (only valid for persisted props)
11097
+ * @param {boolean} [days_or_options.days] - number of days since the user's last visit to store the super properties (only valid for persisted props)
11098
+ * @param {boolean} [days_or_options.persistent=true] - whether to put in persistent storage (cookie/localStorage)
11900
11099
  */
11901
- MixpanelLib.prototype.name_tag = function(name_tag) {
11902
- this._register_single('mp_name_tag', name_tag);
11100
+ MixpanelLib.prototype.register = function(props, days_or_options) {
11101
+ var options = options_for_register(days_or_options);
11102
+ if (options['persistent']) {
11103
+ this['persistence'].register(props, options['days']);
11104
+ } else {
11105
+ _.extend(this.unpersisted_superprops, props);
11106
+ }
11903
11107
  };
11904
11108
 
11905
11109
  /**
11906
- * Update the configuration of a mixpanel library instance.
11907
- *
11908
- * The default config is:
11909
- *
11910
- * {
11911
- * // HTTP method for tracking requests
11912
- * api_method: 'POST'
11913
- *
11914
- * // transport for sending requests ('XHR' or 'sendBeacon')
11915
- * // NB: sendBeacon should only be used for scenarios such as
11916
- * // page unload where a "best-effort" attempt to send is
11917
- * // acceptable; the sendBeacon API does not support callbacks
11918
- * // or any way to know the result of the request. Mixpanel
11919
- * // tracking via sendBeacon will not support any event-
11920
- * // batching or retry mechanisms.
11921
- * api_transport: 'XHR'
11922
- *
11923
- * // turn on request-batching/queueing/retry
11924
- * batch_requests: false,
11925
- *
11926
- * // maximum number of events/updates to send in a single
11927
- * // network request
11928
- * batch_size: 50,
11929
- *
11930
- * // milliseconds to wait between sending batch requests
11931
- * batch_flush_interval_ms: 5000,
11932
- *
11933
- * // milliseconds to wait for network responses to batch requests
11934
- * // before they are considered timed-out and retried
11935
- * batch_request_timeout_ms: 90000,
11936
- *
11937
- * // override value for cookie domain, only useful for ensuring
11938
- * // correct cross-subdomain cookies on unusual domains like
11939
- * // subdomain.mainsite.avocat.fr; NB this cannot be used to
11940
- * // set cookies on a different domain than the current origin
11941
- * cookie_domain: ''
11942
- *
11943
- * // super properties cookie expiration (in days)
11944
- * cookie_expiration: 365
11945
- *
11946
- * // if true, cookie will be set with SameSite=None; Secure
11947
- * // this is only useful in special situations, like embedded
11948
- * // 3rd-party iframes that set up a Mixpanel instance
11949
- * cross_site_cookie: false
11950
- *
11951
- * // super properties span subdomains
11952
- * cross_subdomain_cookie: true
11953
- *
11954
- * // debug mode
11955
- * debug: false
11956
- *
11957
- * // if this is true, the mixpanel cookie or localStorage entry
11958
- * // will be deleted, and no user persistence will take place
11959
- * disable_persistence: false
11960
- *
11961
- * // if this is true, Mixpanel will automatically determine
11962
- * // City, Region and Country data using the IP address of
11963
- * //the client
11964
- * ip: true
11965
- *
11966
- * // opt users out of tracking by this Mixpanel instance by default
11967
- * opt_out_tracking_by_default: false
11968
- *
11969
- * // opt users out of browser data storage by this Mixpanel instance by default
11970
- * opt_out_persistence_by_default: false
11971
- *
11972
- * // persistence mechanism used by opt-in/opt-out methods - cookie
11973
- * // or localStorage - falls back to cookie if localStorage is unavailable
11974
- * opt_out_tracking_persistence_type: 'localStorage'
11110
+ * Register a set of super properties only once. This will not
11111
+ * overwrite previous super property values, unlike register().
11975
11112
  *
11976
- * // customize the name of cookie/localStorage set by opt-in/opt-out methods
11977
- * opt_out_tracking_cookie_prefix: null
11113
+ * ### Usage:
11978
11114
  *
11979
- * // type of persistent store for super properties (cookie/
11980
- * // localStorage) if set to 'localStorage', any existing
11981
- * // mixpanel cookie value with the same persistence_name
11982
- * // will be transferred to localStorage and deleted
11983
- * persistence: 'cookie'
11115
+ * // register a super property for the first time only
11116
+ * mixpanel.register_once({
11117
+ * 'First Login Date': new Date().toISOString()
11118
+ * });
11984
11119
  *
11985
- * // name for super properties persistent store
11986
- * persistence_name: ''
11120
+ * // register once, only for the current pageload
11121
+ * mixpanel.register_once({
11122
+ * 'First interaction time': new Date().toISOString()
11123
+ * }, 'None', {persistent: false});
11987
11124
  *
11988
- * // names of properties/superproperties which should never
11989
- * // be sent with track() calls
11990
- * property_blacklist: []
11125
+ * ### Notes:
11991
11126
  *
11992
- * // if this is true, mixpanel cookies will be marked as
11993
- * // secure, meaning they will only be transmitted over https
11994
- * secure_cookie: false
11127
+ * If default_value is specified, current super properties
11128
+ * with that value will be overwritten.
11995
11129
  *
11996
- * // the amount of time track_links will
11997
- * // wait for Mixpanel's servers to respond
11998
- * track_links_timeout: 300
11130
+ * @param {Object} properties An associative array of properties to store about the user
11131
+ * @param {*} [default_value] Value to override if already set in super properties (ex: 'False') Default: 'None'
11132
+ * @param {Number|Object} [days_or_options] Options object or number of days since the user's last visit to store the super properties (only valid for persisted props)
11133
+ * @param {boolean} [days_or_options.days] - number of days since the user's last visit to store the super properties (only valid for persisted props)
11134
+ * @param {boolean} [days_or_options.persistent=true] - whether to put in persistent storage (cookie/localStorage)
11135
+ */
11136
+ MixpanelLib.prototype.register_once = function(props, default_value, days_or_options) {
11137
+ var options = options_for_register(days_or_options);
11138
+ if (options['persistent']) {
11139
+ this['persistence'].register_once(props, default_value, options['days']);
11140
+ } else {
11141
+ if (typeof(default_value) === 'undefined') {
11142
+ default_value = 'None';
11143
+ }
11144
+ _.each(props, function(val, prop) {
11145
+ if (!this.unpersisted_superprops.hasOwnProperty(prop) || this.unpersisted_superprops[prop] === default_value) {
11146
+ this.unpersisted_superprops[prop] = val;
11147
+ }
11148
+ }, this);
11149
+ }
11150
+ };
11151
+
11152
+ /**
11153
+ * Delete a super property stored with the current user.
11999
11154
  *
12000
- * // if you set upgrade to be true, the library will check for
12001
- * // a cookie from our old js library and import super
12002
- * // properties from it, then the old cookie is deleted
12003
- * // The upgrade config option only works in the initialization,
12004
- * // so make sure you set it when you create the library.
12005
- * upgrade: false
11155
+ * @param {String} property The name of the super property to remove
11156
+ * @param {Object} [options]
11157
+ * @param {boolean} [options.persistent=true] - whether to look in persistent storage (cookie/localStorage)
11158
+ */
11159
+ MixpanelLib.prototype.unregister = function(property, options) {
11160
+ options = options_for_register(options);
11161
+ if (options['persistent']) {
11162
+ this['persistence'].unregister(property);
11163
+ } else {
11164
+ delete this.unpersisted_superprops[property];
11165
+ }
11166
+ };
11167
+
11168
+ MixpanelLib.prototype._register_single = function(prop, value) {
11169
+ var props = {};
11170
+ props[prop] = value;
11171
+ this.register(props);
11172
+ };
11173
+
11174
+ /**
11175
+ * Identify a user with a unique ID to track user activity across
11176
+ * devices, tie a user to their events, and create a user profile.
11177
+ * If you never call this method, unique visitors are tracked using
11178
+ * a UUID generated the first time they visit the site.
12006
11179
  *
12007
- * // extra HTTP request headers to set for each API request, in
12008
- * // the format {'Header-Name': value}
12009
- * xhr_headers: {}
11180
+ * Call identify when you know the identity of the current user,
11181
+ * typically after login or signup. We recommend against using
11182
+ * identify for anonymous visitors to your site.
12010
11183
  *
12011
- * // whether to ignore or respect the web browser's Do Not Track setting
12012
- * ignore_dnt: false
12013
- * }
11184
+ * ### Notes:
11185
+ * If your project has
11186
+ * <a href="https://help.mixpanel.com/hc/en-us/articles/360039133851">ID Merge</a>
11187
+ * enabled, the identify method will connect pre- and
11188
+ * post-authentication events when appropriate.
12014
11189
  *
11190
+ * If your project does not have ID Merge enabled, identify will
11191
+ * change the user's local distinct_id to the unique ID you pass.
11192
+ * Events tracked prior to authentication will not be connected
11193
+ * to the same user identity. If ID Merge is disabled, alias can
11194
+ * be used to connect pre- and post-registration events.
12015
11195
  *
12016
- * @param {Object} config A dictionary of new configuration values to update
11196
+ * @param {String} [unique_id] A string that uniquely identifies a user. If not provided, the distinct_id currently in the persistent store (cookie or localStorage) will be used.
12017
11197
  */
12018
- MixpanelLib.prototype.set_config = function(config) {
12019
- if (_.isObject(config)) {
12020
- _.extend(this['config'], config);
11198
+ MixpanelLib.prototype.identify = function(
11199
+ new_distinct_id, _set_callback, _add_callback, _append_callback, _set_once_callback, _union_callback, _unset_callback, _remove_callback
11200
+ ) {
11201
+ // Optional Parameters
11202
+ // _set_callback:function A callback to be run if and when the People set queue is flushed
11203
+ // _add_callback:function A callback to be run if and when the People add queue is flushed
11204
+ // _append_callback:function A callback to be run if and when the People append queue is flushed
11205
+ // _set_once_callback:function A callback to be run if and when the People set_once queue is flushed
11206
+ // _union_callback:function A callback to be run if and when the People union queue is flushed
11207
+ // _unset_callback:function A callback to be run if and when the People unset queue is flushed
12021
11208
 
12022
- var new_batch_size = config['batch_size'];
12023
- if (new_batch_size) {
12024
- _.each(this.request_batchers, function(batcher) {
12025
- batcher.resetBatchSize();
12026
- });
12027
- }
11209
+ var previous_distinct_id = this.get_distinct_id();
11210
+ this.register({'$user_id': new_distinct_id});
12028
11211
 
12029
- if (!this.get_config('persistence_name')) {
12030
- this['config']['persistence_name'] = this['config']['cookie_name'];
12031
- }
12032
- if (!this.get_config('disable_persistence')) {
12033
- this['config']['disable_persistence'] = this['config']['disable_cookie'];
12034
- }
11212
+ if (!this.get_property('$device_id')) {
11213
+ // The persisted distinct id might not actually be a device id at all
11214
+ // it might be a distinct id of the user from before
11215
+ var device_id = previous_distinct_id;
11216
+ this.register_once({
11217
+ '$had_persisted_distinct_id': true,
11218
+ '$device_id': device_id
11219
+ }, '');
11220
+ }
12035
11221
 
12036
- if (this['persistence']) {
12037
- this['persistence'].update_config(this['config']);
12038
- }
12039
- Config.DEBUG = Config.DEBUG || this.get_config('debug');
11222
+ // identify only changes the distinct id if it doesn't match either the existing or the alias;
11223
+ // if it's new, blow away the alias as well.
11224
+ if (new_distinct_id !== previous_distinct_id && new_distinct_id !== this.get_property(ALIAS_ID_KEY)) {
11225
+ this.unregister(ALIAS_ID_KEY);
11226
+ this.register({'distinct_id': new_distinct_id});
12040
11227
  }
12041
- };
11228
+ this._flags.identify_called = true;
11229
+ // Flush any queued up people requests
11230
+ this['people']._flush(_set_callback, _add_callback, _append_callback, _set_once_callback, _union_callback, _unset_callback, _remove_callback);
12042
11231
 
12043
- /**
12044
- * returns the current config object for the library.
12045
- */
12046
- MixpanelLib.prototype.get_config = function(prop_name) {
12047
- return this['config'][prop_name];
11232
+ // send an $identify event any time the distinct_id is changing - logic on the server
11233
+ // will determine whether or not to do anything with it.
11234
+ if (new_distinct_id !== previous_distinct_id) {
11235
+ this.track('$identify', {
11236
+ 'distinct_id': new_distinct_id,
11237
+ '$anon_distinct_id': previous_distinct_id
11238
+ }, {skip_hooks: true});
11239
+ }
12048
11240
  };
12049
11241
 
12050
11242
  /**
12051
- * Fetch a hook function from config, with safe default, and run it
12052
- * against the given arguments
12053
- * @param {string} hook_name which hook to retrieve
12054
- * @returns {any|null} return value of user-provided hook, or null if nothing was returned
11243
+ * Clears super properties and generates a new random distinct_id for this instance.
11244
+ * Useful for clearing data when a user logs out.
12055
11245
  */
12056
- MixpanelLib.prototype._run_hook = function(hook_name) {
12057
- var ret = (this['config']['hooks'][hook_name] || IDENTITY_FUNC).apply(this, slice.call(arguments, 1));
12058
- if (typeof ret === 'undefined') {
12059
- this.report_error(hook_name + ' hook did not return a value');
12060
- ret = null;
12061
- }
12062
- return ret;
11246
+ MixpanelLib.prototype.reset = function() {
11247
+ this['persistence'].clear();
11248
+ this._flags.identify_called = false;
11249
+ var uuid = _.UUID();
11250
+ this.register_once({
11251
+ 'distinct_id': uuid,
11252
+ '$device_id': uuid
11253
+ }, '');
12063
11254
  };
12064
11255
 
12065
11256
  /**
12066
- * Returns the value of the super property named property_name. If no such
12067
- * property is set, get_property() will return the undefined value.
11257
+ * Returns the current distinct id of the user. This is either the id automatically
11258
+ * generated by the library or the id that has been passed by a call to identify().
12068
11259
  *
12069
11260
  * ### Notes:
12070
11261
  *
12071
- * get_property() can only be called after the Mixpanel library has finished loading.
11262
+ * get_distinct_id() can only be called after the Mixpanel library has finished loading.
12072
11263
  * init() has a loaded function available to handle this automatically. For example:
12073
11264
  *
12074
- * // grab value for 'user_id' after the mixpanel library has loaded
11265
+ * // set distinct_id after the mixpanel library has loaded
12075
11266
  * mixpanel.init('YOUR PROJECT TOKEN', {
12076
11267
  * loaded: function(mixpanel) {
12077
- * user_id = mixpanel.get_property('user_id');
11268
+ * distinct_id = mixpanel.get_distinct_id();
12078
11269
  * }
12079
11270
  * });
12080
- *
12081
- * @param {String} property_name The name of the super property you want to retrieve
12082
- */
12083
- MixpanelLib.prototype.get_property = function(property_name) {
12084
- return this['persistence']['props'][property_name];
12085
- };
12086
-
12087
- MixpanelLib.prototype.toString = function() {
12088
- var name = this.get_config('name');
12089
- if (name !== PRIMARY_INSTANCE_NAME) {
12090
- name = PRIMARY_INSTANCE_NAME + '.' + name;
12091
- }
12092
- return name;
12093
- };
12094
-
12095
- MixpanelLib.prototype._event_is_disabled = function(event_name) {
12096
- return _.isBlockedUA(userAgent) ||
12097
- this._flags.disable_all_events ||
12098
- _.include(this.__disabled_events, event_name);
12099
- };
12100
-
12101
- // perform some housekeeping around GDPR opt-in/out state
12102
- MixpanelLib.prototype._gdpr_init = function() {
12103
- var is_localStorage_requested = this.get_config('opt_out_tracking_persistence_type') === 'localStorage';
12104
-
12105
- // try to convert opt-in/out cookies to localStorage if possible
12106
- if (is_localStorage_requested && _.localStorage.is_supported()) {
12107
- if (!this.has_opted_in_tracking() && this.has_opted_in_tracking({'persistence_type': 'cookie'})) {
12108
- this.opt_in_tracking({'enable_persistence': false});
12109
- }
12110
- if (!this.has_opted_out_tracking() && this.has_opted_out_tracking({'persistence_type': 'cookie'})) {
12111
- this.opt_out_tracking({'clear_persistence': false});
12112
- }
12113
- this.clear_opt_in_out_tracking({
12114
- 'persistence_type': 'cookie',
12115
- 'enable_persistence': false
12116
- });
12117
- }
12118
-
12119
- // check whether the user has already opted out - if so, clear & disable persistence
12120
- if (this.has_opted_out_tracking()) {
12121
- this._gdpr_update_persistence({'clear_persistence': true});
12122
-
12123
- // check whether we should opt out by default
12124
- // note: we don't clear persistence here by default since opt-out default state is often
12125
- // used as an initial state while GDPR information is being collected
12126
- } else if (!this.has_opted_in_tracking() && (
12127
- this.get_config('opt_out_tracking_by_default') || _.cookie.get('mp_optout')
12128
- )) {
12129
- _.cookie.remove('mp_optout');
12130
- this.opt_out_tracking({
12131
- 'clear_persistence': this.get_config('opt_out_persistence_by_default')
12132
- });
12133
- }
12134
- };
12135
-
12136
- /**
12137
- * Enable or disable persistence based on options
12138
- * only enable/disable if persistence is not already in this state
12139
- * @param {boolean} [options.clear_persistence] If true, will delete all data stored by the sdk in persistence and disable it
12140
- * @param {boolean} [options.enable_persistence] If true, will re-enable sdk persistence
12141
11271
  */
12142
- MixpanelLib.prototype._gdpr_update_persistence = function(options) {
12143
- var disabled;
12144
- if (options && options['clear_persistence']) {
12145
- disabled = true;
12146
- } else if (options && options['enable_persistence']) {
12147
- disabled = false;
12148
- } else {
12149
- return;
12150
- }
12151
-
12152
- if (!this.get_config('disable_persistence') && this['persistence'].disabled !== disabled) {
12153
- this['persistence'].set_disabled(disabled);
12154
- }
12155
-
12156
- if (disabled) {
12157
- _.each(this.request_batchers, function(batcher) {
12158
- batcher.clear();
12159
- });
12160
- }
12161
- };
12162
-
12163
- // call a base gdpr function after constructing the appropriate token and options args
12164
- MixpanelLib.prototype._gdpr_call_func = function(func, options) {
12165
- options = _.extend({
12166
- 'track': _.bind(this.track, this),
12167
- 'persistence_type': this.get_config('opt_out_tracking_persistence_type'),
12168
- 'cookie_prefix': this.get_config('opt_out_tracking_cookie_prefix'),
12169
- 'cookie_expiration': this.get_config('cookie_expiration'),
12170
- 'cross_site_cookie': this.get_config('cross_site_cookie'),
12171
- 'cross_subdomain_cookie': this.get_config('cross_subdomain_cookie'),
12172
- 'cookie_domain': this.get_config('cookie_domain'),
12173
- 'secure_cookie': this.get_config('secure_cookie'),
12174
- 'ignore_dnt': this.get_config('ignore_dnt')
12175
- }, options);
12176
-
12177
- // check if localStorage can be used for recording opt out status, fall back to cookie if not
12178
- if (!_.localStorage.is_supported()) {
12179
- options['persistence_type'] = 'cookie';
12180
- }
12181
-
12182
- return func(this.get_config('token'), {
12183
- track: options['track'],
12184
- trackEventName: options['track_event_name'],
12185
- trackProperties: options['track_properties'],
12186
- persistenceType: options['persistence_type'],
12187
- persistencePrefix: options['cookie_prefix'],
12188
- cookieDomain: options['cookie_domain'],
12189
- cookieExpiration: options['cookie_expiration'],
12190
- crossSiteCookie: options['cross_site_cookie'],
12191
- crossSubdomainCookie: options['cross_subdomain_cookie'],
12192
- secureCookie: options['secure_cookie'],
12193
- ignoreDnt: options['ignore_dnt']
12194
- });
11272
+ MixpanelLib.prototype.get_distinct_id = function() {
11273
+ return this.get_property('distinct_id');
12195
11274
  };
12196
11275
 
12197
11276
  /**
12198
- * Opt the user in to data tracking and cookies/localstorage for this Mixpanel instance
11277
+ * The alias method creates an alias which Mixpanel will use to
11278
+ * remap one id to another. Multiple aliases can point to the
11279
+ * same identifier.
12199
11280
  *
12200
- * ### Usage
11281
+ * The following is a valid use of alias:
12201
11282
  *
12202
- * // opt user in
12203
- * mixpanel.opt_in_tracking();
11283
+ * mixpanel.alias('new_id', 'existing_id');
11284
+ * // You can add multiple id aliases to the existing ID
11285
+ * mixpanel.alias('newer_id', 'existing_id');
12204
11286
  *
12205
- * // opt user in with specific event name, properties, cookie configuration
12206
- * mixpanel.opt_in_tracking({
12207
- * track_event_name: 'User opted in',
12208
- * track_event_properties: {
12209
- * 'Email': 'jdoe@example.com'
12210
- * },
12211
- * cookie_expiration: 30,
12212
- * secure_cookie: true
12213
- * });
11287
+ * Aliases can also be chained - the following is a valid example:
12214
11288
  *
12215
- * @param {Object} [options] A dictionary of config options to override
12216
- * @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)
12217
- * @param {string} [options.track_event_name=$opt_in] Event name to be used for tracking the opt-in action
12218
- * @param {Object} [options.track_properties] Set of properties to be tracked along with the opt-in action
12219
- * @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence
12220
- * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
12221
- * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
12222
- * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
12223
- * @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
12224
- * @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)
12225
- * @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)
12226
- * @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)
12227
- */
12228
- MixpanelLib.prototype.opt_in_tracking = function(options) {
12229
- options = _.extend({
12230
- 'enable_persistence': true
12231
- }, options);
12232
-
12233
- this._gdpr_call_func(optIn, options);
12234
- this._gdpr_update_persistence(options);
12235
- };
12236
-
12237
- /**
12238
- * Opt the user out of data tracking and cookies/localstorage for this Mixpanel instance
11289
+ * mixpanel.alias('new_id', 'existing_id');
11290
+ * // chain newer_id - new_id - existing_id
11291
+ * mixpanel.alias('newer_id', 'new_id');
12239
11292
  *
12240
- * ### Usage
11293
+ * Aliases cannot point to multiple identifiers - the following
11294
+ * example will not work:
12241
11295
  *
12242
- * // opt user out
12243
- * mixpanel.opt_out_tracking();
11296
+ * mixpanel.alias('new_id', 'existing_id');
11297
+ * // this is invalid as 'new_id' already points to 'existing_id'
11298
+ * mixpanel.alias('new_id', 'newer_id');
12244
11299
  *
12245
- * // opt user out with different cookie configuration from Mixpanel instance
12246
- * mixpanel.opt_out_tracking({
12247
- * cookie_expiration: 30,
12248
- * secure_cookie: true
12249
- * });
11300
+ * ### Notes:
12250
11301
  *
12251
- * @param {Object} [options] A dictionary of config options to override
12252
- * @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
12253
- * @param {boolean} [options.clear_persistence=true] If true, will delete all data stored by the sdk in persistence
12254
- * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
12255
- * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
12256
- * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
12257
- * @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
12258
- * @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)
12259
- * @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)
12260
- * @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)
12261
- */
12262
- MixpanelLib.prototype.opt_out_tracking = function(options) {
12263
- options = _.extend({
12264
- 'clear_persistence': true,
12265
- 'delete_user': true
12266
- }, options);
12267
-
12268
- // delete user and clear charges since these methods may be disabled by opt-out
12269
- if (options['delete_user'] && this['people'] && this['people']._identify_called()) {
12270
- this['people'].delete_user();
12271
- this['people'].clear_charges();
11302
+ * If your project does not have
11303
+ * <a href="https://help.mixpanel.com/hc/en-us/articles/360039133851">ID Merge</a>
11304
+ * enabled, the best practice is to call alias once when a unique
11305
+ * ID is first created for a user (e.g., when a user first registers
11306
+ * for an account). Do not use alias multiple times for a single
11307
+ * user without ID Merge enabled.
11308
+ *
11309
+ * @param {String} alias A unique identifier that you want to use for this user in the future.
11310
+ * @param {String} [original] The current identifier being used for this user.
11311
+ */
11312
+ MixpanelLib.prototype.alias = function(alias, original) {
11313
+ // If the $people_distinct_id key exists in persistence, there has been a previous
11314
+ // mixpanel.people.identify() call made for this user. It is VERY BAD to make an alias with
11315
+ // this ID, as it will duplicate users.
11316
+ if (alias === this.get_property(PEOPLE_DISTINCT_ID_KEY)) {
11317
+ this.report_error('Attempting to create alias for existing People user - aborting.');
11318
+ return -2;
12272
11319
  }
12273
11320
 
12274
- this._gdpr_call_func(optOut, options);
12275
- this._gdpr_update_persistence(options);
11321
+ var _this = this;
11322
+ if (_.isUndefined(original)) {
11323
+ original = this.get_distinct_id();
11324
+ }
11325
+ if (alias !== original) {
11326
+ this._register_single(ALIAS_ID_KEY, alias);
11327
+ return this.track('$create_alias', {
11328
+ 'alias': alias,
11329
+ 'distinct_id': original
11330
+ }, {
11331
+ skip_hooks: true
11332
+ }, function() {
11333
+ // Flush the people queue
11334
+ _this.identify(alias);
11335
+ });
11336
+ } else {
11337
+ this.report_error('alias matches current distinct_id - skipping api call.');
11338
+ this.identify(alias);
11339
+ return -1;
11340
+ }
12276
11341
  };
12277
11342
 
12278
11343
  /**
12279
- * Check whether the user has opted in to data tracking and cookies/localstorage for this Mixpanel instance
12280
- *
12281
- * ### Usage
11344
+ * Provide a string to recognize the user by. The string passed to
11345
+ * this method will appear in the Mixpanel Streams product rather
11346
+ * than an automatically generated name. Name tags do not have to
11347
+ * be unique.
12282
11348
  *
12283
- * var has_opted_in = mixpanel.has_opted_in_tracking();
12284
- * // use has_opted_in value
11349
+ * This value will only be included in Streams data.
12285
11350
  *
12286
- * @param {Object} [options] A dictionary of config options to override
12287
- * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
12288
- * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
12289
- * @returns {boolean} current opt-in status
11351
+ * @param {String} name_tag A human readable name for the user
11352
+ * @deprecated
12290
11353
  */
12291
- MixpanelLib.prototype.has_opted_in_tracking = function(options) {
12292
- return this._gdpr_call_func(hasOptedIn, options);
11354
+ MixpanelLib.prototype.name_tag = function(name_tag) {
11355
+ this._register_single('mp_name_tag', name_tag);
12293
11356
  };
12294
11357
 
12295
11358
  /**
12296
- * Check whether the user has opted out of data tracking and cookies/localstorage for this Mixpanel instance
11359
+ * Update the configuration of a mixpanel library instance.
12297
11360
  *
12298
- * ### Usage
11361
+ * The default config is:
12299
11362
  *
12300
- * var has_opted_out = mixpanel.has_opted_out_tracking();
12301
- * // use has_opted_out value
11363
+ * {
11364
+ * // HTTP method for tracking requests
11365
+ * api_method: 'POST'
12302
11366
  *
12303
- * @param {Object} [options] A dictionary of config options to override
12304
- * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
12305
- * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
12306
- * @returns {boolean} current opt-out status
12307
- */
12308
- MixpanelLib.prototype.has_opted_out_tracking = function(options) {
12309
- return this._gdpr_call_func(hasOptedOut, options);
12310
- };
12311
-
12312
- /**
12313
- * Clear the user's opt in/out status of data tracking and cookies/localstorage for this Mixpanel instance
11367
+ * // transport for sending requests ('XHR' or 'sendBeacon')
11368
+ * // NB: sendBeacon should only be used for scenarios such as
11369
+ * // page unload where a "best-effort" attempt to send is
11370
+ * // acceptable; the sendBeacon API does not support callbacks
11371
+ * // or any way to know the result of the request. Mixpanel
11372
+ * // tracking via sendBeacon will not support any event-
11373
+ * // batching or retry mechanisms.
11374
+ * api_transport: 'XHR'
12314
11375
  *
12315
- * ### Usage
11376
+ * // turn on request-batching/queueing/retry
11377
+ * batch_requests: false,
12316
11378
  *
12317
- * // clear user's opt-in/out status
12318
- * mixpanel.clear_opt_in_out_tracking();
11379
+ * // maximum number of events/updates to send in a single
11380
+ * // network request
11381
+ * batch_size: 50,
12319
11382
  *
12320
- * // clear user's opt-in/out status with specific cookie configuration - should match
12321
- * // configuration used when opt_in_tracking/opt_out_tracking methods were called.
12322
- * mixpanel.clear_opt_in_out_tracking({
12323
- * cookie_expiration: 30,
12324
- * secure_cookie: true
12325
- * });
11383
+ * // milliseconds to wait between sending batch requests
11384
+ * batch_flush_interval_ms: 5000,
12326
11385
  *
12327
- * @param {Object} [options] A dictionary of config options to override
12328
- * @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence
12329
- * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
12330
- * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
12331
- * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
12332
- * @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
12333
- * @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)
12334
- * @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)
12335
- * @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)
12336
- */
12337
- MixpanelLib.prototype.clear_opt_in_out_tracking = function(options) {
12338
- options = _.extend({
12339
- 'enable_persistence': true
12340
- }, options);
12341
-
12342
- this._gdpr_call_func(clearOptInOut, options);
12343
- this._gdpr_update_persistence(options);
12344
- };
12345
-
12346
- MixpanelLib.prototype.report_error = function(msg, err) {
12347
- console$1.error.apply(console$1.error, arguments);
12348
- try {
12349
- if (!err && !(msg instanceof Error)) {
12350
- msg = new Error(msg);
12351
- }
12352
- this.get_config('error_reporter')(msg, err);
12353
- } catch(err) {
12354
- console$1.error(err);
12355
- }
12356
- };
12357
-
12358
- // EXPORTS (for closure compiler)
12359
-
12360
- // MixpanelLib Exports
12361
- MixpanelLib.prototype['init'] = MixpanelLib.prototype.init;
12362
- MixpanelLib.prototype['reset'] = MixpanelLib.prototype.reset;
12363
- MixpanelLib.prototype['disable'] = MixpanelLib.prototype.disable;
12364
- MixpanelLib.prototype['time_event'] = MixpanelLib.prototype.time_event;
12365
- MixpanelLib.prototype['track'] = MixpanelLib.prototype.track;
12366
- MixpanelLib.prototype['track_links'] = MixpanelLib.prototype.track_links;
12367
- MixpanelLib.prototype['track_forms'] = MixpanelLib.prototype.track_forms;
12368
- MixpanelLib.prototype['track_pageview'] = MixpanelLib.prototype.track_pageview;
12369
- MixpanelLib.prototype['register'] = MixpanelLib.prototype.register;
12370
- MixpanelLib.prototype['register_once'] = MixpanelLib.prototype.register_once;
12371
- MixpanelLib.prototype['unregister'] = MixpanelLib.prototype.unregister;
12372
- MixpanelLib.prototype['identify'] = MixpanelLib.prototype.identify;
12373
- MixpanelLib.prototype['alias'] = MixpanelLib.prototype.alias;
12374
- MixpanelLib.prototype['name_tag'] = MixpanelLib.prototype.name_tag;
12375
- MixpanelLib.prototype['set_config'] = MixpanelLib.prototype.set_config;
12376
- MixpanelLib.prototype['get_config'] = MixpanelLib.prototype.get_config;
12377
- MixpanelLib.prototype['get_property'] = MixpanelLib.prototype.get_property;
12378
- MixpanelLib.prototype['get_distinct_id'] = MixpanelLib.prototype.get_distinct_id;
12379
- MixpanelLib.prototype['toString'] = MixpanelLib.prototype.toString;
12380
- MixpanelLib.prototype['opt_out_tracking'] = MixpanelLib.prototype.opt_out_tracking;
12381
- MixpanelLib.prototype['opt_in_tracking'] = MixpanelLib.prototype.opt_in_tracking;
12382
- MixpanelLib.prototype['has_opted_out_tracking'] = MixpanelLib.prototype.has_opted_out_tracking;
12383
- MixpanelLib.prototype['has_opted_in_tracking'] = MixpanelLib.prototype.has_opted_in_tracking;
12384
- MixpanelLib.prototype['clear_opt_in_out_tracking'] = MixpanelLib.prototype.clear_opt_in_out_tracking;
12385
- MixpanelLib.prototype['get_group'] = MixpanelLib.prototype.get_group;
12386
- MixpanelLib.prototype['set_group'] = MixpanelLib.prototype.set_group;
12387
- MixpanelLib.prototype['add_group'] = MixpanelLib.prototype.add_group;
12388
- MixpanelLib.prototype['remove_group'] = MixpanelLib.prototype.remove_group;
12389
- MixpanelLib.prototype['track_with_groups'] = MixpanelLib.prototype.track_with_groups;
12390
- MixpanelLib.prototype['start_batch_senders'] = MixpanelLib.prototype.start_batch_senders;
12391
- MixpanelLib.prototype['stop_batch_senders'] = MixpanelLib.prototype.stop_batch_senders;
12392
-
12393
- // MixpanelPersistence Exports
12394
- MixpanelPersistence.prototype['properties'] = MixpanelPersistence.prototype.properties;
12395
- MixpanelPersistence.prototype['update_search_keyword'] = MixpanelPersistence.prototype.update_search_keyword;
12396
- MixpanelPersistence.prototype['update_referrer_info'] = MixpanelPersistence.prototype.update_referrer_info;
12397
- MixpanelPersistence.prototype['get_cross_subdomain'] = MixpanelPersistence.prototype.get_cross_subdomain;
12398
- MixpanelPersistence.prototype['clear'] = MixpanelPersistence.prototype.clear;
12399
-
12400
-
12401
- var instances = {};
12402
- var extend_mp = function() {
12403
- // add all the sub mixpanel instances
12404
- _.each(instances, function(instance, name) {
12405
- if (name !== PRIMARY_INSTANCE_NAME) { mixpanel_master[name] = instance; }
12406
- });
12407
-
12408
- // add private functions as _
12409
- mixpanel_master['_'] = _;
12410
- };
12411
-
12412
- var override_mp_init_func = function() {
12413
- // we override the snippets init function to handle the case where a
12414
- // user initializes the mixpanel library after the script loads & runs
12415
- mixpanel_master['init'] = function(token, config, name) {
12416
- if (name) {
12417
- // initialize a sub library
12418
- if (!mixpanel_master[name]) {
12419
- mixpanel_master[name] = instances[name] = create_mplib(token, config, name);
12420
- mixpanel_master[name]._loaded();
12421
- }
12422
- return mixpanel_master[name];
12423
- } else {
12424
- var instance = mixpanel_master;
12425
-
12426
- if (instances[PRIMARY_INSTANCE_NAME]) {
12427
- // main mixpanel lib already initialized
12428
- instance = instances[PRIMARY_INSTANCE_NAME];
12429
- } else if (token) {
12430
- // intialize the main mixpanel lib
12431
- instance = create_mplib(token, config, PRIMARY_INSTANCE_NAME);
12432
- instance._loaded();
12433
- instances[PRIMARY_INSTANCE_NAME] = instance;
12434
- }
12435
-
12436
- mixpanel_master = instance;
12437
- if (init_type === INIT_SNIPPET) {
12438
- window$1[PRIMARY_INSTANCE_NAME] = mixpanel_master;
12439
- }
12440
- extend_mp();
12441
- }
12442
- };
12443
- };
12444
-
12445
- var add_dom_loaded_handler = function() {
12446
- // Cross browser DOM Loaded support
12447
- function dom_loaded_handler() {
12448
- // function flag since we only want to execute this once
12449
- if (dom_loaded_handler.done) { return; }
12450
- dom_loaded_handler.done = true;
12451
-
12452
- DOM_LOADED = true;
12453
- ENQUEUE_REQUESTS = false;
12454
-
12455
- _.each(instances, function(inst) {
12456
- inst._dom_loaded();
12457
- });
12458
- }
11386
+ * // milliseconds to wait for network responses to batch requests
11387
+ * // before they are considered timed-out and retried
11388
+ * batch_request_timeout_ms: 90000,
11389
+ *
11390
+ * // override value for cookie domain, only useful for ensuring
11391
+ * // correct cross-subdomain cookies on unusual domains like
11392
+ * // subdomain.mainsite.avocat.fr; NB this cannot be used to
11393
+ * // set cookies on a different domain than the current origin
11394
+ * cookie_domain: ''
11395
+ *
11396
+ * // super properties cookie expiration (in days)
11397
+ * cookie_expiration: 365
11398
+ *
11399
+ * // if true, cookie will be set with SameSite=None; Secure
11400
+ * // this is only useful in special situations, like embedded
11401
+ * // 3rd-party iframes that set up a Mixpanel instance
11402
+ * cross_site_cookie: false
11403
+ *
11404
+ * // super properties span subdomains
11405
+ * cross_subdomain_cookie: true
11406
+ *
11407
+ * // debug mode
11408
+ * debug: false
11409
+ *
11410
+ * // if this is true, the mixpanel cookie or localStorage entry
11411
+ * // will be deleted, and no user persistence will take place
11412
+ * disable_persistence: false
11413
+ *
11414
+ * // if this is true, Mixpanel will automatically determine
11415
+ * // City, Region and Country data using the IP address of
11416
+ * //the client
11417
+ * ip: true
11418
+ *
11419
+ * // opt users out of tracking by this Mixpanel instance by default
11420
+ * opt_out_tracking_by_default: false
11421
+ *
11422
+ * // opt users out of browser data storage by this Mixpanel instance by default
11423
+ * opt_out_persistence_by_default: false
11424
+ *
11425
+ * // persistence mechanism used by opt-in/opt-out methods - cookie
11426
+ * // or localStorage - falls back to cookie if localStorage is unavailable
11427
+ * opt_out_tracking_persistence_type: 'localStorage'
11428
+ *
11429
+ * // customize the name of cookie/localStorage set by opt-in/opt-out methods
11430
+ * opt_out_tracking_cookie_prefix: null
11431
+ *
11432
+ * // type of persistent store for super properties (cookie/
11433
+ * // localStorage) if set to 'localStorage', any existing
11434
+ * // mixpanel cookie value with the same persistence_name
11435
+ * // will be transferred to localStorage and deleted
11436
+ * persistence: 'cookie'
11437
+ *
11438
+ * // name for super properties persistent store
11439
+ * persistence_name: ''
11440
+ *
11441
+ * // names of properties/superproperties which should never
11442
+ * // be sent with track() calls
11443
+ * property_blacklist: []
11444
+ *
11445
+ * // if this is true, mixpanel cookies will be marked as
11446
+ * // secure, meaning they will only be transmitted over https
11447
+ * secure_cookie: false
11448
+ *
11449
+ * // the amount of time track_links will
11450
+ * // wait for Mixpanel's servers to respond
11451
+ * track_links_timeout: 300
11452
+ *
11453
+ * // if you set upgrade to be true, the library will check for
11454
+ * // a cookie from our old js library and import super
11455
+ * // properties from it, then the old cookie is deleted
11456
+ * // The upgrade config option only works in the initialization,
11457
+ * // so make sure you set it when you create the library.
11458
+ * upgrade: false
11459
+ *
11460
+ * // extra HTTP request headers to set for each API request, in
11461
+ * // the format {'Header-Name': value}
11462
+ * xhr_headers: {}
11463
+ *
11464
+ * // whether to ignore or respect the web browser's Do Not Track setting
11465
+ * ignore_dnt: false
11466
+ * }
11467
+ *
11468
+ *
11469
+ * @param {Object} config A dictionary of new configuration values to update
11470
+ */
11471
+ MixpanelLib.prototype.set_config = function(config) {
11472
+ if (_.isObject(config)) {
11473
+ _.extend(this['config'], config);
12459
11474
 
12460
- function do_scroll_check() {
12461
- try {
12462
- document$1.documentElement.doScroll('left');
12463
- } catch(e) {
12464
- setTimeout(do_scroll_check, 1);
12465
- return;
11475
+ var new_batch_size = config['batch_size'];
11476
+ if (new_batch_size) {
11477
+ _.each(this.request_batchers, function(batcher) {
11478
+ batcher.resetBatchSize();
11479
+ });
12466
11480
  }
12467
11481
 
12468
- dom_loaded_handler();
12469
- }
12470
-
12471
- if (document$1.addEventListener) {
12472
- if (document$1.readyState === 'complete') {
12473
- // safari 4 can fire the DOMContentLoaded event before loading all
12474
- // external JS (including this file). you will see some copypasta
12475
- // on the internet that checks for 'complete' and 'loaded', but
12476
- // 'loaded' is an IE thing
12477
- dom_loaded_handler();
12478
- } else {
12479
- document$1.addEventListener('DOMContentLoaded', dom_loaded_handler, false);
11482
+ if (!this.get_config('persistence_name')) {
11483
+ this['config']['persistence_name'] = this['config']['cookie_name'];
12480
11484
  }
12481
- } else if (document$1.attachEvent) {
12482
- // IE
12483
- document$1.attachEvent('onreadystatechange', dom_loaded_handler);
12484
-
12485
- // check to make sure we arn't in a frame
12486
- var toplevel = false;
12487
- try {
12488
- toplevel = window$1.frameElement === null;
12489
- } catch(e) {
12490
- // noop
11485
+ if (!this.get_config('disable_persistence')) {
11486
+ this['config']['disable_persistence'] = this['config']['disable_cookie'];
12491
11487
  }
12492
11488
 
12493
- if (document$1.documentElement.doScroll && toplevel) {
12494
- do_scroll_check();
11489
+ if (this['persistence']) {
11490
+ this['persistence'].update_config(this['config']);
12495
11491
  }
11492
+ Config.DEBUG = Config.DEBUG || this.get_config('debug');
12496
11493
  }
12497
-
12498
- // fallback handler, always will work
12499
- _.register_event(window$1, 'load', dom_loaded_handler, true);
12500
11494
  };
12501
11495
 
12502
- function init_as_module() {
12503
- init_type = INIT_MODULE;
12504
- mixpanel_master = new MixpanelLib();
11496
+ /**
11497
+ * returns the current config object for the library.
11498
+ */
11499
+ MixpanelLib.prototype.get_config = function(prop_name) {
11500
+ return this['config'][prop_name];
11501
+ };
12505
11502
 
12506
- override_mp_init_func();
12507
- mixpanel_master['init']();
12508
- add_dom_loaded_handler();
11503
+ /**
11504
+ * Fetch a hook function from config, with safe default, and run it
11505
+ * against the given arguments
11506
+ * @param {string} hook_name which hook to retrieve
11507
+ * @returns {any|null} return value of user-provided hook, or null if nothing was returned
11508
+ */
11509
+ MixpanelLib.prototype._run_hook = function(hook_name) {
11510
+ var ret = (this['config']['hooks'][hook_name] || IDENTITY_FUNC).apply(this, slice.call(arguments, 1));
11511
+ if (typeof ret === 'undefined') {
11512
+ this.report_error(hook_name + ' hook did not return a value');
11513
+ ret = null;
11514
+ }
11515
+ return ret;
11516
+ };
12509
11517
 
12510
- return mixpanel_master;
12511
- }
11518
+ /**
11519
+ * Returns the value of the super property named property_name. If no such
11520
+ * property is set, get_property() will return the undefined value.
11521
+ *
11522
+ * ### Notes:
11523
+ *
11524
+ * get_property() can only be called after the Mixpanel library has finished loading.
11525
+ * init() has a loaded function available to handle this automatically. For example:
11526
+ *
11527
+ * // grab value for 'user_id' after the mixpanel library has loaded
11528
+ * mixpanel.init('YOUR PROJECT TOKEN', {
11529
+ * loaded: function(mixpanel) {
11530
+ * user_id = mixpanel.get_property('user_id');
11531
+ * }
11532
+ * });
11533
+ *
11534
+ * @param {String} property_name The name of the super property you want to retrieve
11535
+ */
11536
+ MixpanelLib.prototype.get_property = function(property_name) {
11537
+ return this['persistence']['props'][property_name];
11538
+ };
12512
11539
 
12513
- var mixpanel = init_as_module();
11540
+ MixpanelLib.prototype.toString = function() {
11541
+ var name = this.get_config('name');
11542
+ if (name !== PRIMARY_INSTANCE_NAME) {
11543
+ name = PRIMARY_INSTANCE_NAME + '.' + name;
11544
+ }
11545
+ return name;
11546
+ };
12514
11547
 
12515
- var mixpanel_cjs = mixpanel;
11548
+ MixpanelLib.prototype._event_is_disabled = function(event_name) {
11549
+ return _.isBlockedUA(userAgent) ||
11550
+ this._flags.disable_all_events ||
11551
+ _.include(this.__disabled_events, event_name);
11552
+ };
12516
11553
 
12517
- var mixpanel$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), mixpanel_cjs, {
12518
- 'default': mixpanel_cjs
12519
- }));
11554
+ // perform some housekeeping around GDPR opt-in/out state
11555
+ MixpanelLib.prototype._gdpr_init = function() {
11556
+ var is_localStorage_requested = this.get_config('opt_out_tracking_persistence_type') === 'localStorage';
12520
11557
 
12521
- // Needed to avoid error in CJS builds on some bundlers.
12522
- const mixpanelLib = mixpanel_cjs || mixpanel$1;
12523
- let mixpanelInstance;
12524
- const MIXPANEL_EVENT = {
12525
- VISUAL_SDK_RENDER_START: 'visual-sdk-render-start',
12526
- VISUAL_SDK_CALLED_INIT: 'visual-sdk-called-init',
12527
- VISUAL_SDK_RENDER_COMPLETE: 'visual-sdk-render-complete',
12528
- VISUAL_SDK_RENDER_FAILED: 'visual-sdk-render-failed',
12529
- VISUAL_SDK_TRIGGER: 'visual-sdk-trigger',
12530
- VISUAL_SDK_ON: 'visual-sdk-on',
12531
- VISUAL_SDK_IFRAME_LOAD_PERFORMANCE: 'visual-sdk-iframe-load-performance',
12532
- VISUAL_SDK_EMBED_CREATE: 'visual-sdk-embed-create',
12533
- VERCEL_INTEGRATION_COMPLETED: 'vercel-integration-completed',
12534
- };
12535
- let isMixpanelInitialized = false;
12536
- let eventQueue = [];
12537
- /**
12538
- * Pushes the event with its Property key-value map to mixpanel.
12539
- *
12540
- * @param eventId
12541
- * @param eventProps
12542
- */
12543
- function uploadMixpanelEvent(eventId, eventProps = {}) {
12544
- if (!isMixpanelInitialized) {
12545
- eventQueue.push({ eventId, eventProps });
12546
- return;
12547
- }
12548
- mixpanelInstance.track(eventId, eventProps);
12549
- }
12550
- /**
12551
- *
12552
- */
12553
- function emptyQueue() {
12554
- if (!isMixpanelInitialized) {
12555
- return;
12556
- }
12557
- eventQueue.forEach((event) => {
12558
- uploadMixpanelEvent(event.eventId, event.eventProps);
12559
- });
12560
- eventQueue = [];
12561
- }
12562
- /**
12563
- *
12564
- * @param sessionInfo
12565
- */
12566
- function initMixpanel(sessionInfo) {
12567
- var _a;
12568
- if (!sessionInfo || !sessionInfo.mixpanelToken) {
12569
- return;
12570
- }
12571
- // On a public cluster the user is anonymous, so don't set the identify to
12572
- // userGUID
12573
- const isPublicCluster = !!sessionInfo.isPublicUser;
12574
- const token = sessionInfo.mixpanelToken;
12575
- try {
12576
- if (token) {
12577
- mixpanelInstance = mixpanelLib.init(token, undefined, 'tsEmbed');
12578
- if (!isPublicCluster) {
12579
- mixpanelInstance.identify(sessionInfo.userGUID);
12580
- }
12581
- mixpanelInstance.register_once({
12582
- clusterId: sessionInfo.clusterId,
12583
- clusterName: sessionInfo.clusterName,
12584
- releaseVersion: sessionInfo.releaseVersion,
12585
- hostAppUrl: ((_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.host) || '',
12586
- });
12587
- isMixpanelInitialized = true;
12588
- emptyQueue();
12589
- }
12590
- }
12591
- catch (e) {
12592
- logger.error('Error initializing mixpanel', e);
12593
- }
12594
- }
11558
+ // try to convert opt-in/out cookies to localStorage if possible
11559
+ if (is_localStorage_requested && _.localStorage.is_supported()) {
11560
+ if (!this.has_opted_in_tracking() && this.has_opted_in_tracking({'persistence_type': 'cookie'})) {
11561
+ this.opt_in_tracking({'enable_persistence': false});
11562
+ }
11563
+ if (!this.has_opted_out_tracking() && this.has_opted_out_tracking({'persistence_type': 'cookie'})) {
11564
+ this.opt_out_tracking({'clear_persistence': false});
11565
+ }
11566
+ this.clear_opt_in_out_tracking({
11567
+ 'persistence_type': 'cookie',
11568
+ 'enable_persistence': false
11569
+ });
11570
+ }
12595
11571
 
12596
- var eventemitter3 = createCommonjsModule(function (module) {
11572
+ // check whether the user has already opted out - if so, clear & disable persistence
11573
+ if (this.has_opted_out_tracking()) {
11574
+ this._gdpr_update_persistence({'clear_persistence': true});
12597
11575
 
12598
- var has = Object.prototype.hasOwnProperty
12599
- , prefix = '~';
11576
+ // check whether we should opt out by default
11577
+ // note: we don't clear persistence here by default since opt-out default state is often
11578
+ // used as an initial state while GDPR information is being collected
11579
+ } else if (!this.has_opted_in_tracking() && (
11580
+ this.get_config('opt_out_tracking_by_default') || _.cookie.get('mp_optout')
11581
+ )) {
11582
+ _.cookie.remove('mp_optout');
11583
+ this.opt_out_tracking({
11584
+ 'clear_persistence': this.get_config('opt_out_persistence_by_default')
11585
+ });
11586
+ }
11587
+ };
12600
11588
 
12601
11589
  /**
12602
- * Constructor to create a storage for our `EE` objects.
12603
- * An `Events` instance is a plain object whose properties are event names.
12604
- *
12605
- * @constructor
12606
- * @private
11590
+ * Enable or disable persistence based on options
11591
+ * only enable/disable if persistence is not already in this state
11592
+ * @param {boolean} [options.clear_persistence] If true, will delete all data stored by the sdk in persistence and disable it
11593
+ * @param {boolean} [options.enable_persistence] If true, will re-enable sdk persistence
12607
11594
  */
12608
- function Events() {}
11595
+ MixpanelLib.prototype._gdpr_update_persistence = function(options) {
11596
+ var disabled;
11597
+ if (options && options['clear_persistence']) {
11598
+ disabled = true;
11599
+ } else if (options && options['enable_persistence']) {
11600
+ disabled = false;
11601
+ } else {
11602
+ return;
11603
+ }
12609
11604
 
12610
- //
12611
- // We try to not inherit from `Object.prototype`. In some engines creating an
12612
- // instance in this way is faster than calling `Object.create(null)` directly.
12613
- // If `Object.create(null)` is not supported we prefix the event names with a
12614
- // character to make sure that the built-in object properties are not
12615
- // overridden or used as an attack vector.
12616
- //
12617
- if (Object.create) {
12618
- Events.prototype = Object.create(null);
11605
+ if (!this.get_config('disable_persistence') && this['persistence'].disabled !== disabled) {
11606
+ this['persistence'].set_disabled(disabled);
11607
+ }
12619
11608
 
12620
- //
12621
- // This hack is needed because the `__proto__` property is still inherited in
12622
- // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.
12623
- //
12624
- if (!new Events().__proto__) prefix = false;
12625
- }
11609
+ if (disabled) {
11610
+ _.each(this.request_batchers, function(batcher) {
11611
+ batcher.clear();
11612
+ });
11613
+ }
11614
+ };
11615
+
11616
+ // call a base gdpr function after constructing the appropriate token and options args
11617
+ MixpanelLib.prototype._gdpr_call_func = function(func, options) {
11618
+ options = _.extend({
11619
+ 'track': _.bind(this.track, this),
11620
+ 'persistence_type': this.get_config('opt_out_tracking_persistence_type'),
11621
+ 'cookie_prefix': this.get_config('opt_out_tracking_cookie_prefix'),
11622
+ 'cookie_expiration': this.get_config('cookie_expiration'),
11623
+ 'cross_site_cookie': this.get_config('cross_site_cookie'),
11624
+ 'cross_subdomain_cookie': this.get_config('cross_subdomain_cookie'),
11625
+ 'cookie_domain': this.get_config('cookie_domain'),
11626
+ 'secure_cookie': this.get_config('secure_cookie'),
11627
+ 'ignore_dnt': this.get_config('ignore_dnt')
11628
+ }, options);
11629
+
11630
+ // check if localStorage can be used for recording opt out status, fall back to cookie if not
11631
+ if (!_.localStorage.is_supported()) {
11632
+ options['persistence_type'] = 'cookie';
11633
+ }
11634
+
11635
+ return func(this.get_config('token'), {
11636
+ track: options['track'],
11637
+ trackEventName: options['track_event_name'],
11638
+ trackProperties: options['track_properties'],
11639
+ persistenceType: options['persistence_type'],
11640
+ persistencePrefix: options['cookie_prefix'],
11641
+ cookieDomain: options['cookie_domain'],
11642
+ cookieExpiration: options['cookie_expiration'],
11643
+ crossSiteCookie: options['cross_site_cookie'],
11644
+ crossSubdomainCookie: options['cross_subdomain_cookie'],
11645
+ secureCookie: options['secure_cookie'],
11646
+ ignoreDnt: options['ignore_dnt']
11647
+ });
11648
+ };
12626
11649
 
12627
11650
  /**
12628
- * Representation of a single event listener.
11651
+ * Opt the user in to data tracking and cookies/localstorage for this Mixpanel instance
12629
11652
  *
12630
- * @param {Function} fn The listener function.
12631
- * @param {*} context The context to invoke the listener with.
12632
- * @param {Boolean} [once=false] Specify if the listener is a one-time listener.
12633
- * @constructor
12634
- * @private
11653
+ * ### Usage
11654
+ *
11655
+ * // opt user in
11656
+ * mixpanel.opt_in_tracking();
11657
+ *
11658
+ * // opt user in with specific event name, properties, cookie configuration
11659
+ * mixpanel.opt_in_tracking({
11660
+ * track_event_name: 'User opted in',
11661
+ * track_event_properties: {
11662
+ * 'Email': 'jdoe@example.com'
11663
+ * },
11664
+ * cookie_expiration: 30,
11665
+ * secure_cookie: true
11666
+ * });
11667
+ *
11668
+ * @param {Object} [options] A dictionary of config options to override
11669
+ * @param {function} [options.track] Function used for tracking a Mixpanel event to record the opt-in action (default is this Mixpanel instance's track method)
11670
+ * @param {string} [options.track_event_name=$opt_in] Event name to be used for tracking the opt-in action
11671
+ * @param {Object} [options.track_properties] Set of properties to be tracked along with the opt-in action
11672
+ * @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence
11673
+ * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11674
+ * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11675
+ * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
11676
+ * @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
11677
+ * @param {boolean} [options.cross_site_cookie] Whether the opt-in cookie is set as cross-site-enabled (overrides value specified in this Mixpanel instance's config)
11678
+ * @param {boolean} [options.cross_subdomain_cookie] Whether the opt-in cookie is set as cross-subdomain or not (overrides value specified in this Mixpanel instance's config)
11679
+ * @param {boolean} [options.secure_cookie] Whether the opt-in cookie is set as secure or not (overrides value specified in this Mixpanel instance's config)
12635
11680
  */
12636
- function EE(fn, context, once) {
12637
- this.fn = fn;
12638
- this.context = context;
12639
- this.once = once || false;
12640
- }
11681
+ MixpanelLib.prototype.opt_in_tracking = function(options) {
11682
+ options = _.extend({
11683
+ 'enable_persistence': true
11684
+ }, options);
11685
+
11686
+ this._gdpr_call_func(optIn, options);
11687
+ this._gdpr_update_persistence(options);
11688
+ };
12641
11689
 
12642
11690
  /**
12643
- * Add a listener for a given event.
11691
+ * Opt the user out of data tracking and cookies/localstorage for this Mixpanel instance
12644
11692
  *
12645
- * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
12646
- * @param {(String|Symbol)} event The event name.
12647
- * @param {Function} fn The listener function.
12648
- * @param {*} context The context to invoke the listener with.
12649
- * @param {Boolean} once Specify if the listener is a one-time listener.
12650
- * @returns {EventEmitter}
12651
- * @private
11693
+ * ### Usage
11694
+ *
11695
+ * // opt user out
11696
+ * mixpanel.opt_out_tracking();
11697
+ *
11698
+ * // opt user out with different cookie configuration from Mixpanel instance
11699
+ * mixpanel.opt_out_tracking({
11700
+ * cookie_expiration: 30,
11701
+ * secure_cookie: true
11702
+ * });
11703
+ *
11704
+ * @param {Object} [options] A dictionary of config options to override
11705
+ * @param {boolean} [options.delete_user=true] If true, will delete the currently identified user's profile and clear all charges after opting the user out
11706
+ * @param {boolean} [options.clear_persistence=true] If true, will delete all data stored by the sdk in persistence
11707
+ * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11708
+ * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11709
+ * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
11710
+ * @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
11711
+ * @param {boolean} [options.cross_site_cookie] Whether the opt-in cookie is set as cross-site-enabled (overrides value specified in this Mixpanel instance's config)
11712
+ * @param {boolean} [options.cross_subdomain_cookie] Whether the opt-in cookie is set as cross-subdomain or not (overrides value specified in this Mixpanel instance's config)
11713
+ * @param {boolean} [options.secure_cookie] Whether the opt-in cookie is set as secure or not (overrides value specified in this Mixpanel instance's config)
12652
11714
  */
12653
- function addListener(emitter, event, fn, context, once) {
12654
- if (typeof fn !== 'function') {
12655
- throw new TypeError('The listener must be a function');
12656
- }
12657
-
12658
- var listener = new EE(fn, context || emitter, once)
12659
- , evt = prefix ? prefix + event : event;
11715
+ MixpanelLib.prototype.opt_out_tracking = function(options) {
11716
+ options = _.extend({
11717
+ 'clear_persistence': true,
11718
+ 'delete_user': true
11719
+ }, options);
12660
11720
 
12661
- if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;
12662
- else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);
12663
- else emitter._events[evt] = [emitter._events[evt], listener];
11721
+ // delete user and clear charges since these methods may be disabled by opt-out
11722
+ if (options['delete_user'] && this['people'] && this['people']._identify_called()) {
11723
+ this['people'].delete_user();
11724
+ this['people'].clear_charges();
11725
+ }
12664
11726
 
12665
- return emitter;
12666
- }
11727
+ this._gdpr_call_func(optOut, options);
11728
+ this._gdpr_update_persistence(options);
11729
+ };
12667
11730
 
12668
11731
  /**
12669
- * Clear event by name.
11732
+ * Check whether the user has opted in to data tracking and cookies/localstorage for this Mixpanel instance
12670
11733
  *
12671
- * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
12672
- * @param {(String|Symbol)} evt The Event name.
12673
- * @private
11734
+ * ### Usage
11735
+ *
11736
+ * var has_opted_in = mixpanel.has_opted_in_tracking();
11737
+ * // use has_opted_in value
11738
+ *
11739
+ * @param {Object} [options] A dictionary of config options to override
11740
+ * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11741
+ * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11742
+ * @returns {boolean} current opt-in status
12674
11743
  */
12675
- function clearEvent(emitter, evt) {
12676
- if (--emitter._eventsCount === 0) emitter._events = new Events();
12677
- else delete emitter._events[evt];
12678
- }
11744
+ MixpanelLib.prototype.has_opted_in_tracking = function(options) {
11745
+ return this._gdpr_call_func(hasOptedIn, options);
11746
+ };
12679
11747
 
12680
11748
  /**
12681
- * Minimal `EventEmitter` interface that is molded against the Node.js
12682
- * `EventEmitter` interface.
11749
+ * Check whether the user has opted out of data tracking and cookies/localstorage for this Mixpanel instance
12683
11750
  *
12684
- * @constructor
12685
- * @public
11751
+ * ### Usage
11752
+ *
11753
+ * var has_opted_out = mixpanel.has_opted_out_tracking();
11754
+ * // use has_opted_out value
11755
+ *
11756
+ * @param {Object} [options] A dictionary of config options to override
11757
+ * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11758
+ * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11759
+ * @returns {boolean} current opt-out status
12686
11760
  */
12687
- function EventEmitter() {
12688
- this._events = new Events();
12689
- this._eventsCount = 0;
12690
- }
11761
+ MixpanelLib.prototype.has_opted_out_tracking = function(options) {
11762
+ return this._gdpr_call_func(hasOptedOut, options);
11763
+ };
12691
11764
 
12692
11765
  /**
12693
- * Return an array listing the events for which the emitter has registered
12694
- * listeners.
11766
+ * Clear the user's opt in/out status of data tracking and cookies/localstorage for this Mixpanel instance
11767
+ *
11768
+ * ### Usage
11769
+ *
11770
+ * // clear user's opt-in/out status
11771
+ * mixpanel.clear_opt_in_out_tracking();
11772
+ *
11773
+ * // clear user's opt-in/out status with specific cookie configuration - should match
11774
+ * // configuration used when opt_in_tracking/opt_out_tracking methods were called.
11775
+ * mixpanel.clear_opt_in_out_tracking({
11776
+ * cookie_expiration: 30,
11777
+ * secure_cookie: true
11778
+ * });
12695
11779
  *
12696
- * @returns {Array}
12697
- * @public
11780
+ * @param {Object} [options] A dictionary of config options to override
11781
+ * @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence
11782
+ * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11783
+ * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11784
+ * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
11785
+ * @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
11786
+ * @param {boolean} [options.cross_site_cookie] Whether the opt-in cookie is set as cross-site-enabled (overrides value specified in this Mixpanel instance's config)
11787
+ * @param {boolean} [options.cross_subdomain_cookie] Whether the opt-in cookie is set as cross-subdomain or not (overrides value specified in this Mixpanel instance's config)
11788
+ * @param {boolean} [options.secure_cookie] Whether the opt-in cookie is set as secure or not (overrides value specified in this Mixpanel instance's config)
12698
11789
  */
12699
- EventEmitter.prototype.eventNames = function eventNames() {
12700
- var names = []
12701
- , events
12702
- , name;
12703
-
12704
- if (this._eventsCount === 0) return names;
12705
-
12706
- for (name in (events = this._events)) {
12707
- if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
12708
- }
11790
+ MixpanelLib.prototype.clear_opt_in_out_tracking = function(options) {
11791
+ options = _.extend({
11792
+ 'enable_persistence': true
11793
+ }, options);
12709
11794
 
12710
- if (Object.getOwnPropertySymbols) {
12711
- return names.concat(Object.getOwnPropertySymbols(events));
12712
- }
11795
+ this._gdpr_call_func(clearOptInOut, options);
11796
+ this._gdpr_update_persistence(options);
11797
+ };
12713
11798
 
12714
- return names;
11799
+ MixpanelLib.prototype.report_error = function(msg, err) {
11800
+ console$1.error.apply(console$1.error, arguments);
11801
+ try {
11802
+ if (!err && !(msg instanceof Error)) {
11803
+ msg = new Error(msg);
11804
+ }
11805
+ this.get_config('error_reporter')(msg, err);
11806
+ } catch(err) {
11807
+ console$1.error(err);
11808
+ }
12715
11809
  };
12716
11810
 
12717
- /**
12718
- * Return the listeners registered for a given event.
12719
- *
12720
- * @param {(String|Symbol)} event The event name.
12721
- * @returns {Array} The registered listeners.
12722
- * @public
12723
- */
12724
- EventEmitter.prototype.listeners = function listeners(event) {
12725
- var evt = prefix ? prefix + event : event
12726
- , handlers = this._events[evt];
11811
+ // EXPORTS (for closure compiler)
12727
11812
 
12728
- if (!handlers) return [];
12729
- if (handlers.fn) return [handlers.fn];
11813
+ // MixpanelLib Exports
11814
+ MixpanelLib.prototype['init'] = MixpanelLib.prototype.init;
11815
+ MixpanelLib.prototype['reset'] = MixpanelLib.prototype.reset;
11816
+ MixpanelLib.prototype['disable'] = MixpanelLib.prototype.disable;
11817
+ MixpanelLib.prototype['time_event'] = MixpanelLib.prototype.time_event;
11818
+ MixpanelLib.prototype['track'] = MixpanelLib.prototype.track;
11819
+ MixpanelLib.prototype['track_links'] = MixpanelLib.prototype.track_links;
11820
+ MixpanelLib.prototype['track_forms'] = MixpanelLib.prototype.track_forms;
11821
+ MixpanelLib.prototype['track_pageview'] = MixpanelLib.prototype.track_pageview;
11822
+ MixpanelLib.prototype['register'] = MixpanelLib.prototype.register;
11823
+ MixpanelLib.prototype['register_once'] = MixpanelLib.prototype.register_once;
11824
+ MixpanelLib.prototype['unregister'] = MixpanelLib.prototype.unregister;
11825
+ MixpanelLib.prototype['identify'] = MixpanelLib.prototype.identify;
11826
+ MixpanelLib.prototype['alias'] = MixpanelLib.prototype.alias;
11827
+ MixpanelLib.prototype['name_tag'] = MixpanelLib.prototype.name_tag;
11828
+ MixpanelLib.prototype['set_config'] = MixpanelLib.prototype.set_config;
11829
+ MixpanelLib.prototype['get_config'] = MixpanelLib.prototype.get_config;
11830
+ MixpanelLib.prototype['get_property'] = MixpanelLib.prototype.get_property;
11831
+ MixpanelLib.prototype['get_distinct_id'] = MixpanelLib.prototype.get_distinct_id;
11832
+ MixpanelLib.prototype['toString'] = MixpanelLib.prototype.toString;
11833
+ MixpanelLib.prototype['opt_out_tracking'] = MixpanelLib.prototype.opt_out_tracking;
11834
+ MixpanelLib.prototype['opt_in_tracking'] = MixpanelLib.prototype.opt_in_tracking;
11835
+ MixpanelLib.prototype['has_opted_out_tracking'] = MixpanelLib.prototype.has_opted_out_tracking;
11836
+ MixpanelLib.prototype['has_opted_in_tracking'] = MixpanelLib.prototype.has_opted_in_tracking;
11837
+ MixpanelLib.prototype['clear_opt_in_out_tracking'] = MixpanelLib.prototype.clear_opt_in_out_tracking;
11838
+ MixpanelLib.prototype['get_group'] = MixpanelLib.prototype.get_group;
11839
+ MixpanelLib.prototype['set_group'] = MixpanelLib.prototype.set_group;
11840
+ MixpanelLib.prototype['add_group'] = MixpanelLib.prototype.add_group;
11841
+ MixpanelLib.prototype['remove_group'] = MixpanelLib.prototype.remove_group;
11842
+ MixpanelLib.prototype['track_with_groups'] = MixpanelLib.prototype.track_with_groups;
11843
+ MixpanelLib.prototype['start_batch_senders'] = MixpanelLib.prototype.start_batch_senders;
11844
+ MixpanelLib.prototype['stop_batch_senders'] = MixpanelLib.prototype.stop_batch_senders;
12730
11845
 
12731
- for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {
12732
- ee[i] = handlers[i].fn;
12733
- }
11846
+ // MixpanelPersistence Exports
11847
+ MixpanelPersistence.prototype['properties'] = MixpanelPersistence.prototype.properties;
11848
+ MixpanelPersistence.prototype['update_search_keyword'] = MixpanelPersistence.prototype.update_search_keyword;
11849
+ MixpanelPersistence.prototype['update_referrer_info'] = MixpanelPersistence.prototype.update_referrer_info;
11850
+ MixpanelPersistence.prototype['get_cross_subdomain'] = MixpanelPersistence.prototype.get_cross_subdomain;
11851
+ MixpanelPersistence.prototype['clear'] = MixpanelPersistence.prototype.clear;
12734
11852
 
12735
- return ee;
12736
- };
12737
11853
 
12738
- /**
12739
- * Return the number of listeners listening to a given event.
12740
- *
12741
- * @param {(String|Symbol)} event The event name.
12742
- * @returns {Number} The number of listeners.
12743
- * @public
12744
- */
12745
- EventEmitter.prototype.listenerCount = function listenerCount(event) {
12746
- var evt = prefix ? prefix + event : event
12747
- , listeners = this._events[evt];
11854
+ var instances = {};
11855
+ var extend_mp = function() {
11856
+ // add all the sub mixpanel instances
11857
+ _.each(instances, function(instance, name) {
11858
+ if (name !== PRIMARY_INSTANCE_NAME) { mixpanel_master[name] = instance; }
11859
+ });
12748
11860
 
12749
- if (!listeners) return 0;
12750
- if (listeners.fn) return 1;
12751
- return listeners.length;
11861
+ // add private functions as _
11862
+ mixpanel_master['_'] = _;
12752
11863
  };
12753
11864
 
12754
- /**
12755
- * Calls each of the listeners registered for a given event.
12756
- *
12757
- * @param {(String|Symbol)} event The event name.
12758
- * @returns {Boolean} `true` if the event had listeners, else `false`.
12759
- * @public
12760
- */
12761
- EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
12762
- var evt = prefix ? prefix + event : event;
11865
+ var override_mp_init_func = function() {
11866
+ // we override the snippets init function to handle the case where a
11867
+ // user initializes the mixpanel library after the script loads & runs
11868
+ mixpanel_master['init'] = function(token, config, name) {
11869
+ if (name) {
11870
+ // initialize a sub library
11871
+ if (!mixpanel_master[name]) {
11872
+ mixpanel_master[name] = instances[name] = create_mplib(token, config, name);
11873
+ mixpanel_master[name]._loaded();
11874
+ }
11875
+ return mixpanel_master[name];
11876
+ } else {
11877
+ var instance = mixpanel_master;
12763
11878
 
12764
- if (!this._events[evt]) return false;
11879
+ if (instances[PRIMARY_INSTANCE_NAME]) {
11880
+ // main mixpanel lib already initialized
11881
+ instance = instances[PRIMARY_INSTANCE_NAME];
11882
+ } else if (token) {
11883
+ // intialize the main mixpanel lib
11884
+ instance = create_mplib(token, config, PRIMARY_INSTANCE_NAME);
11885
+ instance._loaded();
11886
+ instances[PRIMARY_INSTANCE_NAME] = instance;
11887
+ }
12765
11888
 
12766
- var listeners = this._events[evt]
12767
- , len = arguments.length
12768
- , args
12769
- , i;
11889
+ mixpanel_master = instance;
11890
+ if (init_type === INIT_SNIPPET) {
11891
+ window$1[PRIMARY_INSTANCE_NAME] = mixpanel_master;
11892
+ }
11893
+ extend_mp();
11894
+ }
11895
+ };
11896
+ };
12770
11897
 
12771
- if (listeners.fn) {
12772
- if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);
11898
+ var add_dom_loaded_handler = function() {
11899
+ // Cross browser DOM Loaded support
11900
+ function dom_loaded_handler() {
11901
+ // function flag since we only want to execute this once
11902
+ if (dom_loaded_handler.done) { return; }
11903
+ dom_loaded_handler.done = true;
12773
11904
 
12774
- switch (len) {
12775
- case 1: return listeners.fn.call(listeners.context), true;
12776
- case 2: return listeners.fn.call(listeners.context, a1), true;
12777
- case 3: return listeners.fn.call(listeners.context, a1, a2), true;
12778
- case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;
12779
- case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
12780
- case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
12781
- }
11905
+ DOM_LOADED = true;
11906
+ ENQUEUE_REQUESTS = false;
12782
11907
 
12783
- for (i = 1, args = new Array(len -1); i < len; i++) {
12784
- args[i - 1] = arguments[i];
11908
+ _.each(instances, function(inst) {
11909
+ inst._dom_loaded();
11910
+ });
12785
11911
  }
12786
11912
 
12787
- listeners.fn.apply(listeners.context, args);
12788
- } else {
12789
- var length = listeners.length
12790
- , j;
12791
-
12792
- for (i = 0; i < length; i++) {
12793
- if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);
12794
-
12795
- switch (len) {
12796
- case 1: listeners[i].fn.call(listeners[i].context); break;
12797
- case 2: listeners[i].fn.call(listeners[i].context, a1); break;
12798
- case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;
12799
- case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;
12800
- default:
12801
- if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {
12802
- args[j - 1] = arguments[j];
12803
- }
11913
+ function do_scroll_check() {
11914
+ try {
11915
+ document$1.documentElement.doScroll('left');
11916
+ } catch(e) {
11917
+ setTimeout(do_scroll_check, 1);
11918
+ return;
11919
+ }
12804
11920
 
12805
- listeners[i].fn.apply(listeners[i].context, args);
12806
- }
11921
+ dom_loaded_handler();
12807
11922
  }
12808
- }
12809
11923
 
12810
- return true;
12811
- };
11924
+ if (document$1.addEventListener) {
11925
+ if (document$1.readyState === 'complete') {
11926
+ // safari 4 can fire the DOMContentLoaded event before loading all
11927
+ // external JS (including this file). you will see some copypasta
11928
+ // on the internet that checks for 'complete' and 'loaded', but
11929
+ // 'loaded' is an IE thing
11930
+ dom_loaded_handler();
11931
+ } else {
11932
+ document$1.addEventListener('DOMContentLoaded', dom_loaded_handler, false);
11933
+ }
11934
+ } else if (document$1.attachEvent) {
11935
+ // IE
11936
+ document$1.attachEvent('onreadystatechange', dom_loaded_handler);
12812
11937
 
12813
- /**
12814
- * Add a listener for a given event.
12815
- *
12816
- * @param {(String|Symbol)} event The event name.
12817
- * @param {Function} fn The listener function.
12818
- * @param {*} [context=this] The context to invoke the listener with.
12819
- * @returns {EventEmitter} `this`.
12820
- * @public
12821
- */
12822
- EventEmitter.prototype.on = function on(event, fn, context) {
12823
- return addListener(this, event, fn, context, false);
12824
- };
11938
+ // check to make sure we arn't in a frame
11939
+ var toplevel = false;
11940
+ try {
11941
+ toplevel = window$1.frameElement === null;
11942
+ } catch(e) {
11943
+ // noop
11944
+ }
11945
+
11946
+ if (document$1.documentElement.doScroll && toplevel) {
11947
+ do_scroll_check();
11948
+ }
11949
+ }
12825
11950
 
12826
- /**
12827
- * Add a one-time listener for a given event.
12828
- *
12829
- * @param {(String|Symbol)} event The event name.
12830
- * @param {Function} fn The listener function.
12831
- * @param {*} [context=this] The context to invoke the listener with.
12832
- * @returns {EventEmitter} `this`.
12833
- * @public
12834
- */
12835
- EventEmitter.prototype.once = function once(event, fn, context) {
12836
- return addListener(this, event, fn, context, true);
11951
+ // fallback handler, always will work
11952
+ _.register_event(window$1, 'load', dom_loaded_handler, true);
12837
11953
  };
12838
11954
 
12839
- /**
12840
- * Remove the listeners of a given event.
12841
- *
12842
- * @param {(String|Symbol)} event The event name.
12843
- * @param {Function} fn Only remove the listeners that match this function.
12844
- * @param {*} context Only remove the listeners that have this context.
12845
- * @param {Boolean} once Only remove one-time listeners.
12846
- * @returns {EventEmitter} `this`.
12847
- * @public
12848
- */
12849
- EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
12850
- var evt = prefix ? prefix + event : event;
11955
+ function init_as_module() {
11956
+ init_type = INIT_MODULE;
11957
+ mixpanel_master = new MixpanelLib();
12851
11958
 
12852
- if (!this._events[evt]) return this;
12853
- if (!fn) {
12854
- clearEvent(this, evt);
12855
- return this;
12856
- }
11959
+ override_mp_init_func();
11960
+ mixpanel_master['init']();
11961
+ add_dom_loaded_handler();
12857
11962
 
12858
- var listeners = this._events[evt];
11963
+ return mixpanel_master;
11964
+ }
12859
11965
 
12860
- if (listeners.fn) {
12861
- if (
12862
- listeners.fn === fn &&
12863
- (!once || listeners.once) &&
12864
- (!context || listeners.context === context)
12865
- ) {
12866
- clearEvent(this, evt);
12867
- }
12868
- } else {
12869
- for (var i = 0, events = [], length = listeners.length; i < length; i++) {
12870
- if (
12871
- listeners[i].fn !== fn ||
12872
- (once && !listeners[i].once) ||
12873
- (context && listeners[i].context !== context)
12874
- ) {
12875
- events.push(listeners[i]);
12876
- }
12877
- }
11966
+ var mixpanel = init_as_module();
12878
11967
 
12879
- //
12880
- // Reset the array, or remove it completely if we have no more listeners.
12881
- //
12882
- if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;
12883
- else clearEvent(this, evt);
12884
- }
11968
+ var mixpanel_cjs = mixpanel;
12885
11969
 
12886
- return this;
11970
+ var mixpanel$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), mixpanel_cjs, {
11971
+ 'default': mixpanel_cjs
11972
+ }));
11973
+
11974
+ // Needed to avoid error in CJS builds on some bundlers.
11975
+ const mixpanelLib = mixpanel_cjs || mixpanel$1;
11976
+ let mixpanelInstance;
11977
+ const MIXPANEL_EVENT = {
11978
+ VISUAL_SDK_RENDER_START: 'visual-sdk-render-start',
11979
+ VISUAL_SDK_CALLED_INIT: 'visual-sdk-called-init',
11980
+ VISUAL_SDK_RENDER_COMPLETE: 'visual-sdk-render-complete',
11981
+ VISUAL_SDK_RENDER_FAILED: 'visual-sdk-render-failed',
11982
+ VISUAL_SDK_TRIGGER: 'visual-sdk-trigger',
11983
+ VISUAL_SDK_ON: 'visual-sdk-on',
11984
+ VISUAL_SDK_IFRAME_LOAD_PERFORMANCE: 'visual-sdk-iframe-load-performance',
11985
+ VISUAL_SDK_EMBED_CREATE: 'visual-sdk-embed-create',
11986
+ VERCEL_INTEGRATION_COMPLETED: 'vercel-integration-completed',
11987
+ };
11988
+ let isMixpanelInitialized = false;
11989
+ let eventQueue = [];
11990
+ /**
11991
+ * Pushes the event with its Property key-value map to mixpanel.
11992
+ *
11993
+ * @param eventId
11994
+ * @param eventProps
11995
+ */
11996
+ function uploadMixpanelEvent(eventId, eventProps = {}) {
11997
+ if (!isMixpanelInitialized) {
11998
+ eventQueue.push({ eventId, eventProps });
11999
+ return;
12000
+ }
12001
+ mixpanelInstance.track(eventId, eventProps);
12002
+ }
12003
+ /**
12004
+ *
12005
+ */
12006
+ function emptyQueue() {
12007
+ if (!isMixpanelInitialized) {
12008
+ return;
12009
+ }
12010
+ eventQueue.forEach((event) => {
12011
+ uploadMixpanelEvent(event.eventId, event.eventProps);
12012
+ });
12013
+ eventQueue = [];
12014
+ }
12015
+ /**
12016
+ *
12017
+ * @param sessionInfo
12018
+ */
12019
+ function initMixpanel(sessionInfo) {
12020
+ var _a;
12021
+ if (!sessionInfo || !sessionInfo.mixpanelToken) {
12022
+ return;
12023
+ }
12024
+ // On a public cluster the user is anonymous, so don't set the identify to
12025
+ // userGUID
12026
+ const isPublicCluster = !!sessionInfo.isPublicUser;
12027
+ const token = sessionInfo.mixpanelToken;
12028
+ try {
12029
+ if (token) {
12030
+ mixpanelInstance = mixpanelLib.init(token, undefined, 'tsEmbed');
12031
+ if (!isPublicCluster) {
12032
+ mixpanelInstance.identify(sessionInfo.userGUID);
12033
+ }
12034
+ mixpanelInstance.register_once({
12035
+ clusterId: sessionInfo.clusterId,
12036
+ clusterName: sessionInfo.clusterName,
12037
+ releaseVersion: sessionInfo.releaseVersion,
12038
+ hostAppUrl: ((_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.host) || '',
12039
+ });
12040
+ isMixpanelInitialized = true;
12041
+ emptyQueue();
12042
+ }
12043
+ }
12044
+ catch (e) {
12045
+ logger.error('Error initializing mixpanel', e);
12046
+ }
12047
+ }
12048
+
12049
+ let config = {};
12050
+ /**
12051
+ * Gets the configuration embed was initialized with.
12052
+ *
12053
+ * @returns {@link EmbedConfig} The configuration embed was initialized with.
12054
+ * @version SDK: 1.19.0 | ThoughtSpot: *
12055
+ * @group Global methods
12056
+ */
12057
+ const getEmbedConfig = () => config;
12058
+
12059
+ /**
12060
+ * Fetch wrapper that adds the authentication token to the request.
12061
+ * Use this to call the ThoughtSpot APIs when using the visual embed sdk.
12062
+ *
12063
+ * @param input
12064
+ * @param init
12065
+ * @version SDK: 1.28.0
12066
+ * @group Global methods
12067
+ */
12068
+ const tokenizedFetch = async (input, init) => {
12069
+ const embedConfig = getEmbedConfig();
12070
+ if (embedConfig.authType !== AuthType.TrustedAuthTokenCookieless) {
12071
+ return fetch(input, init);
12072
+ }
12073
+ const req = new Request(input, init);
12074
+ const authToken = await getAuthenticationToken(embedConfig);
12075
+ if (authToken) {
12076
+ req.headers.append('Authorization', `Bearer ${authToken}`);
12077
+ }
12078
+ return fetch(req);
12079
+ };
12080
+
12081
+ /**
12082
+ *
12083
+ * @param url
12084
+ * @param options
12085
+ */
12086
+ function tokenisedFailureLoggedFetch(url, options = {}) {
12087
+ return tokenizedFetch(url, options).then(async (r) => {
12088
+ var _a;
12089
+ if (!r.ok && r.type !== 'opaqueredirect' && r.type !== 'opaque') {
12090
+ logger.error('Failure', await ((_a = r.text) === null || _a === void 0 ? void 0 : _a.call(r)));
12091
+ }
12092
+ return r;
12093
+ });
12094
+ }
12095
+ /**
12096
+ *
12097
+ * @param authVerificationUrl
12098
+ */
12099
+ function fetchSessionInfoService(authVerificationUrl) {
12100
+ return tokenisedFailureLoggedFetch(authVerificationUrl, {
12101
+ credentials: 'include',
12102
+ });
12103
+ }
12104
+
12105
+ // eslint-disable-next-line import/no-mutable-exports
12106
+ let loggedInStatus = false;
12107
+ // eslint-disable-next-line import/no-mutable-exports
12108
+ let samlAuthWindow = null;
12109
+ // eslint-disable-next-line import/no-mutable-exports
12110
+ let samlCompletionPromise = null;
12111
+ let sessionInfo = null;
12112
+ let sessionInfoResolver = null;
12113
+ const sessionInfoPromise = new Promise((resolve) => {
12114
+ sessionInfoResolver = resolve;
12115
+ });
12116
+ let releaseVersion = '';
12117
+ const SSO_REDIRECTION_MARKER_GUID = '5e16222e-ef02-43e9-9fbd-24226bf3ce5b';
12118
+ /**
12119
+ * Enum for auth failure types. This is the parameter passed to the listner
12120
+ * of {@link AuthStatus.FAILURE}.
12121
+ *
12122
+ * @group Authentication / Init
12123
+ */
12124
+ var AuthFailureType;
12125
+ (function (AuthFailureType) {
12126
+ AuthFailureType["SDK"] = "SDK";
12127
+ AuthFailureType["NO_COOKIE_ACCESS"] = "NO_COOKIE_ACCESS";
12128
+ AuthFailureType["EXPIRY"] = "EXPIRY";
12129
+ AuthFailureType["OTHER"] = "OTHER";
12130
+ })(AuthFailureType || (AuthFailureType = {}));
12131
+ /**
12132
+ * Enum for auth status emitted by the emitter returned from {@link init}.
12133
+ *
12134
+ * @group Authentication / Init
12135
+ */
12136
+ var AuthStatus;
12137
+ (function (AuthStatus) {
12138
+ /**
12139
+ * Emits when the SDK fails to authenticate
12140
+ */
12141
+ AuthStatus["FAILURE"] = "FAILURE";
12142
+ /**
12143
+ * Emits when the SDK authenticates successfully
12144
+ */
12145
+ AuthStatus["SDK_SUCCESS"] = "SDK_SUCCESS";
12146
+ /**
12147
+ * Emits when the app sends an authentication success message
12148
+ */
12149
+ AuthStatus["SUCCESS"] = "SUCCESS";
12150
+ /**
12151
+ * Emits when a user logs out
12152
+ */
12153
+ AuthStatus["LOGOUT"] = "LOGOUT";
12154
+ /**
12155
+ * Emitted when inPopup is true in the SAMLRedirect flow and the
12156
+ * popup is waiting to be triggered either programmatically
12157
+ * or by the trigger button.
12158
+ *
12159
+ * @version SDK: 1.19.0
12160
+ */
12161
+ AuthStatus["WAITING_FOR_POPUP"] = "WAITING_FOR_POPUP";
12162
+ })(AuthStatus || (AuthStatus = {}));
12163
+ /**
12164
+ * Events which can be triggered on the emitter returned from {@link init}.
12165
+ *
12166
+ * @group Authentication / Init
12167
+ */
12168
+ var AuthEvent;
12169
+ (function (AuthEvent) {
12170
+ /**
12171
+ * Manually trigger the SSO popup. This is useful when
12172
+ * authStatus is SAMLRedirect/OIDCRedirect and inPopup is set to true
12173
+ */
12174
+ AuthEvent["TRIGGER_SSO_POPUP"] = "TRIGGER_SSO_POPUP";
12175
+ })(AuthEvent || (AuthEvent = {}));
12176
+ /**
12177
+ *
12178
+ */
12179
+ function notifyAuthSDKSuccess() {
12180
+ {
12181
+ logger.error('SDK not initialized');
12182
+ return;
12183
+ }
12184
+ }
12185
+ /**
12186
+ *
12187
+ */
12188
+ function notifyAuthSuccess() {
12189
+ {
12190
+ logger.error('SDK not initialized');
12191
+ return;
12192
+ }
12193
+ }
12194
+ /**
12195
+ *
12196
+ * @param failureType
12197
+ */
12198
+ function notifyAuthFailure(failureType) {
12199
+ {
12200
+ logger.error('SDK not initialized');
12201
+ return;
12202
+ }
12203
+ }
12204
+ /**
12205
+ *
12206
+ */
12207
+ function notifyLogout() {
12208
+ {
12209
+ logger.error('SDK not initialized');
12210
+ return;
12211
+ }
12212
+ }
12213
+ const initSession = (sessionDetails) => {
12214
+ const embedConfig = getEmbedConfig();
12215
+ if (sessionInfo == null) {
12216
+ sessionInfo = sessionDetails;
12217
+ if (!embedConfig.disableSDKTracking) {
12218
+ initMixpanel(sessionInfo);
12219
+ }
12220
+ sessionInfoResolver(sessionInfo);
12221
+ }
12222
+ };
12223
+ const getSessionDetails = (sessionInfoResp) => {
12224
+ const devMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.devSdkKey;
12225
+ const prodMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.prodSdkKey;
12226
+ const mixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.production
12227
+ ? prodMixpanelToken
12228
+ : devMixpanelToken;
12229
+ return {
12230
+ userGUID: sessionInfoResp.userGUID,
12231
+ mixpanelToken,
12232
+ isPublicUser: sessionInfoResp.configInfo.isPublicUser,
12233
+ releaseVersion: sessionInfoResp.releaseVersion,
12234
+ clusterId: sessionInfoResp.configInfo.selfClusterId,
12235
+ clusterName: sessionInfoResp.configInfo.selfClusterName,
12236
+ ...sessionInfoResp,
12237
+ };
12238
+ };
12239
+ /**
12240
+ * Check if we are logged into the ThoughtSpot cluster
12241
+ *
12242
+ * @param thoughtSpotHost The ThoughtSpot cluster hostname or IP
12243
+ */
12244
+ async function isLoggedIn(thoughtSpotHost) {
12245
+ const authVerificationUrl = `${thoughtSpotHost}${EndPoints.AUTH_VERIFICATION}`;
12246
+ let response = null;
12247
+ try {
12248
+ response = await fetchSessionInfoService(authVerificationUrl);
12249
+ const sessionInfoResp = await response.json();
12250
+ const sessionDetails = getSessionDetails(sessionInfoResp);
12251
+ // Store user session details from session info
12252
+ initSession(sessionDetails);
12253
+ releaseVersion = sessionInfoResp.releaseVersion;
12254
+ }
12255
+ catch (e) {
12256
+ return false;
12257
+ }
12258
+ return response.status === 200;
12259
+ }
12260
+ /**
12261
+ * Return releaseVersion if available
12262
+ */
12263
+ function getReleaseVersion() {
12264
+ return releaseVersion;
12265
+ }
12266
+ /**
12267
+ * Check if we are stuck at the SSO redirect URL
12268
+ */
12269
+ function isAtSSORedirectUrl() {
12270
+ return window.location.href.indexOf(SSO_REDIRECTION_MARKER_GUID) >= 0;
12271
+ }
12272
+ /**
12273
+ * Remove the SSO redirect URL marker
12274
+ */
12275
+ function removeSSORedirectUrlMarker() {
12276
+ // Note (sunny): This will leave a # around even if it was not in the URL
12277
+ // to begin with. Trying to remove the hash by changing window.location will
12278
+ // reload the page which we don't want. We'll live with adding an
12279
+ // unnecessary hash to the parent page URL until we find any use case where
12280
+ // that creates an issue.
12281
+ window.location.hash = window.location.hash.replace(SSO_REDIRECTION_MARKER_GUID, '');
12282
+ }
12283
+ /**
12284
+ * Perform token based authentication
12285
+ *
12286
+ * @param embedConfig The embed configuration
12287
+ */
12288
+ const doTokenAuth = async (embedConfig) => {
12289
+ const { thoughtSpotHost, username, authEndpoint, getAuthToken, } = embedConfig;
12290
+ if (!authEndpoint && !getAuthToken) {
12291
+ throw new Error('Either auth endpoint or getAuthToken function must be provided');
12292
+ }
12293
+ loggedInStatus = await isLoggedIn(thoughtSpotHost);
12294
+ if (!loggedInStatus) {
12295
+ const authToken = await getAuthenticationToken(embedConfig);
12296
+ let resp;
12297
+ try {
12298
+ resp = await fetchAuthPostService(thoughtSpotHost, username, authToken);
12299
+ }
12300
+ catch (e) {
12301
+ resp = await fetchAuthService(thoughtSpotHost, username, authToken);
12302
+ }
12303
+ // token login issues a 302 when successful
12304
+ loggedInStatus = resp.ok || resp.type === 'opaqueredirect';
12305
+ if (loggedInStatus && embedConfig.detectCookieAccessSlow) {
12306
+ // When 3rd party cookie access is blocked, this will fail because
12307
+ // cookies will not be sent with the call.
12308
+ loggedInStatus = await isLoggedIn(thoughtSpotHost);
12309
+ }
12310
+ }
12311
+ return loggedInStatus;
12312
+ };
12313
+ /**
12314
+ * Validate embedConfig parameters required for cookielessTokenAuth
12315
+ *
12316
+ * @param embedConfig The embed configuration
12317
+ */
12318
+ const doCookielessTokenAuth = async (embedConfig) => {
12319
+ const { authEndpoint, getAuthToken } = embedConfig;
12320
+ if (!authEndpoint && !getAuthToken) {
12321
+ throw new Error('Either auth endpoint or getAuthToken function must be provided');
12322
+ }
12323
+ let authSuccess = false;
12324
+ try {
12325
+ const authToken = await getAuthenticationToken(embedConfig);
12326
+ if (authToken) {
12327
+ authSuccess = true;
12328
+ }
12329
+ }
12330
+ catch {
12331
+ authSuccess = false;
12332
+ }
12333
+ return authSuccess;
12334
+ };
12335
+ /**
12336
+ * Perform basic authentication to the ThoughtSpot cluster using the cluster
12337
+ * credentials.
12338
+ *
12339
+ * Warning: This feature is primarily intended for developer testing. It is
12340
+ * strongly advised not to use this authentication method in production.
12341
+ *
12342
+ * @param embedConfig The embed configuration
12343
+ */
12344
+ const doBasicAuth = async (embedConfig) => {
12345
+ const { thoughtSpotHost, username, password } = embedConfig;
12346
+ const loggedIn = await isLoggedIn(thoughtSpotHost);
12347
+ if (!loggedIn) {
12348
+ const response = await fetchBasicAuthService(thoughtSpotHost, username, password);
12349
+ loggedInStatus = response.ok;
12350
+ if (embedConfig.detectCookieAccessSlow) {
12351
+ loggedInStatus = await isLoggedIn(thoughtSpotHost);
12352
+ }
12353
+ }
12354
+ else {
12355
+ loggedInStatus = true;
12356
+ }
12357
+ return loggedInStatus;
12358
+ };
12359
+ /**
12360
+ *
12361
+ * @param ssoURL
12362
+ * @param triggerContainer
12363
+ * @param triggerText
12364
+ */
12365
+ async function samlPopupFlow(ssoURL, triggerContainer, triggerText) {
12366
+ const openPopup = () => {
12367
+ if (samlAuthWindow === null || samlAuthWindow.closed) {
12368
+ samlAuthWindow = window.open(ssoURL, '_blank', 'location=no,height=570,width=520,scrollbars=yes,status=yes');
12369
+ }
12370
+ else {
12371
+ samlAuthWindow.focus();
12372
+ }
12373
+ };
12374
+ const containerEl = getDOMNode(triggerContainer);
12375
+ if (containerEl) {
12376
+ containerEl.innerHTML = '<button id="ts-auth-btn" class="ts-auth-btn" style="margin: auto;"></button>';
12377
+ const authElem = document.getElementById('ts-auth-btn');
12378
+ authElem.textContent = triggerText;
12379
+ authElem.addEventListener('click', openPopup, { once: true });
12380
+ }
12381
+ samlCompletionPromise = samlCompletionPromise
12382
+ || new Promise((resolve, reject) => {
12383
+ window.addEventListener('message', (e) => {
12384
+ if (e.data.type === exports.EmbedEvent.SAMLComplete) {
12385
+ e.source.close();
12386
+ resolve();
12387
+ }
12388
+ });
12389
+ });
12390
+ return samlCompletionPromise;
12391
+ }
12392
+ /**
12393
+ * Perform SAML authentication
12394
+ *
12395
+ * @param embedConfig The embed configuration
12396
+ * @param ssoEndPoint
12397
+ */
12398
+ const doSSOAuth = async (embedConfig, ssoEndPoint) => {
12399
+ const { thoughtSpotHost } = embedConfig;
12400
+ const loggedIn = await isLoggedIn(thoughtSpotHost);
12401
+ if (loggedIn) {
12402
+ if (isAtSSORedirectUrl()) {
12403
+ removeSSORedirectUrlMarker();
12404
+ }
12405
+ loggedInStatus = true;
12406
+ return;
12407
+ }
12408
+ // we have already tried authentication and it did not succeed, restore
12409
+ // the current URL to the original one and invoke the callback.
12410
+ if (isAtSSORedirectUrl()) {
12411
+ removeSSORedirectUrlMarker();
12412
+ loggedInStatus = false;
12413
+ return;
12414
+ }
12415
+ const ssoURL = `${thoughtSpotHost}${ssoEndPoint}`;
12416
+ if (embedConfig.inPopup) {
12417
+ await samlPopupFlow(ssoURL, embedConfig.authTriggerContainer, embedConfig.authTriggerText);
12418
+ loggedInStatus = await isLoggedIn(thoughtSpotHost);
12419
+ return;
12420
+ }
12421
+ window.location.href = ssoURL;
12422
+ };
12423
+ const doSamlAuth = async (embedConfig) => {
12424
+ const { thoughtSpotHost } = embedConfig;
12425
+ // redirect for SSO, when the SSO authentication is done, this page will be
12426
+ // loaded again and the same JS will execute again.
12427
+ const ssoRedirectUrl = embedConfig.inPopup
12428
+ ? `${thoughtSpotHost}/v2/#/embed/saml-complete`
12429
+ : getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
12430
+ // bring back the page to the same URL
12431
+ const ssoEndPoint = `${EndPoints.SAML_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
12432
+ await doSSOAuth(embedConfig, ssoEndPoint);
12433
+ return loggedInStatus;
12434
+ };
12435
+ const doOIDCAuth = async (embedConfig) => {
12436
+ const { thoughtSpotHost } = embedConfig;
12437
+ // redirect for SSO, when the SSO authentication is done, this page will be
12438
+ // loaded again and the same JS will execute again.
12439
+ const ssoRedirectUrl = embedConfig.noRedirect || embedConfig.inPopup
12440
+ ? `${thoughtSpotHost}/v2/#/embed/saml-complete`
12441
+ : getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
12442
+ // bring back the page to the same URL
12443
+ const ssoEndPoint = `${EndPoints.OIDC_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
12444
+ await doSSOAuth(embedConfig, ssoEndPoint);
12445
+ return loggedInStatus;
12446
+ };
12447
+ /**
12448
+ * Perform authentication on the ThoughtSpot cluster
12449
+ *
12450
+ * @param embedConfig The embed configuration
12451
+ */
12452
+ const authenticate = async (embedConfig) => {
12453
+ const { authType } = embedConfig;
12454
+ switch (authType) {
12455
+ case AuthType.SSO:
12456
+ case AuthType.SAMLRedirect:
12457
+ case AuthType.SAML:
12458
+ return doSamlAuth(embedConfig);
12459
+ case AuthType.OIDC:
12460
+ case AuthType.OIDCRedirect:
12461
+ return doOIDCAuth(embedConfig);
12462
+ case AuthType.AuthServer:
12463
+ case AuthType.TrustedAuthToken:
12464
+ return doTokenAuth(embedConfig);
12465
+ case AuthType.TrustedAuthTokenCookieless:
12466
+ return doCookielessTokenAuth(embedConfig);
12467
+ case AuthType.Basic:
12468
+ return doBasicAuth(embedConfig);
12469
+ default:
12470
+ return Promise.resolve(true);
12471
+ }
12887
12472
  };
12888
12473
 
12889
- /**
12890
- * Remove all listeners, or those of the specified event.
12891
- *
12892
- * @param {(String|Symbol)} [event] The event name.
12893
- * @returns {EventEmitter} `this`.
12894
- * @public
12895
- */
12896
- EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
12897
- var evt;
12898
-
12899
- if (event) {
12900
- evt = prefix ? prefix + event : event;
12901
- if (this._events[evt]) clearEvent(this, evt);
12902
- } else {
12903
- this._events = new Events();
12904
- this._eventsCount = 0;
12905
- }
12906
-
12907
- return this;
12474
+ const ERROR_MESSAGE = {
12475
+ INVALID_THOUGHTSPOT_HOST: 'Error parsing ThoughtSpot host. Please provide a valid URL.',
12476
+ LIVEBOARD_VIZ_ID_VALIDATION: 'Please provide either liveboardId or pinboardId',
12477
+ TRIGGER_TIMED_OUT: 'Trigger timedout in getting response',
12478
+ SEARCHEMBED_BETA_WRANING_MESSAGE: 'Search Embed is in Beta in this release.',
12479
+ SAGE_EMBED_BETA_WARNING_MESSAGE: 'Sage Embed is in Beta in this release.',
12908
12480
  };
12909
12481
 
12910
- //
12911
- // Alias methods names because people roll like that.
12912
- //
12913
- EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
12914
- EventEmitter.prototype.addListener = EventEmitter.prototype.on;
12915
-
12916
- //
12917
- // Expose the prefix.
12918
- //
12919
- EventEmitter.prefixed = prefix;
12920
-
12921
- //
12922
- // Allow `EventEmitter` to be imported as module namespace.
12923
- //
12924
- EventEmitter.EventEmitter = EventEmitter;
12925
-
12926
- //
12927
- // Expose the module.
12928
- //
12929
- {
12930
- module.exports = EventEmitter;
12931
- }
12932
- });
12933
-
12934
- /** Used as references for various `Number` constants. */
12935
- var INFINITY = 1 / 0;
12936
-
12937
- /**
12938
- * Creates a set object of `values`.
12939
- *
12940
- * @private
12941
- * @param {Array} values The values to add to the set.
12942
- * @returns {Object} Returns the new set.
12943
- */
12944
- var createSet = !(_Set && (1 / _setToArray(new _Set([,-0]))[1]) == INFINITY) ? noop_1 : function(values) {
12945
- return new _Set(values);
12946
- };
12482
+ /**
12483
+ * Copyright (c) 2023
12484
+ *
12485
+ * Utilities related to reading configuration objects
12486
+ *
12487
+ * @summary Config-related utils
12488
+ * @author Ayon Ghosh <ayon.ghosh@thoughtspot.com>
12489
+ */
12490
+ const urlRegex = new RegExp([
12491
+ '(^(https?:)//)?',
12492
+ '(([^:/?#]*)(?::([0-9]+))?)',
12493
+ '(/{0,1}[^?#]*)',
12494
+ '(\\?[^#]*|)',
12495
+ '(#.*|)$', // hash
12496
+ ].join(''));
12497
+ /**
12498
+ * Parse and construct the ThoughtSpot hostname or IP address
12499
+ * from the embed configuration object.
12500
+ *
12501
+ * @param config
12502
+ */
12503
+ const getThoughtSpotHost = (config) => {
12504
+ if (!config.thoughtSpotHost) {
12505
+ throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
12506
+ }
12507
+ const urlParts = config.thoughtSpotHost.match(urlRegex);
12508
+ if (!urlParts) {
12509
+ throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
12510
+ }
12511
+ const protocol = urlParts[2] || window.location.protocol;
12512
+ const host = urlParts[3];
12513
+ let path = urlParts[6];
12514
+ // Lose the trailing / if any
12515
+ if (path.charAt(path.length - 1) === '/') {
12516
+ path = path.substring(0, path.length - 1);
12517
+ }
12518
+ // const urlParams = urlParts[7];
12519
+ // const hash = urlParts[8];
12520
+ return `${protocol}//${host}${path}`;
12521
+ };
12522
+ const getV2BasePath = (config) => {
12523
+ if (config.basepath) {
12524
+ return config.basepath;
12525
+ }
12526
+ const tsHost = getThoughtSpotHost(config);
12527
+ // This is to handle when e2e's. Search is run on pods for
12528
+ // comp-blink-test-pipeline with baseUrl=https://localhost:8443.
12529
+ // This is to handle when the developer is developing in their local
12530
+ // environment.
12531
+ if (tsHost.includes('://localhost') && !tsHost.includes(':8443')) {
12532
+ return '';
12533
+ }
12534
+ return 'v2';
12535
+ };
12536
+ /**
12537
+ * It is a good idea to keep URLs under 2000 chars.
12538
+ * If this is ever breached, since we pass view configuration through
12539
+ * URL params, we would like to log a warning.
12540
+ * Reference: https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
12541
+ */
12542
+ const URL_MAX_LENGTH = 2000;
12543
+ /**
12544
+ * The default CSS dimensions of the embedded app
12545
+ */
12546
+ const DEFAULT_EMBED_WIDTH = '100%';
12547
+ const DEFAULT_EMBED_HEIGHT = '100%';
12947
12548
 
12948
12549
  /**
12949
12550
  *
12950
- * @param url
12951
- * @param options
12551
+ * @param root0
12552
+ * @param root0.query
12553
+ * @param root0.variables
12554
+ * @param root0.thoughtSpotHost
12555
+ * @param root0.isCompositeQuery
12952
12556
  */
12953
- function tokenisedFailureLoggedFetch(url, options = {}) {
12954
- return tokenizedFetch(url, options).then(async (r) => {
12955
- var _a;
12956
- if (!r.ok && r.type !== 'opaqueredirect' && r.type !== 'opaque') {
12957
- logger.error('Failure', await ((_a = r.text) === null || _a === void 0 ? void 0 : _a.call(r)));
12958
- }
12959
- return r;
12960
- });
12961
- }
12557
+ async function graphqlQuery({ query, variables, thoughtSpotHost, isCompositeQuery = false, }) {
12558
+ const operationName = getOperationNameFromQuery(query);
12559
+ try {
12560
+ const response = await fetch(`${thoughtSpotHost}/prism/?op=${operationName}`, {
12561
+ method: 'POST',
12562
+ headers: {
12563
+ 'content-type': 'application/json;charset=UTF-8',
12564
+ 'x-requested-by': 'ThoughtSpot',
12565
+ accept: '*/*',
12566
+ 'accept-language': 'en-us',
12567
+ },
12568
+ body: JSON.stringify({
12569
+ operationName,
12570
+ query,
12571
+ variables,
12572
+ }),
12573
+ credentials: 'include',
12574
+ });
12575
+ const result = await response.json();
12576
+ const dataValues = Object.values(result.data);
12577
+ return (isCompositeQuery) ? result.data : dataValues[0];
12578
+ }
12579
+ catch (error) {
12580
+ return error;
12581
+ }
12582
+ }
12583
+
12584
+ const getSourceDetailQuery = `
12585
+ query GetSourceDetail($ids: [GUID!]!) {
12586
+ getSourceDetailById(ids: $ids, type: LOGICAL_TABLE) {
12587
+ id
12588
+ name
12589
+ description
12590
+ authorName
12591
+ authorDisplayName
12592
+ isExternal
12593
+ type
12594
+ created
12595
+ modified
12596
+ columns {
12597
+ id
12598
+ name
12599
+ author
12600
+ authorDisplayName
12601
+ description
12602
+ dataType
12603
+ type
12604
+ modified
12605
+ ownerName
12606
+ owner
12607
+ dataRecency
12608
+ sources {
12609
+ tableId
12610
+ tableName
12611
+ columnId
12612
+ columnName
12613
+ __typename
12614
+ }
12615
+ synonyms
12616
+ cohortAnswerId
12617
+ __typename
12618
+ }
12619
+ relationships
12620
+ destinationRelationships
12621
+ dataSourceId
12622
+ __typename
12623
+ }
12624
+ }
12625
+ `;
12626
+ const sourceDetailCache = new Map();
12962
12627
  /**
12963
12628
  *
12964
- * @param authVerificationUrl
12629
+ * @param thoughtSpotHost
12630
+ * @param sourceId
12965
12631
  */
12966
- function fetchSessionInfoService(authVerificationUrl) {
12967
- return tokenisedFailureLoggedFetch(authVerificationUrl, {
12968
- credentials: 'include',
12632
+ async function getSourceDetail(thoughtSpotHost, sourceId) {
12633
+ if (sourceDetailCache.get(sourceId)) {
12634
+ return sourceDetailCache.get(sourceId);
12635
+ }
12636
+ const details = await graphqlQuery({
12637
+ query: getSourceDetailQuery,
12638
+ variables: {
12639
+ ids: [sourceId],
12640
+ },
12641
+ thoughtSpotHost,
12969
12642
  });
12643
+ const souceDetails = details[0];
12644
+ if (souceDetails) {
12645
+ sourceDetailCache.set(sourceId, souceDetails);
12646
+ }
12647
+ return souceDetails;
12970
12648
  }
12971
12649
 
12972
- // eslint-disable-next-line import/no-mutable-exports
12973
- let loggedInStatus = false;
12974
- // eslint-disable-next-line import/no-mutable-exports
12975
- let samlAuthWindow = null;
12976
- // eslint-disable-next-line import/no-mutable-exports
12977
- let samlCompletionPromise = null;
12978
- let sessionInfo = null;
12979
- let sessionInfoResolver = null;
12980
- const sessionInfoPromise = new Promise((resolve) => {
12981
- sessionInfoResolver = resolve;
12982
- });
12983
- let releaseVersion = '';
12984
- const SSO_REDIRECTION_MARKER_GUID = '5e16222e-ef02-43e9-9fbd-24226bf3ce5b';
12985
- /**
12986
- * Enum for auth failure types. This is the parameter passed to the listner
12987
- * of {@link AuthStatus.FAILURE}.
12988
- *
12989
- * @group Authentication / Init
12990
- */
12991
- var AuthFailureType;
12992
- (function (AuthFailureType) {
12993
- AuthFailureType["SDK"] = "SDK";
12994
- AuthFailureType["NO_COOKIE_ACCESS"] = "NO_COOKIE_ACCESS";
12995
- AuthFailureType["EXPIRY"] = "EXPIRY";
12996
- AuthFailureType["OTHER"] = "OTHER";
12997
- })(AuthFailureType || (AuthFailureType = {}));
12650
+ const bachSessionId = `
12651
+ id {
12652
+ sessionId
12653
+ genNo
12654
+ acSession {
12655
+ sessionId
12656
+ genNo
12657
+ }
12658
+ }
12659
+ `;
12660
+ const getUnaggregatedAnswerSession = `
12661
+ mutation GetUnAggregatedAnswerSession($session: BachSessionIdInput!, $columns: [UserPointSelectionInput!]!) {
12662
+ Answer__getUnaggregatedAnswer(session: $session, columns: $columns) {
12663
+ ${bachSessionId}
12664
+ answer {
12665
+ visualizations {
12666
+ ... on TableViz {
12667
+ columns {
12668
+ column {
12669
+ id
12670
+ name
12671
+ referencedColumns {
12672
+ guid
12673
+ displayName
12674
+ }
12675
+ }
12676
+ }
12677
+ }
12678
+ }
12679
+ }
12680
+ }
12681
+ }
12682
+ `;
12683
+ const removeColumns = `
12684
+ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!], $columnIds: [GUID!]) {
12685
+ Answer__removeColumns(
12686
+ session: $session
12687
+ logicalColumnIds: $logicalColumnIds
12688
+ columnIds: $columnIds
12689
+ ) {
12690
+ ${bachSessionId}
12691
+ }
12692
+ }
12693
+ `;
12694
+ const addColumns = `
12695
+ mutation AddColumns($session: BachSessionIdInput!, $columns: [AnswerColumnInfo!]!) {
12696
+ Answer__addColumn(session: $session, columns: $columns) {
12697
+ ${bachSessionId}
12698
+ }
12699
+ }
12700
+ `;
12701
+ const getAnswerData = `
12702
+ query GetTableWithHeadlineData($session: BachSessionIdInput!, $deadline: Int!, $dataPaginationParams: DataPaginationParamsInput!) {
12703
+ getAnswer(session: $session) {
12704
+ ${bachSessionId}
12705
+ answer {
12706
+ id
12707
+ visualizations {
12708
+ id
12709
+ ... on TableViz {
12710
+ columns {
12711
+ column {
12712
+ id
12713
+ name
12714
+ type
12715
+ aggregationType
12716
+ dataType
12717
+ }
12718
+ }
12719
+ data(deadline: $deadline, pagination: $dataPaginationParams)
12720
+ }
12721
+ }
12722
+ }
12723
+ }
12724
+ }
12725
+ `;
12726
+
12727
+ // eslint-disable-next-line no-shadow
12728
+ var OperationType;
12729
+ (function (OperationType) {
12730
+ OperationType["GetChartWithData"] = "GetChartWithData";
12731
+ OperationType["GetTableWithHeadlineData"] = "GetTableWithHeadlineData";
12732
+ })(OperationType || (OperationType = {}));
12998
12733
  /**
12999
- * Enum for auth status emitted by the emitter returned from {@link init}.
12734
+ * Class representing the answer service provided with the
12735
+ * custom action payload. This service could be used to run
12736
+ * graphql queries in the context of the answer on which the
12737
+ * custom action was triggered.
13000
12738
  *
13001
- * @group Authentication / Init
12739
+ * @example
12740
+ * ```js
12741
+ * embed.on(EmbedEvent.CustomAction, e => {
12742
+ * const underlying = await e.answerService.getUnderlyingDataForPoint([
12743
+ * 'col name 1'
12744
+ * ]);
12745
+ * const data = await underlying.fetchData(0, 100);
12746
+ * })
12747
+ * ```
12748
+ * @version SDK: 1.25.0| ThoughtSpot: 9.10.0.cl
12749
+ * @group Events
13002
12750
  */
13003
- var AuthStatus;
13004
- (function (AuthStatus) {
13005
- /**
13006
- * Emits when the SDK fails to authenticate
13007
- */
13008
- AuthStatus["FAILURE"] = "FAILURE";
13009
- /**
13010
- * Emits when the SDK authenticates successfully
13011
- */
13012
- AuthStatus["SDK_SUCCESS"] = "SDK_SUCCESS";
12751
+ class AnswerService {
13013
12752
  /**
13014
- * Emits when the app sends an authentication success message
12753
+ * Should not need to be called directly.
12754
+ *
12755
+ * @param session
12756
+ * @param answer
12757
+ * @param thoughtSpotHost
12758
+ * @param selectedPoints
13015
12759
  */
13016
- AuthStatus["SUCCESS"] = "SUCCESS";
12760
+ constructor(session, answer, thoughtSpotHost, selectedPoints) {
12761
+ this.session = session;
12762
+ this.answer = answer;
12763
+ this.thoughtSpotHost = thoughtSpotHost;
12764
+ this.selectedPoints = selectedPoints;
12765
+ this.session = removeTypename(session);
12766
+ }
13017
12767
  /**
13018
- * Emits when a user logs out
12768
+ * Get the details about the source used in the answer.
12769
+ * This can be used to get the list of all columns in the data source for example.
13019
12770
  */
13020
- AuthStatus["LOGOUT"] = "LOGOUT";
12771
+ async getSourceDetail() {
12772
+ const sourceId = this.answer.sources[0].header.guid;
12773
+ return getSourceDetail(this.thoughtSpotHost, sourceId);
12774
+ }
13021
12775
  /**
13022
- * Emitted when inPopup is true in the SAMLRedirect flow and the
13023
- * popup is waiting to be triggered either programmatically
13024
- * or by the trigger button.
12776
+ * Remove columnIds and return updated answer session.
13025
12777
  *
13026
- * @version SDK: 1.19.0
13027
- */
13028
- AuthStatus["WAITING_FOR_POPUP"] = "WAITING_FOR_POPUP";
13029
- })(AuthStatus || (AuthStatus = {}));
13030
- /**
13031
- * Events which can be triggered on the emitter returned from {@link init}.
13032
- *
13033
- * @group Authentication / Init
13034
- */
13035
- var AuthEvent;
13036
- (function (AuthEvent) {
13037
- /**
13038
- * Manually trigger the SSO popup. This is useful when
13039
- * authStatus is SAMLRedirect/OIDCRedirect and inPopup is set to true
12778
+ * @param columnIds
12779
+ * @returns
13040
12780
  */
13041
- AuthEvent["TRIGGER_SSO_POPUP"] = "TRIGGER_SSO_POPUP";
13042
- })(AuthEvent || (AuthEvent = {}));
13043
- /**
13044
- *
13045
- */
13046
- function notifyAuthSDKSuccess() {
13047
- {
13048
- logger.error('SDK not initialized');
13049
- return;
13050
- }
13051
- }
13052
- /**
13053
- *
13054
- */
13055
- function notifyAuthSuccess() {
13056
- {
13057
- logger.error('SDK not initialized');
13058
- return;
13059
- }
13060
- }
13061
- /**
13062
- *
13063
- * @param failureType
13064
- */
13065
- function notifyAuthFailure(failureType) {
13066
- {
13067
- logger.error('SDK not initialized');
13068
- return;
13069
- }
13070
- }
13071
- /**
13072
- *
13073
- */
13074
- function notifyLogout() {
13075
- {
13076
- logger.error('SDK not initialized');
13077
- return;
12781
+ async removeColumns(columnIds) {
12782
+ return this.executeQuery(removeColumns, {
12783
+ logicalColumnIds: columnIds,
12784
+ });
13078
12785
  }
13079
- }
13080
- const initSession = (sessionDetails) => {
13081
- const embedConfig = getEmbedConfig();
13082
- if (sessionInfo == null) {
13083
- sessionInfo = sessionDetails;
13084
- if (!embedConfig.disableSDKTracking) {
13085
- initMixpanel(sessionInfo);
13086
- }
13087
- sessionInfoResolver(sessionInfo);
12786
+ /**
12787
+ * Add columnIds and return updated answer session.
12788
+ *
12789
+ * @param columnIds
12790
+ * @returns
12791
+ */
12792
+ async addColumns(columnIds) {
12793
+ return this.executeQuery(addColumns, {
12794
+ columns: columnIds.map((colId) => ({ logicalColumnId: colId })),
12795
+ });
13088
12796
  }
13089
- };
13090
- const getSessionDetails = (sessionInfoResp) => {
13091
- const devMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.devSdkKey;
13092
- const prodMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.prodSdkKey;
13093
- const mixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.production
13094
- ? prodMixpanelToken
13095
- : devMixpanelToken;
13096
- return {
13097
- userGUID: sessionInfoResp.userGUID,
13098
- mixpanelToken,
13099
- isPublicUser: sessionInfoResp.configInfo.isPublicUser,
13100
- releaseVersion: sessionInfoResp.releaseVersion,
13101
- clusterId: sessionInfoResp.configInfo.selfClusterId,
13102
- clusterName: sessionInfoResp.configInfo.selfClusterName,
13103
- ...sessionInfoResp,
13104
- };
13105
- };
13106
- /**
13107
- * Check if we are logged into the ThoughtSpot cluster
13108
- *
13109
- * @param thoughtSpotHost The ThoughtSpot cluster hostname or IP
13110
- */
13111
- async function isLoggedIn(thoughtSpotHost) {
13112
- const authVerificationUrl = `${thoughtSpotHost}${EndPoints.AUTH_VERIFICATION}`;
13113
- let response = null;
13114
- try {
13115
- response = await fetchSessionInfoService(authVerificationUrl);
13116
- const sessionInfoResp = await response.json();
13117
- const sessionDetails = getSessionDetails(sessionInfoResp);
13118
- // Store user session details from session info
13119
- initSession(sessionDetails);
13120
- releaseVersion = sessionInfoResp.releaseVersion;
12797
+ /**
12798
+ * Fetch data from the answer.
12799
+ *
12800
+ * @param offset
12801
+ * @param size
12802
+ * @returns
12803
+ */
12804
+ async fetchData(offset = 0, size = 1000) {
12805
+ const { answer } = await this.executeQuery(getAnswerData, {
12806
+ deadline: 0,
12807
+ dataPaginationParams: {
12808
+ isClientPaginated: true,
12809
+ offset,
12810
+ size,
12811
+ },
12812
+ });
12813
+ const { columns, data } = answer.visualizations.find((viz) => !!viz.data) || {};
12814
+ return {
12815
+ columns,
12816
+ data,
12817
+ };
13121
12818
  }
13122
- catch (e) {
13123
- return false;
12819
+ /**
12820
+ * Fetch the data for the answer as a CSV blob. This might be
12821
+ * quicker for larger data.
12822
+ *
12823
+ * @param userLocale
12824
+ * @param includeInfo Include the CSV header in the output
12825
+ * @returns Response
12826
+ */
12827
+ async fetchCSVBlob(userLocale = 'en-us', includeInfo = false) {
12828
+ const fetchUrl = this.getFetchCSVBlobUrl(userLocale, includeInfo);
12829
+ return tokenizedFetch(fetchUrl, {
12830
+ credentials: 'include',
12831
+ });
13124
12832
  }
13125
- return response.status === 200;
13126
- }
13127
- /**
13128
- * Return releaseVersion if available
13129
- */
13130
- function getReleaseVersion() {
13131
- return releaseVersion;
13132
- }
13133
- /**
13134
- * Check if we are stuck at the SSO redirect URL
13135
- */
13136
- function isAtSSORedirectUrl() {
13137
- return window.location.href.indexOf(SSO_REDIRECTION_MARKER_GUID) >= 0;
13138
- }
13139
- /**
13140
- * Remove the SSO redirect URL marker
13141
- */
13142
- function removeSSORedirectUrlMarker() {
13143
- // Note (sunny): This will leave a # around even if it was not in the URL
13144
- // to begin with. Trying to remove the hash by changing window.location will
13145
- // reload the page which we don't want. We'll live with adding an
13146
- // unnecessary hash to the parent page URL until we find any use case where
13147
- // that creates an issue.
13148
- window.location.hash = window.location.hash.replace(SSO_REDIRECTION_MARKER_GUID, '');
13149
- }
13150
- /**
13151
- * Perform token based authentication
13152
- *
13153
- * @param embedConfig The embed configuration
13154
- */
13155
- const doTokenAuth = async (embedConfig) => {
13156
- const { thoughtSpotHost, username, authEndpoint, getAuthToken, } = embedConfig;
13157
- if (!authEndpoint && !getAuthToken) {
13158
- throw new Error('Either auth endpoint or getAuthToken function must be provided');
12833
+ /**
12834
+ * Just get the internal URL for this answer's data
12835
+ * as a CSV blob.
12836
+ *
12837
+ * @param userLocale
12838
+ * @param includeInfo
12839
+ * @returns
12840
+ */
12841
+ getFetchCSVBlobUrl(userLocale = 'en-us', includeInfo = false) {
12842
+ return `${this.thoughtSpotHost}/prism/download/answer/csv?sessionId=${this.session.sessionId}&genNo=${this.session.genNo}&userLocale=${userLocale}&exportFileName=data&hideCsvHeader=${!includeInfo}`;
13159
12843
  }
13160
- loggedInStatus = await isLoggedIn(thoughtSpotHost);
13161
- if (!loggedInStatus) {
13162
- const authToken = await getAuthenticationToken(embedConfig);
13163
- let resp;
13164
- try {
13165
- resp = await fetchAuthPostService(thoughtSpotHost, username, authToken);
12844
+ /**
12845
+ * Get underlying data given a point and the output column names.
12846
+ * In case of a context menu action, the selectedPoints are
12847
+ * automatically passed.
12848
+ *
12849
+ * @param outputColumnNames
12850
+ * @param selectedPoints
12851
+ * @example
12852
+ * ```js
12853
+ * embed.on(EmbedEvent.CustomAction, e => {
12854
+ * const underlying = await e.answerService.getUnderlyingDataForPoint([
12855
+ * 'col name 1' // The column should exist in the data source.
12856
+ * ]);
12857
+ * const data = await underlying.fetchData(0, 100);
12858
+ * })
12859
+ * ```
12860
+ * @version SDK: 1.25.0| ThoughtSpot: 9.10.0.cl
12861
+ */
12862
+ async getUnderlyingDataForPoint(outputColumnNames, selectedPoints) {
12863
+ if (!selectedPoints && !this.selectedPoints) {
12864
+ throw new Error('Needs to be triggered in context of a point');
13166
12865
  }
13167
- catch (e) {
13168
- resp = await fetchAuthService(thoughtSpotHost, username, authToken);
12866
+ if (!selectedPoints) {
12867
+ selectedPoints = getSelectedPointsForUnderlyingDataQuery(this.selectedPoints);
13169
12868
  }
13170
- // token login issues a 302 when successful
13171
- loggedInStatus = resp.ok || resp.type === 'opaqueredirect';
13172
- if (loggedInStatus && embedConfig.detectCookieAccessSlow) {
13173
- // When 3rd party cookie access is blocked, this will fail because
13174
- // cookies will not be sent with the call.
13175
- loggedInStatus = await isLoggedIn(thoughtSpotHost);
12869
+ const sourceDetail = await this.getSourceDetail();
12870
+ const ouputColumnGuids = getGuidsFromColumnNames(sourceDetail, outputColumnNames);
12871
+ const unAggAnswer = await graphqlQuery({
12872
+ query: getUnaggregatedAnswerSession,
12873
+ variables: {
12874
+ session: this.session,
12875
+ columns: selectedPoints,
12876
+ },
12877
+ thoughtSpotHost: this.thoughtSpotHost,
12878
+ });
12879
+ const unaggAnswerSession = new AnswerService(unAggAnswer.id, unAggAnswer.answer, this.thoughtSpotHost);
12880
+ const currentColumns = new Set(unAggAnswer.answer.visualizations[0].columns
12881
+ .map((c) => c.column.referencedColumns[0].guid));
12882
+ const columnsToAdd = [...ouputColumnGuids].filter((col) => !currentColumns.has(col));
12883
+ if (columnsToAdd.length) {
12884
+ await unaggAnswerSession.addColumns(columnsToAdd);
13176
12885
  }
13177
- }
13178
- return loggedInStatus;
13179
- };
13180
- /**
13181
- * Validate embedConfig parameters required for cookielessTokenAuth
13182
- *
13183
- * @param embedConfig The embed configuration
13184
- */
13185
- const doCookielessTokenAuth = async (embedConfig) => {
13186
- const { authEndpoint, getAuthToken } = embedConfig;
13187
- if (!authEndpoint && !getAuthToken) {
13188
- throw new Error('Either auth endpoint or getAuthToken function must be provided');
13189
- }
13190
- let authSuccess = false;
13191
- try {
13192
- const authToken = await getAuthenticationToken(embedConfig);
13193
- if (authToken) {
13194
- authSuccess = true;
12886
+ const columnsToRemove = [...currentColumns].filter((col) => !ouputColumnGuids.has(col));
12887
+ if (columnsToRemove.length) {
12888
+ await unaggAnswerSession.removeColumns(columnsToRemove);
13195
12889
  }
12890
+ return unaggAnswerSession;
13196
12891
  }
13197
- catch {
13198
- authSuccess = false;
13199
- }
13200
- return authSuccess;
13201
- };
13202
- /**
13203
- * Perform basic authentication to the ThoughtSpot cluster using the cluster
13204
- * credentials.
13205
- *
13206
- * Warning: This feature is primarily intended for developer testing. It is
13207
- * strongly advised not to use this authentication method in production.
13208
- *
13209
- * @param embedConfig The embed configuration
13210
- */
13211
- const doBasicAuth = async (embedConfig) => {
13212
- const { thoughtSpotHost, username, password } = embedConfig;
13213
- const loggedIn = await isLoggedIn(thoughtSpotHost);
13214
- if (!loggedIn) {
13215
- const response = await fetchBasicAuthService(thoughtSpotHost, username, password);
13216
- loggedInStatus = response.ok;
13217
- if (embedConfig.detectCookieAccessSlow) {
13218
- loggedInStatus = await isLoggedIn(thoughtSpotHost);
13219
- }
12892
+ /**
12893
+ * Execute a custom graphql query in the context of the answer.
12894
+ *
12895
+ * @param query graphql query
12896
+ * @param variables graphql variables
12897
+ * @returns
12898
+ */
12899
+ async executeQuery(query, variables) {
12900
+ const data = await graphqlQuery({
12901
+ query,
12902
+ variables: {
12903
+ session: this.session,
12904
+ ...variables,
12905
+ },
12906
+ thoughtSpotHost: this.thoughtSpotHost,
12907
+ isCompositeQuery: false,
12908
+ });
12909
+ this.session = deepMerge(this.session, (data === null || data === void 0 ? void 0 : data.id) || {});
12910
+ return data;
13220
12911
  }
13221
- else {
13222
- loggedInStatus = true;
12912
+ /**
12913
+ * Get the internal session details for the answer.
12914
+ *
12915
+ * @returns
12916
+ */
12917
+ getSession() {
12918
+ return this.session;
13223
12919
  }
13224
- return loggedInStatus;
13225
- };
12920
+ }
13226
12921
  /**
13227
12922
  *
13228
- * @param ssoURL
13229
- * @param triggerContainer
13230
- * @param triggerText
12923
+ * @param sourceDetail
12924
+ * @param colNames
13231
12925
  */
13232
- async function samlPopupFlow(ssoURL, triggerContainer, triggerText) {
13233
- const openPopup = () => {
13234
- if (samlAuthWindow === null || samlAuthWindow.closed) {
13235
- samlAuthWindow = window.open(ssoURL, '_blank', 'location=no,height=570,width=520,scrollbars=yes,status=yes');
13236
- }
13237
- else {
13238
- samlAuthWindow.focus();
13239
- }
13240
- };
13241
- const containerEl = getDOMNode(triggerContainer);
13242
- if (containerEl) {
13243
- containerEl.innerHTML = '<button id="ts-auth-btn" class="ts-auth-btn" style="margin: auto;"></button>';
13244
- const authElem = document.getElementById('ts-auth-btn');
13245
- authElem.textContent = triggerText;
13246
- authElem.addEventListener('click', openPopup, { once: true });
13247
- }
13248
- samlCompletionPromise = samlCompletionPromise
13249
- || new Promise((resolve, reject) => {
13250
- window.addEventListener('message', (e) => {
13251
- if (e.data.type === exports.EmbedEvent.SAMLComplete) {
13252
- e.source.close();
13253
- resolve();
13254
- }
13255
- });
13256
- });
13257
- return samlCompletionPromise;
12926
+ function getGuidsFromColumnNames(sourceDetail, colNames) {
12927
+ const cols = sourceDetail.columns.reduce((colSet, col) => {
12928
+ colSet[col.name] = col;
12929
+ return colSet;
12930
+ }, {});
12931
+ return new Set(colNames.map((colName) => {
12932
+ const col = cols[colName];
12933
+ return col.id;
12934
+ }));
13258
12935
  }
13259
12936
  /**
13260
- * Perform SAML authentication
13261
12937
  *
13262
- * @param embedConfig The embed configuration
13263
- * @param ssoEndPoint
12938
+ * @param selectedPoints
13264
12939
  */
13265
- const doSSOAuth = async (embedConfig, ssoEndPoint) => {
13266
- const { thoughtSpotHost } = embedConfig;
13267
- const loggedIn = await isLoggedIn(thoughtSpotHost);
13268
- if (loggedIn) {
13269
- if (isAtSSORedirectUrl()) {
13270
- removeSSORedirectUrlMarker();
12940
+ function getSelectedPointsForUnderlyingDataQuery(selectedPoints) {
12941
+ const underlyingDataPoint = [];
12942
+ /**
12943
+ *
12944
+ * @param colVal
12945
+ */
12946
+ function addPointFromColVal(colVal) {
12947
+ var _a;
12948
+ const dataType = colVal.column.dataType;
12949
+ const id = colVal.column.id;
12950
+ let dataValue;
12951
+ if (dataType === 'DATE') {
12952
+ if (Number.isFinite(colVal.value)) {
12953
+ dataValue = [{
12954
+ epochRange: {
12955
+ startEpoch: colVal.value,
12956
+ },
12957
+ }];
12958
+ // Case for custom calendar.
12959
+ }
12960
+ else if ((_a = colVal.value) === null || _a === void 0 ? void 0 : _a.v) {
12961
+ dataValue = [{
12962
+ epochRange: {
12963
+ startEpoch: colVal.value.v.s,
12964
+ endEpoch: colVal.value.v.e,
12965
+ },
12966
+ }];
12967
+ }
13271
12968
  }
13272
- loggedInStatus = true;
13273
- return;
13274
- }
13275
- // we have already tried authentication and it did not succeed, restore
13276
- // the current URL to the original one and invoke the callback.
13277
- if (isAtSSORedirectUrl()) {
13278
- removeSSORedirectUrlMarker();
13279
- loggedInStatus = false;
13280
- return;
13281
- }
13282
- const ssoURL = `${thoughtSpotHost}${ssoEndPoint}`;
13283
- if (embedConfig.inPopup) {
13284
- await samlPopupFlow(ssoURL, embedConfig.authTriggerContainer, embedConfig.authTriggerText);
13285
- loggedInStatus = await isLoggedIn(thoughtSpotHost);
13286
- return;
13287
- }
13288
- window.location.href = ssoURL;
13289
- };
13290
- const doSamlAuth = async (embedConfig) => {
13291
- const { thoughtSpotHost } = embedConfig;
13292
- // redirect for SSO, when the SSO authentication is done, this page will be
13293
- // loaded again and the same JS will execute again.
13294
- const ssoRedirectUrl = embedConfig.inPopup
13295
- ? `${thoughtSpotHost}/v2/#/embed/saml-complete`
13296
- : getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
13297
- // bring back the page to the same URL
13298
- const ssoEndPoint = `${EndPoints.SAML_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
13299
- await doSSOAuth(embedConfig, ssoEndPoint);
13300
- return loggedInStatus;
13301
- };
13302
- const doOIDCAuth = async (embedConfig) => {
13303
- const { thoughtSpotHost } = embedConfig;
13304
- // redirect for SSO, when the SSO authentication is done, this page will be
13305
- // loaded again and the same JS will execute again.
13306
- const ssoRedirectUrl = embedConfig.noRedirect || embedConfig.inPopup
13307
- ? `${thoughtSpotHost}/v2/#/embed/saml-complete`
13308
- : getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
13309
- // bring back the page to the same URL
13310
- const ssoEndPoint = `${EndPoints.OIDC_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
13311
- await doSSOAuth(embedConfig, ssoEndPoint);
13312
- return loggedInStatus;
13313
- };
13314
- /**
13315
- * Perform authentication on the ThoughtSpot cluster
13316
- *
13317
- * @param embedConfig The embed configuration
13318
- */
13319
- const authenticate = async (embedConfig) => {
13320
- const { authType } = embedConfig;
13321
- switch (authType) {
13322
- case AuthType.SSO:
13323
- case AuthType.SAMLRedirect:
13324
- case AuthType.SAML:
13325
- return doSamlAuth(embedConfig);
13326
- case AuthType.OIDC:
13327
- case AuthType.OIDCRedirect:
13328
- return doOIDCAuth(embedConfig);
13329
- case AuthType.AuthServer:
13330
- case AuthType.TrustedAuthToken:
13331
- return doTokenAuth(embedConfig);
13332
- case AuthType.TrustedAuthTokenCookieless:
13333
- return doCookielessTokenAuth(embedConfig);
13334
- case AuthType.Basic:
13335
- return doBasicAuth(embedConfig);
13336
- default:
13337
- return Promise.resolve(true);
12969
+ else {
12970
+ dataValue = [{ value: colVal.value }];
12971
+ }
12972
+ underlyingDataPoint.push({
12973
+ columnId: colVal.column.id,
12974
+ dataValue,
12975
+ });
13338
12976
  }
12977
+ selectedPoints.forEach((p) => {
12978
+ p.selectedAttributes.forEach(addPointFromColVal);
12979
+ });
12980
+ return underlyingDataPoint;
12981
+ }
12982
+
12983
+ var eventemitter3 = createCommonjsModule(function (module) {
12984
+
12985
+ var has = Object.prototype.hasOwnProperty
12986
+ , prefix = '~';
12987
+
12988
+ /**
12989
+ * Constructor to create a storage for our `EE` objects.
12990
+ * An `Events` instance is a plain object whose properties are event names.
12991
+ *
12992
+ * @constructor
12993
+ * @private
12994
+ */
12995
+ function Events() {}
12996
+
12997
+ //
12998
+ // We try to not inherit from `Object.prototype`. In some engines creating an
12999
+ // instance in this way is faster than calling `Object.create(null)` directly.
13000
+ // If `Object.create(null)` is not supported we prefix the event names with a
13001
+ // character to make sure that the built-in object properties are not
13002
+ // overridden or used as an attack vector.
13003
+ //
13004
+ if (Object.create) {
13005
+ Events.prototype = Object.create(null);
13006
+
13007
+ //
13008
+ // This hack is needed because the `__proto__` property is still inherited in
13009
+ // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.
13010
+ //
13011
+ if (!new Events().__proto__) prefix = false;
13012
+ }
13013
+
13014
+ /**
13015
+ * Representation of a single event listener.
13016
+ *
13017
+ * @param {Function} fn The listener function.
13018
+ * @param {*} context The context to invoke the listener with.
13019
+ * @param {Boolean} [once=false] Specify if the listener is a one-time listener.
13020
+ * @constructor
13021
+ * @private
13022
+ */
13023
+ function EE(fn, context, once) {
13024
+ this.fn = fn;
13025
+ this.context = context;
13026
+ this.once = once || false;
13027
+ }
13028
+
13029
+ /**
13030
+ * Add a listener for a given event.
13031
+ *
13032
+ * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
13033
+ * @param {(String|Symbol)} event The event name.
13034
+ * @param {Function} fn The listener function.
13035
+ * @param {*} context The context to invoke the listener with.
13036
+ * @param {Boolean} once Specify if the listener is a one-time listener.
13037
+ * @returns {EventEmitter}
13038
+ * @private
13039
+ */
13040
+ function addListener(emitter, event, fn, context, once) {
13041
+ if (typeof fn !== 'function') {
13042
+ throw new TypeError('The listener must be a function');
13043
+ }
13044
+
13045
+ var listener = new EE(fn, context || emitter, once)
13046
+ , evt = prefix ? prefix + event : event;
13047
+
13048
+ if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;
13049
+ else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);
13050
+ else emitter._events[evt] = [emitter._events[evt], listener];
13051
+
13052
+ return emitter;
13053
+ }
13054
+
13055
+ /**
13056
+ * Clear event by name.
13057
+ *
13058
+ * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
13059
+ * @param {(String|Symbol)} evt The Event name.
13060
+ * @private
13061
+ */
13062
+ function clearEvent(emitter, evt) {
13063
+ if (--emitter._eventsCount === 0) emitter._events = new Events();
13064
+ else delete emitter._events[evt];
13065
+ }
13066
+
13067
+ /**
13068
+ * Minimal `EventEmitter` interface that is molded against the Node.js
13069
+ * `EventEmitter` interface.
13070
+ *
13071
+ * @constructor
13072
+ * @public
13073
+ */
13074
+ function EventEmitter() {
13075
+ this._events = new Events();
13076
+ this._eventsCount = 0;
13077
+ }
13078
+
13079
+ /**
13080
+ * Return an array listing the events for which the emitter has registered
13081
+ * listeners.
13082
+ *
13083
+ * @returns {Array}
13084
+ * @public
13085
+ */
13086
+ EventEmitter.prototype.eventNames = function eventNames() {
13087
+ var names = []
13088
+ , events
13089
+ , name;
13090
+
13091
+ if (this._eventsCount === 0) return names;
13092
+
13093
+ for (name in (events = this._events)) {
13094
+ if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
13095
+ }
13096
+
13097
+ if (Object.getOwnPropertySymbols) {
13098
+ return names.concat(Object.getOwnPropertySymbols(events));
13099
+ }
13100
+
13101
+ return names;
13102
+ };
13103
+
13104
+ /**
13105
+ * Return the listeners registered for a given event.
13106
+ *
13107
+ * @param {(String|Symbol)} event The event name.
13108
+ * @returns {Array} The registered listeners.
13109
+ * @public
13110
+ */
13111
+ EventEmitter.prototype.listeners = function listeners(event) {
13112
+ var evt = prefix ? prefix + event : event
13113
+ , handlers = this._events[evt];
13114
+
13115
+ if (!handlers) return [];
13116
+ if (handlers.fn) return [handlers.fn];
13117
+
13118
+ for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {
13119
+ ee[i] = handlers[i].fn;
13120
+ }
13121
+
13122
+ return ee;
13123
+ };
13124
+
13125
+ /**
13126
+ * Return the number of listeners listening to a given event.
13127
+ *
13128
+ * @param {(String|Symbol)} event The event name.
13129
+ * @returns {Number} The number of listeners.
13130
+ * @public
13131
+ */
13132
+ EventEmitter.prototype.listenerCount = function listenerCount(event) {
13133
+ var evt = prefix ? prefix + event : event
13134
+ , listeners = this._events[evt];
13135
+
13136
+ if (!listeners) return 0;
13137
+ if (listeners.fn) return 1;
13138
+ return listeners.length;
13139
+ };
13140
+
13141
+ /**
13142
+ * Calls each of the listeners registered for a given event.
13143
+ *
13144
+ * @param {(String|Symbol)} event The event name.
13145
+ * @returns {Boolean} `true` if the event had listeners, else `false`.
13146
+ * @public
13147
+ */
13148
+ EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
13149
+ var evt = prefix ? prefix + event : event;
13150
+
13151
+ if (!this._events[evt]) return false;
13152
+
13153
+ var listeners = this._events[evt]
13154
+ , len = arguments.length
13155
+ , args
13156
+ , i;
13157
+
13158
+ if (listeners.fn) {
13159
+ if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);
13160
+
13161
+ switch (len) {
13162
+ case 1: return listeners.fn.call(listeners.context), true;
13163
+ case 2: return listeners.fn.call(listeners.context, a1), true;
13164
+ case 3: return listeners.fn.call(listeners.context, a1, a2), true;
13165
+ case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;
13166
+ case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
13167
+ case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
13168
+ }
13169
+
13170
+ for (i = 1, args = new Array(len -1); i < len; i++) {
13171
+ args[i - 1] = arguments[i];
13172
+ }
13173
+
13174
+ listeners.fn.apply(listeners.context, args);
13175
+ } else {
13176
+ var length = listeners.length
13177
+ , j;
13178
+
13179
+ for (i = 0; i < length; i++) {
13180
+ if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);
13181
+
13182
+ switch (len) {
13183
+ case 1: listeners[i].fn.call(listeners[i].context); break;
13184
+ case 2: listeners[i].fn.call(listeners[i].context, a1); break;
13185
+ case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;
13186
+ case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;
13187
+ default:
13188
+ if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {
13189
+ args[j - 1] = arguments[j];
13190
+ }
13191
+
13192
+ listeners[i].fn.apply(listeners[i].context, args);
13193
+ }
13194
+ }
13195
+ }
13196
+
13197
+ return true;
13198
+ };
13199
+
13200
+ /**
13201
+ * Add a listener for a given event.
13202
+ *
13203
+ * @param {(String|Symbol)} event The event name.
13204
+ * @param {Function} fn The listener function.
13205
+ * @param {*} [context=this] The context to invoke the listener with.
13206
+ * @returns {EventEmitter} `this`.
13207
+ * @public
13208
+ */
13209
+ EventEmitter.prototype.on = function on(event, fn, context) {
13210
+ return addListener(this, event, fn, context, false);
13211
+ };
13212
+
13213
+ /**
13214
+ * Add a one-time listener for a given event.
13215
+ *
13216
+ * @param {(String|Symbol)} event The event name.
13217
+ * @param {Function} fn The listener function.
13218
+ * @param {*} [context=this] The context to invoke the listener with.
13219
+ * @returns {EventEmitter} `this`.
13220
+ * @public
13221
+ */
13222
+ EventEmitter.prototype.once = function once(event, fn, context) {
13223
+ return addListener(this, event, fn, context, true);
13224
+ };
13225
+
13226
+ /**
13227
+ * Remove the listeners of a given event.
13228
+ *
13229
+ * @param {(String|Symbol)} event The event name.
13230
+ * @param {Function} fn Only remove the listeners that match this function.
13231
+ * @param {*} context Only remove the listeners that have this context.
13232
+ * @param {Boolean} once Only remove one-time listeners.
13233
+ * @returns {EventEmitter} `this`.
13234
+ * @public
13235
+ */
13236
+ EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
13237
+ var evt = prefix ? prefix + event : event;
13238
+
13239
+ if (!this._events[evt]) return this;
13240
+ if (!fn) {
13241
+ clearEvent(this, evt);
13242
+ return this;
13243
+ }
13244
+
13245
+ var listeners = this._events[evt];
13246
+
13247
+ if (listeners.fn) {
13248
+ if (
13249
+ listeners.fn === fn &&
13250
+ (!once || listeners.once) &&
13251
+ (!context || listeners.context === context)
13252
+ ) {
13253
+ clearEvent(this, evt);
13254
+ }
13255
+ } else {
13256
+ for (var i = 0, events = [], length = listeners.length; i < length; i++) {
13257
+ if (
13258
+ listeners[i].fn !== fn ||
13259
+ (once && !listeners[i].once) ||
13260
+ (context && listeners[i].context !== context)
13261
+ ) {
13262
+ events.push(listeners[i]);
13263
+ }
13264
+ }
13265
+
13266
+ //
13267
+ // Reset the array, or remove it completely if we have no more listeners.
13268
+ //
13269
+ if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;
13270
+ else clearEvent(this, evt);
13271
+ }
13272
+
13273
+ return this;
13274
+ };
13275
+
13276
+ /**
13277
+ * Remove all listeners, or those of the specified event.
13278
+ *
13279
+ * @param {(String|Symbol)} [event] The event name.
13280
+ * @returns {EventEmitter} `this`.
13281
+ * @public
13282
+ */
13283
+ EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
13284
+ var evt;
13285
+
13286
+ if (event) {
13287
+ evt = prefix ? prefix + event : event;
13288
+ if (this._events[evt]) clearEvent(this, evt);
13289
+ } else {
13290
+ this._events = new Events();
13291
+ this._eventsCount = 0;
13292
+ }
13293
+
13294
+ return this;
13295
+ };
13296
+
13297
+ //
13298
+ // Alias methods names because people roll like that.
13299
+ //
13300
+ EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
13301
+ EventEmitter.prototype.addListener = EventEmitter.prototype.on;
13302
+
13303
+ //
13304
+ // Expose the prefix.
13305
+ //
13306
+ EventEmitter.prefixed = prefix;
13307
+
13308
+ //
13309
+ // Allow `EventEmitter` to be imported as module namespace.
13310
+ //
13311
+ EventEmitter.EventEmitter = EventEmitter;
13312
+
13313
+ //
13314
+ // Expose the module.
13315
+ //
13316
+ {
13317
+ module.exports = EventEmitter;
13318
+ }
13319
+ });
13320
+
13321
+ /** Used as references for various `Number` constants. */
13322
+ var INFINITY = 1 / 0;
13323
+
13324
+ /**
13325
+ * Creates a set object of `values`.
13326
+ *
13327
+ * @private
13328
+ * @param {Array} values The values to add to the set.
13329
+ * @returns {Object} Returns the new set.
13330
+ */
13331
+ var createSet = !(_Set && (1 / _setToArray(new _Set([,-0]))[1]) == INFINITY) ? noop_1 : function(values) {
13332
+ return new _Set(values);
13339
13333
  };
13340
13334
 
13341
13335
  /* eslint-disable camelcase */
@@ -13551,8 +13545,6 @@ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!]
13551
13545
  });
13552
13546
  }
13553
13547
 
13554
- var name="@thoughtspot/visual-embed-sdk";var version="1.28.0-alpha.5";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};
13555
-
13556
13548
  /**
13557
13549
  * Copyright (c) 2022
13558
13550
  *
@@ -14785,7 +14777,7 @@ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!]
14785
14777
  }
14786
14778
  getEmbedParams() {
14787
14779
  var _a;
14788
- const { hideResults, enableSearchAssist, forceTable, searchOptions, runtimeFilters, dataSource, dataSources, excludeRuntimeFiltersfromURL = true, hideSearchBar, dataPanelV2 = false, useLastSelectedSources = false, runtimeParameters, } = this.viewConfig;
14780
+ const { hideResults, expandAllDataSource, enableSearchAssist, forceTable, searchOptions, runtimeFilters, dataSource, dataSources, excludeRuntimeFiltersfromURL = true, hideSearchBar, dataPanelV2 = false, useLastSelectedSources = false, runtimeParameters, } = this.viewConfig;
14789
14781
  const queryParams = this.getBaseQueryParams();
14790
14782
  queryParams[Param.HideActions] = [
14791
14783
  ...((_a = queryParams[Param.HideActions]) !== null && _a !== void 0 ? _a : []),