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

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