@thoughtspot/visual-embed-sdk 1.25.0 → 1.26.0-token-cache.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/README.md +1 -1
  2. package/cjs/package.json +1 -1
  3. package/cjs/src/auth.d.ts +0 -12
  4. package/cjs/src/auth.d.ts.map +1 -1
  5. package/cjs/src/auth.js +15 -54
  6. package/cjs/src/auth.js.map +1 -1
  7. package/cjs/src/auth.spec.d.ts.map +1 -1
  8. package/cjs/src/auth.spec.js +44 -5
  9. package/cjs/src/auth.spec.js.map +1 -1
  10. package/cjs/src/authToken.d.ts +4 -0
  11. package/cjs/src/authToken.d.ts.map +1 -0
  12. package/cjs/src/authToken.js +60 -0
  13. package/cjs/src/authToken.js.map +1 -0
  14. package/cjs/src/config.d.ts.map +1 -1
  15. package/cjs/src/config.js +3 -0
  16. package/cjs/src/config.js.map +1 -1
  17. package/cjs/src/config.spec.js +1 -1
  18. package/cjs/src/config.spec.js.map +1 -1
  19. package/cjs/src/embed/TsEmbed.d.ts +302 -0
  20. package/cjs/src/embed/TsEmbed.d.ts.map +1 -0
  21. package/cjs/src/embed/TsEmbed.js +851 -0
  22. package/cjs/src/embed/TsEmbed.js.map +1 -0
  23. package/cjs/src/embed/base.d.ts +0 -1
  24. package/cjs/src/embed/base.d.ts.map +1 -1
  25. package/cjs/src/embed/base.js +6 -5
  26. package/cjs/src/embed/base.js.map +1 -1
  27. package/cjs/src/embed/base.spec.js +7 -5
  28. package/cjs/src/embed/base.spec.js.map +1 -1
  29. package/cjs/src/embed/search.d.ts +0 -4
  30. package/cjs/src/embed/search.d.ts.map +1 -1
  31. package/cjs/src/embed/search.js +3 -2
  32. package/cjs/src/embed/search.js.map +1 -1
  33. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  34. package/cjs/src/embed/ts-embed.js +3 -2
  35. package/cjs/src/embed/ts-embed.js.map +1 -1
  36. package/cjs/src/embed/ts-embed.spec.js +48 -37
  37. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  38. package/cjs/src/react/index.spec.js +0 -12
  39. package/cjs/src/react/index.spec.js.map +1 -1
  40. package/cjs/src/tokenizedFetch.d.ts +2 -0
  41. package/cjs/src/tokenizedFetch.d.ts.map +1 -0
  42. package/cjs/src/tokenizedFetch.js +20 -0
  43. package/cjs/src/tokenizedFetch.js.map +1 -0
  44. package/cjs/src/types.d.ts +11 -1
  45. package/cjs/src/types.d.ts.map +1 -1
  46. package/cjs/src/types.js +7 -1
  47. package/cjs/src/types.js.map +1 -1
  48. package/cjs/src/utils/answerService.d.ts +10 -0
  49. package/cjs/src/utils/answerService.d.ts.map +1 -0
  50. package/cjs/src/utils/answerService.js +61 -0
  51. package/cjs/src/utils/answerService.js.map +1 -0
  52. package/cjs/src/utils/answerService.spec.d.ts +2 -0
  53. package/cjs/src/utils/answerService.spec.d.ts.map +1 -0
  54. package/cjs/src/utils/answerService.spec.js +31 -0
  55. package/cjs/src/utils/answerService.spec.js.map +1 -0
  56. package/cjs/src/utils/authService.d.ts +12 -1
  57. package/cjs/src/utils/authService.d.ts.map +1 -1
  58. package/cjs/src/utils/authService.js +32 -16
  59. package/cjs/src/utils/authService.js.map +1 -1
  60. package/cjs/src/utils/authService.spec.js +3 -4
  61. package/cjs/src/utils/authService.spec.js.map +1 -1
  62. package/cjs/src/utils/graphql/answerService/answerService.d.ts +1 -0
  63. package/cjs/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  64. package/cjs/src/utils/graphql/answerService/answerService.js +6 -2
  65. package/cjs/src/utils/graphql/answerService/answerService.js.map +1 -1
  66. package/cjs/src/utils/graphql/answerService/answerService.spec.js +18 -2
  67. package/cjs/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
  68. package/cjs/src/utils/graphql/graphql-request.spec.d.ts +2 -0
  69. package/cjs/src/utils/graphql/graphql-request.spec.d.ts.map +1 -0
  70. package/cjs/src/utils/graphql/graphql-request.spec.js +39 -0
  71. package/cjs/src/utils/graphql/graphql-request.spec.js.map +1 -0
  72. package/cjs/src/utils/logger.d.ts +28 -0
  73. package/cjs/src/utils/logger.d.ts.map +1 -0
  74. package/cjs/src/utils/logger.js +82 -0
  75. package/cjs/src/utils/logger.js.map +1 -0
  76. package/cjs/src/utils/processData.d.ts.map +1 -1
  77. package/cjs/src/utils/processData.js +2 -2
  78. package/cjs/src/utils/processData.js.map +1 -1
  79. package/cjs/src/utils/processData.spec.js +2 -2
  80. package/cjs/src/utils/processData.spec.js.map +1 -1
  81. package/dist/src/auth.d.ts +0 -12
  82. package/dist/src/auth.d.ts.map +1 -1
  83. package/dist/src/auth.spec.d.ts.map +1 -1
  84. package/dist/src/authToken.d.ts +4 -0
  85. package/dist/src/authToken.d.ts.map +1 -0
  86. package/dist/src/config.d.ts.map +1 -1
  87. package/dist/src/embed/base.d.ts +0 -1
  88. package/dist/src/embed/base.d.ts.map +1 -1
  89. package/dist/src/embed/search.d.ts +0 -4
  90. package/dist/src/embed/search.d.ts.map +1 -1
  91. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  92. package/dist/src/tokenizedFetch.d.ts +2 -0
  93. package/dist/src/tokenizedFetch.d.ts.map +1 -0
  94. package/dist/src/types.d.ts +11 -1
  95. package/dist/src/types.d.ts.map +1 -1
  96. package/dist/src/utils/answerService.d.ts +10 -0
  97. package/dist/src/utils/answerService.d.ts.map +1 -0
  98. package/dist/src/utils/answerService.spec.d.ts +2 -0
  99. package/dist/src/utils/answerService.spec.d.ts.map +1 -0
  100. package/dist/src/utils/authService.d.ts +12 -1
  101. package/dist/src/utils/authService.d.ts.map +1 -1
  102. package/dist/src/utils/graphql/answerService/answerService.d.ts +1 -0
  103. package/dist/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  104. package/dist/src/utils/graphql/graphql-request.spec.d.ts +2 -0
  105. package/dist/src/utils/graphql/graphql-request.spec.d.ts.map +1 -0
  106. package/dist/src/utils/logger.d.ts +28 -0
  107. package/dist/src/utils/logger.d.ts.map +1 -0
  108. package/dist/src/utils/processData.d.ts.map +1 -1
  109. package/dist/tsembed-react.es.js +2149 -2094
  110. package/dist/tsembed-react.js +2152 -2097
  111. package/dist/tsembed.es.js +6483 -6425
  112. package/dist/tsembed.js +6483 -6425
  113. package/dist/visual-embed-sdk-react-full.d.ts +12 -18
  114. package/dist/visual-embed-sdk-react.d.ts +12 -18
  115. package/dist/visual-embed-sdk.d.ts +12 -18
  116. package/lib/package.json +1 -1
  117. package/lib/src/auth.d.ts +0 -12
  118. package/lib/src/auth.d.ts.map +1 -1
  119. package/lib/src/auth.js +10 -48
  120. package/lib/src/auth.js.map +1 -1
  121. package/lib/src/auth.spec.d.ts.map +1 -1
  122. package/lib/src/auth.spec.js +44 -5
  123. package/lib/src/auth.spec.js.map +1 -1
  124. package/lib/src/authToken.d.ts +4 -0
  125. package/lib/src/authToken.d.ts.map +1 -0
  126. package/lib/src/authToken.js +55 -0
  127. package/lib/src/authToken.js.map +1 -0
  128. package/lib/src/config.d.ts.map +1 -1
  129. package/lib/src/config.js +3 -0
  130. package/lib/src/config.js.map +1 -1
  131. package/lib/src/config.spec.js +1 -1
  132. package/lib/src/config.spec.js.map +1 -1
  133. package/lib/src/embed/TsEmbed.d.ts +302 -0
  134. package/lib/src/embed/TsEmbed.d.ts.map +1 -0
  135. package/lib/src/embed/TsEmbed.js +847 -0
  136. package/lib/src/embed/TsEmbed.js.map +1 -0
  137. package/lib/src/embed/base.d.ts +0 -1
  138. package/lib/src/embed/base.d.ts.map +1 -1
  139. package/lib/src/embed/base.js +3 -2
  140. package/lib/src/embed/base.js.map +1 -1
  141. package/lib/src/embed/base.spec.js +7 -5
  142. package/lib/src/embed/base.spec.js.map +1 -1
  143. package/lib/src/embed/search.d.ts +0 -4
  144. package/lib/src/embed/search.d.ts.map +1 -1
  145. package/lib/src/embed/search.js +3 -2
  146. package/lib/src/embed/search.js.map +1 -1
  147. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  148. package/lib/src/embed/ts-embed.js +2 -1
  149. package/lib/src/embed/ts-embed.js.map +1 -1
  150. package/lib/src/embed/ts-embed.spec.js +48 -37
  151. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  152. package/lib/src/react/index.spec.js +0 -12
  153. package/lib/src/react/index.spec.js.map +1 -1
  154. package/lib/src/tokenizedFetch.d.ts +2 -0
  155. package/lib/src/tokenizedFetch.d.ts.map +1 -0
  156. package/lib/src/tokenizedFetch.js +16 -0
  157. package/lib/src/tokenizedFetch.js.map +1 -0
  158. package/lib/src/types.d.ts +11 -1
  159. package/lib/src/types.d.ts.map +1 -1
  160. package/lib/src/types.js +7 -1
  161. package/lib/src/types.js.map +1 -1
  162. package/lib/src/utils/answerService.d.ts +10 -0
  163. package/lib/src/utils/answerService.d.ts.map +1 -0
  164. package/lib/src/utils/answerService.js +57 -0
  165. package/lib/src/utils/answerService.js.map +1 -0
  166. package/lib/src/utils/answerService.spec.d.ts +2 -0
  167. package/lib/src/utils/answerService.spec.d.ts.map +1 -0
  168. package/lib/src/utils/answerService.spec.js +29 -0
  169. package/lib/src/utils/answerService.spec.js.map +1 -0
  170. package/lib/src/utils/authService.d.ts +12 -1
  171. package/lib/src/utils/authService.d.ts.map +1 -1
  172. package/lib/src/utils/authService.js +26 -10
  173. package/lib/src/utils/authService.js.map +1 -1
  174. package/lib/src/utils/authService.spec.js +1 -2
  175. package/lib/src/utils/authService.spec.js.map +1 -1
  176. package/lib/src/utils/graphql/answerService/answerService.d.ts +1 -0
  177. package/lib/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  178. package/lib/src/utils/graphql/answerService/answerService.js +6 -2
  179. package/lib/src/utils/graphql/answerService/answerService.js.map +1 -1
  180. package/lib/src/utils/graphql/answerService/answerService.spec.js +17 -2
  181. package/lib/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
  182. package/lib/src/utils/graphql/graphql-request.spec.d.ts +2 -0
  183. package/lib/src/utils/graphql/graphql-request.spec.d.ts.map +1 -0
  184. package/lib/src/utils/graphql/graphql-request.spec.js +36 -0
  185. package/lib/src/utils/graphql/graphql-request.spec.js.map +1 -0
  186. package/lib/src/utils/logger.d.ts +28 -0
  187. package/lib/src/utils/logger.d.ts.map +1 -0
  188. package/lib/src/utils/logger.js +75 -0
  189. package/lib/src/utils/logger.js.map +1 -0
  190. package/lib/src/utils/processData.d.ts.map +1 -1
  191. package/lib/src/utils/processData.js +2 -2
  192. package/lib/src/utils/processData.js.map +1 -1
  193. package/lib/src/utils/processData.spec.js +2 -2
  194. package/lib/src/utils/processData.spec.js.map +1 -1
  195. package/lib/src/visual-embed-sdk.d.ts +12 -18
  196. package/package.json +1 -1
  197. package/src/auth.spec.ts +47 -7
  198. package/src/auth.ts +9 -50
  199. package/src/authToken.ts +60 -0
  200. package/src/config.spec.ts +1 -1
  201. package/src/config.ts +3 -0
  202. package/src/embed/base.spec.ts +7 -6
  203. package/src/embed/base.ts +2 -3
  204. package/src/embed/search.ts +2 -6
  205. package/src/embed/ts-embed.spec.ts +54 -40
  206. package/src/embed/ts-embed.ts +2 -1
  207. package/src/react/index.spec.tsx +0 -29
  208. package/src/tokenizedFetch.ts +16 -0
  209. package/src/types.ts +12 -2
  210. package/src/utils/authService.spec.ts +1 -2
  211. package/src/utils/authService.ts +29 -10
  212. package/src/utils/graphql/answerService/answerService.spec.ts +27 -3
  213. package/src/utils/graphql/answerService/answerService.ts +7 -2
  214. package/src/utils/processData.spec.ts +2 -2
  215. package/src/utils/processData.ts +2 -1
@@ -1121,11 +1121,17 @@
1121
1121
  */
1122
1122
  EmbedEvent["SageWorksheetUpdated"] = "sageWorksheetUpdated";
1123
1123
  /**
1124
- * Emitten when a user updates a connection in Data tab
1124
+ * Emitted when a user updates a connection in Data tab
1125
1125
  *
1126
1126
  * @version SDK : 1.27.0 | Thoughtspot: 9.8.0.cl
1127
1127
  */
1128
1128
  EmbedEvent["UpdateConnection"] = "updateConnection";
1129
+ /**
1130
+ * Emitted when a user updates a connection in Data tab
1131
+ *
1132
+ * @version SDK : 1.27.0 | Thoughtspot: 9.8.0.cl
1133
+ */
1134
+ EmbedEvent["CreateConnection"] = "createConnection";
1129
1135
  /**
1130
1136
  * Emitted when name, status (private or public) or filter values of a
1131
1137
  * PersonalisedView is updated.
@@ -5028,384 +5034,543 @@
5028
5034
 
5029
5035
  var isEqual_1 = isEqual;
5030
5036
 
5037
+ const EndPoints = {
5038
+ AUTH_VERIFICATION: '/callosum/v1/session/info',
5039
+ SAML_LOGIN_TEMPLATE: (targetUrl) => `/callosum/v1/saml/login?targetURLPath=${targetUrl}`,
5040
+ OIDC_LOGIN_TEMPLATE: (targetUrl) => `/callosum/v1/oidc/login?targetURLPath=${targetUrl}`,
5041
+ TOKEN_LOGIN: '/callosum/v1/session/login/token',
5042
+ BASIC_LOGIN: '/callosum/v1/session/login',
5043
+ LOGOUT: '/callosum/v1/session/logout',
5044
+ EXECUTE_TML: '/api/rest/2.0/metadata/tml/import',
5045
+ EXPORT_TML: '/api/rest/2.0/metadata/tml/export',
5046
+ IS_ACTIVE: '/callosum/v1/session/isactive',
5047
+ };
5031
5048
  /**
5032
5049
  *
5033
- * @param root0
5034
- * @param root0.query
5035
- * @param root0.variables
5036
- * @param root0.thoughtSpotHost
5037
- * @param root0.isCompositeQuery
5050
+ * @param url
5051
+ * @param options
5038
5052
  */
5039
- async function graphqlQuery({ query, variables, thoughtSpotHost, isCompositeQuery = false, }) {
5040
- const operationName = getOperationNameFromQuery(query);
5053
+ function failureLoggedFetch(url, options = {}) {
5054
+ return fetch(url, options).then(async (r) => {
5055
+ var _a;
5056
+ if (!r.ok && r.type !== 'opaqueredirect' && r.type !== 'opaque') {
5057
+ console.error('Failure', await ((_a = r.text) === null || _a === void 0 ? void 0 : _a.call(r)));
5058
+ }
5059
+ return r;
5060
+ });
5061
+ }
5062
+ /**
5063
+ *
5064
+ * @param authVerificationUrl
5065
+ */
5066
+ function fetchSessionInfoService(authVerificationUrl) {
5067
+ return failureLoggedFetch(authVerificationUrl, {
5068
+ credentials: 'include',
5069
+ });
5070
+ }
5071
+ /**
5072
+ * Service to validate a auth token against a ThoughtSpot host.
5073
+ *
5074
+ * @param thoughtSpotHost : ThoughtSpot host to verify the token against.
5075
+ * @param authToken : Auth token to verify.
5076
+ */
5077
+ async function verifyTokenService(thoughtSpotHost, authToken) {
5078
+ const authVerificationUrl = `${thoughtSpotHost}${EndPoints.IS_ACTIVE}`;
5041
5079
  try {
5042
- const response = await fetch(`${thoughtSpotHost}/prism/?op=${operationName}`, {
5043
- method: 'POST',
5080
+ const res = await fetch(authVerificationUrl, {
5044
5081
  headers: {
5045
- 'content-type': 'application/json;charset=UTF-8',
5082
+ Authorization: `Bearer ${authToken}`,
5046
5083
  'x-requested-by': 'ThoughtSpot',
5047
- accept: '*/*',
5048
- 'accept-language': 'en-us',
5049
5084
  },
5050
- body: JSON.stringify({
5051
- operationName,
5052
- query,
5053
- variables,
5054
- }),
5055
- credentials: 'include',
5085
+ credentials: 'omit',
5056
5086
  });
5057
- const result = await response.json();
5058
- const dataValues = Object.values(result.data);
5059
- return (isCompositeQuery) ? result.data : dataValues[0];
5087
+ return res.ok;
5060
5088
  }
5061
- catch (error) {
5062
- return error;
5089
+ catch (e) {
5090
+ console.error(`Token Verification Service failed : ${e.message}`);
5063
5091
  }
5064
- }
5065
-
5066
- const getSourceDetailQuery = `
5067
- query GetSourceDetail($ids: [GUID!]!) {
5068
- getSourceDetailById(ids: $ids, type: LOGICAL_TABLE) {
5069
- id
5070
- name
5071
- description
5072
- authorName
5073
- authorDisplayName
5074
- isExternal
5075
- type
5076
- created
5077
- modified
5078
- columns {
5079
- id
5080
- name
5081
- author
5082
- authorDisplayName
5083
- description
5084
- dataType
5085
- type
5086
- modified
5087
- ownerName
5088
- owner
5089
- dataRecency
5090
- sources {
5091
- tableId
5092
- tableName
5093
- columnId
5094
- columnName
5095
- __typename
5096
- }
5097
- synonyms
5098
- cohortAnswerId
5099
- __typename
5100
- }
5101
- relationships
5102
- destinationRelationships
5103
- dataSourceId
5104
- __typename
5105
- }
5106
- }
5107
- `;
5108
- const sourceDetailCache = new Map();
5092
+ return false;
5093
+ }
5094
+ /**
5095
+ *
5096
+ * @param authEndpoint
5097
+ */
5098
+ async function fetchAuthTokenService(authEndpoint) {
5099
+ return fetch(authEndpoint);
5100
+ }
5109
5101
  /**
5110
5102
  *
5111
5103
  * @param thoughtSpotHost
5112
- * @param sourceId
5104
+ * @param username
5105
+ * @param authToken
5113
5106
  */
5114
- async function getSourceDetail(thoughtSpotHost, sourceId) {
5115
- if (sourceDetailCache.get(sourceId)) {
5116
- return sourceDetailCache.get(sourceId);
5117
- }
5118
- const details = await graphqlQuery({
5119
- query: getSourceDetailQuery,
5120
- variables: {
5121
- ids: [sourceId],
5107
+ async function fetchAuthService(thoughtSpotHost, username, authToken) {
5108
+ return failureLoggedFetch(`${thoughtSpotHost}${EndPoints.TOKEN_LOGIN}?username=${username}&auth_token=${authToken}`, {
5109
+ credentials: 'include',
5110
+ // We do not want to follow the redirect, as it starts giving a CORS
5111
+ // error
5112
+ redirect: 'manual',
5113
+ });
5114
+ }
5115
+ /**
5116
+ *
5117
+ * @param thoughtSpotHost
5118
+ * @param username
5119
+ * @param authToken
5120
+ */
5121
+ async function fetchAuthPostService(thoughtSpotHost, username, authToken) {
5122
+ return failureLoggedFetch(`${thoughtSpotHost}${EndPoints.TOKEN_LOGIN}`, {
5123
+ method: 'POST',
5124
+ headers: {
5125
+ 'content-type': 'application/x-www-form-urlencoded',
5126
+ 'x-requested-by': 'ThoughtSpot',
5122
5127
  },
5123
- thoughtSpotHost,
5128
+ body: `username=${encodeURIComponent(username)}&auth_token=${encodeURIComponent(authToken)}`,
5129
+ credentials: 'include',
5130
+ // We do not want to follow the redirect, as it starts giving a CORS
5131
+ // error
5132
+ redirect: 'manual',
5124
5133
  });
5125
- const souceDetails = details[0];
5126
- if (souceDetails) {
5127
- sourceDetailCache.set(sourceId, souceDetails);
5134
+ }
5135
+ /**
5136
+ *
5137
+ * @param thoughtSpotHost
5138
+ * @param username
5139
+ * @param password
5140
+ */
5141
+ async function fetchBasicAuthService(thoughtSpotHost, username, password) {
5142
+ return failureLoggedFetch(`${thoughtSpotHost}${EndPoints.BASIC_LOGIN}`, {
5143
+ method: 'POST',
5144
+ headers: {
5145
+ 'content-type': 'application/x-www-form-urlencoded',
5146
+ 'x-requested-by': 'ThoughtSpot',
5147
+ },
5148
+ body: `username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}`,
5149
+ credentials: 'include',
5150
+ });
5151
+ }
5152
+
5153
+ const DUPLICATE_TOKEN_ERR = 'Duplicate token, please issue a new token every time getAuthToken callback is called.'
5154
+ + 'See https://developers.thoughtspot.com/docs/?pageid=embed-auth#trusted-auth-embed for more details.';
5155
+ const INVALID_TOKEN_ERR = 'Invalid token received form token callback or authToken endpoint.';
5156
+ let cachedAuthToken = null;
5157
+ // This method can be used to get the authToken using the embedConfig
5158
+ const getAuthenticationToken = async (embedConfig) => {
5159
+ if (cachedAuthToken) {
5160
+ try {
5161
+ const isCachedTokenStillValid = await validateAuthToken(embedConfig, cachedAuthToken);
5162
+ if (isCachedTokenStillValid)
5163
+ return cachedAuthToken;
5164
+ }
5165
+ catch {
5166
+ // Continue to get a new token if validation fails
5167
+ }
5128
5168
  }
5129
- return souceDetails;
5169
+ const { authEndpoint, getAuthToken } = embedConfig;
5170
+ let authToken = null;
5171
+ if (getAuthToken) {
5172
+ authToken = await getAuthToken();
5173
+ }
5174
+ else {
5175
+ const response = await fetchAuthTokenService(authEndpoint);
5176
+ authToken = await response.text();
5177
+ }
5178
+ // this will throw error if the token is not valid
5179
+ await validateAuthToken(embedConfig, authToken);
5180
+ cachedAuthToken = authToken;
5181
+ return authToken;
5182
+ };
5183
+ const validateAuthToken = async (embedConfig, authToken) => {
5184
+ try {
5185
+ const isTokenValid = await verifyTokenService(embedConfig.thoughtSpotHost, authToken);
5186
+ if (isTokenValid)
5187
+ return true;
5188
+ }
5189
+ catch {
5190
+ return false;
5191
+ }
5192
+ if (cachedAuthToken && cachedAuthToken === authToken) {
5193
+ if (!embedConfig.suppressErrorAlerts) {
5194
+ // eslint-disable-next-line no-alert
5195
+ alert(DUPLICATE_TOKEN_ERR);
5196
+ }
5197
+ throw new Error(DUPLICATE_TOKEN_ERR);
5198
+ }
5199
+ else {
5200
+ throw new Error(INVALID_TOKEN_ERR);
5201
+ }
5202
+ };
5203
+
5204
+ var eventemitter3 = createCommonjsModule(function (module) {
5205
+
5206
+ var has = Object.prototype.hasOwnProperty
5207
+ , prefix = '~';
5208
+
5209
+ /**
5210
+ * Constructor to create a storage for our `EE` objects.
5211
+ * An `Events` instance is a plain object whose properties are event names.
5212
+ *
5213
+ * @constructor
5214
+ * @private
5215
+ */
5216
+ function Events() {}
5217
+
5218
+ //
5219
+ // We try to not inherit from `Object.prototype`. In some engines creating an
5220
+ // instance in this way is faster than calling `Object.create(null)` directly.
5221
+ // If `Object.create(null)` is not supported we prefix the event names with a
5222
+ // character to make sure that the built-in object properties are not
5223
+ // overridden or used as an attack vector.
5224
+ //
5225
+ if (Object.create) {
5226
+ Events.prototype = Object.create(null);
5227
+
5228
+ //
5229
+ // This hack is needed because the `__proto__` property is still inherited in
5230
+ // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.
5231
+ //
5232
+ if (!new Events().__proto__) prefix = false;
5130
5233
  }
5131
5234
 
5132
- const bachSessionId = `
5133
- id {
5134
- sessionId
5135
- genNo
5136
- acSession {
5137
- sessionId
5138
- genNo
5139
- }
5140
- }
5141
- `;
5142
- const getUnaggregatedAnswerSession = `
5143
- mutation GetUnAggregatedAnswerSession($session: BachSessionIdInput!, $columns: [UserPointSelectionInput!]!) {
5144
- Answer__getUnaggregatedAnswer(session: $session, columns: $columns) {
5145
- ${bachSessionId}
5146
- answer {
5147
- visualizations {
5148
- ... on TableViz {
5149
- columns {
5150
- column {
5151
- id
5152
- name
5153
- referencedColumns {
5154
- guid
5155
- displayName
5156
- }
5157
- }
5158
- }
5159
- }
5160
- }
5161
- }
5162
- }
5163
- }
5164
- `;
5165
- const removeColumns = `
5166
- mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!], $columnIds: [GUID!]) {
5167
- Answer__removeColumns(
5168
- session: $session
5169
- logicalColumnIds: $logicalColumnIds
5170
- columnIds: $columnIds
5171
- ) {
5172
- ${bachSessionId}
5173
- }
5174
- }
5175
- `;
5176
- const addColumns = `
5177
- mutation AddColumns($session: BachSessionIdInput!, $columns: [AnswerColumnInfo!]!) {
5178
- Answer__addColumn(session: $session, columns: $columns) {
5179
- ${bachSessionId}
5180
- }
5181
- }
5182
- `;
5183
- const getAnswerData = `
5184
- query GetTableWithHeadlineData($session: BachSessionIdInput!, $deadline: Int!, $dataPaginationParams: DataPaginationParamsInput!) {
5185
- getAnswer(session: $session) {
5186
- ${bachSessionId}
5187
- answer {
5188
- id
5189
- visualizations {
5190
- id
5191
- ... on TableViz {
5192
- columns {
5193
- column {
5194
- id
5195
- name
5196
- type
5197
- aggregationType
5198
- dataType
5199
- }
5200
- }
5201
- data(deadline: $deadline, pagination: $dataPaginationParams)
5202
- }
5203
- }
5204
- }
5205
- }
5206
- }
5207
- `;
5235
+ /**
5236
+ * Representation of a single event listener.
5237
+ *
5238
+ * @param {Function} fn The listener function.
5239
+ * @param {*} context The context to invoke the listener with.
5240
+ * @param {Boolean} [once=false] Specify if the listener is a one-time listener.
5241
+ * @constructor
5242
+ * @private
5243
+ */
5244
+ function EE(fn, context, once) {
5245
+ this.fn = fn;
5246
+ this.context = context;
5247
+ this.once = once || false;
5248
+ }
5249
+
5250
+ /**
5251
+ * Add a listener for a given event.
5252
+ *
5253
+ * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
5254
+ * @param {(String|Symbol)} event The event name.
5255
+ * @param {Function} fn The listener function.
5256
+ * @param {*} context The context to invoke the listener with.
5257
+ * @param {Boolean} once Specify if the listener is a one-time listener.
5258
+ * @returns {EventEmitter}
5259
+ * @private
5260
+ */
5261
+ function addListener(emitter, event, fn, context, once) {
5262
+ if (typeof fn !== 'function') {
5263
+ throw new TypeError('The listener must be a function');
5264
+ }
5265
+
5266
+ var listener = new EE(fn, context || emitter, once)
5267
+ , evt = prefix ? prefix + event : event;
5268
+
5269
+ if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;
5270
+ else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);
5271
+ else emitter._events[evt] = [emitter._events[evt], listener];
5272
+
5273
+ return emitter;
5274
+ }
5275
+
5276
+ /**
5277
+ * Clear event by name.
5278
+ *
5279
+ * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
5280
+ * @param {(String|Symbol)} evt The Event name.
5281
+ * @private
5282
+ */
5283
+ function clearEvent(emitter, evt) {
5284
+ if (--emitter._eventsCount === 0) emitter._events = new Events();
5285
+ else delete emitter._events[evt];
5286
+ }
5287
+
5288
+ /**
5289
+ * Minimal `EventEmitter` interface that is molded against the Node.js
5290
+ * `EventEmitter` interface.
5291
+ *
5292
+ * @constructor
5293
+ * @public
5294
+ */
5295
+ function EventEmitter() {
5296
+ this._events = new Events();
5297
+ this._eventsCount = 0;
5298
+ }
5299
+
5300
+ /**
5301
+ * Return an array listing the events for which the emitter has registered
5302
+ * listeners.
5303
+ *
5304
+ * @returns {Array}
5305
+ * @public
5306
+ */
5307
+ EventEmitter.prototype.eventNames = function eventNames() {
5308
+ var names = []
5309
+ , events
5310
+ , name;
5311
+
5312
+ if (this._eventsCount === 0) return names;
5313
+
5314
+ for (name in (events = this._events)) {
5315
+ if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
5316
+ }
5317
+
5318
+ if (Object.getOwnPropertySymbols) {
5319
+ return names.concat(Object.getOwnPropertySymbols(events));
5320
+ }
5321
+
5322
+ return names;
5323
+ };
5324
+
5325
+ /**
5326
+ * Return the listeners registered for a given event.
5327
+ *
5328
+ * @param {(String|Symbol)} event The event name.
5329
+ * @returns {Array} The registered listeners.
5330
+ * @public
5331
+ */
5332
+ EventEmitter.prototype.listeners = function listeners(event) {
5333
+ var evt = prefix ? prefix + event : event
5334
+ , handlers = this._events[evt];
5335
+
5336
+ if (!handlers) return [];
5337
+ if (handlers.fn) return [handlers.fn];
5338
+
5339
+ for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {
5340
+ ee[i] = handlers[i].fn;
5341
+ }
5342
+
5343
+ return ee;
5344
+ };
5345
+
5346
+ /**
5347
+ * Return the number of listeners listening to a given event.
5348
+ *
5349
+ * @param {(String|Symbol)} event The event name.
5350
+ * @returns {Number} The number of listeners.
5351
+ * @public
5352
+ */
5353
+ EventEmitter.prototype.listenerCount = function listenerCount(event) {
5354
+ var evt = prefix ? prefix + event : event
5355
+ , listeners = this._events[evt];
5356
+
5357
+ if (!listeners) return 0;
5358
+ if (listeners.fn) return 1;
5359
+ return listeners.length;
5360
+ };
5361
+
5362
+ /**
5363
+ * Calls each of the listeners registered for a given event.
5364
+ *
5365
+ * @param {(String|Symbol)} event The event name.
5366
+ * @returns {Boolean} `true` if the event had listeners, else `false`.
5367
+ * @public
5368
+ */
5369
+ EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
5370
+ var evt = prefix ? prefix + event : event;
5371
+
5372
+ if (!this._events[evt]) return false;
5373
+
5374
+ var listeners = this._events[evt]
5375
+ , len = arguments.length
5376
+ , args
5377
+ , i;
5378
+
5379
+ if (listeners.fn) {
5380
+ if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);
5381
+
5382
+ switch (len) {
5383
+ case 1: return listeners.fn.call(listeners.context), true;
5384
+ case 2: return listeners.fn.call(listeners.context, a1), true;
5385
+ case 3: return listeners.fn.call(listeners.context, a1, a2), true;
5386
+ case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;
5387
+ case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
5388
+ case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
5389
+ }
5390
+
5391
+ for (i = 1, args = new Array(len -1); i < len; i++) {
5392
+ args[i - 1] = arguments[i];
5393
+ }
5394
+
5395
+ listeners.fn.apply(listeners.context, args);
5396
+ } else {
5397
+ var length = listeners.length
5398
+ , j;
5399
+
5400
+ for (i = 0; i < length; i++) {
5401
+ if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);
5402
+
5403
+ switch (len) {
5404
+ case 1: listeners[i].fn.call(listeners[i].context); break;
5405
+ case 2: listeners[i].fn.call(listeners[i].context, a1); break;
5406
+ case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;
5407
+ case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;
5408
+ default:
5409
+ if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {
5410
+ args[j - 1] = arguments[j];
5411
+ }
5412
+
5413
+ listeners[i].fn.apply(listeners[i].context, args);
5414
+ }
5415
+ }
5416
+ }
5417
+
5418
+ return true;
5419
+ };
5420
+
5421
+ /**
5422
+ * Add a listener for a given event.
5423
+ *
5424
+ * @param {(String|Symbol)} event The event name.
5425
+ * @param {Function} fn The listener function.
5426
+ * @param {*} [context=this] The context to invoke the listener with.
5427
+ * @returns {EventEmitter} `this`.
5428
+ * @public
5429
+ */
5430
+ EventEmitter.prototype.on = function on(event, fn, context) {
5431
+ return addListener(this, event, fn, context, false);
5432
+ };
5433
+
5434
+ /**
5435
+ * Add a one-time listener for a given event.
5436
+ *
5437
+ * @param {(String|Symbol)} event The event name.
5438
+ * @param {Function} fn The listener function.
5439
+ * @param {*} [context=this] The context to invoke the listener with.
5440
+ * @returns {EventEmitter} `this`.
5441
+ * @public
5442
+ */
5443
+ EventEmitter.prototype.once = function once(event, fn, context) {
5444
+ return addListener(this, event, fn, context, true);
5445
+ };
5446
+
5447
+ /**
5448
+ * Remove the listeners of a given event.
5449
+ *
5450
+ * @param {(String|Symbol)} event The event name.
5451
+ * @param {Function} fn Only remove the listeners that match this function.
5452
+ * @param {*} context Only remove the listeners that have this context.
5453
+ * @param {Boolean} once Only remove one-time listeners.
5454
+ * @returns {EventEmitter} `this`.
5455
+ * @public
5456
+ */
5457
+ EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
5458
+ var evt = prefix ? prefix + event : event;
5459
+
5460
+ if (!this._events[evt]) return this;
5461
+ if (!fn) {
5462
+ clearEvent(this, evt);
5463
+ return this;
5464
+ }
5465
+
5466
+ var listeners = this._events[evt];
5467
+
5468
+ if (listeners.fn) {
5469
+ if (
5470
+ listeners.fn === fn &&
5471
+ (!once || listeners.once) &&
5472
+ (!context || listeners.context === context)
5473
+ ) {
5474
+ clearEvent(this, evt);
5475
+ }
5476
+ } else {
5477
+ for (var i = 0, events = [], length = listeners.length; i < length; i++) {
5478
+ if (
5479
+ listeners[i].fn !== fn ||
5480
+ (once && !listeners[i].once) ||
5481
+ (context && listeners[i].context !== context)
5482
+ ) {
5483
+ events.push(listeners[i]);
5484
+ }
5485
+ }
5486
+
5487
+ //
5488
+ // Reset the array, or remove it completely if we have no more listeners.
5489
+ //
5490
+ if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;
5491
+ else clearEvent(this, evt);
5492
+ }
5493
+
5494
+ return this;
5495
+ };
5496
+
5497
+ /**
5498
+ * Remove all listeners, or those of the specified event.
5499
+ *
5500
+ * @param {(String|Symbol)} [event] The event name.
5501
+ * @returns {EventEmitter} `this`.
5502
+ * @public
5503
+ */
5504
+ EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
5505
+ var evt;
5208
5506
 
5209
- // eslint-disable-next-line no-shadow
5210
- var OperationType;
5211
- (function (OperationType) {
5212
- OperationType["GetChartWithData"] = "GetChartWithData";
5213
- OperationType["GetTableWithHeadlineData"] = "GetTableWithHeadlineData";
5214
- })(OperationType || (OperationType = {}));
5215
- /**
5216
- * Class representing the answer service provided with the
5217
- * custom action payload. This service could be used to run
5218
- * graphql queries in the context of the answer on which the
5219
- * custom action was triggered.
5220
- *
5221
- * @example
5222
- * ```js
5223
- * embed.on(EmbedEvent.CustomAction, e => {
5224
- * const underlying = await e.answerService.getUnderlyingDataForPoint([
5225
- * 'col name 1'
5226
- * ]);
5227
- * const data = await underlying.fetchData(0, 100);
5228
- * })
5229
- * ```
5230
- * @version
5231
- * ThoughtSpot: 9.9.0.cl / SDK: 1.25.0
5232
- * @group Events
5233
- */
5234
- class AnswerService {
5235
- constructor(session, answer, thoughtSpotHost, selectedPoints) {
5236
- this.session = session;
5237
- this.answer = answer;
5238
- this.thoughtSpotHost = thoughtSpotHost;
5239
- this.selectedPoints = selectedPoints;
5240
- this.session = removeTypename(session);
5241
- }
5242
- async getSourceDetail() {
5243
- const sourceId = this.answer.sources[0].header.guid;
5244
- return getSourceDetail(this.thoughtSpotHost, sourceId);
5245
- }
5246
- async removeColumns(columnIds) {
5247
- return this.executeQuery(removeColumns, {
5248
- logicalColumnIds: columnIds,
5249
- });
5250
- }
5251
- async addColumns(columnIds) {
5252
- return this.executeQuery(addColumns, {
5253
- columns: columnIds.map((colId) => ({ logicalColumnId: colId })),
5254
- });
5255
- }
5256
- async fetchData(offset = 0, size = 1000) {
5257
- const { answer } = await this.executeQuery(getAnswerData, {
5258
- deadline: 0,
5259
- dataPaginationParams: {
5260
- isClientPaginated: true,
5261
- offset,
5262
- size,
5263
- },
5264
- });
5265
- const { columns, data } = answer.visualizations[0];
5266
- return {
5267
- columns,
5268
- data,
5269
- };
5270
- }
5271
- /**
5272
- *
5273
- * @param userLocale
5274
- * @param includeInfo Include the CSV header in the output
5275
- * @returns Response
5276
- */
5277
- async fetchCSVBlob(userLocale = 'en-us', includeInfo = false) {
5278
- const fetchUrl = `${this.thoughtSpotHost}/prism/download/answer/csv?sessionId=${this.session.sessionId}&genNo=${this.session.genNo}&userLocale=${userLocale}&exportFileName=data&hideCsvHeader=${!includeInfo}`;
5279
- return fetch(fetchUrl, {
5280
- credentials: 'include',
5281
- });
5282
- }
5283
- /**
5284
- * Get underlying data given a point and the output column names.
5285
- *
5286
- * @param outputColumnNames
5287
- * @param selectedPoints
5288
- * @example
5289
- * ```js
5290
- * embed.on(EmbedEvent.CustomAction, e => {
5291
- * const underlying = await e.answerService.getUnderlyingDataForPoint([
5292
- * 'col name 1' // The column should exist in the data source.
5293
- * ]);
5294
- * const data = await underlying.fetchData(0, 100);
5295
- * })
5296
- * ```
5297
- * @version
5298
- * ThoughtSpot: 9.9.0.cl / SDK: 1.25.0
5299
- */
5300
- async getUnderlyingDataForPoint(outputColumnNames, selectedPoints) {
5301
- if (!selectedPoints && !this.selectedPoints) {
5302
- throw new Error('Needs to be triggered in context of a point');
5303
- }
5304
- if (!selectedPoints) {
5305
- selectedPoints = getSelectedPointsForUnderlyingDataQuery(this.selectedPoints);
5306
- }
5307
- const sourceDetail = await this.getSourceDetail();
5308
- const ouputColumnGuids = getGuidsFromColumnNames(sourceDetail, outputColumnNames);
5309
- const unAggAnswer = await graphqlQuery({
5310
- query: getUnaggregatedAnswerSession,
5311
- variables: {
5312
- session: this.session,
5313
- columns: selectedPoints,
5314
- },
5315
- thoughtSpotHost: this.thoughtSpotHost,
5316
- });
5317
- const unaggAnswerSession = new AnswerService(unAggAnswer.id, unAggAnswer.answer, this.thoughtSpotHost);
5318
- const currentColumns = new Set(unAggAnswer.answer.visualizations[0].columns
5319
- .map((c) => c.column.referencedColumns[0].guid));
5320
- const columnsToAdd = [...ouputColumnGuids].filter((col) => !currentColumns.has(col));
5321
- if (columnsToAdd.length) {
5322
- await unaggAnswerSession.addColumns(columnsToAdd);
5323
- }
5324
- const columnsToRemove = [...currentColumns].filter((col) => !ouputColumnGuids.has(col));
5325
- if (columnsToRemove.length) {
5326
- await unaggAnswerSession.removeColumns(columnsToRemove);
5327
- }
5328
- return unaggAnswerSession;
5329
- }
5330
- async executeQuery(query, variables) {
5331
- const data = await graphqlQuery({
5332
- query,
5333
- variables: {
5334
- session: this.session,
5335
- ...variables,
5336
- },
5337
- thoughtSpotHost: this.thoughtSpotHost,
5338
- isCompositeQuery: false,
5339
- });
5340
- this.session = deepMerge(this.session, (data === null || data === void 0 ? void 0 : data.id) || {});
5341
- return data;
5342
- }
5343
- getSession() {
5344
- return this.session;
5345
- }
5346
- }
5347
- /**
5348
- *
5349
- * @param sourceDetail
5350
- * @param colNames
5351
- */
5352
- function getGuidsFromColumnNames(sourceDetail, colNames) {
5353
- const cols = sourceDetail.columns.reduce((colSet, col) => {
5354
- colSet[col.name] = col;
5355
- return colSet;
5356
- }, {});
5357
- return new Set(colNames.map((colName) => {
5358
- const col = cols[colName];
5359
- return col.id;
5360
- }));
5361
- }
5362
- /**
5363
- *
5364
- * @param selectedPoints
5365
- */
5366
- function getSelectedPointsForUnderlyingDataQuery(selectedPoints) {
5367
- const underlyingDataPoint = [];
5368
- /**
5369
- *
5370
- * @param colVal
5371
- */
5372
- function addPointFromColVal(colVal) {
5373
- var _a;
5374
- const dataType = colVal.column.dataType;
5375
- const id = colVal.column.id;
5376
- let dataValue;
5377
- if (dataType === 'DATE') {
5378
- if (Number.isFinite(colVal.value)) {
5379
- dataValue = [{
5380
- epochRange: {
5381
- startEpoch: colVal.value,
5382
- },
5383
- }];
5384
- // Case for custom calendar.
5385
- }
5386
- else if ((_a = colVal.value) === null || _a === void 0 ? void 0 : _a.v) {
5387
- dataValue = [{
5388
- epochRange: {
5389
- startEpoch: colVal.value.v.s,
5390
- endEpoch: colVal.value.v.e,
5391
- },
5392
- }];
5393
- }
5394
- }
5395
- else {
5396
- dataValue = [{ value: colVal.value }];
5397
- }
5398
- underlyingDataPoint.push({
5399
- columnId: colVal.column.id,
5400
- dataValue,
5401
- });
5402
- }
5403
- selectedPoints.forEach((p) => {
5404
- p.selectedAttributes.forEach(addPointFromColVal);
5405
- });
5406
- return underlyingDataPoint;
5507
+ if (event) {
5508
+ evt = prefix ? prefix + event : event;
5509
+ if (this._events[evt]) clearEvent(this, evt);
5510
+ } else {
5511
+ this._events = new Events();
5512
+ this._eventsCount = 0;
5513
+ }
5514
+
5515
+ return this;
5516
+ };
5517
+
5518
+ //
5519
+ // Alias methods names because people roll like that.
5520
+ //
5521
+ EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
5522
+ EventEmitter.prototype.addListener = EventEmitter.prototype.on;
5523
+
5524
+ //
5525
+ // Expose the prefix.
5526
+ //
5527
+ EventEmitter.prefixed = prefix;
5528
+
5529
+ //
5530
+ // Allow `EventEmitter` to be imported as module namespace.
5531
+ //
5532
+ EventEmitter.EventEmitter = EventEmitter;
5533
+
5534
+ //
5535
+ // Expose the module.
5536
+ //
5537
+ {
5538
+ module.exports = EventEmitter;
5539
+ }
5540
+ });
5541
+
5542
+ /**
5543
+ * This method returns `undefined`.
5544
+ *
5545
+ * @static
5546
+ * @memberOf _
5547
+ * @since 2.3.0
5548
+ * @category Util
5549
+ * @example
5550
+ *
5551
+ * _.times(2, _.noop);
5552
+ * // => [undefined, undefined]
5553
+ */
5554
+ function noop() {
5555
+ // No operation performed.
5407
5556
  }
5408
5557
 
5558
+ var noop_1 = noop;
5559
+
5560
+ /** Used as references for various `Number` constants. */
5561
+ var INFINITY = 1 / 0;
5562
+
5563
+ /**
5564
+ * Creates a set object of `values`.
5565
+ *
5566
+ * @private
5567
+ * @param {Array} values The values to add to the set.
5568
+ * @returns {Object} Returns the new set.
5569
+ */
5570
+ var createSet = !(_Set && (1 / _setToArray(new _Set([,-0]))[1]) == INFINITY) ? noop_1 : function(values) {
5571
+ return new _Set(values);
5572
+ };
5573
+
5409
5574
  const ERROR_MESSAGE = {
5410
5575
  INVALID_THOUGHTSPOT_HOST: 'Error parsing ThoughtSpot host. Please provide a valid URL.',
5411
5576
  LIVEBOARD_VIZ_ID_VALIDATION: 'Please provide either liveboardId or pinboardId',
@@ -5436,6 +5601,9 @@ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!]
5436
5601
  * @param config
5437
5602
  */
5438
5603
  const getThoughtSpotHost = (config) => {
5604
+ if (!config.thoughtSpotHost) {
5605
+ throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
5606
+ }
5439
5607
  const urlParts = config.thoughtSpotHost.match(urlRegex);
5440
5608
  if (!urlParts) {
5441
5609
  throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
@@ -10396,1611 +10564,1142 @@ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!]
10396
10564
  * @param {Object=} groups An object mapping group name keys to one or more values
10397
10565
  * @param {Function} [callback] If provided, the callback will be called after tracking the event.
10398
10566
  */
10399
- MixpanelLib.prototype.track_with_groups = addOptOutCheckMixpanelLib(function(event_name, properties, groups, callback) {
10400
- var tracking_props = _.extend({}, properties || {});
10401
- _.each(groups, function(v, k) {
10402
- if (v !== null && v !== undefined) {
10403
- tracking_props[k] = v;
10404
- }
10405
- });
10406
- return this.track(event_name, tracking_props, callback);
10407
- });
10408
-
10409
- MixpanelLib.prototype._create_map_key = function (group_key, group_id) {
10410
- return group_key + '_' + JSON.stringify(group_id);
10411
- };
10412
-
10413
- MixpanelLib.prototype._remove_group_from_cache = function (group_key, group_id) {
10414
- delete this._cached_groups[this._create_map_key(group_key, group_id)];
10415
- };
10416
-
10417
- /**
10418
- * Look up reference to a Mixpanel group
10419
- *
10420
- * ### Usage:
10421
- *
10422
- * mixpanel.get_group(group_key, group_id)
10423
- *
10424
- * @param {String} group_key Group key
10425
- * @param {Object} group_id A valid Mixpanel property type
10426
- * @returns {Object} A MixpanelGroup identifier
10427
- */
10428
- MixpanelLib.prototype.get_group = function (group_key, group_id) {
10429
- var map_key = this._create_map_key(group_key, group_id);
10430
- var group = this._cached_groups[map_key];
10431
- if (group === undefined || group._group_key !== group_key || group._group_id !== group_id) {
10432
- group = new MixpanelGroup();
10433
- group._init(this, group_key, group_id);
10434
- this._cached_groups[map_key] = group;
10435
- }
10436
- return group;
10437
- };
10438
-
10439
- /**
10440
- * Track mp_page_view event. This is now ignored by the server.
10441
- *
10442
- * @param {String} [page] The url of the page to record. If you don't include this, it defaults to the current url.
10443
- * @deprecated
10444
- */
10445
- MixpanelLib.prototype.track_pageview = function(page) {
10446
- if (_.isUndefined(page)) {
10447
- page = document$1.location.href;
10448
- }
10449
- this.track('mp_page_view', _.info.pageviewInfo(page));
10450
- };
10451
-
10452
- /**
10453
- * Track clicks on a set of document elements. Selector must be a
10454
- * valid query. Elements must exist on the page at the time track_links is called.
10455
- *
10456
- * ### Usage:
10457
- *
10458
- * // track click for link id #nav
10459
- * mixpanel.track_links('#nav', 'Clicked Nav Link');
10460
- *
10461
- * ### Notes:
10462
- *
10463
- * This function will wait up to 300 ms for the Mixpanel
10464
- * servers to respond. If they have not responded by that time
10465
- * it will head to the link without ensuring that your event
10466
- * has been tracked. To configure this timeout please see the
10467
- * set_config() documentation below.
10468
- *
10469
- * If you pass a function in as the properties argument, the
10470
- * function will receive the DOMElement that triggered the
10471
- * event as an argument. You are expected to return an object
10472
- * from the function; any properties defined on this object
10473
- * will be sent to mixpanel as event properties.
10474
- *
10475
- * @type {Function}
10476
- * @param {Object|String} query A valid DOM query, element or jQuery-esque list
10477
- * @param {String} event_name The name of the event to track
10478
- * @param {Object|Function} [properties] A properties object or function that returns a dictionary of properties when passed a DOMElement
10479
- */
10480
- MixpanelLib.prototype.track_links = function() {
10481
- return this._track_dom.call(this, LinkTracker, arguments);
10482
- };
10483
-
10484
- /**
10485
- * Track form submissions. Selector must be a valid query.
10486
- *
10487
- * ### Usage:
10488
- *
10489
- * // track submission for form id 'register'
10490
- * mixpanel.track_forms('#register', 'Created Account');
10491
- *
10492
- * ### Notes:
10493
- *
10494
- * This function will wait up to 300 ms for the mixpanel
10495
- * servers to respond, if they have not responded by that time
10496
- * it will head to the link without ensuring that your event
10497
- * has been tracked. To configure this timeout please see the
10498
- * set_config() documentation below.
10499
- *
10500
- * If you pass a function in as the properties argument, the
10501
- * function will receive the DOMElement that triggered the
10502
- * event as an argument. You are expected to return an object
10503
- * from the function; any properties defined on this object
10504
- * will be sent to mixpanel as event properties.
10505
- *
10506
- * @type {Function}
10507
- * @param {Object|String} query A valid DOM query, element or jQuery-esque list
10508
- * @param {String} event_name The name of the event to track
10509
- * @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
10510
- */
10511
- MixpanelLib.prototype.track_forms = function() {
10512
- return this._track_dom.call(this, FormTracker, arguments);
10513
- };
10514
-
10515
- /**
10516
- * Time an event by including the time between this call and a
10517
- * later 'track' call for the same event in the properties sent
10518
- * with the event.
10519
- *
10520
- * ### Usage:
10521
- *
10522
- * // time an event named 'Registered'
10523
- * mixpanel.time_event('Registered');
10524
- * mixpanel.track('Registered', {'Gender': 'Male', 'Age': 21});
10525
- *
10526
- * When called for a particular event name, the next track call for that event
10527
- * name will include the elapsed time between the 'time_event' and 'track'
10528
- * calls. This value is stored as seconds in the '$duration' property.
10529
- *
10530
- * @param {String} event_name The name of the event.
10531
- */
10532
- MixpanelLib.prototype.time_event = function(event_name) {
10533
- if (_.isUndefined(event_name)) {
10534
- this.report_error('No event name provided to mixpanel.time_event');
10535
- return;
10536
- }
10537
-
10538
- if (this._event_is_disabled(event_name)) {
10539
- return;
10540
- }
10541
-
10542
- this['persistence'].set_event_timer(event_name, new Date().getTime());
10543
- };
10544
-
10545
- var REGISTER_DEFAULTS = {
10546
- 'persistent': true
10547
- };
10548
- /**
10549
- * Helper to parse options param for register methods, maintaining
10550
- * legacy support for plain "days" param instead of options object
10551
- * @param {Number|Object} [days_or_options] 'days' option (Number), or Options object for register methods
10552
- * @returns {Object} options object
10553
- */
10554
- var options_for_register = function(days_or_options) {
10555
- var options;
10556
- if (_.isObject(days_or_options)) {
10557
- options = days_or_options;
10558
- } else if (!_.isUndefined(days_or_options)) {
10559
- options = {'days': days_or_options};
10560
- } else {
10561
- options = {};
10562
- }
10563
- return _.extend({}, REGISTER_DEFAULTS, options);
10564
- };
10565
-
10566
- /**
10567
- * Register a set of super properties, which are included with all
10568
- * events. This will overwrite previous super property values.
10569
- *
10570
- * ### Usage:
10571
- *
10572
- * // register 'Gender' as a super property
10573
- * mixpanel.register({'Gender': 'Female'});
10574
- *
10575
- * // register several super properties when a user signs up
10576
- * mixpanel.register({
10577
- * 'Email': 'jdoe@example.com',
10578
- * 'Account Type': 'Free'
10579
- * });
10580
- *
10581
- * // register only for the current pageload
10582
- * mixpanel.register({'Name': 'Pat'}, {persistent: false});
10583
- *
10584
- * @param {Object} properties An associative array of properties to store about the user
10585
- * @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)
10586
- * @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)
10587
- * @param {boolean} [days_or_options.persistent=true] - whether to put in persistent storage (cookie/localStorage)
10588
- */
10589
- MixpanelLib.prototype.register = function(props, days_or_options) {
10590
- var options = options_for_register(days_or_options);
10591
- if (options['persistent']) {
10592
- this['persistence'].register(props, options['days']);
10593
- } else {
10594
- _.extend(this.unpersisted_superprops, props);
10595
- }
10596
- };
10597
-
10598
- /**
10599
- * Register a set of super properties only once. This will not
10600
- * overwrite previous super property values, unlike register().
10601
- *
10602
- * ### Usage:
10603
- *
10604
- * // register a super property for the first time only
10605
- * mixpanel.register_once({
10606
- * 'First Login Date': new Date().toISOString()
10607
- * });
10608
- *
10609
- * // register once, only for the current pageload
10610
- * mixpanel.register_once({
10611
- * 'First interaction time': new Date().toISOString()
10612
- * }, 'None', {persistent: false});
10613
- *
10614
- * ### Notes:
10615
- *
10616
- * If default_value is specified, current super properties
10617
- * with that value will be overwritten.
10618
- *
10619
- * @param {Object} properties An associative array of properties to store about the user
10620
- * @param {*} [default_value] Value to override if already set in super properties (ex: 'False') Default: 'None'
10621
- * @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)
10622
- * @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)
10623
- * @param {boolean} [days_or_options.persistent=true] - whether to put in persistent storage (cookie/localStorage)
10624
- */
10625
- MixpanelLib.prototype.register_once = function(props, default_value, days_or_options) {
10626
- var options = options_for_register(days_or_options);
10627
- if (options['persistent']) {
10628
- this['persistence'].register_once(props, default_value, options['days']);
10629
- } else {
10630
- if (typeof(default_value) === 'undefined') {
10631
- default_value = 'None';
10632
- }
10633
- _.each(props, function(val, prop) {
10634
- if (!this.unpersisted_superprops.hasOwnProperty(prop) || this.unpersisted_superprops[prop] === default_value) {
10635
- this.unpersisted_superprops[prop] = val;
10636
- }
10637
- }, this);
10638
- }
10639
- };
10640
-
10641
- /**
10642
- * Delete a super property stored with the current user.
10643
- *
10644
- * @param {String} property The name of the super property to remove
10645
- * @param {Object} [options]
10646
- * @param {boolean} [options.persistent=true] - whether to look in persistent storage (cookie/localStorage)
10647
- */
10648
- MixpanelLib.prototype.unregister = function(property, options) {
10649
- options = options_for_register(options);
10650
- if (options['persistent']) {
10651
- this['persistence'].unregister(property);
10652
- } else {
10653
- delete this.unpersisted_superprops[property];
10654
- }
10567
+ MixpanelLib.prototype.track_with_groups = addOptOutCheckMixpanelLib(function(event_name, properties, groups, callback) {
10568
+ var tracking_props = _.extend({}, properties || {});
10569
+ _.each(groups, function(v, k) {
10570
+ if (v !== null && v !== undefined) {
10571
+ tracking_props[k] = v;
10572
+ }
10573
+ });
10574
+ return this.track(event_name, tracking_props, callback);
10575
+ });
10576
+
10577
+ MixpanelLib.prototype._create_map_key = function (group_key, group_id) {
10578
+ return group_key + '_' + JSON.stringify(group_id);
10655
10579
  };
10656
10580
 
10657
- MixpanelLib.prototype._register_single = function(prop, value) {
10658
- var props = {};
10659
- props[prop] = value;
10660
- this.register(props);
10581
+ MixpanelLib.prototype._remove_group_from_cache = function (group_key, group_id) {
10582
+ delete this._cached_groups[this._create_map_key(group_key, group_id)];
10661
10583
  };
10662
10584
 
10663
10585
  /**
10664
- * Identify a user with a unique ID to track user activity across
10665
- * devices, tie a user to their events, and create a user profile.
10666
- * If you never call this method, unique visitors are tracked using
10667
- * a UUID generated the first time they visit the site.
10668
- *
10669
- * Call identify when you know the identity of the current user,
10670
- * typically after login or signup. We recommend against using
10671
- * identify for anonymous visitors to your site.
10586
+ * Look up reference to a Mixpanel group
10672
10587
  *
10673
- * ### Notes:
10674
- * If your project has
10675
- * <a href="https://help.mixpanel.com/hc/en-us/articles/360039133851">ID Merge</a>
10676
- * enabled, the identify method will connect pre- and
10677
- * post-authentication events when appropriate.
10588
+ * ### Usage:
10678
10589
  *
10679
- * If your project does not have ID Merge enabled, identify will
10680
- * change the user's local distinct_id to the unique ID you pass.
10681
- * Events tracked prior to authentication will not be connected
10682
- * to the same user identity. If ID Merge is disabled, alias can
10683
- * be used to connect pre- and post-registration events.
10590
+ * mixpanel.get_group(group_key, group_id)
10684
10591
  *
10685
- * @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.
10592
+ * @param {String} group_key Group key
10593
+ * @param {Object} group_id A valid Mixpanel property type
10594
+ * @returns {Object} A MixpanelGroup identifier
10686
10595
  */
10687
- MixpanelLib.prototype.identify = function(
10688
- new_distinct_id, _set_callback, _add_callback, _append_callback, _set_once_callback, _union_callback, _unset_callback, _remove_callback
10689
- ) {
10690
- // Optional Parameters
10691
- // _set_callback:function A callback to be run if and when the People set queue is flushed
10692
- // _add_callback:function A callback to be run if and when the People add queue is flushed
10693
- // _append_callback:function A callback to be run if and when the People append queue is flushed
10694
- // _set_once_callback:function A callback to be run if and when the People set_once queue is flushed
10695
- // _union_callback:function A callback to be run if and when the People union queue is flushed
10696
- // _unset_callback:function A callback to be run if and when the People unset queue is flushed
10697
-
10698
- var previous_distinct_id = this.get_distinct_id();
10699
- this.register({'$user_id': new_distinct_id});
10700
-
10701
- if (!this.get_property('$device_id')) {
10702
- // The persisted distinct id might not actually be a device id at all
10703
- // it might be a distinct id of the user from before
10704
- var device_id = previous_distinct_id;
10705
- this.register_once({
10706
- '$had_persisted_distinct_id': true,
10707
- '$device_id': device_id
10708
- }, '');
10709
- }
10710
-
10711
- // identify only changes the distinct id if it doesn't match either the existing or the alias;
10712
- // if it's new, blow away the alias as well.
10713
- if (new_distinct_id !== previous_distinct_id && new_distinct_id !== this.get_property(ALIAS_ID_KEY)) {
10714
- this.unregister(ALIAS_ID_KEY);
10715
- this.register({'distinct_id': new_distinct_id});
10716
- }
10717
- this._flags.identify_called = true;
10718
- // Flush any queued up people requests
10719
- this['people']._flush(_set_callback, _add_callback, _append_callback, _set_once_callback, _union_callback, _unset_callback, _remove_callback);
10720
-
10721
- // send an $identify event any time the distinct_id is changing - logic on the server
10722
- // will determine whether or not to do anything with it.
10723
- if (new_distinct_id !== previous_distinct_id) {
10724
- this.track('$identify', {
10725
- 'distinct_id': new_distinct_id,
10726
- '$anon_distinct_id': previous_distinct_id
10727
- }, {skip_hooks: true});
10596
+ MixpanelLib.prototype.get_group = function (group_key, group_id) {
10597
+ var map_key = this._create_map_key(group_key, group_id);
10598
+ var group = this._cached_groups[map_key];
10599
+ if (group === undefined || group._group_key !== group_key || group._group_id !== group_id) {
10600
+ group = new MixpanelGroup();
10601
+ group._init(this, group_key, group_id);
10602
+ this._cached_groups[map_key] = group;
10728
10603
  }
10604
+ return group;
10729
10605
  };
10730
10606
 
10731
10607
  /**
10732
- * Clears super properties and generates a new random distinct_id for this instance.
10733
- * Useful for clearing data when a user logs out.
10608
+ * Track mp_page_view event. This is now ignored by the server.
10609
+ *
10610
+ * @param {String} [page] The url of the page to record. If you don't include this, it defaults to the current url.
10611
+ * @deprecated
10734
10612
  */
10735
- MixpanelLib.prototype.reset = function() {
10736
- this['persistence'].clear();
10737
- this._flags.identify_called = false;
10738
- var uuid = _.UUID();
10739
- this.register_once({
10740
- 'distinct_id': uuid,
10741
- '$device_id': uuid
10742
- }, '');
10613
+ MixpanelLib.prototype.track_pageview = function(page) {
10614
+ if (_.isUndefined(page)) {
10615
+ page = document$1.location.href;
10616
+ }
10617
+ this.track('mp_page_view', _.info.pageviewInfo(page));
10743
10618
  };
10744
10619
 
10745
10620
  /**
10746
- * Returns the current distinct id of the user. This is either the id automatically
10747
- * generated by the library or the id that has been passed by a call to identify().
10621
+ * Track clicks on a set of document elements. Selector must be a
10622
+ * valid query. Elements must exist on the page at the time track_links is called.
10623
+ *
10624
+ * ### Usage:
10625
+ *
10626
+ * // track click for link id #nav
10627
+ * mixpanel.track_links('#nav', 'Clicked Nav Link');
10748
10628
  *
10749
10629
  * ### Notes:
10750
10630
  *
10751
- * get_distinct_id() can only be called after the Mixpanel library has finished loading.
10752
- * init() has a loaded function available to handle this automatically. For example:
10631
+ * This function will wait up to 300 ms for the Mixpanel
10632
+ * servers to respond. If they have not responded by that time
10633
+ * it will head to the link without ensuring that your event
10634
+ * has been tracked. To configure this timeout please see the
10635
+ * set_config() documentation below.
10753
10636
  *
10754
- * // set distinct_id after the mixpanel library has loaded
10755
- * mixpanel.init('YOUR PROJECT TOKEN', {
10756
- * loaded: function(mixpanel) {
10757
- * distinct_id = mixpanel.get_distinct_id();
10758
- * }
10759
- * });
10637
+ * If you pass a function in as the properties argument, the
10638
+ * function will receive the DOMElement that triggered the
10639
+ * event as an argument. You are expected to return an object
10640
+ * from the function; any properties defined on this object
10641
+ * will be sent to mixpanel as event properties.
10642
+ *
10643
+ * @type {Function}
10644
+ * @param {Object|String} query A valid DOM query, element or jQuery-esque list
10645
+ * @param {String} event_name The name of the event to track
10646
+ * @param {Object|Function} [properties] A properties object or function that returns a dictionary of properties when passed a DOMElement
10760
10647
  */
10761
- MixpanelLib.prototype.get_distinct_id = function() {
10762
- return this.get_property('distinct_id');
10648
+ MixpanelLib.prototype.track_links = function() {
10649
+ return this._track_dom.call(this, LinkTracker, arguments);
10763
10650
  };
10764
10651
 
10765
10652
  /**
10766
- * The alias method creates an alias which Mixpanel will use to
10767
- * remap one id to another. Multiple aliases can point to the
10768
- * same identifier.
10653
+ * Track form submissions. Selector must be a valid query.
10769
10654
  *
10770
- * The following is a valid use of alias:
10655
+ * ### Usage:
10771
10656
  *
10772
- * mixpanel.alias('new_id', 'existing_id');
10773
- * // You can add multiple id aliases to the existing ID
10774
- * mixpanel.alias('newer_id', 'existing_id');
10657
+ * // track submission for form id 'register'
10658
+ * mixpanel.track_forms('#register', 'Created Account');
10775
10659
  *
10776
- * Aliases can also be chained - the following is a valid example:
10660
+ * ### Notes:
10777
10661
  *
10778
- * mixpanel.alias('new_id', 'existing_id');
10779
- * // chain newer_id - new_id - existing_id
10780
- * mixpanel.alias('newer_id', 'new_id');
10662
+ * This function will wait up to 300 ms for the mixpanel
10663
+ * servers to respond, if they have not responded by that time
10664
+ * it will head to the link without ensuring that your event
10665
+ * has been tracked. To configure this timeout please see the
10666
+ * set_config() documentation below.
10781
10667
  *
10782
- * Aliases cannot point to multiple identifiers - the following
10783
- * example will not work:
10668
+ * If you pass a function in as the properties argument, the
10669
+ * function will receive the DOMElement that triggered the
10670
+ * event as an argument. You are expected to return an object
10671
+ * from the function; any properties defined on this object
10672
+ * will be sent to mixpanel as event properties.
10784
10673
  *
10785
- * mixpanel.alias('new_id', 'existing_id');
10786
- * // this is invalid as 'new_id' already points to 'existing_id'
10787
- * mixpanel.alias('new_id', 'newer_id');
10674
+ * @type {Function}
10675
+ * @param {Object|String} query A valid DOM query, element or jQuery-esque list
10676
+ * @param {String} event_name The name of the event to track
10677
+ * @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
10678
+ */
10679
+ MixpanelLib.prototype.track_forms = function() {
10680
+ return this._track_dom.call(this, FormTracker, arguments);
10681
+ };
10682
+
10683
+ /**
10684
+ * Time an event by including the time between this call and a
10685
+ * later 'track' call for the same event in the properties sent
10686
+ * with the event.
10788
10687
  *
10789
- * ### Notes:
10688
+ * ### Usage:
10790
10689
  *
10791
- * If your project does not have
10792
- * <a href="https://help.mixpanel.com/hc/en-us/articles/360039133851">ID Merge</a>
10793
- * enabled, the best practice is to call alias once when a unique
10794
- * ID is first created for a user (e.g., when a user first registers
10795
- * for an account). Do not use alias multiple times for a single
10796
- * user without ID Merge enabled.
10690
+ * // time an event named 'Registered'
10691
+ * mixpanel.time_event('Registered');
10692
+ * mixpanel.track('Registered', {'Gender': 'Male', 'Age': 21});
10797
10693
  *
10798
- * @param {String} alias A unique identifier that you want to use for this user in the future.
10799
- * @param {String} [original] The current identifier being used for this user.
10694
+ * When called for a particular event name, the next track call for that event
10695
+ * name will include the elapsed time between the 'time_event' and 'track'
10696
+ * calls. This value is stored as seconds in the '$duration' property.
10697
+ *
10698
+ * @param {String} event_name The name of the event.
10800
10699
  */
10801
- MixpanelLib.prototype.alias = function(alias, original) {
10802
- // If the $people_distinct_id key exists in persistence, there has been a previous
10803
- // mixpanel.people.identify() call made for this user. It is VERY BAD to make an alias with
10804
- // this ID, as it will duplicate users.
10805
- if (alias === this.get_property(PEOPLE_DISTINCT_ID_KEY)) {
10806
- this.report_error('Attempting to create alias for existing People user - aborting.');
10807
- return -2;
10700
+ MixpanelLib.prototype.time_event = function(event_name) {
10701
+ if (_.isUndefined(event_name)) {
10702
+ this.report_error('No event name provided to mixpanel.time_event');
10703
+ return;
10808
10704
  }
10809
10705
 
10810
- var _this = this;
10811
- if (_.isUndefined(original)) {
10812
- original = this.get_distinct_id();
10706
+ if (this._event_is_disabled(event_name)) {
10707
+ return;
10813
10708
  }
10814
- if (alias !== original) {
10815
- this._register_single(ALIAS_ID_KEY, alias);
10816
- return this.track('$create_alias', {
10817
- 'alias': alias,
10818
- 'distinct_id': original
10819
- }, {
10820
- skip_hooks: true
10821
- }, function() {
10822
- // Flush the people queue
10823
- _this.identify(alias);
10824
- });
10709
+
10710
+ this['persistence'].set_event_timer(event_name, new Date().getTime());
10711
+ };
10712
+
10713
+ var REGISTER_DEFAULTS = {
10714
+ 'persistent': true
10715
+ };
10716
+ /**
10717
+ * Helper to parse options param for register methods, maintaining
10718
+ * legacy support for plain "days" param instead of options object
10719
+ * @param {Number|Object} [days_or_options] 'days' option (Number), or Options object for register methods
10720
+ * @returns {Object} options object
10721
+ */
10722
+ var options_for_register = function(days_or_options) {
10723
+ var options;
10724
+ if (_.isObject(days_or_options)) {
10725
+ options = days_or_options;
10726
+ } else if (!_.isUndefined(days_or_options)) {
10727
+ options = {'days': days_or_options};
10825
10728
  } else {
10826
- this.report_error('alias matches current distinct_id - skipping api call.');
10827
- this.identify(alias);
10828
- return -1;
10729
+ options = {};
10829
10730
  }
10731
+ return _.extend({}, REGISTER_DEFAULTS, options);
10830
10732
  };
10831
10733
 
10832
10734
  /**
10833
- * Provide a string to recognize the user by. The string passed to
10834
- * this method will appear in the Mixpanel Streams product rather
10835
- * than an automatically generated name. Name tags do not have to
10836
- * be unique.
10735
+ * Register a set of super properties, which are included with all
10736
+ * events. This will overwrite previous super property values.
10837
10737
  *
10838
- * This value will only be included in Streams data.
10738
+ * ### Usage:
10839
10739
  *
10840
- * @param {String} name_tag A human readable name for the user
10841
- * @deprecated
10740
+ * // register 'Gender' as a super property
10741
+ * mixpanel.register({'Gender': 'Female'});
10742
+ *
10743
+ * // register several super properties when a user signs up
10744
+ * mixpanel.register({
10745
+ * 'Email': 'jdoe@example.com',
10746
+ * 'Account Type': 'Free'
10747
+ * });
10748
+ *
10749
+ * // register only for the current pageload
10750
+ * mixpanel.register({'Name': 'Pat'}, {persistent: false});
10751
+ *
10752
+ * @param {Object} properties An associative array of properties to store about the user
10753
+ * @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)
10754
+ * @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)
10755
+ * @param {boolean} [days_or_options.persistent=true] - whether to put in persistent storage (cookie/localStorage)
10842
10756
  */
10843
- MixpanelLib.prototype.name_tag = function(name_tag) {
10844
- this._register_single('mp_name_tag', name_tag);
10757
+ MixpanelLib.prototype.register = function(props, days_or_options) {
10758
+ var options = options_for_register(days_or_options);
10759
+ if (options['persistent']) {
10760
+ this['persistence'].register(props, options['days']);
10761
+ } else {
10762
+ _.extend(this.unpersisted_superprops, props);
10763
+ }
10845
10764
  };
10846
10765
 
10847
10766
  /**
10848
- * Update the configuration of a mixpanel library instance.
10849
- *
10850
- * The default config is:
10851
- *
10852
- * {
10853
- * // HTTP method for tracking requests
10854
- * api_method: 'POST'
10855
- *
10856
- * // transport for sending requests ('XHR' or 'sendBeacon')
10857
- * // NB: sendBeacon should only be used for scenarios such as
10858
- * // page unload where a "best-effort" attempt to send is
10859
- * // acceptable; the sendBeacon API does not support callbacks
10860
- * // or any way to know the result of the request. Mixpanel
10861
- * // tracking via sendBeacon will not support any event-
10862
- * // batching or retry mechanisms.
10863
- * api_transport: 'XHR'
10864
- *
10865
- * // turn on request-batching/queueing/retry
10866
- * batch_requests: false,
10867
- *
10868
- * // maximum number of events/updates to send in a single
10869
- * // network request
10870
- * batch_size: 50,
10871
- *
10872
- * // milliseconds to wait between sending batch requests
10873
- * batch_flush_interval_ms: 5000,
10874
- *
10875
- * // milliseconds to wait for network responses to batch requests
10876
- * // before they are considered timed-out and retried
10877
- * batch_request_timeout_ms: 90000,
10878
- *
10879
- * // override value for cookie domain, only useful for ensuring
10880
- * // correct cross-subdomain cookies on unusual domains like
10881
- * // subdomain.mainsite.avocat.fr; NB this cannot be used to
10882
- * // set cookies on a different domain than the current origin
10883
- * cookie_domain: ''
10884
- *
10885
- * // super properties cookie expiration (in days)
10886
- * cookie_expiration: 365
10887
- *
10888
- * // if true, cookie will be set with SameSite=None; Secure
10889
- * // this is only useful in special situations, like embedded
10890
- * // 3rd-party iframes that set up a Mixpanel instance
10891
- * cross_site_cookie: false
10892
- *
10893
- * // super properties span subdomains
10894
- * cross_subdomain_cookie: true
10895
- *
10896
- * // debug mode
10897
- * debug: false
10898
- *
10899
- * // if this is true, the mixpanel cookie or localStorage entry
10900
- * // will be deleted, and no user persistence will take place
10901
- * disable_persistence: false
10902
- *
10903
- * // if this is true, Mixpanel will automatically determine
10904
- * // City, Region and Country data using the IP address of
10905
- * //the client
10906
- * ip: true
10907
- *
10908
- * // opt users out of tracking by this Mixpanel instance by default
10909
- * opt_out_tracking_by_default: false
10910
- *
10911
- * // opt users out of browser data storage by this Mixpanel instance by default
10912
- * opt_out_persistence_by_default: false
10913
- *
10914
- * // persistence mechanism used by opt-in/opt-out methods - cookie
10915
- * // or localStorage - falls back to cookie if localStorage is unavailable
10916
- * opt_out_tracking_persistence_type: 'localStorage'
10767
+ * Register a set of super properties only once. This will not
10768
+ * overwrite previous super property values, unlike register().
10917
10769
  *
10918
- * // customize the name of cookie/localStorage set by opt-in/opt-out methods
10919
- * opt_out_tracking_cookie_prefix: null
10770
+ * ### Usage:
10920
10771
  *
10921
- * // type of persistent store for super properties (cookie/
10922
- * // localStorage) if set to 'localStorage', any existing
10923
- * // mixpanel cookie value with the same persistence_name
10924
- * // will be transferred to localStorage and deleted
10925
- * persistence: 'cookie'
10772
+ * // register a super property for the first time only
10773
+ * mixpanel.register_once({
10774
+ * 'First Login Date': new Date().toISOString()
10775
+ * });
10926
10776
  *
10927
- * // name for super properties persistent store
10928
- * persistence_name: ''
10777
+ * // register once, only for the current pageload
10778
+ * mixpanel.register_once({
10779
+ * 'First interaction time': new Date().toISOString()
10780
+ * }, 'None', {persistent: false});
10929
10781
  *
10930
- * // names of properties/superproperties which should never
10931
- * // be sent with track() calls
10932
- * property_blacklist: []
10782
+ * ### Notes:
10933
10783
  *
10934
- * // if this is true, mixpanel cookies will be marked as
10935
- * // secure, meaning they will only be transmitted over https
10936
- * secure_cookie: false
10784
+ * If default_value is specified, current super properties
10785
+ * with that value will be overwritten.
10937
10786
  *
10938
- * // the amount of time track_links will
10939
- * // wait for Mixpanel's servers to respond
10940
- * track_links_timeout: 300
10787
+ * @param {Object} properties An associative array of properties to store about the user
10788
+ * @param {*} [default_value] Value to override if already set in super properties (ex: 'False') Default: 'None'
10789
+ * @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)
10790
+ * @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)
10791
+ * @param {boolean} [days_or_options.persistent=true] - whether to put in persistent storage (cookie/localStorage)
10792
+ */
10793
+ MixpanelLib.prototype.register_once = function(props, default_value, days_or_options) {
10794
+ var options = options_for_register(days_or_options);
10795
+ if (options['persistent']) {
10796
+ this['persistence'].register_once(props, default_value, options['days']);
10797
+ } else {
10798
+ if (typeof(default_value) === 'undefined') {
10799
+ default_value = 'None';
10800
+ }
10801
+ _.each(props, function(val, prop) {
10802
+ if (!this.unpersisted_superprops.hasOwnProperty(prop) || this.unpersisted_superprops[prop] === default_value) {
10803
+ this.unpersisted_superprops[prop] = val;
10804
+ }
10805
+ }, this);
10806
+ }
10807
+ };
10808
+
10809
+ /**
10810
+ * Delete a super property stored with the current user.
10941
10811
  *
10942
- * // if you set upgrade to be true, the library will check for
10943
- * // a cookie from our old js library and import super
10944
- * // properties from it, then the old cookie is deleted
10945
- * // The upgrade config option only works in the initialization,
10946
- * // so make sure you set it when you create the library.
10947
- * upgrade: false
10812
+ * @param {String} property The name of the super property to remove
10813
+ * @param {Object} [options]
10814
+ * @param {boolean} [options.persistent=true] - whether to look in persistent storage (cookie/localStorage)
10815
+ */
10816
+ MixpanelLib.prototype.unregister = function(property, options) {
10817
+ options = options_for_register(options);
10818
+ if (options['persistent']) {
10819
+ this['persistence'].unregister(property);
10820
+ } else {
10821
+ delete this.unpersisted_superprops[property];
10822
+ }
10823
+ };
10824
+
10825
+ MixpanelLib.prototype._register_single = function(prop, value) {
10826
+ var props = {};
10827
+ props[prop] = value;
10828
+ this.register(props);
10829
+ };
10830
+
10831
+ /**
10832
+ * Identify a user with a unique ID to track user activity across
10833
+ * devices, tie a user to their events, and create a user profile.
10834
+ * If you never call this method, unique visitors are tracked using
10835
+ * a UUID generated the first time they visit the site.
10948
10836
  *
10949
- * // extra HTTP request headers to set for each API request, in
10950
- * // the format {'Header-Name': value}
10951
- * xhr_headers: {}
10837
+ * Call identify when you know the identity of the current user,
10838
+ * typically after login or signup. We recommend against using
10839
+ * identify for anonymous visitors to your site.
10952
10840
  *
10953
- * // whether to ignore or respect the web browser's Do Not Track setting
10954
- * ignore_dnt: false
10955
- * }
10841
+ * ### Notes:
10842
+ * If your project has
10843
+ * <a href="https://help.mixpanel.com/hc/en-us/articles/360039133851">ID Merge</a>
10844
+ * enabled, the identify method will connect pre- and
10845
+ * post-authentication events when appropriate.
10956
10846
  *
10847
+ * If your project does not have ID Merge enabled, identify will
10848
+ * change the user's local distinct_id to the unique ID you pass.
10849
+ * Events tracked prior to authentication will not be connected
10850
+ * to the same user identity. If ID Merge is disabled, alias can
10851
+ * be used to connect pre- and post-registration events.
10957
10852
  *
10958
- * @param {Object} config A dictionary of new configuration values to update
10853
+ * @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.
10959
10854
  */
10960
- MixpanelLib.prototype.set_config = function(config) {
10961
- if (_.isObject(config)) {
10962
- _.extend(this['config'], config);
10855
+ MixpanelLib.prototype.identify = function(
10856
+ new_distinct_id, _set_callback, _add_callback, _append_callback, _set_once_callback, _union_callback, _unset_callback, _remove_callback
10857
+ ) {
10858
+ // Optional Parameters
10859
+ // _set_callback:function A callback to be run if and when the People set queue is flushed
10860
+ // _add_callback:function A callback to be run if and when the People add queue is flushed
10861
+ // _append_callback:function A callback to be run if and when the People append queue is flushed
10862
+ // _set_once_callback:function A callback to be run if and when the People set_once queue is flushed
10863
+ // _union_callback:function A callback to be run if and when the People union queue is flushed
10864
+ // _unset_callback:function A callback to be run if and when the People unset queue is flushed
10963
10865
 
10964
- var new_batch_size = config['batch_size'];
10965
- if (new_batch_size) {
10966
- _.each(this.request_batchers, function(batcher) {
10967
- batcher.resetBatchSize();
10968
- });
10969
- }
10866
+ var previous_distinct_id = this.get_distinct_id();
10867
+ this.register({'$user_id': new_distinct_id});
10970
10868
 
10971
- if (!this.get_config('persistence_name')) {
10972
- this['config']['persistence_name'] = this['config']['cookie_name'];
10973
- }
10974
- if (!this.get_config('disable_persistence')) {
10975
- this['config']['disable_persistence'] = this['config']['disable_cookie'];
10976
- }
10869
+ if (!this.get_property('$device_id')) {
10870
+ // The persisted distinct id might not actually be a device id at all
10871
+ // it might be a distinct id of the user from before
10872
+ var device_id = previous_distinct_id;
10873
+ this.register_once({
10874
+ '$had_persisted_distinct_id': true,
10875
+ '$device_id': device_id
10876
+ }, '');
10877
+ }
10977
10878
 
10978
- if (this['persistence']) {
10979
- this['persistence'].update_config(this['config']);
10980
- }
10981
- Config.DEBUG = Config.DEBUG || this.get_config('debug');
10879
+ // identify only changes the distinct id if it doesn't match either the existing or the alias;
10880
+ // if it's new, blow away the alias as well.
10881
+ if (new_distinct_id !== previous_distinct_id && new_distinct_id !== this.get_property(ALIAS_ID_KEY)) {
10882
+ this.unregister(ALIAS_ID_KEY);
10883
+ this.register({'distinct_id': new_distinct_id});
10982
10884
  }
10983
- };
10885
+ this._flags.identify_called = true;
10886
+ // Flush any queued up people requests
10887
+ this['people']._flush(_set_callback, _add_callback, _append_callback, _set_once_callback, _union_callback, _unset_callback, _remove_callback);
10984
10888
 
10985
- /**
10986
- * returns the current config object for the library.
10987
- */
10988
- MixpanelLib.prototype.get_config = function(prop_name) {
10989
- return this['config'][prop_name];
10889
+ // send an $identify event any time the distinct_id is changing - logic on the server
10890
+ // will determine whether or not to do anything with it.
10891
+ if (new_distinct_id !== previous_distinct_id) {
10892
+ this.track('$identify', {
10893
+ 'distinct_id': new_distinct_id,
10894
+ '$anon_distinct_id': previous_distinct_id
10895
+ }, {skip_hooks: true});
10896
+ }
10990
10897
  };
10991
10898
 
10992
10899
  /**
10993
- * Fetch a hook function from config, with safe default, and run it
10994
- * against the given arguments
10995
- * @param {string} hook_name which hook to retrieve
10996
- * @returns {any|null} return value of user-provided hook, or null if nothing was returned
10900
+ * Clears super properties and generates a new random distinct_id for this instance.
10901
+ * Useful for clearing data when a user logs out.
10997
10902
  */
10998
- MixpanelLib.prototype._run_hook = function(hook_name) {
10999
- var ret = (this['config']['hooks'][hook_name] || IDENTITY_FUNC).apply(this, slice.call(arguments, 1));
11000
- if (typeof ret === 'undefined') {
11001
- this.report_error(hook_name + ' hook did not return a value');
11002
- ret = null;
11003
- }
11004
- return ret;
10903
+ MixpanelLib.prototype.reset = function() {
10904
+ this['persistence'].clear();
10905
+ this._flags.identify_called = false;
10906
+ var uuid = _.UUID();
10907
+ this.register_once({
10908
+ 'distinct_id': uuid,
10909
+ '$device_id': uuid
10910
+ }, '');
11005
10911
  };
11006
10912
 
11007
10913
  /**
11008
- * Returns the value of the super property named property_name. If no such
11009
- * property is set, get_property() will return the undefined value.
10914
+ * Returns the current distinct id of the user. This is either the id automatically
10915
+ * generated by the library or the id that has been passed by a call to identify().
11010
10916
  *
11011
10917
  * ### Notes:
11012
10918
  *
11013
- * get_property() can only be called after the Mixpanel library has finished loading.
10919
+ * get_distinct_id() can only be called after the Mixpanel library has finished loading.
11014
10920
  * init() has a loaded function available to handle this automatically. For example:
11015
10921
  *
11016
- * // grab value for 'user_id' after the mixpanel library has loaded
10922
+ * // set distinct_id after the mixpanel library has loaded
11017
10923
  * mixpanel.init('YOUR PROJECT TOKEN', {
11018
10924
  * loaded: function(mixpanel) {
11019
- * user_id = mixpanel.get_property('user_id');
10925
+ * distinct_id = mixpanel.get_distinct_id();
11020
10926
  * }
11021
10927
  * });
11022
- *
11023
- * @param {String} property_name The name of the super property you want to retrieve
11024
- */
11025
- MixpanelLib.prototype.get_property = function(property_name) {
11026
- return this['persistence']['props'][property_name];
11027
- };
11028
-
11029
- MixpanelLib.prototype.toString = function() {
11030
- var name = this.get_config('name');
11031
- if (name !== PRIMARY_INSTANCE_NAME) {
11032
- name = PRIMARY_INSTANCE_NAME + '.' + name;
11033
- }
11034
- return name;
11035
- };
11036
-
11037
- MixpanelLib.prototype._event_is_disabled = function(event_name) {
11038
- return _.isBlockedUA(userAgent) ||
11039
- this._flags.disable_all_events ||
11040
- _.include(this.__disabled_events, event_name);
11041
- };
11042
-
11043
- // perform some housekeeping around GDPR opt-in/out state
11044
- MixpanelLib.prototype._gdpr_init = function() {
11045
- var is_localStorage_requested = this.get_config('opt_out_tracking_persistence_type') === 'localStorage';
11046
-
11047
- // try to convert opt-in/out cookies to localStorage if possible
11048
- if (is_localStorage_requested && _.localStorage.is_supported()) {
11049
- if (!this.has_opted_in_tracking() && this.has_opted_in_tracking({'persistence_type': 'cookie'})) {
11050
- this.opt_in_tracking({'enable_persistence': false});
11051
- }
11052
- if (!this.has_opted_out_tracking() && this.has_opted_out_tracking({'persistence_type': 'cookie'})) {
11053
- this.opt_out_tracking({'clear_persistence': false});
11054
- }
11055
- this.clear_opt_in_out_tracking({
11056
- 'persistence_type': 'cookie',
11057
- 'enable_persistence': false
11058
- });
11059
- }
11060
-
11061
- // check whether the user has already opted out - if so, clear & disable persistence
11062
- if (this.has_opted_out_tracking()) {
11063
- this._gdpr_update_persistence({'clear_persistence': true});
11064
-
11065
- // check whether we should opt out by default
11066
- // note: we don't clear persistence here by default since opt-out default state is often
11067
- // used as an initial state while GDPR information is being collected
11068
- } else if (!this.has_opted_in_tracking() && (
11069
- this.get_config('opt_out_tracking_by_default') || _.cookie.get('mp_optout')
11070
- )) {
11071
- _.cookie.remove('mp_optout');
11072
- this.opt_out_tracking({
11073
- 'clear_persistence': this.get_config('opt_out_persistence_by_default')
11074
- });
11075
- }
11076
- };
11077
-
11078
- /**
11079
- * Enable or disable persistence based on options
11080
- * only enable/disable if persistence is not already in this state
11081
- * @param {boolean} [options.clear_persistence] If true, will delete all data stored by the sdk in persistence and disable it
11082
- * @param {boolean} [options.enable_persistence] If true, will re-enable sdk persistence
11083
10928
  */
11084
- MixpanelLib.prototype._gdpr_update_persistence = function(options) {
11085
- var disabled;
11086
- if (options && options['clear_persistence']) {
11087
- disabled = true;
11088
- } else if (options && options['enable_persistence']) {
11089
- disabled = false;
11090
- } else {
11091
- return;
11092
- }
11093
-
11094
- if (!this.get_config('disable_persistence') && this['persistence'].disabled !== disabled) {
11095
- this['persistence'].set_disabled(disabled);
11096
- }
11097
-
11098
- if (disabled) {
11099
- _.each(this.request_batchers, function(batcher) {
11100
- batcher.clear();
11101
- });
11102
- }
11103
- };
11104
-
11105
- // call a base gdpr function after constructing the appropriate token and options args
11106
- MixpanelLib.prototype._gdpr_call_func = function(func, options) {
11107
- options = _.extend({
11108
- 'track': _.bind(this.track, this),
11109
- 'persistence_type': this.get_config('opt_out_tracking_persistence_type'),
11110
- 'cookie_prefix': this.get_config('opt_out_tracking_cookie_prefix'),
11111
- 'cookie_expiration': this.get_config('cookie_expiration'),
11112
- 'cross_site_cookie': this.get_config('cross_site_cookie'),
11113
- 'cross_subdomain_cookie': this.get_config('cross_subdomain_cookie'),
11114
- 'cookie_domain': this.get_config('cookie_domain'),
11115
- 'secure_cookie': this.get_config('secure_cookie'),
11116
- 'ignore_dnt': this.get_config('ignore_dnt')
11117
- }, options);
11118
-
11119
- // check if localStorage can be used for recording opt out status, fall back to cookie if not
11120
- if (!_.localStorage.is_supported()) {
11121
- options['persistence_type'] = 'cookie';
11122
- }
11123
-
11124
- return func(this.get_config('token'), {
11125
- track: options['track'],
11126
- trackEventName: options['track_event_name'],
11127
- trackProperties: options['track_properties'],
11128
- persistenceType: options['persistence_type'],
11129
- persistencePrefix: options['cookie_prefix'],
11130
- cookieDomain: options['cookie_domain'],
11131
- cookieExpiration: options['cookie_expiration'],
11132
- crossSiteCookie: options['cross_site_cookie'],
11133
- crossSubdomainCookie: options['cross_subdomain_cookie'],
11134
- secureCookie: options['secure_cookie'],
11135
- ignoreDnt: options['ignore_dnt']
11136
- });
10929
+ MixpanelLib.prototype.get_distinct_id = function() {
10930
+ return this.get_property('distinct_id');
11137
10931
  };
11138
10932
 
11139
10933
  /**
11140
- * Opt the user in to data tracking and cookies/localstorage for this Mixpanel instance
10934
+ * The alias method creates an alias which Mixpanel will use to
10935
+ * remap one id to another. Multiple aliases can point to the
10936
+ * same identifier.
11141
10937
  *
11142
- * ### Usage
10938
+ * The following is a valid use of alias:
11143
10939
  *
11144
- * // opt user in
11145
- * mixpanel.opt_in_tracking();
10940
+ * mixpanel.alias('new_id', 'existing_id');
10941
+ * // You can add multiple id aliases to the existing ID
10942
+ * mixpanel.alias('newer_id', 'existing_id');
11146
10943
  *
11147
- * // opt user in with specific event name, properties, cookie configuration
11148
- * mixpanel.opt_in_tracking({
11149
- * track_event_name: 'User opted in',
11150
- * track_event_properties: {
11151
- * 'Email': 'jdoe@example.com'
11152
- * },
11153
- * cookie_expiration: 30,
11154
- * secure_cookie: true
11155
- * });
10944
+ * Aliases can also be chained - the following is a valid example:
11156
10945
  *
11157
- * @param {Object} [options] A dictionary of config options to override
11158
- * @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)
11159
- * @param {string} [options.track_event_name=$opt_in] Event name to be used for tracking the opt-in action
11160
- * @param {Object} [options.track_properties] Set of properties to be tracked along with the opt-in action
11161
- * @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence
11162
- * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11163
- * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11164
- * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
11165
- * @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
11166
- * @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)
11167
- * @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)
11168
- * @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)
11169
- */
11170
- MixpanelLib.prototype.opt_in_tracking = function(options) {
11171
- options = _.extend({
11172
- 'enable_persistence': true
11173
- }, options);
11174
-
11175
- this._gdpr_call_func(optIn, options);
11176
- this._gdpr_update_persistence(options);
11177
- };
11178
-
11179
- /**
11180
- * Opt the user out of data tracking and cookies/localstorage for this Mixpanel instance
10946
+ * mixpanel.alias('new_id', 'existing_id');
10947
+ * // chain newer_id - new_id - existing_id
10948
+ * mixpanel.alias('newer_id', 'new_id');
11181
10949
  *
11182
- * ### Usage
10950
+ * Aliases cannot point to multiple identifiers - the following
10951
+ * example will not work:
11183
10952
  *
11184
- * // opt user out
11185
- * mixpanel.opt_out_tracking();
10953
+ * mixpanel.alias('new_id', 'existing_id');
10954
+ * // this is invalid as 'new_id' already points to 'existing_id'
10955
+ * mixpanel.alias('new_id', 'newer_id');
11186
10956
  *
11187
- * // opt user out with different cookie configuration from Mixpanel instance
11188
- * mixpanel.opt_out_tracking({
11189
- * cookie_expiration: 30,
11190
- * secure_cookie: true
11191
- * });
10957
+ * ### Notes:
11192
10958
  *
11193
- * @param {Object} [options] A dictionary of config options to override
11194
- * @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
11195
- * @param {boolean} [options.clear_persistence=true] If true, will delete all data stored by the sdk in persistence
11196
- * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11197
- * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11198
- * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
11199
- * @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
11200
- * @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)
11201
- * @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)
11202
- * @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)
10959
+ * If your project does not have
10960
+ * <a href="https://help.mixpanel.com/hc/en-us/articles/360039133851">ID Merge</a>
10961
+ * enabled, the best practice is to call alias once when a unique
10962
+ * ID is first created for a user (e.g., when a user first registers
10963
+ * for an account). Do not use alias multiple times for a single
10964
+ * user without ID Merge enabled.
10965
+ *
10966
+ * @param {String} alias A unique identifier that you want to use for this user in the future.
10967
+ * @param {String} [original] The current identifier being used for this user.
11203
10968
  */
11204
- MixpanelLib.prototype.opt_out_tracking = function(options) {
11205
- options = _.extend({
11206
- 'clear_persistence': true,
11207
- 'delete_user': true
11208
- }, options);
11209
-
11210
- // delete user and clear charges since these methods may be disabled by opt-out
11211
- if (options['delete_user'] && this['people'] && this['people']._identify_called()) {
11212
- this['people'].delete_user();
11213
- this['people'].clear_charges();
10969
+ MixpanelLib.prototype.alias = function(alias, original) {
10970
+ // If the $people_distinct_id key exists in persistence, there has been a previous
10971
+ // mixpanel.people.identify() call made for this user. It is VERY BAD to make an alias with
10972
+ // this ID, as it will duplicate users.
10973
+ if (alias === this.get_property(PEOPLE_DISTINCT_ID_KEY)) {
10974
+ this.report_error('Attempting to create alias for existing People user - aborting.');
10975
+ return -2;
11214
10976
  }
11215
10977
 
11216
- this._gdpr_call_func(optOut, options);
11217
- this._gdpr_update_persistence(options);
10978
+ var _this = this;
10979
+ if (_.isUndefined(original)) {
10980
+ original = this.get_distinct_id();
10981
+ }
10982
+ if (alias !== original) {
10983
+ this._register_single(ALIAS_ID_KEY, alias);
10984
+ return this.track('$create_alias', {
10985
+ 'alias': alias,
10986
+ 'distinct_id': original
10987
+ }, {
10988
+ skip_hooks: true
10989
+ }, function() {
10990
+ // Flush the people queue
10991
+ _this.identify(alias);
10992
+ });
10993
+ } else {
10994
+ this.report_error('alias matches current distinct_id - skipping api call.');
10995
+ this.identify(alias);
10996
+ return -1;
10997
+ }
11218
10998
  };
11219
10999
 
11220
11000
  /**
11221
- * Check whether the user has opted in to data tracking and cookies/localstorage for this Mixpanel instance
11222
- *
11223
- * ### Usage
11001
+ * Provide a string to recognize the user by. The string passed to
11002
+ * this method will appear in the Mixpanel Streams product rather
11003
+ * than an automatically generated name. Name tags do not have to
11004
+ * be unique.
11224
11005
  *
11225
- * var has_opted_in = mixpanel.has_opted_in_tracking();
11226
- * // use has_opted_in value
11006
+ * This value will only be included in Streams data.
11227
11007
  *
11228
- * @param {Object} [options] A dictionary of config options to override
11229
- * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11230
- * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11231
- * @returns {boolean} current opt-in status
11008
+ * @param {String} name_tag A human readable name for the user
11009
+ * @deprecated
11232
11010
  */
11233
- MixpanelLib.prototype.has_opted_in_tracking = function(options) {
11234
- return this._gdpr_call_func(hasOptedIn, options);
11011
+ MixpanelLib.prototype.name_tag = function(name_tag) {
11012
+ this._register_single('mp_name_tag', name_tag);
11235
11013
  };
11236
11014
 
11237
11015
  /**
11238
- * Check whether the user has opted out of data tracking and cookies/localstorage for this Mixpanel instance
11016
+ * Update the configuration of a mixpanel library instance.
11239
11017
  *
11240
- * ### Usage
11018
+ * The default config is:
11241
11019
  *
11242
- * var has_opted_out = mixpanel.has_opted_out_tracking();
11243
- * // use has_opted_out value
11020
+ * {
11021
+ * // HTTP method for tracking requests
11022
+ * api_method: 'POST'
11244
11023
  *
11245
- * @param {Object} [options] A dictionary of config options to override
11246
- * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11247
- * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11248
- * @returns {boolean} current opt-out status
11249
- */
11250
- MixpanelLib.prototype.has_opted_out_tracking = function(options) {
11251
- return this._gdpr_call_func(hasOptedOut, options);
11252
- };
11253
-
11254
- /**
11255
- * Clear the user's opt in/out status of data tracking and cookies/localstorage for this Mixpanel instance
11024
+ * // transport for sending requests ('XHR' or 'sendBeacon')
11025
+ * // NB: sendBeacon should only be used for scenarios such as
11026
+ * // page unload where a "best-effort" attempt to send is
11027
+ * // acceptable; the sendBeacon API does not support callbacks
11028
+ * // or any way to know the result of the request. Mixpanel
11029
+ * // tracking via sendBeacon will not support any event-
11030
+ * // batching or retry mechanisms.
11031
+ * api_transport: 'XHR'
11256
11032
  *
11257
- * ### Usage
11033
+ * // turn on request-batching/queueing/retry
11034
+ * batch_requests: false,
11258
11035
  *
11259
- * // clear user's opt-in/out status
11260
- * mixpanel.clear_opt_in_out_tracking();
11036
+ * // maximum number of events/updates to send in a single
11037
+ * // network request
11038
+ * batch_size: 50,
11261
11039
  *
11262
- * // clear user's opt-in/out status with specific cookie configuration - should match
11263
- * // configuration used when opt_in_tracking/opt_out_tracking methods were called.
11264
- * mixpanel.clear_opt_in_out_tracking({
11265
- * cookie_expiration: 30,
11266
- * secure_cookie: true
11267
- * });
11040
+ * // milliseconds to wait between sending batch requests
11041
+ * batch_flush_interval_ms: 5000,
11268
11042
  *
11269
- * @param {Object} [options] A dictionary of config options to override
11270
- * @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence
11271
- * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11272
- * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11273
- * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
11274
- * @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
11275
- * @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)
11276
- * @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)
11277
- * @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)
11278
- */
11279
- MixpanelLib.prototype.clear_opt_in_out_tracking = function(options) {
11280
- options = _.extend({
11281
- 'enable_persistence': true
11282
- }, options);
11283
-
11284
- this._gdpr_call_func(clearOptInOut, options);
11285
- this._gdpr_update_persistence(options);
11286
- };
11287
-
11288
- MixpanelLib.prototype.report_error = function(msg, err) {
11289
- console$1.error.apply(console$1.error, arguments);
11290
- try {
11291
- if (!err && !(msg instanceof Error)) {
11292
- msg = new Error(msg);
11293
- }
11294
- this.get_config('error_reporter')(msg, err);
11295
- } catch(err) {
11296
- console$1.error(err);
11297
- }
11298
- };
11299
-
11300
- // EXPORTS (for closure compiler)
11301
-
11302
- // MixpanelLib Exports
11303
- MixpanelLib.prototype['init'] = MixpanelLib.prototype.init;
11304
- MixpanelLib.prototype['reset'] = MixpanelLib.prototype.reset;
11305
- MixpanelLib.prototype['disable'] = MixpanelLib.prototype.disable;
11306
- MixpanelLib.prototype['time_event'] = MixpanelLib.prototype.time_event;
11307
- MixpanelLib.prototype['track'] = MixpanelLib.prototype.track;
11308
- MixpanelLib.prototype['track_links'] = MixpanelLib.prototype.track_links;
11309
- MixpanelLib.prototype['track_forms'] = MixpanelLib.prototype.track_forms;
11310
- MixpanelLib.prototype['track_pageview'] = MixpanelLib.prototype.track_pageview;
11311
- MixpanelLib.prototype['register'] = MixpanelLib.prototype.register;
11312
- MixpanelLib.prototype['register_once'] = MixpanelLib.prototype.register_once;
11313
- MixpanelLib.prototype['unregister'] = MixpanelLib.prototype.unregister;
11314
- MixpanelLib.prototype['identify'] = MixpanelLib.prototype.identify;
11315
- MixpanelLib.prototype['alias'] = MixpanelLib.prototype.alias;
11316
- MixpanelLib.prototype['name_tag'] = MixpanelLib.prototype.name_tag;
11317
- MixpanelLib.prototype['set_config'] = MixpanelLib.prototype.set_config;
11318
- MixpanelLib.prototype['get_config'] = MixpanelLib.prototype.get_config;
11319
- MixpanelLib.prototype['get_property'] = MixpanelLib.prototype.get_property;
11320
- MixpanelLib.prototype['get_distinct_id'] = MixpanelLib.prototype.get_distinct_id;
11321
- MixpanelLib.prototype['toString'] = MixpanelLib.prototype.toString;
11322
- MixpanelLib.prototype['opt_out_tracking'] = MixpanelLib.prototype.opt_out_tracking;
11323
- MixpanelLib.prototype['opt_in_tracking'] = MixpanelLib.prototype.opt_in_tracking;
11324
- MixpanelLib.prototype['has_opted_out_tracking'] = MixpanelLib.prototype.has_opted_out_tracking;
11325
- MixpanelLib.prototype['has_opted_in_tracking'] = MixpanelLib.prototype.has_opted_in_tracking;
11326
- MixpanelLib.prototype['clear_opt_in_out_tracking'] = MixpanelLib.prototype.clear_opt_in_out_tracking;
11327
- MixpanelLib.prototype['get_group'] = MixpanelLib.prototype.get_group;
11328
- MixpanelLib.prototype['set_group'] = MixpanelLib.prototype.set_group;
11329
- MixpanelLib.prototype['add_group'] = MixpanelLib.prototype.add_group;
11330
- MixpanelLib.prototype['remove_group'] = MixpanelLib.prototype.remove_group;
11331
- MixpanelLib.prototype['track_with_groups'] = MixpanelLib.prototype.track_with_groups;
11332
- MixpanelLib.prototype['start_batch_senders'] = MixpanelLib.prototype.start_batch_senders;
11333
- MixpanelLib.prototype['stop_batch_senders'] = MixpanelLib.prototype.stop_batch_senders;
11334
-
11335
- // MixpanelPersistence Exports
11336
- MixpanelPersistence.prototype['properties'] = MixpanelPersistence.prototype.properties;
11337
- MixpanelPersistence.prototype['update_search_keyword'] = MixpanelPersistence.prototype.update_search_keyword;
11338
- MixpanelPersistence.prototype['update_referrer_info'] = MixpanelPersistence.prototype.update_referrer_info;
11339
- MixpanelPersistence.prototype['get_cross_subdomain'] = MixpanelPersistence.prototype.get_cross_subdomain;
11340
- MixpanelPersistence.prototype['clear'] = MixpanelPersistence.prototype.clear;
11341
-
11342
-
11343
- var instances = {};
11344
- var extend_mp = function() {
11345
- // add all the sub mixpanel instances
11346
- _.each(instances, function(instance, name) {
11347
- if (name !== PRIMARY_INSTANCE_NAME) { mixpanel_master[name] = instance; }
11348
- });
11349
-
11350
- // add private functions as _
11351
- mixpanel_master['_'] = _;
11352
- };
11353
-
11354
- var override_mp_init_func = function() {
11355
- // we override the snippets init function to handle the case where a
11356
- // user initializes the mixpanel library after the script loads & runs
11357
- mixpanel_master['init'] = function(token, config, name) {
11358
- if (name) {
11359
- // initialize a sub library
11360
- if (!mixpanel_master[name]) {
11361
- mixpanel_master[name] = instances[name] = create_mplib(token, config, name);
11362
- mixpanel_master[name]._loaded();
11363
- }
11364
- return mixpanel_master[name];
11365
- } else {
11366
- var instance = mixpanel_master;
11367
-
11368
- if (instances[PRIMARY_INSTANCE_NAME]) {
11369
- // main mixpanel lib already initialized
11370
- instance = instances[PRIMARY_INSTANCE_NAME];
11371
- } else if (token) {
11372
- // intialize the main mixpanel lib
11373
- instance = create_mplib(token, config, PRIMARY_INSTANCE_NAME);
11374
- instance._loaded();
11375
- instances[PRIMARY_INSTANCE_NAME] = instance;
11376
- }
11377
-
11378
- mixpanel_master = instance;
11379
- if (init_type === INIT_SNIPPET) {
11380
- window$1[PRIMARY_INSTANCE_NAME] = mixpanel_master;
11381
- }
11382
- extend_mp();
11383
- }
11384
- };
11385
- };
11386
-
11387
- var add_dom_loaded_handler = function() {
11388
- // Cross browser DOM Loaded support
11389
- function dom_loaded_handler() {
11390
- // function flag since we only want to execute this once
11391
- if (dom_loaded_handler.done) { return; }
11392
- dom_loaded_handler.done = true;
11393
-
11394
- DOM_LOADED = true;
11395
- ENQUEUE_REQUESTS = false;
11396
-
11397
- _.each(instances, function(inst) {
11398
- inst._dom_loaded();
11399
- });
11400
- }
11043
+ * // milliseconds to wait for network responses to batch requests
11044
+ * // before they are considered timed-out and retried
11045
+ * batch_request_timeout_ms: 90000,
11046
+ *
11047
+ * // override value for cookie domain, only useful for ensuring
11048
+ * // correct cross-subdomain cookies on unusual domains like
11049
+ * // subdomain.mainsite.avocat.fr; NB this cannot be used to
11050
+ * // set cookies on a different domain than the current origin
11051
+ * cookie_domain: ''
11052
+ *
11053
+ * // super properties cookie expiration (in days)
11054
+ * cookie_expiration: 365
11055
+ *
11056
+ * // if true, cookie will be set with SameSite=None; Secure
11057
+ * // this is only useful in special situations, like embedded
11058
+ * // 3rd-party iframes that set up a Mixpanel instance
11059
+ * cross_site_cookie: false
11060
+ *
11061
+ * // super properties span subdomains
11062
+ * cross_subdomain_cookie: true
11063
+ *
11064
+ * // debug mode
11065
+ * debug: false
11066
+ *
11067
+ * // if this is true, the mixpanel cookie or localStorage entry
11068
+ * // will be deleted, and no user persistence will take place
11069
+ * disable_persistence: false
11070
+ *
11071
+ * // if this is true, Mixpanel will automatically determine
11072
+ * // City, Region and Country data using the IP address of
11073
+ * //the client
11074
+ * ip: true
11075
+ *
11076
+ * // opt users out of tracking by this Mixpanel instance by default
11077
+ * opt_out_tracking_by_default: false
11078
+ *
11079
+ * // opt users out of browser data storage by this Mixpanel instance by default
11080
+ * opt_out_persistence_by_default: false
11081
+ *
11082
+ * // persistence mechanism used by opt-in/opt-out methods - cookie
11083
+ * // or localStorage - falls back to cookie if localStorage is unavailable
11084
+ * opt_out_tracking_persistence_type: 'localStorage'
11085
+ *
11086
+ * // customize the name of cookie/localStorage set by opt-in/opt-out methods
11087
+ * opt_out_tracking_cookie_prefix: null
11088
+ *
11089
+ * // type of persistent store for super properties (cookie/
11090
+ * // localStorage) if set to 'localStorage', any existing
11091
+ * // mixpanel cookie value with the same persistence_name
11092
+ * // will be transferred to localStorage and deleted
11093
+ * persistence: 'cookie'
11094
+ *
11095
+ * // name for super properties persistent store
11096
+ * persistence_name: ''
11097
+ *
11098
+ * // names of properties/superproperties which should never
11099
+ * // be sent with track() calls
11100
+ * property_blacklist: []
11101
+ *
11102
+ * // if this is true, mixpanel cookies will be marked as
11103
+ * // secure, meaning they will only be transmitted over https
11104
+ * secure_cookie: false
11105
+ *
11106
+ * // the amount of time track_links will
11107
+ * // wait for Mixpanel's servers to respond
11108
+ * track_links_timeout: 300
11109
+ *
11110
+ * // if you set upgrade to be true, the library will check for
11111
+ * // a cookie from our old js library and import super
11112
+ * // properties from it, then the old cookie is deleted
11113
+ * // The upgrade config option only works in the initialization,
11114
+ * // so make sure you set it when you create the library.
11115
+ * upgrade: false
11116
+ *
11117
+ * // extra HTTP request headers to set for each API request, in
11118
+ * // the format {'Header-Name': value}
11119
+ * xhr_headers: {}
11120
+ *
11121
+ * // whether to ignore or respect the web browser's Do Not Track setting
11122
+ * ignore_dnt: false
11123
+ * }
11124
+ *
11125
+ *
11126
+ * @param {Object} config A dictionary of new configuration values to update
11127
+ */
11128
+ MixpanelLib.prototype.set_config = function(config) {
11129
+ if (_.isObject(config)) {
11130
+ _.extend(this['config'], config);
11401
11131
 
11402
- function do_scroll_check() {
11403
- try {
11404
- document$1.documentElement.doScroll('left');
11405
- } catch(e) {
11406
- setTimeout(do_scroll_check, 1);
11407
- return;
11132
+ var new_batch_size = config['batch_size'];
11133
+ if (new_batch_size) {
11134
+ _.each(this.request_batchers, function(batcher) {
11135
+ batcher.resetBatchSize();
11136
+ });
11408
11137
  }
11409
11138
 
11410
- dom_loaded_handler();
11411
- }
11412
-
11413
- if (document$1.addEventListener) {
11414
- if (document$1.readyState === 'complete') {
11415
- // safari 4 can fire the DOMContentLoaded event before loading all
11416
- // external JS (including this file). you will see some copypasta
11417
- // on the internet that checks for 'complete' and 'loaded', but
11418
- // 'loaded' is an IE thing
11419
- dom_loaded_handler();
11420
- } else {
11421
- document$1.addEventListener('DOMContentLoaded', dom_loaded_handler, false);
11139
+ if (!this.get_config('persistence_name')) {
11140
+ this['config']['persistence_name'] = this['config']['cookie_name'];
11422
11141
  }
11423
- } else if (document$1.attachEvent) {
11424
- // IE
11425
- document$1.attachEvent('onreadystatechange', dom_loaded_handler);
11426
-
11427
- // check to make sure we arn't in a frame
11428
- var toplevel = false;
11429
- try {
11430
- toplevel = window$1.frameElement === null;
11431
- } catch(e) {
11432
- // noop
11142
+ if (!this.get_config('disable_persistence')) {
11143
+ this['config']['disable_persistence'] = this['config']['disable_cookie'];
11433
11144
  }
11434
11145
 
11435
- if (document$1.documentElement.doScroll && toplevel) {
11436
- do_scroll_check();
11146
+ if (this['persistence']) {
11147
+ this['persistence'].update_config(this['config']);
11437
11148
  }
11149
+ Config.DEBUG = Config.DEBUG || this.get_config('debug');
11438
11150
  }
11439
-
11440
- // fallback handler, always will work
11441
- _.register_event(window$1, 'load', dom_loaded_handler, true);
11442
11151
  };
11443
11152
 
11444
- function init_as_module() {
11445
- init_type = INIT_MODULE;
11446
- mixpanel_master = new MixpanelLib();
11447
-
11448
- override_mp_init_func();
11449
- mixpanel_master['init']();
11450
- add_dom_loaded_handler();
11451
-
11452
- return mixpanel_master;
11453
- }
11454
-
11455
- var mixpanel = init_as_module();
11456
-
11457
- var mixpanel_cjs = mixpanel;
11458
-
11459
- var mixpanel$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), mixpanel_cjs, {
11460
- 'default': mixpanel_cjs
11461
- }));
11462
-
11463
- // Needed to avoid error in CJS builds on some bundlers.
11464
- const mixpanelLib = mixpanel_cjs || mixpanel$1;
11465
- let mixpanelInstance;
11466
- const MIXPANEL_EVENT = {
11467
- VISUAL_SDK_RENDER_START: 'visual-sdk-render-start',
11468
- VISUAL_SDK_CALLED_INIT: 'visual-sdk-called-init',
11469
- VISUAL_SDK_RENDER_COMPLETE: 'visual-sdk-render-complete',
11470
- VISUAL_SDK_RENDER_FAILED: 'visual-sdk-render-failed',
11471
- VISUAL_SDK_TRIGGER: 'visual-sdk-trigger',
11472
- VISUAL_SDK_ON: 'visual-sdk-on',
11473
- VISUAL_SDK_IFRAME_LOAD_PERFORMANCE: 'visual-sdk-iframe-load-performance',
11474
- VISUAL_SDK_EMBED_CREATE: 'visual-sdk-embed-create',
11475
- };
11476
- let isMixpanelInitialized = false;
11477
- let eventQueue = [];
11478
- /**
11479
- * Pushes the event with its Property key-value map to mixpanel.
11480
- *
11481
- * @param eventId
11482
- * @param eventProps
11483
- */
11484
- function uploadMixpanelEvent(eventId, eventProps = {}) {
11485
- if (!isMixpanelInitialized) {
11486
- eventQueue.push({ eventId, eventProps });
11487
- return;
11488
- }
11489
- mixpanelInstance.track(eventId, eventProps);
11490
- }
11491
- /**
11492
- *
11493
- */
11494
- function emptyQueue() {
11495
- if (!isMixpanelInitialized) {
11496
- return;
11497
- }
11498
- eventQueue.forEach((event) => {
11499
- uploadMixpanelEvent(event.eventId, event.eventProps);
11500
- });
11501
- eventQueue = [];
11502
- }
11503
- /**
11504
- *
11505
- * @param sessionInfo
11506
- */
11507
- function initMixpanel(sessionInfo) {
11508
- var _a;
11509
- if (!sessionInfo || !sessionInfo.mixpanelToken) {
11510
- return;
11511
- }
11512
- // On a public cluster the user is anonymous, so don't set the identify to
11513
- // userGUID
11514
- const isPublicCluster = !!sessionInfo.isPublicUser;
11515
- const token = sessionInfo.mixpanelToken;
11516
- try {
11517
- if (token) {
11518
- mixpanelInstance = mixpanelLib.init(token, undefined, 'tsEmbed');
11519
- if (!isPublicCluster) {
11520
- mixpanelInstance.identify(sessionInfo.userGUID);
11521
- }
11522
- mixpanelInstance.register_once({
11523
- clusterId: sessionInfo.clusterId,
11524
- clusterName: sessionInfo.clusterName,
11525
- releaseVersion: sessionInfo.releaseVersion,
11526
- hostAppUrl: ((_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.host) || '',
11527
- });
11528
- isMixpanelInitialized = true;
11529
- emptyQueue();
11530
- }
11531
- }
11532
- catch (e) {
11533
- console.error('Error initializing mixpanel', e);
11534
- }
11535
- }
11536
-
11537
- var eventemitter3 = createCommonjsModule(function (module) {
11538
-
11539
- var has = Object.prototype.hasOwnProperty
11540
- , prefix = '~';
11541
-
11542
11153
  /**
11543
- * Constructor to create a storage for our `EE` objects.
11544
- * An `Events` instance is a plain object whose properties are event names.
11545
- *
11546
- * @constructor
11547
- * @private
11154
+ * returns the current config object for the library.
11548
11155
  */
11549
- function Events() {}
11550
-
11551
- //
11552
- // We try to not inherit from `Object.prototype`. In some engines creating an
11553
- // instance in this way is faster than calling `Object.create(null)` directly.
11554
- // If `Object.create(null)` is not supported we prefix the event names with a
11555
- // character to make sure that the built-in object properties are not
11556
- // overridden or used as an attack vector.
11557
- //
11558
- if (Object.create) {
11559
- Events.prototype = Object.create(null);
11560
-
11561
- //
11562
- // This hack is needed because the `__proto__` property is still inherited in
11563
- // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.
11564
- //
11565
- if (!new Events().__proto__) prefix = false;
11566
- }
11156
+ MixpanelLib.prototype.get_config = function(prop_name) {
11157
+ return this['config'][prop_name];
11158
+ };
11567
11159
 
11568
11160
  /**
11569
- * Representation of a single event listener.
11570
- *
11571
- * @param {Function} fn The listener function.
11572
- * @param {*} context The context to invoke the listener with.
11573
- * @param {Boolean} [once=false] Specify if the listener is a one-time listener.
11574
- * @constructor
11575
- * @private
11161
+ * Fetch a hook function from config, with safe default, and run it
11162
+ * against the given arguments
11163
+ * @param {string} hook_name which hook to retrieve
11164
+ * @returns {any|null} return value of user-provided hook, or null if nothing was returned
11576
11165
  */
11577
- function EE(fn, context, once) {
11578
- this.fn = fn;
11579
- this.context = context;
11580
- this.once = once || false;
11581
- }
11166
+ MixpanelLib.prototype._run_hook = function(hook_name) {
11167
+ var ret = (this['config']['hooks'][hook_name] || IDENTITY_FUNC).apply(this, slice.call(arguments, 1));
11168
+ if (typeof ret === 'undefined') {
11169
+ this.report_error(hook_name + ' hook did not return a value');
11170
+ ret = null;
11171
+ }
11172
+ return ret;
11173
+ };
11582
11174
 
11583
11175
  /**
11584
- * Add a listener for a given event.
11176
+ * Returns the value of the super property named property_name. If no such
11177
+ * property is set, get_property() will return the undefined value.
11585
11178
  *
11586
- * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
11587
- * @param {(String|Symbol)} event The event name.
11588
- * @param {Function} fn The listener function.
11589
- * @param {*} context The context to invoke the listener with.
11590
- * @param {Boolean} once Specify if the listener is a one-time listener.
11591
- * @returns {EventEmitter}
11592
- * @private
11179
+ * ### Notes:
11180
+ *
11181
+ * get_property() can only be called after the Mixpanel library has finished loading.
11182
+ * init() has a loaded function available to handle this automatically. For example:
11183
+ *
11184
+ * // grab value for 'user_id' after the mixpanel library has loaded
11185
+ * mixpanel.init('YOUR PROJECT TOKEN', {
11186
+ * loaded: function(mixpanel) {
11187
+ * user_id = mixpanel.get_property('user_id');
11188
+ * }
11189
+ * });
11190
+ *
11191
+ * @param {String} property_name The name of the super property you want to retrieve
11593
11192
  */
11594
- function addListener(emitter, event, fn, context, once) {
11595
- if (typeof fn !== 'function') {
11596
- throw new TypeError('The listener must be a function');
11597
- }
11193
+ MixpanelLib.prototype.get_property = function(property_name) {
11194
+ return this['persistence']['props'][property_name];
11195
+ };
11598
11196
 
11599
- var listener = new EE(fn, context || emitter, once)
11600
- , evt = prefix ? prefix + event : event;
11197
+ MixpanelLib.prototype.toString = function() {
11198
+ var name = this.get_config('name');
11199
+ if (name !== PRIMARY_INSTANCE_NAME) {
11200
+ name = PRIMARY_INSTANCE_NAME + '.' + name;
11201
+ }
11202
+ return name;
11203
+ };
11601
11204
 
11602
- if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;
11603
- else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);
11604
- else emitter._events[evt] = [emitter._events[evt], listener];
11205
+ MixpanelLib.prototype._event_is_disabled = function(event_name) {
11206
+ return _.isBlockedUA(userAgent) ||
11207
+ this._flags.disable_all_events ||
11208
+ _.include(this.__disabled_events, event_name);
11209
+ };
11605
11210
 
11606
- return emitter;
11607
- }
11211
+ // perform some housekeeping around GDPR opt-in/out state
11212
+ MixpanelLib.prototype._gdpr_init = function() {
11213
+ var is_localStorage_requested = this.get_config('opt_out_tracking_persistence_type') === 'localStorage';
11608
11214
 
11609
- /**
11610
- * Clear event by name.
11611
- *
11612
- * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
11613
- * @param {(String|Symbol)} evt The Event name.
11614
- * @private
11615
- */
11616
- function clearEvent(emitter, evt) {
11617
- if (--emitter._eventsCount === 0) emitter._events = new Events();
11618
- else delete emitter._events[evt];
11619
- }
11215
+ // try to convert opt-in/out cookies to localStorage if possible
11216
+ if (is_localStorage_requested && _.localStorage.is_supported()) {
11217
+ if (!this.has_opted_in_tracking() && this.has_opted_in_tracking({'persistence_type': 'cookie'})) {
11218
+ this.opt_in_tracking({'enable_persistence': false});
11219
+ }
11220
+ if (!this.has_opted_out_tracking() && this.has_opted_out_tracking({'persistence_type': 'cookie'})) {
11221
+ this.opt_out_tracking({'clear_persistence': false});
11222
+ }
11223
+ this.clear_opt_in_out_tracking({
11224
+ 'persistence_type': 'cookie',
11225
+ 'enable_persistence': false
11226
+ });
11227
+ }
11620
11228
 
11621
- /**
11622
- * Minimal `EventEmitter` interface that is molded against the Node.js
11623
- * `EventEmitter` interface.
11624
- *
11625
- * @constructor
11626
- * @public
11627
- */
11628
- function EventEmitter() {
11629
- this._events = new Events();
11630
- this._eventsCount = 0;
11631
- }
11229
+ // check whether the user has already opted out - if so, clear & disable persistence
11230
+ if (this.has_opted_out_tracking()) {
11231
+ this._gdpr_update_persistence({'clear_persistence': true});
11232
+
11233
+ // check whether we should opt out by default
11234
+ // note: we don't clear persistence here by default since opt-out default state is often
11235
+ // used as an initial state while GDPR information is being collected
11236
+ } else if (!this.has_opted_in_tracking() && (
11237
+ this.get_config('opt_out_tracking_by_default') || _.cookie.get('mp_optout')
11238
+ )) {
11239
+ _.cookie.remove('mp_optout');
11240
+ this.opt_out_tracking({
11241
+ 'clear_persistence': this.get_config('opt_out_persistence_by_default')
11242
+ });
11243
+ }
11244
+ };
11632
11245
 
11633
11246
  /**
11634
- * Return an array listing the events for which the emitter has registered
11635
- * listeners.
11636
- *
11637
- * @returns {Array}
11638
- * @public
11247
+ * Enable or disable persistence based on options
11248
+ * only enable/disable if persistence is not already in this state
11249
+ * @param {boolean} [options.clear_persistence] If true, will delete all data stored by the sdk in persistence and disable it
11250
+ * @param {boolean} [options.enable_persistence] If true, will re-enable sdk persistence
11639
11251
  */
11640
- EventEmitter.prototype.eventNames = function eventNames() {
11641
- var names = []
11642
- , events
11643
- , name;
11252
+ MixpanelLib.prototype._gdpr_update_persistence = function(options) {
11253
+ var disabled;
11254
+ if (options && options['clear_persistence']) {
11255
+ disabled = true;
11256
+ } else if (options && options['enable_persistence']) {
11257
+ disabled = false;
11258
+ } else {
11259
+ return;
11260
+ }
11644
11261
 
11645
- if (this._eventsCount === 0) return names;
11262
+ if (!this.get_config('disable_persistence') && this['persistence'].disabled !== disabled) {
11263
+ this['persistence'].set_disabled(disabled);
11264
+ }
11646
11265
 
11647
- for (name in (events = this._events)) {
11648
- if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
11649
- }
11266
+ if (disabled) {
11267
+ _.each(this.request_batchers, function(batcher) {
11268
+ batcher.clear();
11269
+ });
11270
+ }
11271
+ };
11650
11272
 
11651
- if (Object.getOwnPropertySymbols) {
11652
- return names.concat(Object.getOwnPropertySymbols(events));
11653
- }
11273
+ // call a base gdpr function after constructing the appropriate token and options args
11274
+ MixpanelLib.prototype._gdpr_call_func = function(func, options) {
11275
+ options = _.extend({
11276
+ 'track': _.bind(this.track, this),
11277
+ 'persistence_type': this.get_config('opt_out_tracking_persistence_type'),
11278
+ 'cookie_prefix': this.get_config('opt_out_tracking_cookie_prefix'),
11279
+ 'cookie_expiration': this.get_config('cookie_expiration'),
11280
+ 'cross_site_cookie': this.get_config('cross_site_cookie'),
11281
+ 'cross_subdomain_cookie': this.get_config('cross_subdomain_cookie'),
11282
+ 'cookie_domain': this.get_config('cookie_domain'),
11283
+ 'secure_cookie': this.get_config('secure_cookie'),
11284
+ 'ignore_dnt': this.get_config('ignore_dnt')
11285
+ }, options);
11654
11286
 
11655
- return names;
11287
+ // check if localStorage can be used for recording opt out status, fall back to cookie if not
11288
+ if (!_.localStorage.is_supported()) {
11289
+ options['persistence_type'] = 'cookie';
11290
+ }
11291
+
11292
+ return func(this.get_config('token'), {
11293
+ track: options['track'],
11294
+ trackEventName: options['track_event_name'],
11295
+ trackProperties: options['track_properties'],
11296
+ persistenceType: options['persistence_type'],
11297
+ persistencePrefix: options['cookie_prefix'],
11298
+ cookieDomain: options['cookie_domain'],
11299
+ cookieExpiration: options['cookie_expiration'],
11300
+ crossSiteCookie: options['cross_site_cookie'],
11301
+ crossSubdomainCookie: options['cross_subdomain_cookie'],
11302
+ secureCookie: options['secure_cookie'],
11303
+ ignoreDnt: options['ignore_dnt']
11304
+ });
11656
11305
  };
11657
11306
 
11658
11307
  /**
11659
- * Return the listeners registered for a given event.
11308
+ * Opt the user in to data tracking and cookies/localstorage for this Mixpanel instance
11660
11309
  *
11661
- * @param {(String|Symbol)} event The event name.
11662
- * @returns {Array} The registered listeners.
11663
- * @public
11310
+ * ### Usage
11311
+ *
11312
+ * // opt user in
11313
+ * mixpanel.opt_in_tracking();
11314
+ *
11315
+ * // opt user in with specific event name, properties, cookie configuration
11316
+ * mixpanel.opt_in_tracking({
11317
+ * track_event_name: 'User opted in',
11318
+ * track_event_properties: {
11319
+ * 'Email': 'jdoe@example.com'
11320
+ * },
11321
+ * cookie_expiration: 30,
11322
+ * secure_cookie: true
11323
+ * });
11324
+ *
11325
+ * @param {Object} [options] A dictionary of config options to override
11326
+ * @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)
11327
+ * @param {string} [options.track_event_name=$opt_in] Event name to be used for tracking the opt-in action
11328
+ * @param {Object} [options.track_properties] Set of properties to be tracked along with the opt-in action
11329
+ * @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence
11330
+ * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11331
+ * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11332
+ * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
11333
+ * @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
11334
+ * @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)
11335
+ * @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)
11336
+ * @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)
11664
11337
  */
11665
- EventEmitter.prototype.listeners = function listeners(event) {
11666
- var evt = prefix ? prefix + event : event
11667
- , handlers = this._events[evt];
11338
+ MixpanelLib.prototype.opt_in_tracking = function(options) {
11339
+ options = _.extend({
11340
+ 'enable_persistence': true
11341
+ }, options);
11668
11342
 
11669
- if (!handlers) return [];
11670
- if (handlers.fn) return [handlers.fn];
11343
+ this._gdpr_call_func(optIn, options);
11344
+ this._gdpr_update_persistence(options);
11345
+ };
11671
11346
 
11672
- for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {
11673
- ee[i] = handlers[i].fn;
11674
- }
11347
+ /**
11348
+ * Opt the user out of data tracking and cookies/localstorage for this Mixpanel instance
11349
+ *
11350
+ * ### Usage
11351
+ *
11352
+ * // opt user out
11353
+ * mixpanel.opt_out_tracking();
11354
+ *
11355
+ * // opt user out with different cookie configuration from Mixpanel instance
11356
+ * mixpanel.opt_out_tracking({
11357
+ * cookie_expiration: 30,
11358
+ * secure_cookie: true
11359
+ * });
11360
+ *
11361
+ * @param {Object} [options] A dictionary of config options to override
11362
+ * @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
11363
+ * @param {boolean} [options.clear_persistence=true] If true, will delete all data stored by the sdk in persistence
11364
+ * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11365
+ * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11366
+ * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
11367
+ * @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
11368
+ * @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)
11369
+ * @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)
11370
+ * @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)
11371
+ */
11372
+ MixpanelLib.prototype.opt_out_tracking = function(options) {
11373
+ options = _.extend({
11374
+ 'clear_persistence': true,
11375
+ 'delete_user': true
11376
+ }, options);
11377
+
11378
+ // delete user and clear charges since these methods may be disabled by opt-out
11379
+ if (options['delete_user'] && this['people'] && this['people']._identify_called()) {
11380
+ this['people'].delete_user();
11381
+ this['people'].clear_charges();
11382
+ }
11675
11383
 
11676
- return ee;
11384
+ this._gdpr_call_func(optOut, options);
11385
+ this._gdpr_update_persistence(options);
11677
11386
  };
11678
11387
 
11679
11388
  /**
11680
- * Return the number of listeners listening to a given event.
11389
+ * Check whether the user has opted in to data tracking and cookies/localstorage for this Mixpanel instance
11681
11390
  *
11682
- * @param {(String|Symbol)} event The event name.
11683
- * @returns {Number} The number of listeners.
11684
- * @public
11391
+ * ### Usage
11392
+ *
11393
+ * var has_opted_in = mixpanel.has_opted_in_tracking();
11394
+ * // use has_opted_in value
11395
+ *
11396
+ * @param {Object} [options] A dictionary of config options to override
11397
+ * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11398
+ * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11399
+ * @returns {boolean} current opt-in status
11685
11400
  */
11686
- EventEmitter.prototype.listenerCount = function listenerCount(event) {
11687
- var evt = prefix ? prefix + event : event
11688
- , listeners = this._events[evt];
11689
-
11690
- if (!listeners) return 0;
11691
- if (listeners.fn) return 1;
11692
- return listeners.length;
11401
+ MixpanelLib.prototype.has_opted_in_tracking = function(options) {
11402
+ return this._gdpr_call_func(hasOptedIn, options);
11693
11403
  };
11694
11404
 
11695
11405
  /**
11696
- * Calls each of the listeners registered for a given event.
11406
+ * Check whether the user has opted out of data tracking and cookies/localstorage for this Mixpanel instance
11697
11407
  *
11698
- * @param {(String|Symbol)} event The event name.
11699
- * @returns {Boolean} `true` if the event had listeners, else `false`.
11700
- * @public
11408
+ * ### Usage
11409
+ *
11410
+ * var has_opted_out = mixpanel.has_opted_out_tracking();
11411
+ * // use has_opted_out value
11412
+ *
11413
+ * @param {Object} [options] A dictionary of config options to override
11414
+ * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11415
+ * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11416
+ * @returns {boolean} current opt-out status
11701
11417
  */
11702
- EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
11703
- var evt = prefix ? prefix + event : event;
11704
-
11705
- if (!this._events[evt]) return false;
11418
+ MixpanelLib.prototype.has_opted_out_tracking = function(options) {
11419
+ return this._gdpr_call_func(hasOptedOut, options);
11420
+ };
11706
11421
 
11707
- var listeners = this._events[evt]
11708
- , len = arguments.length
11709
- , args
11710
- , i;
11422
+ /**
11423
+ * Clear the user's opt in/out status of data tracking and cookies/localstorage for this Mixpanel instance
11424
+ *
11425
+ * ### Usage
11426
+ *
11427
+ * // clear user's opt-in/out status
11428
+ * mixpanel.clear_opt_in_out_tracking();
11429
+ *
11430
+ * // clear user's opt-in/out status with specific cookie configuration - should match
11431
+ * // configuration used when opt_in_tracking/opt_out_tracking methods were called.
11432
+ * mixpanel.clear_opt_in_out_tracking({
11433
+ * cookie_expiration: 30,
11434
+ * secure_cookie: true
11435
+ * });
11436
+ *
11437
+ * @param {Object} [options] A dictionary of config options to override
11438
+ * @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence
11439
+ * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
11440
+ * @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
11441
+ * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
11442
+ * @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
11443
+ * @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)
11444
+ * @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)
11445
+ * @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)
11446
+ */
11447
+ MixpanelLib.prototype.clear_opt_in_out_tracking = function(options) {
11448
+ options = _.extend({
11449
+ 'enable_persistence': true
11450
+ }, options);
11711
11451
 
11712
- if (listeners.fn) {
11713
- if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);
11452
+ this._gdpr_call_func(clearOptInOut, options);
11453
+ this._gdpr_update_persistence(options);
11454
+ };
11714
11455
 
11715
- switch (len) {
11716
- case 1: return listeners.fn.call(listeners.context), true;
11717
- case 2: return listeners.fn.call(listeners.context, a1), true;
11718
- case 3: return listeners.fn.call(listeners.context, a1, a2), true;
11719
- case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;
11720
- case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
11721
- case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
11456
+ MixpanelLib.prototype.report_error = function(msg, err) {
11457
+ console$1.error.apply(console$1.error, arguments);
11458
+ try {
11459
+ if (!err && !(msg instanceof Error)) {
11460
+ msg = new Error(msg);
11461
+ }
11462
+ this.get_config('error_reporter')(msg, err);
11463
+ } catch(err) {
11464
+ console$1.error(err);
11722
11465
  }
11466
+ };
11723
11467
 
11724
- for (i = 1, args = new Array(len -1); i < len; i++) {
11725
- args[i - 1] = arguments[i];
11726
- }
11468
+ // EXPORTS (for closure compiler)
11727
11469
 
11728
- listeners.fn.apply(listeners.context, args);
11729
- } else {
11730
- var length = listeners.length
11731
- , j;
11470
+ // MixpanelLib Exports
11471
+ MixpanelLib.prototype['init'] = MixpanelLib.prototype.init;
11472
+ MixpanelLib.prototype['reset'] = MixpanelLib.prototype.reset;
11473
+ MixpanelLib.prototype['disable'] = MixpanelLib.prototype.disable;
11474
+ MixpanelLib.prototype['time_event'] = MixpanelLib.prototype.time_event;
11475
+ MixpanelLib.prototype['track'] = MixpanelLib.prototype.track;
11476
+ MixpanelLib.prototype['track_links'] = MixpanelLib.prototype.track_links;
11477
+ MixpanelLib.prototype['track_forms'] = MixpanelLib.prototype.track_forms;
11478
+ MixpanelLib.prototype['track_pageview'] = MixpanelLib.prototype.track_pageview;
11479
+ MixpanelLib.prototype['register'] = MixpanelLib.prototype.register;
11480
+ MixpanelLib.prototype['register_once'] = MixpanelLib.prototype.register_once;
11481
+ MixpanelLib.prototype['unregister'] = MixpanelLib.prototype.unregister;
11482
+ MixpanelLib.prototype['identify'] = MixpanelLib.prototype.identify;
11483
+ MixpanelLib.prototype['alias'] = MixpanelLib.prototype.alias;
11484
+ MixpanelLib.prototype['name_tag'] = MixpanelLib.prototype.name_tag;
11485
+ MixpanelLib.prototype['set_config'] = MixpanelLib.prototype.set_config;
11486
+ MixpanelLib.prototype['get_config'] = MixpanelLib.prototype.get_config;
11487
+ MixpanelLib.prototype['get_property'] = MixpanelLib.prototype.get_property;
11488
+ MixpanelLib.prototype['get_distinct_id'] = MixpanelLib.prototype.get_distinct_id;
11489
+ MixpanelLib.prototype['toString'] = MixpanelLib.prototype.toString;
11490
+ MixpanelLib.prototype['opt_out_tracking'] = MixpanelLib.prototype.opt_out_tracking;
11491
+ MixpanelLib.prototype['opt_in_tracking'] = MixpanelLib.prototype.opt_in_tracking;
11492
+ MixpanelLib.prototype['has_opted_out_tracking'] = MixpanelLib.prototype.has_opted_out_tracking;
11493
+ MixpanelLib.prototype['has_opted_in_tracking'] = MixpanelLib.prototype.has_opted_in_tracking;
11494
+ MixpanelLib.prototype['clear_opt_in_out_tracking'] = MixpanelLib.prototype.clear_opt_in_out_tracking;
11495
+ MixpanelLib.prototype['get_group'] = MixpanelLib.prototype.get_group;
11496
+ MixpanelLib.prototype['set_group'] = MixpanelLib.prototype.set_group;
11497
+ MixpanelLib.prototype['add_group'] = MixpanelLib.prototype.add_group;
11498
+ MixpanelLib.prototype['remove_group'] = MixpanelLib.prototype.remove_group;
11499
+ MixpanelLib.prototype['track_with_groups'] = MixpanelLib.prototype.track_with_groups;
11500
+ MixpanelLib.prototype['start_batch_senders'] = MixpanelLib.prototype.start_batch_senders;
11501
+ MixpanelLib.prototype['stop_batch_senders'] = MixpanelLib.prototype.stop_batch_senders;
11732
11502
 
11733
- for (i = 0; i < length; i++) {
11734
- if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);
11503
+ // MixpanelPersistence Exports
11504
+ MixpanelPersistence.prototype['properties'] = MixpanelPersistence.prototype.properties;
11505
+ MixpanelPersistence.prototype['update_search_keyword'] = MixpanelPersistence.prototype.update_search_keyword;
11506
+ MixpanelPersistence.prototype['update_referrer_info'] = MixpanelPersistence.prototype.update_referrer_info;
11507
+ MixpanelPersistence.prototype['get_cross_subdomain'] = MixpanelPersistence.prototype.get_cross_subdomain;
11508
+ MixpanelPersistence.prototype['clear'] = MixpanelPersistence.prototype.clear;
11735
11509
 
11736
- switch (len) {
11737
- case 1: listeners[i].fn.call(listeners[i].context); break;
11738
- case 2: listeners[i].fn.call(listeners[i].context, a1); break;
11739
- case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;
11740
- case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;
11741
- default:
11742
- if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {
11743
- args[j - 1] = arguments[j];
11744
- }
11745
11510
 
11746
- listeners[i].fn.apply(listeners[i].context, args);
11747
- }
11748
- }
11749
- }
11511
+ var instances = {};
11512
+ var extend_mp = function() {
11513
+ // add all the sub mixpanel instances
11514
+ _.each(instances, function(instance, name) {
11515
+ if (name !== PRIMARY_INSTANCE_NAME) { mixpanel_master[name] = instance; }
11516
+ });
11750
11517
 
11751
- return true;
11518
+ // add private functions as _
11519
+ mixpanel_master['_'] = _;
11752
11520
  };
11753
11521
 
11754
- /**
11755
- * Add a listener for a given event.
11756
- *
11757
- * @param {(String|Symbol)} event The event name.
11758
- * @param {Function} fn The listener function.
11759
- * @param {*} [context=this] The context to invoke the listener with.
11760
- * @returns {EventEmitter} `this`.
11761
- * @public
11762
- */
11763
- EventEmitter.prototype.on = function on(event, fn, context) {
11764
- return addListener(this, event, fn, context, false);
11765
- };
11522
+ var override_mp_init_func = function() {
11523
+ // we override the snippets init function to handle the case where a
11524
+ // user initializes the mixpanel library after the script loads & runs
11525
+ mixpanel_master['init'] = function(token, config, name) {
11526
+ if (name) {
11527
+ // initialize a sub library
11528
+ if (!mixpanel_master[name]) {
11529
+ mixpanel_master[name] = instances[name] = create_mplib(token, config, name);
11530
+ mixpanel_master[name]._loaded();
11531
+ }
11532
+ return mixpanel_master[name];
11533
+ } else {
11534
+ var instance = mixpanel_master;
11766
11535
 
11767
- /**
11768
- * Add a one-time listener for a given event.
11769
- *
11770
- * @param {(String|Symbol)} event The event name.
11771
- * @param {Function} fn The listener function.
11772
- * @param {*} [context=this] The context to invoke the listener with.
11773
- * @returns {EventEmitter} `this`.
11774
- * @public
11775
- */
11776
- EventEmitter.prototype.once = function once(event, fn, context) {
11777
- return addListener(this, event, fn, context, true);
11778
- };
11536
+ if (instances[PRIMARY_INSTANCE_NAME]) {
11537
+ // main mixpanel lib already initialized
11538
+ instance = instances[PRIMARY_INSTANCE_NAME];
11539
+ } else if (token) {
11540
+ // intialize the main mixpanel lib
11541
+ instance = create_mplib(token, config, PRIMARY_INSTANCE_NAME);
11542
+ instance._loaded();
11543
+ instances[PRIMARY_INSTANCE_NAME] = instance;
11544
+ }
11779
11545
 
11780
- /**
11781
- * Remove the listeners of a given event.
11782
- *
11783
- * @param {(String|Symbol)} event The event name.
11784
- * @param {Function} fn Only remove the listeners that match this function.
11785
- * @param {*} context Only remove the listeners that have this context.
11786
- * @param {Boolean} once Only remove one-time listeners.
11787
- * @returns {EventEmitter} `this`.
11788
- * @public
11789
- */
11790
- EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
11791
- var evt = prefix ? prefix + event : event;
11546
+ mixpanel_master = instance;
11547
+ if (init_type === INIT_SNIPPET) {
11548
+ window$1[PRIMARY_INSTANCE_NAME] = mixpanel_master;
11549
+ }
11550
+ extend_mp();
11551
+ }
11552
+ };
11553
+ };
11792
11554
 
11793
- if (!this._events[evt]) return this;
11794
- if (!fn) {
11795
- clearEvent(this, evt);
11796
- return this;
11797
- }
11555
+ var add_dom_loaded_handler = function() {
11556
+ // Cross browser DOM Loaded support
11557
+ function dom_loaded_handler() {
11558
+ // function flag since we only want to execute this once
11559
+ if (dom_loaded_handler.done) { return; }
11560
+ dom_loaded_handler.done = true;
11798
11561
 
11799
- var listeners = this._events[evt];
11562
+ DOM_LOADED = true;
11563
+ ENQUEUE_REQUESTS = false;
11800
11564
 
11801
- if (listeners.fn) {
11802
- if (
11803
- listeners.fn === fn &&
11804
- (!once || listeners.once) &&
11805
- (!context || listeners.context === context)
11806
- ) {
11807
- clearEvent(this, evt);
11808
- }
11809
- } else {
11810
- for (var i = 0, events = [], length = listeners.length; i < length; i++) {
11811
- if (
11812
- listeners[i].fn !== fn ||
11813
- (once && !listeners[i].once) ||
11814
- (context && listeners[i].context !== context)
11815
- ) {
11816
- events.push(listeners[i]);
11817
- }
11565
+ _.each(instances, function(inst) {
11566
+ inst._dom_loaded();
11567
+ });
11818
11568
  }
11819
11569
 
11820
- //
11821
- // Reset the array, or remove it completely if we have no more listeners.
11822
- //
11823
- if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;
11824
- else clearEvent(this, evt);
11825
- }
11826
-
11827
- return this;
11828
- };
11570
+ function do_scroll_check() {
11571
+ try {
11572
+ document$1.documentElement.doScroll('left');
11573
+ } catch(e) {
11574
+ setTimeout(do_scroll_check, 1);
11575
+ return;
11576
+ }
11829
11577
 
11830
- /**
11831
- * Remove all listeners, or those of the specified event.
11832
- *
11833
- * @param {(String|Symbol)} [event] The event name.
11834
- * @returns {EventEmitter} `this`.
11835
- * @public
11836
- */
11837
- EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
11838
- var evt;
11578
+ dom_loaded_handler();
11579
+ }
11839
11580
 
11840
- if (event) {
11841
- evt = prefix ? prefix + event : event;
11842
- if (this._events[evt]) clearEvent(this, evt);
11843
- } else {
11844
- this._events = new Events();
11845
- this._eventsCount = 0;
11846
- }
11581
+ if (document$1.addEventListener) {
11582
+ if (document$1.readyState === 'complete') {
11583
+ // safari 4 can fire the DOMContentLoaded event before loading all
11584
+ // external JS (including this file). you will see some copypasta
11585
+ // on the internet that checks for 'complete' and 'loaded', but
11586
+ // 'loaded' is an IE thing
11587
+ dom_loaded_handler();
11588
+ } else {
11589
+ document$1.addEventListener('DOMContentLoaded', dom_loaded_handler, false);
11590
+ }
11591
+ } else if (document$1.attachEvent) {
11592
+ // IE
11593
+ document$1.attachEvent('onreadystatechange', dom_loaded_handler);
11847
11594
 
11848
- return this;
11849
- };
11595
+ // check to make sure we arn't in a frame
11596
+ var toplevel = false;
11597
+ try {
11598
+ toplevel = window$1.frameElement === null;
11599
+ } catch(e) {
11600
+ // noop
11601
+ }
11850
11602
 
11851
- //
11852
- // Alias methods names because people roll like that.
11853
- //
11854
- EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
11855
- EventEmitter.prototype.addListener = EventEmitter.prototype.on;
11603
+ if (document$1.documentElement.doScroll && toplevel) {
11604
+ do_scroll_check();
11605
+ }
11606
+ }
11856
11607
 
11857
- //
11858
- // Expose the prefix.
11859
- //
11860
- EventEmitter.prefixed = prefix;
11608
+ // fallback handler, always will work
11609
+ _.register_event(window$1, 'load', dom_loaded_handler, true);
11610
+ };
11861
11611
 
11862
- //
11863
- // Allow `EventEmitter` to be imported as module namespace.
11864
- //
11865
- EventEmitter.EventEmitter = EventEmitter;
11612
+ function init_as_module() {
11613
+ init_type = INIT_MODULE;
11614
+ mixpanel_master = new MixpanelLib();
11866
11615
 
11867
- //
11868
- // Expose the module.
11869
- //
11870
- {
11871
- module.exports = EventEmitter;
11872
- }
11873
- });
11616
+ override_mp_init_func();
11617
+ mixpanel_master['init']();
11618
+ add_dom_loaded_handler();
11874
11619
 
11875
- /**
11876
- * This method returns `undefined`.
11877
- *
11878
- * @static
11879
- * @memberOf _
11880
- * @since 2.3.0
11881
- * @category Util
11882
- * @example
11883
- *
11884
- * _.times(2, _.noop);
11885
- * // => [undefined, undefined]
11886
- */
11887
- function noop() {
11888
- // No operation performed.
11620
+ return mixpanel_master;
11889
11621
  }
11890
11622
 
11891
- var noop_1 = noop;
11623
+ var mixpanel = init_as_module();
11892
11624
 
11893
- /** Used as references for various `Number` constants. */
11894
- var INFINITY = 1 / 0;
11625
+ var mixpanel_cjs = mixpanel;
11895
11626
 
11896
- /**
11897
- * Creates a set object of `values`.
11898
- *
11899
- * @private
11900
- * @param {Array} values The values to add to the set.
11901
- * @returns {Object} Returns the new set.
11902
- */
11903
- var createSet = !(_Set && (1 / _setToArray(new _Set([,-0]))[1]) == INFINITY) ? noop_1 : function(values) {
11904
- return new _Set(values);
11905
- };
11627
+ var mixpanel$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), mixpanel_cjs, {
11628
+ 'default': mixpanel_cjs
11629
+ }));
11906
11630
 
11907
- // eslint-disable-next-line import/no-cycle
11908
- /**
11909
- *
11910
- * @param url
11911
- * @param options
11912
- */
11913
- function failureLoggedFetch(url, options = {}) {
11914
- return fetch(url, options).then(async (r) => {
11915
- var _a;
11916
- if (!r.ok && r.type !== 'opaqueredirect' && r.type !== 'opaque') {
11917
- console.error('Failure', await ((_a = r.text) === null || _a === void 0 ? void 0 : _a.call(r)));
11918
- }
11919
- return r;
11920
- });
11921
- }
11922
- /**
11923
- *
11924
- * @param authVerificationUrl
11925
- */
11926
- function fetchSessionInfoService(authVerificationUrl) {
11927
- return failureLoggedFetch(authVerificationUrl, {
11928
- credentials: 'include',
11929
- });
11930
- }
11931
- /**
11932
- * Service to validate a auth token against a ThoughtSpot host.
11933
- *
11934
- * @param thoughtSpotHost : ThoughtSpot host to verify the token against.
11935
- * @param authToken : Auth token to verify.
11936
- */
11937
- function verifyTokenService(thoughtSpotHost, authToken) {
11938
- const authVerificationUrl = `${thoughtSpotHost}${EndPoints.IS_ACTIVE}`;
11939
- return fetch(authVerificationUrl, {
11940
- headers: {
11941
- Authorization: `Bearer ${authToken}`,
11942
- 'x-requested-by': 'ThoughtSpot',
11943
- },
11944
- credentials: 'omit',
11945
- });
11946
- }
11947
- /**
11948
- *
11949
- * @param authEndpoint
11950
- */
11951
- async function fetchAuthTokenService(authEndpoint) {
11952
- return fetch(authEndpoint);
11953
- }
11631
+ // Needed to avoid error in CJS builds on some bundlers.
11632
+ const mixpanelLib = mixpanel_cjs || mixpanel$1;
11633
+ let mixpanelInstance;
11634
+ const MIXPANEL_EVENT = {
11635
+ VISUAL_SDK_RENDER_START: 'visual-sdk-render-start',
11636
+ VISUAL_SDK_CALLED_INIT: 'visual-sdk-called-init',
11637
+ VISUAL_SDK_RENDER_COMPLETE: 'visual-sdk-render-complete',
11638
+ VISUAL_SDK_RENDER_FAILED: 'visual-sdk-render-failed',
11639
+ VISUAL_SDK_TRIGGER: 'visual-sdk-trigger',
11640
+ VISUAL_SDK_ON: 'visual-sdk-on',
11641
+ VISUAL_SDK_IFRAME_LOAD_PERFORMANCE: 'visual-sdk-iframe-load-performance',
11642
+ VISUAL_SDK_EMBED_CREATE: 'visual-sdk-embed-create',
11643
+ };
11644
+ let isMixpanelInitialized = false;
11645
+ let eventQueue = [];
11954
11646
  /**
11647
+ * Pushes the event with its Property key-value map to mixpanel.
11955
11648
  *
11956
- * @param thoughtSpotHost
11957
- * @param username
11958
- * @param authToken
11649
+ * @param eventId
11650
+ * @param eventProps
11959
11651
  */
11960
- async function fetchAuthService(thoughtSpotHost, username, authToken) {
11961
- return failureLoggedFetch(`${thoughtSpotHost}${EndPoints.TOKEN_LOGIN}?username=${username}&auth_token=${authToken}`, {
11962
- credentials: 'include',
11963
- // We do not want to follow the redirect, as it starts giving a CORS
11964
- // error
11965
- redirect: 'manual',
11966
- });
11652
+ function uploadMixpanelEvent(eventId, eventProps = {}) {
11653
+ if (!isMixpanelInitialized) {
11654
+ eventQueue.push({ eventId, eventProps });
11655
+ return;
11656
+ }
11657
+ mixpanelInstance.track(eventId, eventProps);
11967
11658
  }
11968
11659
  /**
11969
11660
  *
11970
- * @param thoughtSpotHost
11971
- * @param username
11972
- * @param authToken
11973
11661
  */
11974
- async function fetchAuthPostService(thoughtSpotHost, username, authToken) {
11975
- return failureLoggedFetch(`${thoughtSpotHost}${EndPoints.TOKEN_LOGIN}`, {
11976
- method: 'POST',
11977
- headers: {
11978
- 'content-type': 'application/x-www-form-urlencoded',
11979
- 'x-requested-by': 'ThoughtSpot',
11980
- },
11981
- body: `username=${encodeURIComponent(username)}&auth_token=${encodeURIComponent(authToken)}`,
11982
- credentials: 'include',
11983
- // We do not want to follow the redirect, as it starts giving a CORS
11984
- // error
11985
- redirect: 'manual',
11662
+ function emptyQueue() {
11663
+ if (!isMixpanelInitialized) {
11664
+ return;
11665
+ }
11666
+ eventQueue.forEach((event) => {
11667
+ uploadMixpanelEvent(event.eventId, event.eventProps);
11986
11668
  });
11669
+ eventQueue = [];
11987
11670
  }
11988
11671
  /**
11989
11672
  *
11990
- * @param thoughtSpotHost
11991
- * @param username
11992
- * @param password
11993
- */
11994
- async function fetchBasicAuthService(thoughtSpotHost, username, password) {
11995
- return failureLoggedFetch(`${thoughtSpotHost}${EndPoints.BASIC_LOGIN}`, {
11996
- method: 'POST',
11997
- headers: {
11998
- 'content-type': 'application/x-www-form-urlencoded',
11999
- 'x-requested-by': 'ThoughtSpot',
12000
- },
12001
- body: `username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}`,
12002
- credentials: 'include',
12003
- });
11673
+ * @param sessionInfo
11674
+ */
11675
+ function initMixpanel(sessionInfo) {
11676
+ var _a;
11677
+ if (!sessionInfo || !sessionInfo.mixpanelToken) {
11678
+ return;
11679
+ }
11680
+ // On a public cluster the user is anonymous, so don't set the identify to
11681
+ // userGUID
11682
+ const isPublicCluster = !!sessionInfo.isPublicUser;
11683
+ const token = sessionInfo.mixpanelToken;
11684
+ try {
11685
+ if (token) {
11686
+ mixpanelInstance = mixpanelLib.init(token, undefined, 'tsEmbed');
11687
+ if (!isPublicCluster) {
11688
+ mixpanelInstance.identify(sessionInfo.userGUID);
11689
+ }
11690
+ mixpanelInstance.register_once({
11691
+ clusterId: sessionInfo.clusterId,
11692
+ clusterName: sessionInfo.clusterName,
11693
+ releaseVersion: sessionInfo.releaseVersion,
11694
+ hostAppUrl: ((_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.host) || '',
11695
+ });
11696
+ isMixpanelInitialized = true;
11697
+ emptyQueue();
11698
+ }
11699
+ }
11700
+ catch (e) {
11701
+ console.error('Error initializing mixpanel', e);
11702
+ }
12004
11703
  }
12005
11704
 
12006
11705
  // eslint-disable-next-line import/no-mutable-exports
@@ -12016,17 +11715,6 @@ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!]
12016
11715
  });
12017
11716
  let releaseVersion = '';
12018
11717
  const SSO_REDIRECTION_MARKER_GUID = '5e16222e-ef02-43e9-9fbd-24226bf3ce5b';
12019
- const EndPoints = {
12020
- AUTH_VERIFICATION: '/callosum/v1/session/info',
12021
- SAML_LOGIN_TEMPLATE: (targetUrl) => `/callosum/v1/saml/login?targetURLPath=${targetUrl}`,
12022
- OIDC_LOGIN_TEMPLATE: (targetUrl) => `/callosum/v1/oidc/login?targetURLPath=${targetUrl}`,
12023
- TOKEN_LOGIN: '/callosum/v1/session/login/token',
12024
- BASIC_LOGIN: '/callosum/v1/session/login',
12025
- LOGOUT: '/callosum/v1/session/logout',
12026
- EXECUTE_TML: '/api/rest/2.0/metadata/tml/import',
12027
- EXPORT_TML: '/api/rest/2.0/metadata/tml/export',
12028
- IS_ACTIVE: '/callosum/v1/session/isactive',
12029
- };
12030
11718
  /**
12031
11719
  * Enum for auth failure types. This is the parameter passed to the listner
12032
11720
  * of {@link AuthStatus.FAILURE}.
@@ -12093,382 +11781,748 @@ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!]
12093
11781
  console.error('SDK not initialized');
12094
11782
  return;
12095
11783
  }
12096
- }
12097
- /**
12098
- *
12099
- */
12100
- function notifyAuthSuccess() {
12101
- {
12102
- console.error('SDK not initialized');
11784
+ }
11785
+ /**
11786
+ *
11787
+ */
11788
+ function notifyAuthSuccess() {
11789
+ {
11790
+ console.error('SDK not initialized');
11791
+ return;
11792
+ }
11793
+ }
11794
+ /**
11795
+ *
11796
+ * @param failureType
11797
+ */
11798
+ function notifyAuthFailure(failureType) {
11799
+ {
11800
+ console.error('SDK not initialized');
11801
+ return;
11802
+ }
11803
+ }
11804
+ /**
11805
+ *
11806
+ */
11807
+ function notifyLogout() {
11808
+ {
11809
+ console.error('SDK not initialized');
11810
+ return;
11811
+ }
11812
+ }
11813
+ const initSession = (sessionDetails) => {
11814
+ if (sessionInfo == null) {
11815
+ sessionInfo = sessionDetails;
11816
+ initMixpanel(sessionInfo);
11817
+ sessionInfoResolver(sessionInfo);
11818
+ }
11819
+ };
11820
+ const getSessionDetails = (sessionInfoResp) => {
11821
+ console.log('helloooo');
11822
+ const devMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.devSdkKey;
11823
+ const prodMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.prodSdkKey;
11824
+ const mixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.production
11825
+ ? prodMixpanelToken
11826
+ : devMixpanelToken;
11827
+ return {
11828
+ userGUID: sessionInfoResp.userGUID,
11829
+ mixpanelToken,
11830
+ isPublicUser: sessionInfoResp.configInfo.isPublicUser,
11831
+ releaseVersion: sessionInfoResp.releaseVersion,
11832
+ clusterId: sessionInfoResp.configInfo.selfClusterId,
11833
+ clusterName: sessionInfoResp.configInfo.selfClusterName,
11834
+ ...sessionInfoResp,
11835
+ };
11836
+ };
11837
+ /**
11838
+ * Check if we are logged into the ThoughtSpot cluster
11839
+ *
11840
+ * @param thoughtSpotHost The ThoughtSpot cluster hostname or IP
11841
+ */
11842
+ async function isLoggedIn(thoughtSpotHost) {
11843
+ const authVerificationUrl = `${thoughtSpotHost}${EndPoints.AUTH_VERIFICATION}`;
11844
+ let response = null;
11845
+ try {
11846
+ response = await fetchSessionInfoService(authVerificationUrl);
11847
+ const sessionInfoResp = await response.json();
11848
+ const sessionDetails = getSessionDetails(sessionInfoResp);
11849
+ // Store user session details from session info
11850
+ initSession(sessionDetails);
11851
+ releaseVersion = sessionInfoResp.releaseVersion;
11852
+ }
11853
+ catch (e) {
11854
+ return false;
11855
+ }
11856
+ return response.status === 200;
11857
+ }
11858
+ /**
11859
+ * Return releaseVersion if available
11860
+ */
11861
+ function getReleaseVersion() {
11862
+ return releaseVersion;
11863
+ }
11864
+ /**
11865
+ * Check if we are stuck at the SSO redirect URL
11866
+ */
11867
+ function isAtSSORedirectUrl() {
11868
+ return window.location.href.indexOf(SSO_REDIRECTION_MARKER_GUID) >= 0;
11869
+ }
11870
+ /**
11871
+ * Remove the SSO redirect URL marker
11872
+ */
11873
+ function removeSSORedirectUrlMarker() {
11874
+ // Note (sunny): This will leave a # around even if it was not in the URL
11875
+ // to begin with. Trying to remove the hash by changing window.location will
11876
+ // reload the page which we don't want. We'll live with adding an
11877
+ // unnecessary hash to the parent page URL until we find any use case where
11878
+ // that creates an issue.
11879
+ window.location.hash = window.location.hash.replace(SSO_REDIRECTION_MARKER_GUID, '');
11880
+ }
11881
+ /**
11882
+ * Perform token based authentication
11883
+ *
11884
+ * @param embedConfig The embed configuration
11885
+ */
11886
+ const doTokenAuth = async (embedConfig) => {
11887
+ const { thoughtSpotHost, username, authEndpoint, getAuthToken, } = embedConfig;
11888
+ if (!authEndpoint && !getAuthToken) {
11889
+ throw new Error('Either auth endpoint or getAuthToken function must be provided');
11890
+ }
11891
+ loggedInStatus = await isLoggedIn(thoughtSpotHost);
11892
+ if (!loggedInStatus) {
11893
+ const authToken = await getAuthenticationToken(embedConfig);
11894
+ let resp;
11895
+ try {
11896
+ resp = await fetchAuthPostService(thoughtSpotHost, username, authToken);
11897
+ }
11898
+ catch (e) {
11899
+ resp = await fetchAuthService(thoughtSpotHost, username, authToken);
11900
+ }
11901
+ // token login issues a 302 when successful
11902
+ loggedInStatus = resp.ok || resp.type === 'opaqueredirect';
11903
+ if (loggedInStatus && embedConfig.detectCookieAccessSlow) {
11904
+ // When 3rd party cookie access is blocked, this will fail because
11905
+ // cookies will not be sent with the call.
11906
+ loggedInStatus = await isLoggedIn(thoughtSpotHost);
11907
+ }
11908
+ }
11909
+ return loggedInStatus;
11910
+ };
11911
+ /**
11912
+ * Validate embedConfig parameters required for cookielessTokenAuth
11913
+ *
11914
+ * @param embedConfig The embed configuration
11915
+ */
11916
+ const doCookielessTokenAuth = async (embedConfig) => {
11917
+ const { authEndpoint, getAuthToken } = embedConfig;
11918
+ if (!authEndpoint && !getAuthToken) {
11919
+ throw new Error('Either auth endpoint or getAuthToken function must be provided');
11920
+ }
11921
+ try {
11922
+ const authToken = await getAuthenticationToken(embedConfig);
11923
+ if (authToken)
11924
+ return true;
11925
+ }
11926
+ catch {
11927
+ // return false if getAuthenticationToken fails
11928
+ }
11929
+ return false;
11930
+ };
11931
+ /**
11932
+ * Perform basic authentication to the ThoughtSpot cluster using the cluster
11933
+ * credentials.
11934
+ *
11935
+ * Warning: This feature is primarily intended for developer testing. It is
11936
+ * strongly advised not to use this authentication method in production.
11937
+ *
11938
+ * @param embedConfig The embed configuration
11939
+ */
11940
+ const doBasicAuth = async (embedConfig) => {
11941
+ const { thoughtSpotHost, username, password } = embedConfig;
11942
+ const loggedIn = await isLoggedIn(thoughtSpotHost);
11943
+ if (!loggedIn) {
11944
+ const response = await fetchBasicAuthService(thoughtSpotHost, username, password);
11945
+ loggedInStatus = response.ok;
11946
+ if (embedConfig.detectCookieAccessSlow) {
11947
+ loggedInStatus = await isLoggedIn(thoughtSpotHost);
11948
+ }
11949
+ }
11950
+ else {
11951
+ loggedInStatus = true;
11952
+ }
11953
+ return loggedInStatus;
11954
+ };
11955
+ /**
11956
+ *
11957
+ * @param ssoURL
11958
+ * @param triggerContainer
11959
+ * @param triggerText
11960
+ */
11961
+ async function samlPopupFlow(ssoURL, triggerContainer, triggerText) {
11962
+ const openPopup = () => {
11963
+ if (samlAuthWindow === null || samlAuthWindow.closed) {
11964
+ samlAuthWindow = window.open(ssoURL, '_blank', 'location=no,height=570,width=520,scrollbars=yes,status=yes');
11965
+ }
11966
+ else {
11967
+ samlAuthWindow.focus();
11968
+ }
11969
+ };
11970
+ const containerEl = getDOMNode(triggerContainer);
11971
+ if (containerEl) {
11972
+ containerEl.innerHTML = '<button id="ts-auth-btn" class="ts-auth-btn" style="margin: auto;"></button>';
11973
+ const authElem = document.getElementById('ts-auth-btn');
11974
+ authElem.textContent = triggerText;
11975
+ authElem.addEventListener('click', openPopup, { once: true });
11976
+ }
11977
+ samlCompletionPromise = samlCompletionPromise
11978
+ || new Promise((resolve, reject) => {
11979
+ window.addEventListener('message', (e) => {
11980
+ if (e.data.type === exports.EmbedEvent.SAMLComplete) {
11981
+ e.source.close();
11982
+ resolve();
11983
+ }
11984
+ });
11985
+ });
11986
+ return samlCompletionPromise;
11987
+ }
11988
+ /**
11989
+ * Perform SAML authentication
11990
+ *
11991
+ * @param embedConfig The embed configuration
11992
+ * @param ssoEndPoint
11993
+ */
11994
+ const doSSOAuth = async (embedConfig, ssoEndPoint) => {
11995
+ const { thoughtSpotHost } = embedConfig;
11996
+ const loggedIn = await isLoggedIn(thoughtSpotHost);
11997
+ if (loggedIn) {
11998
+ if (isAtSSORedirectUrl()) {
11999
+ removeSSORedirectUrlMarker();
12000
+ }
12001
+ loggedInStatus = true;
12002
+ return;
12003
+ }
12004
+ // we have already tried authentication and it did not succeed, restore
12005
+ // the current URL to the original one and invoke the callback.
12006
+ if (isAtSSORedirectUrl()) {
12007
+ removeSSORedirectUrlMarker();
12008
+ loggedInStatus = false;
12009
+ return;
12010
+ }
12011
+ const ssoURL = `${thoughtSpotHost}${ssoEndPoint}`;
12012
+ if (embedConfig.inPopup) {
12013
+ await samlPopupFlow(ssoURL, embedConfig.authTriggerContainer, embedConfig.authTriggerText);
12014
+ loggedInStatus = await isLoggedIn(thoughtSpotHost);
12103
12015
  return;
12104
12016
  }
12105
- }
12017
+ window.location.href = ssoURL;
12018
+ };
12019
+ const doSamlAuth = async (embedConfig) => {
12020
+ const { thoughtSpotHost } = embedConfig;
12021
+ // redirect for SSO, when the SSO authentication is done, this page will be
12022
+ // loaded again and the same JS will execute again.
12023
+ const ssoRedirectUrl = embedConfig.inPopup
12024
+ ? `${thoughtSpotHost}/v2/#/embed/saml-complete`
12025
+ : getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
12026
+ // bring back the page to the same URL
12027
+ const ssoEndPoint = `${EndPoints.SAML_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
12028
+ await doSSOAuth(embedConfig, ssoEndPoint);
12029
+ return loggedInStatus;
12030
+ };
12031
+ const doOIDCAuth = async (embedConfig) => {
12032
+ const { thoughtSpotHost } = embedConfig;
12033
+ // redirect for SSO, when the SSO authentication is done, this page will be
12034
+ // loaded again and the same JS will execute again.
12035
+ const ssoRedirectUrl = embedConfig.noRedirect || embedConfig.inPopup
12036
+ ? `${thoughtSpotHost}/v2/#/embed/saml-complete`
12037
+ : getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
12038
+ // bring back the page to the same URL
12039
+ const ssoEndPoint = `${EndPoints.OIDC_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
12040
+ await doSSOAuth(embedConfig, ssoEndPoint);
12041
+ return loggedInStatus;
12042
+ };
12106
12043
  /**
12044
+ * Perform authentication on the ThoughtSpot cluster
12107
12045
  *
12108
- * @param failureType
12046
+ * @param embedConfig The embed configuration
12109
12047
  */
12110
- function notifyAuthFailure(failureType) {
12111
- {
12112
- console.error('SDK not initialized');
12113
- return;
12048
+ const authenticate = async (embedConfig) => {
12049
+ const { authType } = embedConfig;
12050
+ switch (authType) {
12051
+ case AuthType.SSO:
12052
+ case AuthType.SAMLRedirect:
12053
+ case AuthType.SAML:
12054
+ return doSamlAuth(embedConfig);
12055
+ case AuthType.OIDC:
12056
+ case AuthType.OIDCRedirect:
12057
+ return doOIDCAuth(embedConfig);
12058
+ case AuthType.AuthServer:
12059
+ case AuthType.TrustedAuthToken:
12060
+ return doTokenAuth(embedConfig);
12061
+ case AuthType.TrustedAuthTokenCookieless:
12062
+ return doCookielessTokenAuth(embedConfig);
12063
+ case AuthType.Basic:
12064
+ return doBasicAuth(embedConfig);
12065
+ default:
12066
+ return Promise.resolve(true);
12114
12067
  }
12115
- }
12068
+ };
12069
+
12070
+ /* eslint-disable camelcase */
12071
+ let config = {};
12072
+ const CONFIG_DEFAULTS = {
12073
+ loginFailedMessage: 'Not logged in',
12074
+ authTriggerText: 'Authorize',
12075
+ authType: AuthType.None,
12076
+ };
12077
+ let authPromise;
12116
12078
  /**
12079
+ * Gets the configuration embed was initialized with.
12117
12080
  *
12081
+ * @returns {@link EmbedConfig} The configuration embed was initialized with.
12082
+ * @version SDK: 1.19.0 | ThoughtSpot: *
12083
+ * @group Global methods
12118
12084
  */
12119
- function notifyLogout() {
12120
- {
12121
- console.error('SDK not initialized');
12122
- return;
12123
- }
12124
- }
12125
- const initSession = (sessionDetails) => {
12126
- if (sessionInfo == null) {
12127
- sessionInfo = sessionDetails;
12128
- initMixpanel(sessionInfo);
12129
- sessionInfoResolver(sessionInfo);
12130
- }
12085
+ const getEmbedConfig = () => config;
12086
+ const getAuthPromise = () => authPromise;
12087
+ /**
12088
+ * Perform authentication on the ThoughtSpot app as applicable.
12089
+ */
12090
+ const handleAuth = () => {
12091
+ authPromise = authenticate(config);
12092
+ authPromise.then((isLoggedIn) => {
12093
+ if (!isLoggedIn) {
12094
+ notifyAuthFailure(AuthFailureType.SDK);
12095
+ }
12096
+ else {
12097
+ notifyAuthSDKSuccess();
12098
+ }
12099
+ }, () => {
12100
+ notifyAuthFailure(AuthFailureType.SDK);
12101
+ });
12102
+ return authPromise;
12131
12103
  };
12132
- const getSessionDetails = (sessionInfoResp) => {
12133
- const devMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.devSdkKey;
12134
- const prodMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.prodSdkKey;
12135
- const mixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.production
12136
- ? prodMixpanelToken
12137
- : devMixpanelToken;
12138
- return {
12139
- userGUID: sessionInfoResp.userGUID,
12140
- mixpanelToken,
12141
- isPublicUser: sessionInfoResp.configInfo.isPublicUser,
12142
- releaseVersion: sessionInfoResp.releaseVersion,
12143
- clusterId: sessionInfoResp.configInfo.selfClusterId,
12144
- clusterName: sessionInfoResp.configInfo.selfClusterName,
12145
- ...sessionInfoResp,
12146
- };
12104
+ const hostUrlToFeatureUrl = {
12105
+ [PrefetchFeatures.SearchEmbed]: (url) => `${url}v2/#/embed/answer`,
12106
+ [PrefetchFeatures.LiveboardEmbed]: (url) => url,
12107
+ [PrefetchFeatures.FullApp]: (url) => url,
12108
+ [PrefetchFeatures.VizEmbed]: (url) => url,
12147
12109
  };
12148
12110
  /**
12149
- * Check if we are logged into the ThoughtSpot cluster
12150
12111
  *
12151
- * @param thoughtSpotHost The ThoughtSpot cluster hostname or IP
12152
- */
12153
- async function isLoggedIn(thoughtSpotHost) {
12154
- const authVerificationUrl = `${thoughtSpotHost}${EndPoints.AUTH_VERIFICATION}`;
12155
- let response = null;
12156
- try {
12157
- response = await fetchSessionInfoService(authVerificationUrl);
12158
- const sessionInfoResp = await response.json();
12159
- const sessionDetails = getSessionDetails(sessionInfoResp);
12160
- // Store user session details from session info
12161
- initSession(sessionDetails);
12162
- releaseVersion = sessionInfoResp.releaseVersion;
12163
- }
12164
- catch (e) {
12165
- return false;
12166
- }
12167
- return response.status === 200;
12168
- }
12169
- /**
12170
- * Return releaseVersion if available
12171
12112
  */
12172
- function getReleaseVersion() {
12173
- return releaseVersion;
12113
+ function disableAutoLogin() {
12114
+ config.autoLogin = false;
12174
12115
  }
12175
- const DUPLICATE_TOKEN_ERR = 'Duplicate token, please issue a new token every time getAuthToken callback is called.'
12176
- + 'See https://developers.thoughtspot.com/docs/?pageid=embed-auth#trusted-auth-embed for more details.';
12177
- let prevAuthToken = null;
12116
+ let renderQueue = Promise.resolve();
12178
12117
  /**
12118
+ * Renders functions in a queue, resolves to next function only after the callback next
12119
+ * is called
12179
12120
  *
12180
- * @param authtoken
12121
+ * @param fn The function being registered
12181
12122
  */
12182
- function alertForDuplicateToken(authtoken) {
12183
- if (prevAuthToken === authtoken) {
12184
- // eslint-disable-next-line no-alert
12185
- alert(DUPLICATE_TOKEN_ERR);
12186
- throw new Error(DUPLICATE_TOKEN_ERR);
12123
+ const renderInQueue = (fn) => {
12124
+ const { queueMultiRenders = false } = config;
12125
+ if (queueMultiRenders) {
12126
+ renderQueue = renderQueue.then(() => new Promise((res) => fn(res)));
12127
+ return renderQueue;
12187
12128
  }
12188
- prevAuthToken = authtoken;
12189
- }
12129
+ // Sending an empty function to keep it consistent with the above usage.
12130
+ return fn(() => { }); // eslint-disable-line @typescript-eslint/no-empty-function
12131
+ };
12132
+
12133
+ const tokenizedFetch = async (input, init) => {
12134
+ const req = new Request(input, init);
12135
+ const embedConfig = getEmbedConfig();
12136
+ if (embedConfig.authType !== AuthType.TrustedAuthTokenCookieless) {
12137
+ return fetch(req);
12138
+ }
12139
+ const authToken = await getAuthenticationToken(embedConfig);
12140
+ if (authToken) {
12141
+ req.headers.append('Authorization', `Bearer ${authToken}`);
12142
+ }
12143
+ return fetch(req);
12144
+ };
12145
+
12190
12146
  /**
12191
- * Check if we are stuck at the SSO redirect URL
12147
+ *
12148
+ * @param root0
12149
+ * @param root0.query
12150
+ * @param root0.variables
12151
+ * @param root0.thoughtSpotHost
12152
+ * @param root0.isCompositeQuery
12192
12153
  */
12193
- function isAtSSORedirectUrl() {
12194
- return window.location.href.indexOf(SSO_REDIRECTION_MARKER_GUID) >= 0;
12195
- }
12154
+ async function graphqlQuery({ query, variables, thoughtSpotHost, isCompositeQuery = false, }) {
12155
+ const operationName = getOperationNameFromQuery(query);
12156
+ try {
12157
+ const response = await fetch(`${thoughtSpotHost}/prism/?op=${operationName}`, {
12158
+ method: 'POST',
12159
+ headers: {
12160
+ 'content-type': 'application/json;charset=UTF-8',
12161
+ 'x-requested-by': 'ThoughtSpot',
12162
+ accept: '*/*',
12163
+ 'accept-language': 'en-us',
12164
+ },
12165
+ body: JSON.stringify({
12166
+ operationName,
12167
+ query,
12168
+ variables,
12169
+ }),
12170
+ credentials: 'include',
12171
+ });
12172
+ const result = await response.json();
12173
+ const dataValues = Object.values(result.data);
12174
+ return (isCompositeQuery) ? result.data : dataValues[0];
12175
+ }
12176
+ catch (error) {
12177
+ return error;
12178
+ }
12179
+ }
12180
+
12181
+ const getSourceDetailQuery = `
12182
+ query GetSourceDetail($ids: [GUID!]!) {
12183
+ getSourceDetailById(ids: $ids, type: LOGICAL_TABLE) {
12184
+ id
12185
+ name
12186
+ description
12187
+ authorName
12188
+ authorDisplayName
12189
+ isExternal
12190
+ type
12191
+ created
12192
+ modified
12193
+ columns {
12194
+ id
12195
+ name
12196
+ author
12197
+ authorDisplayName
12198
+ description
12199
+ dataType
12200
+ type
12201
+ modified
12202
+ ownerName
12203
+ owner
12204
+ dataRecency
12205
+ sources {
12206
+ tableId
12207
+ tableName
12208
+ columnId
12209
+ columnName
12210
+ __typename
12211
+ }
12212
+ synonyms
12213
+ cohortAnswerId
12214
+ __typename
12215
+ }
12216
+ relationships
12217
+ destinationRelationships
12218
+ dataSourceId
12219
+ __typename
12220
+ }
12221
+ }
12222
+ `;
12223
+ const sourceDetailCache = new Map();
12196
12224
  /**
12197
- * Remove the SSO redirect URL marker
12225
+ *
12226
+ * @param thoughtSpotHost
12227
+ * @param sourceId
12198
12228
  */
12199
- function removeSSORedirectUrlMarker() {
12200
- // Note (sunny): This will leave a # around even if it was not in the URL
12201
- // to begin with. Trying to remove the hash by changing window.location will
12202
- // reload the page which we don't want. We'll live with adding an
12203
- // unnecessary hash to the parent page URL until we find any use case where
12204
- // that creates an issue.
12205
- window.location.hash = window.location.hash.replace(SSO_REDIRECTION_MARKER_GUID, '');
12206
- }
12207
- const getAuthenticationToken = async (embedConfig) => {
12208
- const { authEndpoint, getAuthToken } = embedConfig;
12209
- let authToken = null;
12210
- if (getAuthToken) {
12211
- authToken = await getAuthToken();
12212
- alertForDuplicateToken(authToken);
12229
+ async function getSourceDetail(thoughtSpotHost, sourceId) {
12230
+ if (sourceDetailCache.get(sourceId)) {
12231
+ return sourceDetailCache.get(sourceId);
12213
12232
  }
12214
- else {
12215
- const response = await fetchAuthTokenService(authEndpoint);
12216
- authToken = await response.text();
12233
+ const details = await graphqlQuery({
12234
+ query: getSourceDetailQuery,
12235
+ variables: {
12236
+ ids: [sourceId],
12237
+ },
12238
+ thoughtSpotHost,
12239
+ });
12240
+ const souceDetails = details[0];
12241
+ if (souceDetails) {
12242
+ sourceDetailCache.set(sourceId, souceDetails);
12217
12243
  }
12218
- return authToken;
12219
- };
12244
+ return souceDetails;
12245
+ }
12246
+
12247
+ const bachSessionId = `
12248
+ id {
12249
+ sessionId
12250
+ genNo
12251
+ acSession {
12252
+ sessionId
12253
+ genNo
12254
+ }
12255
+ }
12256
+ `;
12257
+ const getUnaggregatedAnswerSession = `
12258
+ mutation GetUnAggregatedAnswerSession($session: BachSessionIdInput!, $columns: [UserPointSelectionInput!]!) {
12259
+ Answer__getUnaggregatedAnswer(session: $session, columns: $columns) {
12260
+ ${bachSessionId}
12261
+ answer {
12262
+ visualizations {
12263
+ ... on TableViz {
12264
+ columns {
12265
+ column {
12266
+ id
12267
+ name
12268
+ referencedColumns {
12269
+ guid
12270
+ displayName
12271
+ }
12272
+ }
12273
+ }
12274
+ }
12275
+ }
12276
+ }
12277
+ }
12278
+ }
12279
+ `;
12280
+ const removeColumns = `
12281
+ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!], $columnIds: [GUID!]) {
12282
+ Answer__removeColumns(
12283
+ session: $session
12284
+ logicalColumnIds: $logicalColumnIds
12285
+ columnIds: $columnIds
12286
+ ) {
12287
+ ${bachSessionId}
12288
+ }
12289
+ }
12290
+ `;
12291
+ const addColumns = `
12292
+ mutation AddColumns($session: BachSessionIdInput!, $columns: [AnswerColumnInfo!]!) {
12293
+ Answer__addColumn(session: $session, columns: $columns) {
12294
+ ${bachSessionId}
12295
+ }
12296
+ }
12297
+ `;
12298
+ const getAnswerData = `
12299
+ query GetTableWithHeadlineData($session: BachSessionIdInput!, $deadline: Int!, $dataPaginationParams: DataPaginationParamsInput!) {
12300
+ getAnswer(session: $session) {
12301
+ ${bachSessionId}
12302
+ answer {
12303
+ id
12304
+ visualizations {
12305
+ id
12306
+ ... on TableViz {
12307
+ columns {
12308
+ column {
12309
+ id
12310
+ name
12311
+ type
12312
+ aggregationType
12313
+ dataType
12314
+ }
12315
+ }
12316
+ data(deadline: $deadline, pagination: $dataPaginationParams)
12317
+ }
12318
+ }
12319
+ }
12320
+ }
12321
+ }
12322
+ `;
12323
+
12324
+ // eslint-disable-next-line no-shadow
12325
+ var OperationType;
12326
+ (function (OperationType) {
12327
+ OperationType["GetChartWithData"] = "GetChartWithData";
12328
+ OperationType["GetTableWithHeadlineData"] = "GetTableWithHeadlineData";
12329
+ })(OperationType || (OperationType = {}));
12220
12330
  /**
12221
- * Perform token based authentication
12331
+ * Class representing the answer service provided with the
12332
+ * custom action payload. This service could be used to run
12333
+ * graphql queries in the context of the answer on which the
12334
+ * custom action was triggered.
12222
12335
  *
12223
- * @param embedConfig The embed configuration
12336
+ * @example
12337
+ * ```js
12338
+ * embed.on(EmbedEvent.CustomAction, e => {
12339
+ * const underlying = await e.answerService.getUnderlyingDataForPoint([
12340
+ * 'col name 1'
12341
+ * ]);
12342
+ * const data = await underlying.fetchData(0, 100);
12343
+ * })
12344
+ * ```
12345
+ * @version
12346
+ * ThoughtSpot: 9.9.0.cl / SDK: 1.25.0
12347
+ * @group Events
12224
12348
  */
12225
- const doTokenAuth = async (embedConfig) => {
12226
- const { thoughtSpotHost, username, authEndpoint, getAuthToken, } = embedConfig;
12227
- if (!authEndpoint && !getAuthToken) {
12228
- throw new Error('Either auth endpoint or getAuthToken function must be provided');
12349
+ class AnswerService {
12350
+ constructor(session, answer, thoughtSpotHost, selectedPoints) {
12351
+ this.session = session;
12352
+ this.answer = answer;
12353
+ this.thoughtSpotHost = thoughtSpotHost;
12354
+ this.selectedPoints = selectedPoints;
12355
+ this.session = removeTypename(session);
12229
12356
  }
12230
- loggedInStatus = await isLoggedIn(thoughtSpotHost);
12231
- if (!loggedInStatus) {
12232
- const authToken = await getAuthenticationToken(embedConfig);
12233
- let resp;
12234
- try {
12235
- resp = await fetchAuthPostService(thoughtSpotHost, username, authToken);
12236
- }
12237
- catch (e) {
12238
- resp = await fetchAuthService(thoughtSpotHost, username, authToken);
12239
- }
12240
- // token login issues a 302 when successful
12241
- loggedInStatus = resp.ok || resp.type === 'opaqueredirect';
12242
- if (loggedInStatus && embedConfig.detectCookieAccessSlow) {
12243
- // When 3rd party cookie access is blocked, this will fail because
12244
- // cookies will not be sent with the call.
12245
- loggedInStatus = await isLoggedIn(thoughtSpotHost);
12246
- }
12357
+ async getSourceDetail() {
12358
+ const sourceId = this.answer.sources[0].header.guid;
12359
+ return getSourceDetail(this.thoughtSpotHost, sourceId);
12247
12360
  }
12248
- return loggedInStatus;
12249
- };
12250
- /**
12251
- * Validate embedConfig parameters required for cookielessTokenAuth
12252
- *
12253
- * @param embedConfig The embed configuration
12254
- */
12255
- const doCookielessTokenAuth = async (embedConfig) => {
12256
- const { authEndpoint, getAuthToken } = embedConfig;
12257
- if (!authEndpoint && !getAuthToken) {
12258
- throw new Error('Either auth endpoint or getAuthToken function must be provided');
12361
+ async removeColumns(columnIds) {
12362
+ return this.executeQuery(removeColumns, {
12363
+ logicalColumnIds: columnIds,
12364
+ });
12259
12365
  }
12260
- try {
12261
- const authToken = await getAuthenticationToken(embedConfig);
12262
- const response = await verifyTokenService(embedConfig.thoughtSpotHost, authToken);
12263
- if (!response.ok)
12264
- return false;
12366
+ async addColumns(columnIds) {
12367
+ return this.executeQuery(addColumns, {
12368
+ columns: columnIds.map((colId) => ({ logicalColumnId: colId })),
12369
+ });
12265
12370
  }
12266
- catch (e) {
12267
- return false;
12371
+ async fetchData(offset = 0, size = 1000) {
12372
+ const { answer } = await this.executeQuery(getAnswerData, {
12373
+ deadline: 0,
12374
+ dataPaginationParams: {
12375
+ isClientPaginated: true,
12376
+ offset,
12377
+ size,
12378
+ },
12379
+ });
12380
+ const { columns, data } = answer.visualizations[0];
12381
+ return {
12382
+ columns,
12383
+ data,
12384
+ };
12268
12385
  }
12269
- return true;
12270
- };
12271
- /**
12272
- * Perform basic authentication to the ThoughtSpot cluster using the cluster
12273
- * credentials.
12274
- *
12275
- * Warning: This feature is primarily intended for developer testing. It is
12276
- * strongly advised not to use this authentication method in production.
12277
- *
12278
- * @param embedConfig The embed configuration
12279
- */
12280
- const doBasicAuth = async (embedConfig) => {
12281
- const { thoughtSpotHost, username, password } = embedConfig;
12282
- const loggedIn = await isLoggedIn(thoughtSpotHost);
12283
- if (!loggedIn) {
12284
- const response = await fetchBasicAuthService(thoughtSpotHost, username, password);
12285
- loggedInStatus = response.ok;
12286
- if (embedConfig.detectCookieAccessSlow) {
12287
- loggedInStatus = await isLoggedIn(thoughtSpotHost);
12288
- }
12386
+ /**
12387
+ *
12388
+ * @param userLocale
12389
+ * @param includeInfo Include the CSV header in the output
12390
+ * @returns Response
12391
+ */
12392
+ async fetchCSVBlob(userLocale = 'en-us', includeInfo = false) {
12393
+ const fetchUrl = this.getFetchCSVBlobUrl(userLocale, includeInfo);
12394
+ return tokenizedFetch(fetchUrl, {
12395
+ credentials: 'include',
12396
+ });
12289
12397
  }
12290
- else {
12291
- loggedInStatus = true;
12398
+ getFetchCSVBlobUrl(userLocale = 'en-us', includeInfo = false) {
12399
+ return `${this.thoughtSpotHost}/prism/download/answer/csv?sessionId=${this.session.sessionId}&genNo=${this.session.genNo}&userLocale=${userLocale}&exportFileName=data&hideCsvHeader=${!includeInfo}`;
12292
12400
  }
12293
- return loggedInStatus;
12294
- };
12295
- /**
12296
- *
12297
- * @param ssoURL
12298
- * @param triggerContainer
12299
- * @param triggerText
12300
- */
12301
- async function samlPopupFlow(ssoURL, triggerContainer, triggerText) {
12302
- const openPopup = () => {
12303
- if (samlAuthWindow === null || samlAuthWindow.closed) {
12304
- samlAuthWindow = window.open(ssoURL, '_blank', 'location=no,height=570,width=520,scrollbars=yes,status=yes');
12401
+ /**
12402
+ * Get underlying data given a point and the output column names.
12403
+ *
12404
+ * @param outputColumnNames
12405
+ * @param selectedPoints
12406
+ * @example
12407
+ * ```js
12408
+ * embed.on(EmbedEvent.CustomAction, e => {
12409
+ * const underlying = await e.answerService.getUnderlyingDataForPoint([
12410
+ * 'col name 1' // The column should exist in the data source.
12411
+ * ]);
12412
+ * const data = await underlying.fetchData(0, 100);
12413
+ * })
12414
+ * ```
12415
+ * @version
12416
+ * ThoughtSpot: 9.9.0.cl / SDK: 1.25.0
12417
+ */
12418
+ async getUnderlyingDataForPoint(outputColumnNames, selectedPoints) {
12419
+ if (!selectedPoints && !this.selectedPoints) {
12420
+ throw new Error('Needs to be triggered in context of a point');
12305
12421
  }
12306
- else {
12307
- samlAuthWindow.focus();
12422
+ if (!selectedPoints) {
12423
+ selectedPoints = getSelectedPointsForUnderlyingDataQuery(this.selectedPoints);
12308
12424
  }
12309
- };
12310
- const containerEl = getDOMNode(triggerContainer);
12311
- if (containerEl) {
12312
- containerEl.innerHTML = '<button id="ts-auth-btn" class="ts-auth-btn" style="margin: auto;"></button>';
12313
- const authElem = document.getElementById('ts-auth-btn');
12314
- authElem.textContent = triggerText;
12315
- authElem.addEventListener('click', openPopup, { once: true });
12316
- }
12317
- samlCompletionPromise = samlCompletionPromise
12318
- || new Promise((resolve, reject) => {
12319
- window.addEventListener('message', (e) => {
12320
- if (e.data.type === exports.EmbedEvent.SAMLComplete) {
12321
- e.source.close();
12322
- resolve();
12323
- }
12324
- });
12425
+ const sourceDetail = await this.getSourceDetail();
12426
+ const ouputColumnGuids = getGuidsFromColumnNames(sourceDetail, outputColumnNames);
12427
+ const unAggAnswer = await graphqlQuery({
12428
+ query: getUnaggregatedAnswerSession,
12429
+ variables: {
12430
+ session: this.session,
12431
+ columns: selectedPoints,
12432
+ },
12433
+ thoughtSpotHost: this.thoughtSpotHost,
12325
12434
  });
12326
- return samlCompletionPromise;
12327
- }
12328
- /**
12329
- * Perform SAML authentication
12330
- *
12331
- * @param embedConfig The embed configuration
12332
- * @param ssoEndPoint
12333
- */
12334
- const doSSOAuth = async (embedConfig, ssoEndPoint) => {
12335
- const { thoughtSpotHost } = embedConfig;
12336
- const loggedIn = await isLoggedIn(thoughtSpotHost);
12337
- if (loggedIn) {
12338
- if (isAtSSORedirectUrl()) {
12339
- removeSSORedirectUrlMarker();
12435
+ const unaggAnswerSession = new AnswerService(unAggAnswer.id, unAggAnswer.answer, this.thoughtSpotHost);
12436
+ const currentColumns = new Set(unAggAnswer.answer.visualizations[0].columns
12437
+ .map((c) => c.column.referencedColumns[0].guid));
12438
+ const columnsToAdd = [...ouputColumnGuids].filter((col) => !currentColumns.has(col));
12439
+ if (columnsToAdd.length) {
12440
+ await unaggAnswerSession.addColumns(columnsToAdd);
12340
12441
  }
12341
- loggedInStatus = true;
12342
- return;
12442
+ const columnsToRemove = [...currentColumns].filter((col) => !ouputColumnGuids.has(col));
12443
+ if (columnsToRemove.length) {
12444
+ await unaggAnswerSession.removeColumns(columnsToRemove);
12445
+ }
12446
+ return unaggAnswerSession;
12343
12447
  }
12344
- // we have already tried authentication and it did not succeed, restore
12345
- // the current URL to the original one and invoke the callback.
12346
- if (isAtSSORedirectUrl()) {
12347
- removeSSORedirectUrlMarker();
12348
- loggedInStatus = false;
12349
- return;
12448
+ async executeQuery(query, variables) {
12449
+ const data = await graphqlQuery({
12450
+ query,
12451
+ variables: {
12452
+ session: this.session,
12453
+ ...variables,
12454
+ },
12455
+ thoughtSpotHost: this.thoughtSpotHost,
12456
+ isCompositeQuery: false,
12457
+ });
12458
+ this.session = deepMerge(this.session, (data === null || data === void 0 ? void 0 : data.id) || {});
12459
+ return data;
12350
12460
  }
12351
- const ssoURL = `${thoughtSpotHost}${ssoEndPoint}`;
12352
- if (embedConfig.inPopup) {
12353
- await samlPopupFlow(ssoURL, embedConfig.authTriggerContainer, embedConfig.authTriggerText);
12354
- loggedInStatus = await isLoggedIn(thoughtSpotHost);
12355
- return;
12461
+ getSession() {
12462
+ return this.session;
12356
12463
  }
12357
- window.location.href = ssoURL;
12358
- };
12359
- const doSamlAuth = async (embedConfig) => {
12360
- const { thoughtSpotHost } = embedConfig;
12361
- // redirect for SSO, when the SSO authentication is done, this page will be
12362
- // loaded again and the same JS will execute again.
12363
- const ssoRedirectUrl = embedConfig.inPopup
12364
- ? `${thoughtSpotHost}/v2/#/embed/saml-complete`
12365
- : getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
12366
- // bring back the page to the same URL
12367
- const ssoEndPoint = `${EndPoints.SAML_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
12368
- await doSSOAuth(embedConfig, ssoEndPoint);
12369
- return loggedInStatus;
12370
- };
12371
- const doOIDCAuth = async (embedConfig) => {
12372
- const { thoughtSpotHost } = embedConfig;
12373
- // redirect for SSO, when the SSO authentication is done, this page will be
12374
- // loaded again and the same JS will execute again.
12375
- const ssoRedirectUrl = embedConfig.noRedirect || embedConfig.inPopup
12376
- ? `${thoughtSpotHost}/v2/#/embed/saml-complete`
12377
- : getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
12378
- // bring back the page to the same URL
12379
- const ssoEndPoint = `${EndPoints.OIDC_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
12380
- await doSSOAuth(embedConfig, ssoEndPoint);
12381
- return loggedInStatus;
12382
- };
12464
+ }
12383
12465
  /**
12384
- * Perform authentication on the ThoughtSpot cluster
12385
12466
  *
12386
- * @param embedConfig The embed configuration
12467
+ * @param sourceDetail
12468
+ * @param colNames
12387
12469
  */
12388
- const authenticate = async (embedConfig) => {
12389
- const { authType } = embedConfig;
12390
- switch (authType) {
12391
- case AuthType.SSO:
12392
- case AuthType.SAMLRedirect:
12393
- case AuthType.SAML:
12394
- return doSamlAuth(embedConfig);
12395
- case AuthType.OIDC:
12396
- case AuthType.OIDCRedirect:
12397
- return doOIDCAuth(embedConfig);
12398
- case AuthType.AuthServer:
12399
- case AuthType.TrustedAuthToken:
12400
- return doTokenAuth(embedConfig);
12401
- case AuthType.TrustedAuthTokenCookieless:
12402
- return doCookielessTokenAuth(embedConfig);
12403
- case AuthType.Basic:
12404
- return doBasicAuth(embedConfig);
12405
- default:
12406
- return Promise.resolve(true);
12407
- }
12408
- };
12409
-
12410
- /* eslint-disable camelcase */
12411
- let config = {};
12412
- const CONFIG_DEFAULTS = {
12413
- loginFailedMessage: 'Not logged in',
12414
- authTriggerText: 'Authorize',
12415
- authType: AuthType.None,
12416
- };
12417
- let authPromise;
12470
+ function getGuidsFromColumnNames(sourceDetail, colNames) {
12471
+ const cols = sourceDetail.columns.reduce((colSet, col) => {
12472
+ colSet[col.name] = col;
12473
+ return colSet;
12474
+ }, {});
12475
+ return new Set(colNames.map((colName) => {
12476
+ const col = cols[colName];
12477
+ return col.id;
12478
+ }));
12479
+ }
12418
12480
  /**
12419
- * Gets the configuration embed was initialized with.
12420
12481
  *
12421
- * @returns {@link EmbedConfig} The configuration embed was initialized with.
12422
- * @version SDK: 1.19.0 | ThoughtSpot: *
12423
- * @group Global methods
12424
- */
12425
- const getEmbedConfig = () => config;
12426
- const getAuthPromise = () => authPromise;
12427
- /**
12428
- * Perform authentication on the ThoughtSpot app as applicable.
12482
+ * @param selectedPoints
12429
12483
  */
12430
- const handleAuth = () => {
12431
- authPromise = authenticate(config);
12432
- authPromise.then((isLoggedIn) => {
12433
- if (!isLoggedIn) {
12434
- notifyAuthFailure(AuthFailureType.SDK);
12484
+ function getSelectedPointsForUnderlyingDataQuery(selectedPoints) {
12485
+ const underlyingDataPoint = [];
12486
+ /**
12487
+ *
12488
+ * @param colVal
12489
+ */
12490
+ function addPointFromColVal(colVal) {
12491
+ var _a;
12492
+ const dataType = colVal.column.dataType;
12493
+ const id = colVal.column.id;
12494
+ let dataValue;
12495
+ if (dataType === 'DATE') {
12496
+ if (Number.isFinite(colVal.value)) {
12497
+ dataValue = [{
12498
+ epochRange: {
12499
+ startEpoch: colVal.value,
12500
+ },
12501
+ }];
12502
+ // Case for custom calendar.
12503
+ }
12504
+ else if ((_a = colVal.value) === null || _a === void 0 ? void 0 : _a.v) {
12505
+ dataValue = [{
12506
+ epochRange: {
12507
+ startEpoch: colVal.value.v.s,
12508
+ endEpoch: colVal.value.v.e,
12509
+ },
12510
+ }];
12511
+ }
12435
12512
  }
12436
12513
  else {
12437
- notifyAuthSDKSuccess();
12514
+ dataValue = [{ value: colVal.value }];
12438
12515
  }
12439
- }, () => {
12440
- notifyAuthFailure(AuthFailureType.SDK);
12441
- });
12442
- return authPromise;
12443
- };
12444
- const hostUrlToFeatureUrl = {
12445
- [PrefetchFeatures.SearchEmbed]: (url) => `${url}v2/#/embed/answer`,
12446
- [PrefetchFeatures.LiveboardEmbed]: (url) => url,
12447
- [PrefetchFeatures.FullApp]: (url) => url,
12448
- [PrefetchFeatures.VizEmbed]: (url) => url,
12449
- };
12450
- /**
12451
- *
12452
- */
12453
- function disableAutoLogin() {
12454
- config.autoLogin = false;
12455
- }
12456
- let renderQueue = Promise.resolve();
12457
- /**
12458
- * Renders functions in a queue, resolves to next function only after the callback next
12459
- * is called
12460
- *
12461
- * @param fn The function being registered
12462
- */
12463
- const renderInQueue = (fn) => {
12464
- const { queueMultiRenders = false } = config;
12465
- if (queueMultiRenders) {
12466
- renderQueue = renderQueue.then(() => new Promise((res) => fn(res)));
12467
- return renderQueue;
12516
+ underlyingDataPoint.push({
12517
+ columnId: colVal.column.id,
12518
+ dataValue,
12519
+ });
12468
12520
  }
12469
- // Sending an empty function to keep it consistent with the above usage.
12470
- return fn(() => { }); // eslint-disable-line @typescript-eslint/no-empty-function
12471
- };
12521
+ selectedPoints.forEach((p) => {
12522
+ p.selectedAttributes.forEach(addPointFromColVal);
12523
+ });
12524
+ return underlyingDataPoint;
12525
+ }
12472
12526
 
12473
12527
  /**
12474
12528
  *
@@ -12506,9 +12560,9 @@ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!]
12506
12560
  * @param containerEl
12507
12561
  */
12508
12562
  function processNoCookieAccess(e, containerEl) {
12509
- const { loginFailedMessage, suppressNoCookieAccessAlert, ignoreNoCookieAccess, } = getEmbedConfig();
12563
+ const { loginFailedMessage, suppressNoCookieAccessAlert, ignoreNoCookieAccess, suppressErrorAlerts, } = getEmbedConfig();
12510
12564
  if (!ignoreNoCookieAccess) {
12511
- if (!suppressNoCookieAccessAlert) {
12565
+ if (!suppressNoCookieAccessAlert && !suppressErrorAlerts) {
12512
12566
  // eslint-disable-next-line no-alert
12513
12567
  alert('Third party cookie access is blocked on this browser, please allow third party cookies for this to work properly. \nYou can use `suppressNoCookieAccessAlert` to suppress this message.');
12514
12568
  }
@@ -12626,7 +12680,7 @@ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!]
12626
12680
  });
12627
12681
  }
12628
12682
 
12629
- var name="@thoughtspot/visual-embed-sdk";var version="1.25.0";var description="ThoughtSpot Embed SDK";var module="lib/src/index.js";var main="dist/tsembed.js";var types="lib/src/index.d.ts";var files=["dist/**","lib/**","src/**","cjs/**"];var exports$1={".":{"import":"./lib/src/index.js",require:"./cjs/src/index.js",types:"./lib/src/index.d.ts"},"./react":{"import":"./lib/src/react/all-types-export.js",require:"./cjs/src/react/all-types-export.js",types:"./lib/src/react/all-types-export.d.ts"},"./lib/src/react":{"import":"./lib/src/react/all-types-export.js",require:"./cjs/src/react/all-types-export.js",types:"./lib/src/react/all-types-export.d.ts"}};var typesVersions={"*":{react:["./lib/src/react/all-types-export.d.ts"]}};var scripts={lint:"eslint 'src/**'","lint:fix":"eslint 'src/**/*.*' --fix",tsc:"tsc -p . --incremental false; tsc -p . --incremental false --module commonjs --outDir cjs",start:"gatsby develop","build:gatsby":"npm run clean:gatsby && gatsby build --prefix-paths","build:gatsby:noprefix":"npm run clean:gatsby && gatsby build","serve:gatsby":"gatsby serve","clean:gatsby":"gatsby clean","build-and-publish":"npm run build:gatsby && npm run publish","bundle-dts-file":"dts-bundle --name @thoughtspot/visual-embed-sdk --out visual-embed-sdk.d.ts --main lib/src/index.d.ts","bundle-dts":"dts-bundle --name ../../dist/visual-embed-sdk --main lib/src/index.d.ts --outputAsModuleFolder=true","bundle-dts-react":"dts-bundle --name ../../../dist/visual-embed-sdk-react --main lib/src/react/index.d.ts --outputAsModuleFolder=true","bundle-dts-react-full":"dts-bundle --name ../../../dist/visual-embed-sdk-react-full --main lib/src/react/all-types-export.d.ts --outputAsModuleFolder=true",build:"rollup -c",watch:"rollup -cw","docs-cmd":"node scripts/gatsby-commands.js",docgen:"typedoc --tsconfig tsconfig.json --theme typedoc-theme","test-sdk":"jest -c jest.config.sdk.js --runInBand","test-docs":"jest -c jest.config.docs.js",test:"npm run test-sdk && npm run test-docs",posttest:"cat ./coverage/sdk/lcov.info | coveralls","is-publish-allowed":"node scripts/is-publish-allowed.js",prepublishOnly:"npm run is-publish-allowed && npm run test && npm run tsc && npm run bundle-dts-file && npm run bundle-dts && npm run bundle-dts-react && npm run bundle-dts-react-full && npm run build","check-size":"npm run build && size-limit","publish-dev":"npm publish --tag dev","publish-prod":"npm publish --tag latest"};var peerDependencies={react:"> 16.8.0","react-dom":"> 16.8.0"};var dependencies={algoliasearch:"^4.10.5",classnames:"^2.3.1",dompurify:"^2.3.4","eslint-plugin-comment-length":"^0.9.2","eslint-plugin-jsdoc":"^40.1.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:"43 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};
12683
+ var name="@thoughtspot/visual-embed-sdk";var version="1.26.0-token-cache.0";var description="ThoughtSpot Embed SDK";var module="lib/src/index.js";var main="dist/tsembed.js";var types="lib/src/index.d.ts";var files=["dist/**","lib/**","src/**","cjs/**"];var exports$1={".":{"import":"./lib/src/index.js",require:"./cjs/src/index.js",types:"./lib/src/index.d.ts"},"./react":{"import":"./lib/src/react/all-types-export.js",require:"./cjs/src/react/all-types-export.js",types:"./lib/src/react/all-types-export.d.ts"},"./lib/src/react":{"import":"./lib/src/react/all-types-export.js",require:"./cjs/src/react/all-types-export.js",types:"./lib/src/react/all-types-export.d.ts"}};var typesVersions={"*":{react:["./lib/src/react/all-types-export.d.ts"]}};var scripts={lint:"eslint 'src/**'","lint:fix":"eslint 'src/**/*.*' --fix",tsc:"tsc -p . --incremental false; tsc -p . --incremental false --module commonjs --outDir cjs",start:"gatsby develop","build:gatsby":"npm run clean:gatsby && gatsby build --prefix-paths","build:gatsby:noprefix":"npm run clean:gatsby && gatsby build","serve:gatsby":"gatsby serve","clean:gatsby":"gatsby clean","build-and-publish":"npm run build:gatsby && npm run publish","bundle-dts-file":"dts-bundle --name @thoughtspot/visual-embed-sdk --out visual-embed-sdk.d.ts --main lib/src/index.d.ts","bundle-dts":"dts-bundle --name ../../dist/visual-embed-sdk --main lib/src/index.d.ts --outputAsModuleFolder=true","bundle-dts-react":"dts-bundle --name ../../../dist/visual-embed-sdk-react --main lib/src/react/index.d.ts --outputAsModuleFolder=true","bundle-dts-react-full":"dts-bundle --name ../../../dist/visual-embed-sdk-react-full --main lib/src/react/all-types-export.d.ts --outputAsModuleFolder=true",build:"rollup -c",watch:"rollup -cw","docs-cmd":"node scripts/gatsby-commands.js",docgen:"typedoc --tsconfig tsconfig.json --theme typedoc-theme","test-sdk":"jest -c jest.config.sdk.js --runInBand","test-docs":"jest -c jest.config.docs.js",test:"npm run test-sdk && npm run test-docs",posttest:"cat ./coverage/sdk/lcov.info | coveralls","is-publish-allowed":"node scripts/is-publish-allowed.js",prepublishOnly:"npm run is-publish-allowed && npm run test && npm run tsc && npm run bundle-dts-file && npm run bundle-dts && npm run bundle-dts-react && npm run bundle-dts-react-full && npm run build","check-size":"npm run build && size-limit","publish-dev":"npm publish --tag dev","publish-prod":"npm publish --tag latest"};var peerDependencies={react:"> 16.8.0","react-dom":"> 16.8.0"};var dependencies={algoliasearch:"^4.10.5",classnames:"^2.3.1",dompurify:"^2.3.4","eslint-plugin-comment-length":"^0.9.2","eslint-plugin-jsdoc":"^40.1.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:"43 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};
12630
12684
 
12631
12685
  /**
12632
12686
  * Copyright (c) 2022
@@ -13837,7 +13891,7 @@ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!]
13837
13891
  }
13838
13892
  getEmbedParams() {
13839
13893
  var _a;
13840
- const { hideResults, expandAllDataSource, enableSearchAssist, forceTable, searchOptions, runtimeFilters, dataSource, dataSources, excludeRuntimeFiltersfromURL, dataPanelV2 = false, useLastSelectedSources = false, runtimeParameters, } = this.viewConfig;
13894
+ const { hideResults, enableSearchAssist, forceTable, searchOptions, runtimeFilters, dataSource, dataSources, excludeRuntimeFiltersfromURL, dataPanelV2 = false, useLastSelectedSources = false, runtimeParameters, } = this.viewConfig;
13841
13895
  const queryParams = this.getBaseQueryParams();
13842
13896
  queryParams[Param.HideActions] = [
13843
13897
  ...((_a = queryParams[Param.HideActions]) !== null && _a !== void 0 ? _a : []),
@@ -13906,7 +13960,8 @@ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!]
13906
13960
  const src = this.getIFrameSrc(answerId);
13907
13961
  this.renderIFrame(src);
13908
13962
  getAuthPromise().then(() => {
13909
- if (checkReleaseVersionInBeta(getReleaseVersion(), getEmbedConfig().suppressSearchEmbedBetaWarning)) {
13963
+ if (checkReleaseVersionInBeta(getReleaseVersion(), getEmbedConfig().suppressSearchEmbedBetaWarning
13964
+ || getEmbedConfig().suppressErrorAlerts)) {
13910
13965
  alert(ERROR_MESSAGE.SEARCHEMBED_BETA_WRANING_MESSAGE);
13911
13966
  }
13912
13967
  });