@thoughtspot/visual-embed-sdk 1.27.8 → 1.28.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/cjs/package.json +1 -1
- package/cjs/src/auth.d.ts.map +1 -1
- package/cjs/src/auth.js +2 -2
- package/cjs/src/auth.js.map +1 -1
- package/cjs/src/embed/base.d.ts +1 -1
- package/cjs/src/embed/base.d.ts.map +1 -1
- package/cjs/src/embed/base.js +5 -5
- package/cjs/src/embed/base.js.map +1 -1
- package/cjs/src/embed/base.spec.js +1 -1
- package/cjs/src/embed/base.spec.js.map +1 -1
- package/cjs/src/embed/sage.d.ts +5 -5
- package/cjs/src/embed/sage.d.ts.map +1 -1
- package/cjs/src/embed/sage.js +1 -16
- package/cjs/src/embed/sage.js.map +1 -1
- package/cjs/src/embed/sage.spec.js +11 -11
- package/cjs/src/embed/sage.spec.js.map +1 -1
- package/cjs/src/embed/search.d.ts +1 -5
- package/cjs/src/embed/search.d.ts.map +1 -1
- package/cjs/src/embed/search.js +4 -4
- package/cjs/src/embed/search.js.map +1 -1
- package/cjs/src/embed/ts-embed.d.ts +1 -1
- package/cjs/src/embed/ts-embed.d.ts.map +1 -1
- package/cjs/src/embed/ts-embed.js +6 -6
- package/cjs/src/embed/ts-embed.js.map +1 -1
- package/cjs/src/embed/ts-embed.spec.js +8 -14
- package/cjs/src/embed/ts-embed.spec.js.map +1 -1
- package/cjs/src/index.d.ts +4 -3
- package/cjs/src/index.d.ts.map +1 -1
- package/cjs/src/index.js +4 -1
- package/cjs/src/index.js.map +1 -1
- package/cjs/src/mixpanel-service.d.ts +1 -0
- package/cjs/src/mixpanel-service.d.ts.map +1 -1
- package/cjs/src/mixpanel-service.js +1 -0
- package/cjs/src/mixpanel-service.js.map +1 -1
- package/cjs/src/react/all-types-export.d.ts +1 -1
- package/cjs/src/react/all-types-export.d.ts.map +1 -1
- package/cjs/src/react/all-types-export.js +2 -1
- package/cjs/src/react/all-types-export.js.map +1 -1
- package/cjs/src/react/index.spec.js +0 -12
- package/cjs/src/react/index.spec.js.map +1 -1
- package/cjs/src/types.d.ts +43 -13
- package/cjs/src/types.d.ts.map +1 -1
- package/cjs/src/types.js +37 -10
- package/cjs/src/types.js.map +1 -1
- package/cjs/src/utils/graphql/answerService/answerService.d.ts +56 -2
- package/cjs/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
- package/cjs/src/utils/graphql/answerService/answerService.js +55 -0
- package/cjs/src/utils/graphql/answerService/answerService.js.map +1 -1
- package/dist/src/auth.d.ts.map +1 -1
- package/dist/src/embed/base.d.ts +1 -1
- package/dist/src/embed/base.d.ts.map +1 -1
- package/dist/src/embed/sage.d.ts +5 -5
- package/dist/src/embed/sage.d.ts.map +1 -1
- package/dist/src/embed/search.d.ts +1 -5
- package/dist/src/embed/search.d.ts.map +1 -1
- package/dist/src/embed/ts-embed.d.ts +1 -1
- package/dist/src/embed/ts-embed.d.ts.map +1 -1
- package/dist/src/index.d.ts +4 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/mixpanel-service.d.ts +1 -0
- package/dist/src/mixpanel-service.d.ts.map +1 -1
- package/dist/src/react/all-types-export.d.ts +1 -1
- package/dist/src/react/all-types-export.d.ts.map +1 -1
- package/dist/src/types.d.ts +43 -13
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils/graphql/answerService/answerService.d.ts +56 -2
- package/dist/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
- package/dist/tsembed-react.es.js +2800 -2732
- package/dist/tsembed-react.js +1525 -1457
- package/dist/tsembed.es.js +1768 -1700
- package/dist/tsembed.js +1674 -1604
- package/dist/visual-embed-sdk-react-full.d.ts +135 -24
- package/dist/visual-embed-sdk-react.d.ts +135 -24
- package/dist/visual-embed-sdk.d.ts +135 -24
- package/lib/package.json +1 -1
- package/lib/src/auth.d.ts.map +1 -1
- package/lib/src/auth.js +3 -3
- package/lib/src/auth.js.map +1 -1
- package/lib/src/embed/base.d.ts +1 -1
- package/lib/src/embed/base.d.ts.map +1 -1
- package/lib/src/embed/base.js +5 -5
- package/lib/src/embed/base.js.map +1 -1
- package/lib/src/embed/base.spec.js +2 -2
- package/lib/src/embed/base.spec.js.map +1 -1
- package/lib/src/embed/sage.d.ts +5 -5
- package/lib/src/embed/sage.d.ts.map +1 -1
- package/lib/src/embed/sage.js +1 -16
- package/lib/src/embed/sage.js.map +1 -1
- package/lib/src/embed/sage.spec.js +11 -11
- package/lib/src/embed/sage.spec.js.map +1 -1
- package/lib/src/embed/search.d.ts +1 -5
- package/lib/src/embed/search.d.ts.map +1 -1
- package/lib/src/embed/search.js +5 -5
- package/lib/src/embed/search.js.map +1 -1
- package/lib/src/embed/ts-embed.d.ts +1 -1
- package/lib/src/embed/ts-embed.d.ts.map +1 -1
- package/lib/src/embed/ts-embed.js +9 -9
- package/lib/src/embed/ts-embed.js.map +1 -1
- package/lib/src/embed/ts-embed.spec.js +8 -14
- package/lib/src/embed/ts-embed.spec.js.map +1 -1
- package/lib/src/index.d.ts +4 -3
- package/lib/src/index.d.ts.map +1 -1
- package/lib/src/index.js +2 -3
- package/lib/src/index.js.map +1 -1
- package/lib/src/mixpanel-service.d.ts +1 -0
- package/lib/src/mixpanel-service.d.ts.map +1 -1
- package/lib/src/mixpanel-service.js +1 -0
- package/lib/src/mixpanel-service.js.map +1 -1
- package/lib/src/react/all-types-export.d.ts +1 -1
- package/lib/src/react/all-types-export.d.ts.map +1 -1
- package/lib/src/react/all-types-export.js +1 -1
- package/lib/src/react/all-types-export.js.map +1 -1
- package/lib/src/react/index.spec.js +0 -12
- package/lib/src/react/index.spec.js.map +1 -1
- package/lib/src/types.d.ts +43 -13
- package/lib/src/types.d.ts.map +1 -1
- package/lib/src/types.js +37 -10
- package/lib/src/types.js.map +1 -1
- package/lib/src/utils/authService/authService.spec.js +1 -1
- package/lib/src/utils/authService/authService.spec.js.map +1 -1
- package/lib/src/utils/graphql/answerService/answerService.d.ts +56 -2
- package/lib/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
- package/lib/src/utils/graphql/answerService/answerService.js +55 -0
- package/lib/src/utils/graphql/answerService/answerService.js.map +1 -1
- package/lib/src/visual-embed-sdk.d.ts +144 -30
- package/package.json +1 -1
- package/src/auth.ts +6 -6
- package/src/embed/base.spec.ts +3 -3
- package/src/embed/base.ts +12 -12
- package/src/embed/sage.spec.ts +11 -11
- package/src/embed/sage.ts +4 -17
- package/src/embed/search.ts +6 -11
- package/src/embed/ts-embed.spec.ts +19 -25
- package/src/embed/ts-embed.ts +37 -34
- package/src/index.ts +10 -1
- package/src/mixpanel-service.ts +1 -0
- package/src/react/all-types-export.ts +1 -0
- package/src/react/index.spec.tsx +0 -29
- package/src/types.ts +53 -24
- package/src/utils/authService/authService.spec.ts +4 -4
- package/src/utils/graphql/answerService/answerService.ts +56 -1
package/dist/tsembed.es.js
CHANGED
|
@@ -183,6 +183,7 @@ var AuthType;
|
|
|
183
183
|
* .then((response) => response.json())
|
|
184
184
|
* .then((data) => data.token);
|
|
185
185
|
* }
|
|
186
|
+
* });
|
|
186
187
|
* ```
|
|
187
188
|
*/
|
|
188
189
|
AuthType["TrustedAuthToken"] = "AuthServer";
|
|
@@ -478,7 +479,8 @@ var EmbedEvent;
|
|
|
478
479
|
* A custom action has been triggered.
|
|
479
480
|
*
|
|
480
481
|
* @returns actionId - ID of the custom action
|
|
481
|
-
* @returns
|
|
482
|
+
* @returns payload {@link CustomActionPayload} - Response payload with the
|
|
483
|
+
* Answer or Liveboard data
|
|
482
484
|
* @example
|
|
483
485
|
* ```js
|
|
484
486
|
* appEmbed.on(EmbedEvent.customAction, payload => {
|
|
@@ -498,7 +500,7 @@ var EmbedEvent;
|
|
|
498
500
|
* @example
|
|
499
501
|
* ```js
|
|
500
502
|
* livebaordEmbed.on(EmbedEvent.VizPointDoubleClick, payload => {
|
|
501
|
-
* console.log('VizPointDoubleClick', payload)
|
|
503
|
+
* console.log('VizPointDoubleClick', payload);
|
|
502
504
|
* })
|
|
503
505
|
* ```
|
|
504
506
|
*/
|
|
@@ -524,15 +526,40 @@ var EmbedEvent;
|
|
|
524
526
|
*/
|
|
525
527
|
EmbedEvent["VizPointClick"] = "vizPointClick";
|
|
526
528
|
/**
|
|
527
|
-
* An error has occurred.
|
|
529
|
+
* An error has occurred. This event is fired for the following error types:
|
|
530
|
+
*
|
|
531
|
+
* `API` - API call failure error.
|
|
532
|
+
*
|
|
533
|
+
* `FULLSCREEN` - Error when presenting a Liveboard or visualization in full screen mode.
|
|
534
|
+
*
|
|
535
|
+
* `SINGLE_VALUE_FILTER` - Error due to multiple values in the single value filter.
|
|
528
536
|
*
|
|
537
|
+
* `NON_EXIST_FILTER` - Error due to a non-existent filter.
|
|
538
|
+
*
|
|
539
|
+
* `INVALID_DATE_VALUE` - Invalid date value error.
|
|
540
|
+
*
|
|
541
|
+
* `INVALID_OPERATOR` - Use of invalid operator during filter application.
|
|
542
|
+
*
|
|
543
|
+
* For more information, see [Developer Documentation](https://developers.thoughtspot.com/docs/events-app-integration#errorType)
|
|
529
544
|
* @returns error - An error object or message
|
|
530
545
|
* @example
|
|
531
546
|
* ```js
|
|
532
|
-
*
|
|
533
|
-
*
|
|
534
|
-
*
|
|
535
|
-
*
|
|
547
|
+
* // API error
|
|
548
|
+
* SearchEmbed.on(EmbedEvent.Error, (error) => {
|
|
549
|
+
* console.log(error);
|
|
550
|
+
* // { type: "Error", data: { errorType: "API", error: { message: '...', error: '...' } } }
|
|
551
|
+
* });
|
|
552
|
+
* ```
|
|
553
|
+
* @example
|
|
554
|
+
* ```js
|
|
555
|
+
* // Fullscreen error (Errors during presenting of a liveboard)
|
|
556
|
+
* LiveboardEmbed.on(EmbedEvent.Error, (error) => {
|
|
557
|
+
* console.log(error);
|
|
558
|
+
* // { type: "Error", data: { errorType: "FULLSCREEN", error: {
|
|
559
|
+
* // message: "Fullscreen API is not enabled",
|
|
560
|
+
* // stack: "..."
|
|
561
|
+
* // } }}
|
|
562
|
+
* })
|
|
536
563
|
* ```
|
|
537
564
|
*/
|
|
538
565
|
EmbedEvent["Error"] = "Error";
|
|
@@ -1242,7 +1269,7 @@ var EmbedEvent;
|
|
|
1242
1269
|
/**
|
|
1243
1270
|
* Emitted when a LB/viz is renamed
|
|
1244
1271
|
*
|
|
1245
|
-
* @version SDK : 1.28.0 | ThoughtSpot: 9.
|
|
1272
|
+
* @version SDK : 1.28.0 | ThoughtSpot: 9.10.5.cl
|
|
1246
1273
|
*/
|
|
1247
1274
|
EmbedEvent["Rename"] = "rename";
|
|
1248
1275
|
})(EmbedEvent || (EmbedEvent = {}));
|
|
@@ -1917,7 +1944,7 @@ var HostEvent;
|
|
|
1917
1944
|
*/
|
|
1918
1945
|
HostEvent["ResetSearch"] = "resetSearch";
|
|
1919
1946
|
/**
|
|
1920
|
-
*
|
|
1947
|
+
*
|
|
1921
1948
|
* Get the currents visible and runtime filters applied on a Liveboard
|
|
1922
1949
|
* @example
|
|
1923
1950
|
* liveboardEmbed.trigger(HostEvent.GetFilters)
|
|
@@ -1925,7 +1952,7 @@ var HostEvent;
|
|
|
1925
1952
|
*/
|
|
1926
1953
|
HostEvent["GetFilters"] = "getFilters";
|
|
1927
1954
|
/**
|
|
1928
|
-
*
|
|
1955
|
+
*
|
|
1929
1956
|
* Update the visible filters on the Liveboard.
|
|
1930
1957
|
* @param - filter: filter object containing column name and filter operation and values
|
|
1931
1958
|
* @example
|
|
@@ -5671,8 +5698,6 @@ function isEqual(value, other) {
|
|
|
5671
5698
|
|
|
5672
5699
|
var isEqual_1 = isEqual;
|
|
5673
5700
|
|
|
5674
|
-
var name="@thoughtspot/visual-embed-sdk";var version="1.27.8";var description="ThoughtSpot Embed SDK";var module="lib/src/index.js";var main="dist/tsembed.js";var types="lib/src/index.d.ts";var files=["dist/**","lib/**","src/**","cjs/**"];var exports={".":{"import":"./lib/src/index.js",require:"./cjs/src/index.js",types:"./lib/src/index.d.ts"},"./react":{"import":"./lib/src/react/all-types-export.js",require:"./cjs/src/react/all-types-export.js",types:"./lib/src/react/all-types-export.d.ts"},"./lib/src/react":{"import":"./lib/src/react/all-types-export.js",require:"./cjs/src/react/all-types-export.js",types:"./lib/src/react/all-types-export.d.ts"}};var typesVersions={"*":{react:["./lib/src/react/all-types-export.d.ts"]}};var scripts={lint:"eslint 'src/**'","lint:fix":"eslint 'src/**/*.*' --fix",tsc:"tsc -p . --incremental false; tsc -p . --incremental false --module commonjs --outDir cjs",start:"gatsby develop","build:gatsby":"npm run clean:gatsby && gatsby build --prefix-paths","build:gatsby:noprefix":"npm run clean:gatsby && gatsby build","serve:gatsby":"gatsby serve","clean:gatsby":"gatsby clean","build-and-publish":"npm run build:gatsby && npm run publish","bundle-dts-file":"dts-bundle --name @thoughtspot/visual-embed-sdk --out visual-embed-sdk.d.ts --main lib/src/index.d.ts","bundle-dts":"dts-bundle --name ../../dist/visual-embed-sdk --main lib/src/index.d.ts --outputAsModuleFolder=true","bundle-dts-react":"dts-bundle --name ../../../dist/visual-embed-sdk-react --main lib/src/react/index.d.ts --outputAsModuleFolder=true","bundle-dts-react-full":"dts-bundle --name ../../../dist/visual-embed-sdk-react-full --main lib/src/react/all-types-export.d.ts --outputAsModuleFolder=true",build:"rollup -c",watch:"rollup -cw","docs-cmd":"node scripts/gatsby-commands.js",docgen:"typedoc --tsconfig tsconfig.json --theme typedoc-theme","test-sdk":"jest -c jest.config.sdk.js --runInBand","test-docs":"jest -c jest.config.docs.js",test:"npm run test-sdk && npm run test-docs",posttest:"cat ./coverage/sdk/lcov.info | coveralls","is-publish-allowed":"node scripts/is-publish-allowed.js",prepublishOnly:"npm run is-publish-allowed && npm run test && npm run tsc && npm run bundle-dts-file && npm run bundle-dts && npm run bundle-dts-react && npm run bundle-dts-react-full && npm run build","check-size":"npm run build && size-limit","publish-dev":"npm publish --tag dev","publish-prod":"npm publish --tag latest"};var peerDependencies={react:"> 16.8.0","react-dom":"> 16.8.0"};var dependencies={algoliasearch:"^4.10.5",classnames:"^2.3.1",dompurify:"^2.3.4","eslint-plugin-comment-length":"^0.9.2","eslint-plugin-jsdoc":"^46.9.0",eventemitter3:"^4.0.7","gatsby-plugin-vercel":"^1.0.3","html-react-parser":"^1.4.12",lodash:"^4.17.21","mixpanel-browser":"^2.45.0","ts-deepmerge":"^6.0.2",tslib:"^2.5.3","use-deep-compare-effect":"^1.8.1"};var devDependencies={"@mdx-js/mdx":"^1.6.22","@mdx-js/react":"^1.6.22","@react-icons/all-files":"^4.1.0","@rollup/plugin-commonjs":"^18.0.0","@rollup/plugin-json":"^4.1.0","@rollup/plugin-node-resolve":"^11.2.1","@rollup/plugin-replace":"^5.0.2","@size-limit/preset-big-lib":"^8.2.6","@testing-library/dom":"^7.31.0","@testing-library/jest-dom":"^5.14.1","@testing-library/react":"^11.2.7","@testing-library/user-event":"^13.1.8","@types/jest":"^22.2.3","@types/mixpanel-browser":"^2.35.6","@types/react-test-renderer":"^17.0.1","@typescript-eslint/eslint-plugin":"^4.6.0","@typescript-eslint/parser":"^4.6.0",asciidoctor:"^2.2.1","babel-jest":"^26.6.3","babel-preset-gatsby":"^1.10.0","command-line-args":"^5.1.1",coveralls:"^3.1.0","current-git-branch":"^1.1.0","dts-bundle":"^0.7.3",eslint:"^7.12.1","eslint-config-airbnb-base":"^14.2.0","eslint-config-prettier":"^6.15.0","eslint-import-resolver-typescript":"^2.3.0","eslint-plugin-import":"^2.22.1","eslint-plugin-prettier":"^3.1.4","eslint-plugin-react-hooks":"^4.2.0","fs-extra":"^10.0.0",gatsby:"3.13.1","gatsby-plugin-algolia":"^0.22.2","gatsby-plugin-catch-links":"^3.1.0","gatsby-plugin-env-variables":"^2.1.0","gatsby-plugin-intl":"^0.3.3","gatsby-plugin-manifest":"^3.2.0","gatsby-plugin-output":"^0.1.3","gatsby-plugin-sass":"6.7.0","gatsby-plugin-sitemap":"^4.10.0","gatsby-source-filesystem":"3.1.0","gatsby-transformer-asciidoc":"2.1.0","gatsby-transformer-rehype":"2.0.0","gh-pages":"^3.1.0","highlight.js":"^10.6.0","html-to-text":"^8.0.0","identity-obj-proxy":"^3.0.0","istanbul-merge":"^1.1.1",jest:"^26.6.3","jest-fetch-mock":"^3.0.3",jsdom:"^17.0.0","node-sass":"^8.0.0",prettier:"2.1.2",react:"^16.14.0","react-dom":"^16.14.0","react-resizable":"^1.11.0","react-resize-detector":"^6.6.0","react-test-renderer":"^17.0.2","react-use-flexsearch":"^0.1.1",rollup:"2.30.0","rollup-plugin-typescript2":"0.27.3","ts-jest":"^26.5.5","ts-loader":"8.0.4",typedoc:"0.21.6","typedoc-plugin-toc-group":"thoughtspot/typedoc-plugin-toc-group",typescript:"^4.9.4","url-search-params-polyfill":"^8.1.0",util:"^0.12.4"};var author="ThoughtSpot";var email="support@thoughtspot.com";var license="ThoughtSpot Development Tools End User License Agreement";var directories={lib:"lib"};var repository={type:"git",url:"git+https://github.com/thoughtspot/visual-embed-sdk.git"};var publishConfig={registry:"https://registry.npmjs.org"};var keywords=["thoughtspot","everywhere","embed","sdk","analytics"];var bugs={url:"https://github.com/thoughtspot/visual-embed-sdk/issues"};var homepage="https://github.com/thoughtspot/visual-embed-sdk#readme";var globals={window:{}};var pkgInfo = {name:name,version:version,description:description,module:module,main:main,types:types,files:files,exports:exports,typesVersions:typesVersions,"size-limit":[{path:"dist/tsembed.js",limit:"44 kB"}],scripts:scripts,peerDependencies:peerDependencies,dependencies:dependencies,devDependencies:devDependencies,author:author,email:email,license:license,directories:directories,repository:repository,publishConfig:publishConfig,keywords:keywords,bugs:bugs,homepage:homepage,globals:globals};
|
|
5675
|
-
|
|
5676
5701
|
const EndPoints = {
|
|
5677
5702
|
AUTH_VERIFICATION: '/callosum/v1/session/info',
|
|
5678
5703
|
SAML_LOGIN_TEMPLATE: (targetUrl) => `/callosum/v1/saml/login?targetURLPath=${targetUrl}`,
|
|
@@ -5835,549 +5860,1093 @@ const resetCachedAuthToken = () => {
|
|
|
5835
5860
|
cachedAuthToken = null;
|
|
5836
5861
|
};
|
|
5837
5862
|
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5863
|
+
let config = {};
|
|
5864
|
+
/**
|
|
5865
|
+
* Gets the configuration embed was initialized with.
|
|
5866
|
+
*
|
|
5867
|
+
* @returns {@link EmbedConfig} The configuration embed was initialized with.
|
|
5868
|
+
* @version SDK: 1.19.0 | ThoughtSpot: *
|
|
5869
|
+
* @group Global methods
|
|
5870
|
+
*/
|
|
5871
|
+
const getEmbedConfig = () => config;
|
|
5872
|
+
/**
|
|
5873
|
+
* Sets the configuration embed was initialized with.
|
|
5874
|
+
* And returns the new configuration.
|
|
5875
|
+
*
|
|
5876
|
+
* @param newConfig The configuration to set.
|
|
5877
|
+
* @version SDK: 1.27.0 | ThoughtSpot: *
|
|
5878
|
+
* @group Global methods
|
|
5879
|
+
*/
|
|
5880
|
+
const setEmbedConfig = (newConfig) => {
|
|
5881
|
+
config = newConfig;
|
|
5882
|
+
return newConfig;
|
|
5841
5883
|
};
|
|
5842
5884
|
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
if (
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
},
|
|
5855
|
-
screen: { width: 0, height: 0 },
|
|
5856
|
-
location: loc
|
|
5857
|
-
};
|
|
5858
|
-
} else {
|
|
5859
|
-
window$1 = window;
|
|
5860
|
-
}
|
|
5861
|
-
|
|
5862
|
-
/*
|
|
5863
|
-
* Saved references to long variable names, so that closure compiler can
|
|
5864
|
-
* minimize file size.
|
|
5865
|
-
*/
|
|
5866
|
-
|
|
5867
|
-
var ArrayProto = Array.prototype;
|
|
5868
|
-
var FuncProto = Function.prototype;
|
|
5869
|
-
var ObjProto = Object.prototype;
|
|
5870
|
-
var slice = ArrayProto.slice;
|
|
5871
|
-
var toString = ObjProto.toString;
|
|
5872
|
-
var hasOwnProperty$9 = ObjProto.hasOwnProperty;
|
|
5873
|
-
var windowConsole = window$1.console;
|
|
5874
|
-
var navigator = window$1.navigator;
|
|
5875
|
-
var document$1 = window$1.document;
|
|
5876
|
-
var windowOpera = window$1.opera;
|
|
5877
|
-
var screen = window$1.screen;
|
|
5878
|
-
var userAgent = navigator.userAgent;
|
|
5879
|
-
var nativeBind = FuncProto.bind;
|
|
5880
|
-
var nativeForEach = ArrayProto.forEach;
|
|
5881
|
-
var nativeIndexOf = ArrayProto.indexOf;
|
|
5882
|
-
var nativeMap = ArrayProto.map;
|
|
5883
|
-
var nativeIsArray = Array.isArray;
|
|
5884
|
-
var breaker = {};
|
|
5885
|
-
var _ = {
|
|
5886
|
-
trim: function(str) {
|
|
5887
|
-
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim#Polyfill
|
|
5888
|
-
return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
|
|
5889
|
-
}
|
|
5885
|
+
const tokenizedFetch = async (input, init) => {
|
|
5886
|
+
const embedConfig = getEmbedConfig();
|
|
5887
|
+
if (embedConfig.authType !== AuthType.TrustedAuthTokenCookieless) {
|
|
5888
|
+
return fetch(input, init);
|
|
5889
|
+
}
|
|
5890
|
+
const req = new Request(input, init);
|
|
5891
|
+
const authToken = await getAuthenticationToken(embedConfig);
|
|
5892
|
+
if (authToken) {
|
|
5893
|
+
req.headers.append('Authorization', `Bearer ${authToken}`);
|
|
5894
|
+
}
|
|
5895
|
+
return fetch(req);
|
|
5890
5896
|
};
|
|
5891
5897
|
|
|
5892
|
-
|
|
5893
|
-
|
|
5894
|
-
|
|
5895
|
-
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
5916
|
-
|
|
5917
|
-
}
|
|
5918
|
-
|
|
5919
|
-
|
|
5920
|
-
|
|
5921
|
-
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
|
|
5925
|
-
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
|
|
5898
|
+
/**
|
|
5899
|
+
*
|
|
5900
|
+
* @param root0
|
|
5901
|
+
* @param root0.query
|
|
5902
|
+
* @param root0.variables
|
|
5903
|
+
* @param root0.thoughtSpotHost
|
|
5904
|
+
* @param root0.isCompositeQuery
|
|
5905
|
+
*/
|
|
5906
|
+
async function graphqlQuery({ query, variables, thoughtSpotHost, isCompositeQuery = false, }) {
|
|
5907
|
+
const operationName = getOperationNameFromQuery(query);
|
|
5908
|
+
try {
|
|
5909
|
+
const response = await fetch(`${thoughtSpotHost}/prism/?op=${operationName}`, {
|
|
5910
|
+
method: 'POST',
|
|
5911
|
+
headers: {
|
|
5912
|
+
'content-type': 'application/json;charset=UTF-8',
|
|
5913
|
+
'x-requested-by': 'ThoughtSpot',
|
|
5914
|
+
accept: '*/*',
|
|
5915
|
+
'accept-language': 'en-us',
|
|
5916
|
+
},
|
|
5917
|
+
body: JSON.stringify({
|
|
5918
|
+
operationName,
|
|
5919
|
+
query,
|
|
5920
|
+
variables,
|
|
5921
|
+
}),
|
|
5922
|
+
credentials: 'include',
|
|
5923
|
+
});
|
|
5924
|
+
const result = await response.json();
|
|
5925
|
+
const dataValues = Object.values(result.data);
|
|
5926
|
+
return (isCompositeQuery) ? result.data : dataValues[0];
|
|
5927
|
+
}
|
|
5928
|
+
catch (error) {
|
|
5929
|
+
return error;
|
|
5930
|
+
}
|
|
5931
|
+
}
|
|
5932
|
+
|
|
5933
|
+
const getSourceDetailQuery = `
|
|
5934
|
+
query GetSourceDetail($ids: [GUID!]!) {
|
|
5935
|
+
getSourceDetailById(ids: $ids, type: LOGICAL_TABLE) {
|
|
5936
|
+
id
|
|
5937
|
+
name
|
|
5938
|
+
description
|
|
5939
|
+
authorName
|
|
5940
|
+
authorDisplayName
|
|
5941
|
+
isExternal
|
|
5942
|
+
type
|
|
5943
|
+
created
|
|
5944
|
+
modified
|
|
5945
|
+
columns {
|
|
5946
|
+
id
|
|
5947
|
+
name
|
|
5948
|
+
author
|
|
5949
|
+
authorDisplayName
|
|
5950
|
+
description
|
|
5951
|
+
dataType
|
|
5952
|
+
type
|
|
5953
|
+
modified
|
|
5954
|
+
ownerName
|
|
5955
|
+
owner
|
|
5956
|
+
dataRecency
|
|
5957
|
+
sources {
|
|
5958
|
+
tableId
|
|
5959
|
+
tableName
|
|
5960
|
+
columnId
|
|
5961
|
+
columnName
|
|
5962
|
+
__typename
|
|
5929
5963
|
}
|
|
5964
|
+
synonyms
|
|
5965
|
+
cohortAnswerId
|
|
5966
|
+
__typename
|
|
5930
5967
|
}
|
|
5931
|
-
|
|
5932
|
-
|
|
5933
|
-
|
|
5934
|
-
|
|
5935
|
-
var args = ['Mixpanel error:'].concat(_.toArray(arguments));
|
|
5936
|
-
try {
|
|
5937
|
-
windowConsole.error.apply(windowConsole, args);
|
|
5938
|
-
} catch (err) {
|
|
5939
|
-
_.each(args, function(arg) {
|
|
5940
|
-
windowConsole.error(arg);
|
|
5941
|
-
});
|
|
5942
|
-
}
|
|
5968
|
+
relationships
|
|
5969
|
+
destinationRelationships
|
|
5970
|
+
dataSourceId
|
|
5971
|
+
__typename
|
|
5943
5972
|
}
|
|
5944
|
-
}
|
|
5945
|
-
|
|
5973
|
+
}
|
|
5974
|
+
`;
|
|
5975
|
+
const sourceDetailCache = new Map();
|
|
5976
|
+
/**
|
|
5977
|
+
*
|
|
5978
|
+
* @param thoughtSpotHost
|
|
5979
|
+
* @param sourceId
|
|
5980
|
+
*/
|
|
5981
|
+
async function getSourceDetail(thoughtSpotHost, sourceId) {
|
|
5982
|
+
if (sourceDetailCache.get(sourceId)) {
|
|
5983
|
+
return sourceDetailCache.get(sourceId);
|
|
5984
|
+
}
|
|
5985
|
+
const details = await graphqlQuery({
|
|
5986
|
+
query: getSourceDetailQuery,
|
|
5987
|
+
variables: {
|
|
5988
|
+
ids: [sourceId],
|
|
5989
|
+
},
|
|
5990
|
+
thoughtSpotHost,
|
|
5991
|
+
});
|
|
5992
|
+
const souceDetails = details[0];
|
|
5993
|
+
if (souceDetails) {
|
|
5994
|
+
sourceDetailCache.set(sourceId, souceDetails);
|
|
5995
|
+
}
|
|
5996
|
+
return souceDetails;
|
|
5997
|
+
}
|
|
5946
5998
|
|
|
5947
|
-
|
|
5948
|
-
|
|
5949
|
-
|
|
5950
|
-
|
|
5951
|
-
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
return {
|
|
5955
|
-
log: log_func_with_prefix(console$1.log, prefix),
|
|
5956
|
-
error: log_func_with_prefix(console$1.error, prefix),
|
|
5957
|
-
critical: log_func_with_prefix(console$1.critical, prefix)
|
|
5958
|
-
};
|
|
5959
|
-
};
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
// UNDERSCORE
|
|
5963
|
-
// Embed part of the Underscore Library
|
|
5964
|
-
_.bind = function(func, context) {
|
|
5965
|
-
var args, bound;
|
|
5966
|
-
if (nativeBind && func.bind === nativeBind) {
|
|
5967
|
-
return nativeBind.apply(func, slice.call(arguments, 1));
|
|
5968
|
-
}
|
|
5969
|
-
if (!_.isFunction(func)) {
|
|
5970
|
-
throw new TypeError();
|
|
5971
|
-
}
|
|
5972
|
-
args = slice.call(arguments, 2);
|
|
5973
|
-
bound = function() {
|
|
5974
|
-
if (!(this instanceof bound)) {
|
|
5975
|
-
return func.apply(context, args.concat(slice.call(arguments)));
|
|
5976
|
-
}
|
|
5977
|
-
var ctor = {};
|
|
5978
|
-
ctor.prototype = func.prototype;
|
|
5979
|
-
var self = new ctor();
|
|
5980
|
-
ctor.prototype = null;
|
|
5981
|
-
var result = func.apply(self, args.concat(slice.call(arguments)));
|
|
5982
|
-
if (Object(result) === result) {
|
|
5983
|
-
return result;
|
|
5984
|
-
}
|
|
5985
|
-
return self;
|
|
5986
|
-
};
|
|
5987
|
-
return bound;
|
|
5988
|
-
};
|
|
5989
|
-
|
|
5990
|
-
/**
|
|
5991
|
-
* @param {*=} obj
|
|
5992
|
-
* @param {function(...*)=} iterator
|
|
5993
|
-
* @param {Object=} context
|
|
5994
|
-
*/
|
|
5995
|
-
_.each = function(obj, iterator, context) {
|
|
5996
|
-
if (obj === null || obj === undefined) {
|
|
5997
|
-
return;
|
|
5999
|
+
const bachSessionId = `
|
|
6000
|
+
id {
|
|
6001
|
+
sessionId
|
|
6002
|
+
genNo
|
|
6003
|
+
acSession {
|
|
6004
|
+
sessionId
|
|
6005
|
+
genNo
|
|
5998
6006
|
}
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
|
|
6009
|
-
|
|
6010
|
-
|
|
6011
|
-
|
|
6007
|
+
}
|
|
6008
|
+
`;
|
|
6009
|
+
const getUnaggregatedAnswerSession = `
|
|
6010
|
+
mutation GetUnAggregatedAnswerSession($session: BachSessionIdInput!, $columns: [UserPointSelectionInput!]!) {
|
|
6011
|
+
Answer__getUnaggregatedAnswer(session: $session, columns: $columns) {
|
|
6012
|
+
${bachSessionId}
|
|
6013
|
+
answer {
|
|
6014
|
+
visualizations {
|
|
6015
|
+
... on TableViz {
|
|
6016
|
+
columns {
|
|
6017
|
+
column {
|
|
6018
|
+
id
|
|
6019
|
+
name
|
|
6020
|
+
referencedColumns {
|
|
6021
|
+
guid
|
|
6022
|
+
displayName
|
|
6023
|
+
}
|
|
6024
|
+
}
|
|
6025
|
+
}
|
|
6012
6026
|
}
|
|
6013
6027
|
}
|
|
6014
6028
|
}
|
|
6015
6029
|
}
|
|
6016
|
-
}
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
return obj;
|
|
6027
|
-
};
|
|
6028
|
-
|
|
6029
|
-
_.isArray = nativeIsArray || function(obj) {
|
|
6030
|
-
return toString.call(obj) === '[object Array]';
|
|
6031
|
-
};
|
|
6032
|
-
|
|
6033
|
-
// from a comment on http://dbj.org/dbj/?p=286
|
|
6034
|
-
// fails on only one very rare and deliberate custom object:
|
|
6035
|
-
// var bomb = { toString : undefined, valueOf: function(o) { return "function BOMBA!"; }};
|
|
6036
|
-
_.isFunction = function(f) {
|
|
6037
|
-
try {
|
|
6038
|
-
return /^\s*\bfunction\b/.test(f);
|
|
6039
|
-
} catch (x) {
|
|
6040
|
-
return false;
|
|
6041
|
-
}
|
|
6042
|
-
};
|
|
6043
|
-
|
|
6044
|
-
_.isArguments = function(obj) {
|
|
6045
|
-
return !!(obj && hasOwnProperty$9.call(obj, 'callee'));
|
|
6046
|
-
};
|
|
6047
|
-
|
|
6048
|
-
_.toArray = function(iterable) {
|
|
6049
|
-
if (!iterable) {
|
|
6050
|
-
return [];
|
|
6051
|
-
}
|
|
6052
|
-
if (iterable.toArray) {
|
|
6053
|
-
return iterable.toArray();
|
|
6054
|
-
}
|
|
6055
|
-
if (_.isArray(iterable)) {
|
|
6056
|
-
return slice.call(iterable);
|
|
6057
|
-
}
|
|
6058
|
-
if (_.isArguments(iterable)) {
|
|
6059
|
-
return slice.call(iterable);
|
|
6060
|
-
}
|
|
6061
|
-
return _.values(iterable);
|
|
6062
|
-
};
|
|
6063
|
-
|
|
6064
|
-
_.map = function(arr, callback, context) {
|
|
6065
|
-
if (nativeMap && arr.map === nativeMap) {
|
|
6066
|
-
return arr.map(callback, context);
|
|
6067
|
-
} else {
|
|
6068
|
-
var results = [];
|
|
6069
|
-
_.each(arr, function(item) {
|
|
6070
|
-
results.push(callback.call(context, item));
|
|
6071
|
-
});
|
|
6072
|
-
return results;
|
|
6073
|
-
}
|
|
6074
|
-
};
|
|
6075
|
-
|
|
6076
|
-
_.keys = function(obj) {
|
|
6077
|
-
var results = [];
|
|
6078
|
-
if (obj === null) {
|
|
6079
|
-
return results;
|
|
6080
|
-
}
|
|
6081
|
-
_.each(obj, function(value, key) {
|
|
6082
|
-
results[results.length] = key;
|
|
6083
|
-
});
|
|
6084
|
-
return results;
|
|
6085
|
-
};
|
|
6086
|
-
|
|
6087
|
-
_.values = function(obj) {
|
|
6088
|
-
var results = [];
|
|
6089
|
-
if (obj === null) {
|
|
6090
|
-
return results;
|
|
6091
|
-
}
|
|
6092
|
-
_.each(obj, function(value) {
|
|
6093
|
-
results[results.length] = value;
|
|
6094
|
-
});
|
|
6095
|
-
return results;
|
|
6096
|
-
};
|
|
6097
|
-
|
|
6098
|
-
_.include = function(obj, target) {
|
|
6099
|
-
var found = false;
|
|
6100
|
-
if (obj === null) {
|
|
6101
|
-
return found;
|
|
6102
|
-
}
|
|
6103
|
-
if (nativeIndexOf && obj.indexOf === nativeIndexOf) {
|
|
6104
|
-
return obj.indexOf(target) != -1;
|
|
6030
|
+
}
|
|
6031
|
+
`;
|
|
6032
|
+
const removeColumns = `
|
|
6033
|
+
mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!], $columnIds: [GUID!]) {
|
|
6034
|
+
Answer__removeColumns(
|
|
6035
|
+
session: $session
|
|
6036
|
+
logicalColumnIds: $logicalColumnIds
|
|
6037
|
+
columnIds: $columnIds
|
|
6038
|
+
) {
|
|
6039
|
+
${bachSessionId}
|
|
6105
6040
|
}
|
|
6106
|
-
|
|
6107
|
-
|
|
6108
|
-
|
|
6041
|
+
}
|
|
6042
|
+
`;
|
|
6043
|
+
const addColumns = `
|
|
6044
|
+
mutation AddColumns($session: BachSessionIdInput!, $columns: [AnswerColumnInfo!]!) {
|
|
6045
|
+
Answer__addColumn(session: $session, columns: $columns) {
|
|
6046
|
+
${bachSessionId}
|
|
6109
6047
|
}
|
|
6110
|
-
}
|
|
6111
|
-
|
|
6112
|
-
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6118
|
-
|
|
6119
|
-
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
|
|
6124
|
-
|
|
6125
|
-
|
|
6126
|
-
|
|
6127
|
-
|
|
6128
|
-
}
|
|
6129
|
-
|
|
6130
|
-
|
|
6131
|
-
|
|
6132
|
-
|
|
6133
|
-
if (hasOwnProperty$9.call(obj, key)) {
|
|
6134
|
-
return false;
|
|
6048
|
+
}
|
|
6049
|
+
`;
|
|
6050
|
+
const getAnswerData = `
|
|
6051
|
+
query GetTableWithHeadlineData($session: BachSessionIdInput!, $deadline: Int!, $dataPaginationParams: DataPaginationParamsInput!) {
|
|
6052
|
+
getAnswer(session: $session) {
|
|
6053
|
+
${bachSessionId}
|
|
6054
|
+
answer {
|
|
6055
|
+
id
|
|
6056
|
+
visualizations {
|
|
6057
|
+
id
|
|
6058
|
+
... on TableViz {
|
|
6059
|
+
columns {
|
|
6060
|
+
column {
|
|
6061
|
+
id
|
|
6062
|
+
name
|
|
6063
|
+
type
|
|
6064
|
+
aggregationType
|
|
6065
|
+
dataType
|
|
6066
|
+
}
|
|
6067
|
+
}
|
|
6068
|
+
data(deadline: $deadline, pagination: $dataPaginationParams)
|
|
6069
|
+
}
|
|
6070
|
+
}
|
|
6135
6071
|
}
|
|
6136
6072
|
}
|
|
6137
|
-
return true;
|
|
6138
6073
|
}
|
|
6139
|
-
|
|
6140
|
-
};
|
|
6141
|
-
|
|
6142
|
-
_.isUndefined = function(obj) {
|
|
6143
|
-
return obj === void 0;
|
|
6144
|
-
};
|
|
6145
|
-
|
|
6146
|
-
_.isString = function(obj) {
|
|
6147
|
-
return toString.call(obj) == '[object String]';
|
|
6148
|
-
};
|
|
6149
|
-
|
|
6150
|
-
_.isDate = function(obj) {
|
|
6151
|
-
return toString.call(obj) == '[object Date]';
|
|
6152
|
-
};
|
|
6153
|
-
|
|
6154
|
-
_.isNumber = function(obj) {
|
|
6155
|
-
return toString.call(obj) == '[object Number]';
|
|
6156
|
-
};
|
|
6074
|
+
`;
|
|
6157
6075
|
|
|
6158
|
-
|
|
6159
|
-
|
|
6160
|
-
|
|
6161
|
-
|
|
6162
|
-
|
|
6163
|
-
|
|
6164
|
-
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6076
|
+
// eslint-disable-next-line no-shadow
|
|
6077
|
+
var OperationType;
|
|
6078
|
+
(function (OperationType) {
|
|
6079
|
+
OperationType["GetChartWithData"] = "GetChartWithData";
|
|
6080
|
+
OperationType["GetTableWithHeadlineData"] = "GetTableWithHeadlineData";
|
|
6081
|
+
})(OperationType || (OperationType = {}));
|
|
6082
|
+
/**
|
|
6083
|
+
* Class representing the answer service provided with the
|
|
6084
|
+
* custom action payload. This service could be used to run
|
|
6085
|
+
* graphql queries in the context of the answer on which the
|
|
6086
|
+
* custom action was triggered.
|
|
6087
|
+
*
|
|
6088
|
+
* @example
|
|
6089
|
+
* ```js
|
|
6090
|
+
* embed.on(EmbedEvent.CustomAction, e => {
|
|
6091
|
+
* const underlying = await e.answerService.getUnderlyingDataForPoint([
|
|
6092
|
+
* 'col name 1'
|
|
6093
|
+
* ]);
|
|
6094
|
+
* const data = await underlying.fetchData(0, 100);
|
|
6095
|
+
* })
|
|
6096
|
+
* ```
|
|
6097
|
+
* @version SDK: 1.25.0| ThoughtSpot: 9.10.0.cl
|
|
6098
|
+
* @group Events
|
|
6099
|
+
*/
|
|
6100
|
+
class AnswerService {
|
|
6101
|
+
/**
|
|
6102
|
+
* Should not need to be called directly.
|
|
6103
|
+
*
|
|
6104
|
+
* @param session
|
|
6105
|
+
* @param answer
|
|
6106
|
+
* @param thoughtSpotHost
|
|
6107
|
+
* @param selectedPoints
|
|
6108
|
+
*/
|
|
6109
|
+
constructor(session, answer, thoughtSpotHost, selectedPoints) {
|
|
6110
|
+
this.session = session;
|
|
6111
|
+
this.answer = answer;
|
|
6112
|
+
this.thoughtSpotHost = thoughtSpotHost;
|
|
6113
|
+
this.selectedPoints = selectedPoints;
|
|
6114
|
+
this.session = removeTypename(session);
|
|
6115
|
+
}
|
|
6116
|
+
/**
|
|
6117
|
+
* Get the details about the source used in the answer.
|
|
6118
|
+
* This can be used to get the list of all columns in the data source for example.
|
|
6119
|
+
*/
|
|
6120
|
+
async getSourceDetail() {
|
|
6121
|
+
const sourceId = this.answer.sources[0].header.guid;
|
|
6122
|
+
return getSourceDetail(this.thoughtSpotHost, sourceId);
|
|
6123
|
+
}
|
|
6124
|
+
/**
|
|
6125
|
+
* Remove columnIds and return updated answer session.
|
|
6126
|
+
*
|
|
6127
|
+
* @param columnIds
|
|
6128
|
+
* @returns
|
|
6129
|
+
*/
|
|
6130
|
+
async removeColumns(columnIds) {
|
|
6131
|
+
return this.executeQuery(removeColumns, {
|
|
6132
|
+
logicalColumnIds: columnIds,
|
|
6133
|
+
});
|
|
6134
|
+
}
|
|
6135
|
+
/**
|
|
6136
|
+
* Add columnIds and return updated answer session.
|
|
6137
|
+
*
|
|
6138
|
+
* @param columnIds
|
|
6139
|
+
* @returns
|
|
6140
|
+
*/
|
|
6141
|
+
async addColumns(columnIds) {
|
|
6142
|
+
return this.executeQuery(addColumns, {
|
|
6143
|
+
columns: columnIds.map((colId) => ({ logicalColumnId: colId })),
|
|
6144
|
+
});
|
|
6145
|
+
}
|
|
6146
|
+
/**
|
|
6147
|
+
* Fetch data from the answer.
|
|
6148
|
+
*
|
|
6149
|
+
* @param offset
|
|
6150
|
+
* @param size
|
|
6151
|
+
* @returns
|
|
6152
|
+
*/
|
|
6153
|
+
async fetchData(offset = 0, size = 1000) {
|
|
6154
|
+
const { answer } = await this.executeQuery(getAnswerData, {
|
|
6155
|
+
deadline: 0,
|
|
6156
|
+
dataPaginationParams: {
|
|
6157
|
+
isClientPaginated: true,
|
|
6158
|
+
offset,
|
|
6159
|
+
size,
|
|
6160
|
+
},
|
|
6161
|
+
});
|
|
6162
|
+
const { columns, data } = answer.visualizations.find((viz) => !!viz.data) || {};
|
|
6163
|
+
return {
|
|
6164
|
+
columns,
|
|
6165
|
+
data,
|
|
6166
|
+
};
|
|
6167
|
+
}
|
|
6168
|
+
/**
|
|
6169
|
+
* Fetch the data for the answer as a CSV blob. This might be
|
|
6170
|
+
* quicker for larger data.
|
|
6171
|
+
*
|
|
6172
|
+
* @param userLocale
|
|
6173
|
+
* @param includeInfo Include the CSV header in the output
|
|
6174
|
+
* @returns Response
|
|
6175
|
+
*/
|
|
6176
|
+
async fetchCSVBlob(userLocale = 'en-us', includeInfo = false) {
|
|
6177
|
+
const fetchUrl = this.getFetchCSVBlobUrl(userLocale, includeInfo);
|
|
6178
|
+
return tokenizedFetch(fetchUrl, {
|
|
6179
|
+
credentials: 'include',
|
|
6180
|
+
});
|
|
6181
|
+
}
|
|
6182
|
+
/**
|
|
6183
|
+
* Just get the internal URL for this answer's data
|
|
6184
|
+
* as a CSV blob.
|
|
6185
|
+
*
|
|
6186
|
+
* @param userLocale
|
|
6187
|
+
* @param includeInfo
|
|
6188
|
+
* @returns
|
|
6189
|
+
*/
|
|
6190
|
+
getFetchCSVBlobUrl(userLocale = 'en-us', includeInfo = false) {
|
|
6191
|
+
return `${this.thoughtSpotHost}/prism/download/answer/csv?sessionId=${this.session.sessionId}&genNo=${this.session.genNo}&userLocale=${userLocale}&exportFileName=data&hideCsvHeader=${!includeInfo}`;
|
|
6192
|
+
}
|
|
6193
|
+
/**
|
|
6194
|
+
* Get underlying data given a point and the output column names.
|
|
6195
|
+
* In case of a context menu action, the selectedPoints are
|
|
6196
|
+
* automatically passed.
|
|
6197
|
+
*
|
|
6198
|
+
* @param outputColumnNames
|
|
6199
|
+
* @param selectedPoints
|
|
6200
|
+
* @example
|
|
6201
|
+
* ```js
|
|
6202
|
+
* embed.on(EmbedEvent.CustomAction, e => {
|
|
6203
|
+
* const underlying = await e.answerService.getUnderlyingDataForPoint([
|
|
6204
|
+
* 'col name 1' // The column should exist in the data source.
|
|
6205
|
+
* ]);
|
|
6206
|
+
* const data = await underlying.fetchData(0, 100);
|
|
6207
|
+
* })
|
|
6208
|
+
* ```
|
|
6209
|
+
* @version SDK: 1.25.0| ThoughtSpot: 9.10.0.cl
|
|
6210
|
+
*/
|
|
6211
|
+
async getUnderlyingDataForPoint(outputColumnNames, selectedPoints) {
|
|
6212
|
+
if (!selectedPoints && !this.selectedPoints) {
|
|
6213
|
+
throw new Error('Needs to be triggered in context of a point');
|
|
6214
|
+
}
|
|
6215
|
+
if (!selectedPoints) {
|
|
6216
|
+
selectedPoints = getSelectedPointsForUnderlyingDataQuery(this.selectedPoints);
|
|
6217
|
+
}
|
|
6218
|
+
const sourceDetail = await this.getSourceDetail();
|
|
6219
|
+
const ouputColumnGuids = getGuidsFromColumnNames(sourceDetail, outputColumnNames);
|
|
6220
|
+
const unAggAnswer = await graphqlQuery({
|
|
6221
|
+
query: getUnaggregatedAnswerSession,
|
|
6222
|
+
variables: {
|
|
6223
|
+
session: this.session,
|
|
6224
|
+
columns: selectedPoints,
|
|
6225
|
+
},
|
|
6226
|
+
thoughtSpotHost: this.thoughtSpotHost,
|
|
6227
|
+
});
|
|
6228
|
+
const unaggAnswerSession = new AnswerService(unAggAnswer.id, unAggAnswer.answer, this.thoughtSpotHost);
|
|
6229
|
+
const currentColumns = new Set(unAggAnswer.answer.visualizations[0].columns
|
|
6230
|
+
.map((c) => c.column.referencedColumns[0].guid));
|
|
6231
|
+
const columnsToAdd = [...ouputColumnGuids].filter((col) => !currentColumns.has(col));
|
|
6232
|
+
if (columnsToAdd.length) {
|
|
6233
|
+
await unaggAnswerSession.addColumns(columnsToAdd);
|
|
6234
|
+
}
|
|
6235
|
+
const columnsToRemove = [...currentColumns].filter((col) => !ouputColumnGuids.has(col));
|
|
6236
|
+
if (columnsToRemove.length) {
|
|
6237
|
+
await unaggAnswerSession.removeColumns(columnsToRemove);
|
|
6238
|
+
}
|
|
6239
|
+
return unaggAnswerSession;
|
|
6240
|
+
}
|
|
6241
|
+
/**
|
|
6242
|
+
* Execute a custom graphql query in the context of the answer.
|
|
6243
|
+
*
|
|
6244
|
+
* @param query graphql query
|
|
6245
|
+
* @param variables graphql variables
|
|
6246
|
+
* @returns
|
|
6247
|
+
*/
|
|
6248
|
+
async executeQuery(query, variables) {
|
|
6249
|
+
const data = await graphqlQuery({
|
|
6250
|
+
query,
|
|
6251
|
+
variables: {
|
|
6252
|
+
session: this.session,
|
|
6253
|
+
...variables,
|
|
6254
|
+
},
|
|
6255
|
+
thoughtSpotHost: this.thoughtSpotHost,
|
|
6256
|
+
isCompositeQuery: false,
|
|
6257
|
+
});
|
|
6258
|
+
this.session = deepMerge(this.session, (data === null || data === void 0 ? void 0 : data.id) || {});
|
|
6259
|
+
return data;
|
|
6260
|
+
}
|
|
6261
|
+
/**
|
|
6262
|
+
* Get the internal session details for the answer.
|
|
6263
|
+
*
|
|
6264
|
+
* @returns
|
|
6265
|
+
*/
|
|
6266
|
+
getSession() {
|
|
6267
|
+
return this.session;
|
|
6268
|
+
}
|
|
6269
|
+
}
|
|
6270
|
+
/**
|
|
6271
|
+
*
|
|
6272
|
+
* @param sourceDetail
|
|
6273
|
+
* @param colNames
|
|
6274
|
+
*/
|
|
6275
|
+
function getGuidsFromColumnNames(sourceDetail, colNames) {
|
|
6276
|
+
const cols = sourceDetail.columns.reduce((colSet, col) => {
|
|
6277
|
+
colSet[col.name] = col;
|
|
6278
|
+
return colSet;
|
|
6279
|
+
}, {});
|
|
6280
|
+
return new Set(colNames.map((colName) => {
|
|
6281
|
+
const col = cols[colName];
|
|
6282
|
+
return col.id;
|
|
6283
|
+
}));
|
|
6284
|
+
}
|
|
6285
|
+
/**
|
|
6286
|
+
*
|
|
6287
|
+
* @param selectedPoints
|
|
6288
|
+
*/
|
|
6289
|
+
function getSelectedPointsForUnderlyingDataQuery(selectedPoints) {
|
|
6290
|
+
const underlyingDataPoint = [];
|
|
6291
|
+
/**
|
|
6292
|
+
*
|
|
6293
|
+
* @param colVal
|
|
6294
|
+
*/
|
|
6295
|
+
function addPointFromColVal(colVal) {
|
|
6296
|
+
var _a;
|
|
6297
|
+
const dataType = colVal.column.dataType;
|
|
6298
|
+
const id = colVal.column.id;
|
|
6299
|
+
let dataValue;
|
|
6300
|
+
if (dataType === 'DATE') {
|
|
6301
|
+
if (Number.isFinite(colVal.value)) {
|
|
6302
|
+
dataValue = [{
|
|
6303
|
+
epochRange: {
|
|
6304
|
+
startEpoch: colVal.value,
|
|
6305
|
+
},
|
|
6306
|
+
}];
|
|
6307
|
+
// Case for custom calendar.
|
|
6308
|
+
}
|
|
6309
|
+
else if ((_a = colVal.value) === null || _a === void 0 ? void 0 : _a.v) {
|
|
6310
|
+
dataValue = [{
|
|
6311
|
+
epochRange: {
|
|
6312
|
+
startEpoch: colVal.value.v.s,
|
|
6313
|
+
endEpoch: colVal.value.v.e,
|
|
6314
|
+
},
|
|
6315
|
+
}];
|
|
6316
|
+
}
|
|
6317
|
+
}
|
|
6318
|
+
else {
|
|
6319
|
+
dataValue = [{ value: colVal.value }];
|
|
6320
|
+
}
|
|
6321
|
+
underlyingDataPoint.push({
|
|
6322
|
+
columnId: colVal.column.id,
|
|
6323
|
+
dataValue,
|
|
6324
|
+
});
|
|
6325
|
+
}
|
|
6326
|
+
selectedPoints.forEach((p) => {
|
|
6327
|
+
p.selectedAttributes.forEach(addPointFromColVal);
|
|
6328
|
+
});
|
|
6329
|
+
return underlyingDataPoint;
|
|
6330
|
+
}
|
|
6172
6331
|
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6332
|
+
const ERROR_MESSAGE = {
|
|
6333
|
+
INVALID_THOUGHTSPOT_HOST: 'Error parsing ThoughtSpot host. Please provide a valid URL.',
|
|
6334
|
+
LIVEBOARD_VIZ_ID_VALIDATION: 'Please provide either liveboardId or pinboardId',
|
|
6335
|
+
TRIGGER_TIMED_OUT: 'Trigger timedout in getting response',
|
|
6336
|
+
SEARCHEMBED_BETA_WRANING_MESSAGE: 'Search Embed is in Beta in this release.',
|
|
6337
|
+
SAGE_EMBED_BETA_WARNING_MESSAGE: 'Sage Embed is in Beta in this release.',
|
|
6178
6338
|
};
|
|
6179
6339
|
|
|
6180
|
-
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6186
|
-
|
|
6187
|
-
|
|
6188
|
-
|
|
6189
|
-
|
|
6190
|
-
|
|
6191
|
-
}
|
|
6340
|
+
/**
|
|
6341
|
+
* Copyright (c) 2023
|
|
6342
|
+
*
|
|
6343
|
+
* Utilities related to reading configuration objects
|
|
6344
|
+
*
|
|
6345
|
+
* @summary Config-related utils
|
|
6346
|
+
* @author Ayon Ghosh <ayon.ghosh@thoughtspot.com>
|
|
6347
|
+
*/
|
|
6348
|
+
const urlRegex = new RegExp([
|
|
6349
|
+
'(^(https?:)//)?',
|
|
6350
|
+
'(([^:/?#]*)(?::([0-9]+))?)',
|
|
6351
|
+
'(/{0,1}[^?#]*)',
|
|
6352
|
+
'(\\?[^#]*|)',
|
|
6353
|
+
'(#.*|)$', // hash
|
|
6354
|
+
].join(''));
|
|
6355
|
+
/**
|
|
6356
|
+
* Parse and construct the ThoughtSpot hostname or IP address
|
|
6357
|
+
* from the embed configuration object.
|
|
6358
|
+
*
|
|
6359
|
+
* @param config
|
|
6360
|
+
*/
|
|
6361
|
+
const getThoughtSpotHost = (config) => {
|
|
6362
|
+
if (!config.thoughtSpotHost) {
|
|
6363
|
+
throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
|
|
6364
|
+
}
|
|
6365
|
+
const urlParts = config.thoughtSpotHost.match(urlRegex);
|
|
6366
|
+
if (!urlParts) {
|
|
6367
|
+
throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
|
|
6368
|
+
}
|
|
6369
|
+
const protocol = urlParts[2] || window.location.protocol;
|
|
6370
|
+
const host = urlParts[3];
|
|
6371
|
+
let path = urlParts[6];
|
|
6372
|
+
// Lose the trailing / if any
|
|
6373
|
+
if (path.charAt(path.length - 1) === '/') {
|
|
6374
|
+
path = path.substring(0, path.length - 1);
|
|
6375
|
+
}
|
|
6376
|
+
// const urlParams = urlParts[7];
|
|
6377
|
+
// const hash = urlParts[8];
|
|
6378
|
+
return `${protocol}//${host}${path}`;
|
|
6379
|
+
};
|
|
6380
|
+
const getV2BasePath = (config) => {
|
|
6381
|
+
if (config.basepath) {
|
|
6382
|
+
return config.basepath;
|
|
6383
|
+
}
|
|
6384
|
+
const tsHost = getThoughtSpotHost(config);
|
|
6385
|
+
// This is to handle when e2e's. Search is run on pods for
|
|
6386
|
+
// comp-blink-test-pipeline with baseUrl=https://localhost:8443.
|
|
6387
|
+
// This is to handle when the developer is developing in their local
|
|
6388
|
+
// environment.
|
|
6389
|
+
if (tsHost.includes('://localhost') && !tsHost.includes(':8443')) {
|
|
6390
|
+
return '';
|
|
6391
|
+
}
|
|
6392
|
+
return 'v2';
|
|
6393
|
+
};
|
|
6394
|
+
/**
|
|
6395
|
+
* It is a good idea to keep URLs under 2000 chars.
|
|
6396
|
+
* If this is ever breached, since we pass view configuration through
|
|
6397
|
+
* URL params, we would like to log a warning.
|
|
6398
|
+
* Reference: https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
|
|
6399
|
+
*/
|
|
6400
|
+
const URL_MAX_LENGTH = 2000;
|
|
6401
|
+
/**
|
|
6402
|
+
* The default CSS dimensions of the embedded app
|
|
6403
|
+
*/
|
|
6404
|
+
const DEFAULT_EMBED_WIDTH = '100%';
|
|
6405
|
+
const DEFAULT_EMBED_HEIGHT = '100%';
|
|
6192
6406
|
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
if (_.isString(v) && v.length > 0) {
|
|
6197
|
-
ret[k] = v;
|
|
6198
|
-
}
|
|
6199
|
-
});
|
|
6200
|
-
return ret;
|
|
6407
|
+
var Config = {
|
|
6408
|
+
DEBUG: false,
|
|
6409
|
+
LIB_VERSION: '2.45.0'
|
|
6201
6410
|
};
|
|
6202
6411
|
|
|
6412
|
+
// since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
|
|
6413
|
+
var window$1;
|
|
6414
|
+
if (typeof(window) === 'undefined') {
|
|
6415
|
+
var loc = {
|
|
6416
|
+
hostname: ''
|
|
6417
|
+
};
|
|
6418
|
+
window$1 = {
|
|
6419
|
+
navigator: { userAgent: '' },
|
|
6420
|
+
document: {
|
|
6421
|
+
location: loc,
|
|
6422
|
+
referrer: ''
|
|
6423
|
+
},
|
|
6424
|
+
screen: { width: 0, height: 0 },
|
|
6425
|
+
location: loc
|
|
6426
|
+
};
|
|
6427
|
+
} else {
|
|
6428
|
+
window$1 = window;
|
|
6429
|
+
}
|
|
6430
|
+
|
|
6203
6431
|
/*
|
|
6204
|
-
*
|
|
6205
|
-
*
|
|
6206
|
-
* truncate all the values recursively.
|
|
6432
|
+
* Saved references to long variable names, so that closure compiler can
|
|
6433
|
+
* minimize file size.
|
|
6207
6434
|
*/
|
|
6208
|
-
_.truncate = function(obj, length) {
|
|
6209
|
-
var ret;
|
|
6210
6435
|
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
|
|
6436
|
+
var ArrayProto = Array.prototype;
|
|
6437
|
+
var FuncProto = Function.prototype;
|
|
6438
|
+
var ObjProto = Object.prototype;
|
|
6439
|
+
var slice = ArrayProto.slice;
|
|
6440
|
+
var toString = ObjProto.toString;
|
|
6441
|
+
var hasOwnProperty$9 = ObjProto.hasOwnProperty;
|
|
6442
|
+
var windowConsole = window$1.console;
|
|
6443
|
+
var navigator = window$1.navigator;
|
|
6444
|
+
var document$1 = window$1.document;
|
|
6445
|
+
var windowOpera = window$1.opera;
|
|
6446
|
+
var screen = window$1.screen;
|
|
6447
|
+
var userAgent = navigator.userAgent;
|
|
6448
|
+
var nativeBind = FuncProto.bind;
|
|
6449
|
+
var nativeForEach = ArrayProto.forEach;
|
|
6450
|
+
var nativeIndexOf = ArrayProto.indexOf;
|
|
6451
|
+
var nativeMap = ArrayProto.map;
|
|
6452
|
+
var nativeIsArray = Array.isArray;
|
|
6453
|
+
var breaker = {};
|
|
6454
|
+
var _ = {
|
|
6455
|
+
trim: function(str) {
|
|
6456
|
+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim#Polyfill
|
|
6457
|
+
return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
|
|
6225
6458
|
}
|
|
6226
|
-
|
|
6227
|
-
return ret;
|
|
6228
6459
|
};
|
|
6229
6460
|
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6233
|
-
|
|
6234
|
-
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
|
|
6239
|
-
|
|
6240
|
-
|
|
6241
|
-
|
|
6242
|
-
|
|
6243
|
-
|
|
6461
|
+
// Console override
|
|
6462
|
+
var console$1 = {
|
|
6463
|
+
/** @type {function(...*)} */
|
|
6464
|
+
log: function() {
|
|
6465
|
+
if (Config.DEBUG && !_.isUndefined(windowConsole) && windowConsole) {
|
|
6466
|
+
try {
|
|
6467
|
+
windowConsole.log.apply(windowConsole, arguments);
|
|
6468
|
+
} catch (err) {
|
|
6469
|
+
_.each(arguments, function(arg) {
|
|
6470
|
+
windowConsole.log(arg);
|
|
6471
|
+
});
|
|
6472
|
+
}
|
|
6473
|
+
}
|
|
6474
|
+
},
|
|
6475
|
+
/** @type {function(...*)} */
|
|
6476
|
+
warn: function() {
|
|
6477
|
+
if (Config.DEBUG && !_.isUndefined(windowConsole) && windowConsole) {
|
|
6478
|
+
var args = ['Mixpanel warning:'].concat(_.toArray(arguments));
|
|
6479
|
+
try {
|
|
6480
|
+
windowConsole.warn.apply(windowConsole, args);
|
|
6481
|
+
} catch (err) {
|
|
6482
|
+
_.each(args, function(arg) {
|
|
6483
|
+
windowConsole.warn(arg);
|
|
6484
|
+
});
|
|
6485
|
+
}
|
|
6486
|
+
}
|
|
6487
|
+
},
|
|
6488
|
+
/** @type {function(...*)} */
|
|
6489
|
+
error: function() {
|
|
6490
|
+
if (Config.DEBUG && !_.isUndefined(windowConsole) && windowConsole) {
|
|
6491
|
+
var args = ['Mixpanel error:'].concat(_.toArray(arguments));
|
|
6492
|
+
try {
|
|
6493
|
+
windowConsole.error.apply(windowConsole, args);
|
|
6494
|
+
} catch (err) {
|
|
6495
|
+
_.each(args, function(arg) {
|
|
6496
|
+
windowConsole.error(arg);
|
|
6497
|
+
});
|
|
6498
|
+
}
|
|
6499
|
+
}
|
|
6500
|
+
},
|
|
6501
|
+
/** @type {function(...*)} */
|
|
6502
|
+
critical: function() {
|
|
6503
|
+
if (!_.isUndefined(windowConsole) && windowConsole) {
|
|
6504
|
+
var args = ['Mixpanel error:'].concat(_.toArray(arguments));
|
|
6505
|
+
try {
|
|
6506
|
+
windowConsole.error.apply(windowConsole, args);
|
|
6507
|
+
} catch (err) {
|
|
6508
|
+
_.each(args, function(arg) {
|
|
6509
|
+
windowConsole.error(arg);
|
|
6510
|
+
});
|
|
6511
|
+
}
|
|
6512
|
+
}
|
|
6513
|
+
}
|
|
6514
|
+
};
|
|
6244
6515
|
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
|
|
6249
|
-
|
|
6250
|
-
|
|
6251
|
-
|
|
6252
|
-
|
|
6253
|
-
|
|
6516
|
+
var log_func_with_prefix = function(func, prefix) {
|
|
6517
|
+
return function() {
|
|
6518
|
+
arguments[0] = '[' + prefix + '] ' + arguments[0];
|
|
6519
|
+
return func.apply(console$1, arguments);
|
|
6520
|
+
};
|
|
6521
|
+
};
|
|
6522
|
+
var console_with_prefix = function(prefix) {
|
|
6523
|
+
return {
|
|
6524
|
+
log: log_func_with_prefix(console$1.log, prefix),
|
|
6525
|
+
error: log_func_with_prefix(console$1.error, prefix),
|
|
6526
|
+
critical: log_func_with_prefix(console$1.critical, prefix)
|
|
6527
|
+
};
|
|
6528
|
+
};
|
|
6254
6529
|
|
|
6255
|
-
var str = function(key, holder) {
|
|
6256
|
-
var gap = '';
|
|
6257
|
-
var indent = ' ';
|
|
6258
|
-
var i = 0; // The loop counter.
|
|
6259
|
-
var k = ''; // The member key.
|
|
6260
|
-
var v = ''; // The member value.
|
|
6261
|
-
var length = 0;
|
|
6262
|
-
var mind = gap;
|
|
6263
|
-
var partial = [];
|
|
6264
|
-
var value = holder[key];
|
|
6265
6530
|
|
|
6266
|
-
|
|
6267
|
-
|
|
6268
|
-
|
|
6269
|
-
|
|
6531
|
+
// UNDERSCORE
|
|
6532
|
+
// Embed part of the Underscore Library
|
|
6533
|
+
_.bind = function(func, context) {
|
|
6534
|
+
var args, bound;
|
|
6535
|
+
if (nativeBind && func.bind === nativeBind) {
|
|
6536
|
+
return nativeBind.apply(func, slice.call(arguments, 1));
|
|
6537
|
+
}
|
|
6538
|
+
if (!_.isFunction(func)) {
|
|
6539
|
+
throw new TypeError();
|
|
6540
|
+
}
|
|
6541
|
+
args = slice.call(arguments, 2);
|
|
6542
|
+
bound = function() {
|
|
6543
|
+
if (!(this instanceof bound)) {
|
|
6544
|
+
return func.apply(context, args.concat(slice.call(arguments)));
|
|
6545
|
+
}
|
|
6546
|
+
var ctor = {};
|
|
6547
|
+
ctor.prototype = func.prototype;
|
|
6548
|
+
var self = new ctor();
|
|
6549
|
+
ctor.prototype = null;
|
|
6550
|
+
var result = func.apply(self, args.concat(slice.call(arguments)));
|
|
6551
|
+
if (Object(result) === result) {
|
|
6552
|
+
return result;
|
|
6553
|
+
}
|
|
6554
|
+
return self;
|
|
6555
|
+
};
|
|
6556
|
+
return bound;
|
|
6557
|
+
};
|
|
6558
|
+
|
|
6559
|
+
/**
|
|
6560
|
+
* @param {*=} obj
|
|
6561
|
+
* @param {function(...*)=} iterator
|
|
6562
|
+
* @param {Object=} context
|
|
6563
|
+
*/
|
|
6564
|
+
_.each = function(obj, iterator, context) {
|
|
6565
|
+
if (obj === null || obj === undefined) {
|
|
6566
|
+
return;
|
|
6567
|
+
}
|
|
6568
|
+
if (nativeForEach && obj.forEach === nativeForEach) {
|
|
6569
|
+
obj.forEach(iterator, context);
|
|
6570
|
+
} else if (obj.length === +obj.length) {
|
|
6571
|
+
for (var i = 0, l = obj.length; i < l; i++) {
|
|
6572
|
+
if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) {
|
|
6573
|
+
return;
|
|
6574
|
+
}
|
|
6575
|
+
}
|
|
6576
|
+
} else {
|
|
6577
|
+
for (var key in obj) {
|
|
6578
|
+
if (hasOwnProperty$9.call(obj, key)) {
|
|
6579
|
+
if (iterator.call(context, obj[key], key, obj) === breaker) {
|
|
6580
|
+
return;
|
|
6581
|
+
}
|
|
6270
6582
|
}
|
|
6583
|
+
}
|
|
6584
|
+
}
|
|
6585
|
+
};
|
|
6271
6586
|
|
|
6272
|
-
|
|
6273
|
-
|
|
6274
|
-
|
|
6275
|
-
|
|
6587
|
+
_.extend = function(obj) {
|
|
6588
|
+
_.each(slice.call(arguments, 1), function(source) {
|
|
6589
|
+
for (var prop in source) {
|
|
6590
|
+
if (source[prop] !== void 0) {
|
|
6591
|
+
obj[prop] = source[prop];
|
|
6592
|
+
}
|
|
6593
|
+
}
|
|
6594
|
+
});
|
|
6595
|
+
return obj;
|
|
6596
|
+
};
|
|
6276
6597
|
|
|
6277
|
-
|
|
6278
|
-
|
|
6279
|
-
|
|
6598
|
+
_.isArray = nativeIsArray || function(obj) {
|
|
6599
|
+
return toString.call(obj) === '[object Array]';
|
|
6600
|
+
};
|
|
6280
6601
|
|
|
6281
|
-
|
|
6282
|
-
|
|
6283
|
-
|
|
6284
|
-
|
|
6285
|
-
|
|
6602
|
+
// from a comment on http://dbj.org/dbj/?p=286
|
|
6603
|
+
// fails on only one very rare and deliberate custom object:
|
|
6604
|
+
// var bomb = { toString : undefined, valueOf: function(o) { return "function BOMBA!"; }};
|
|
6605
|
+
_.isFunction = function(f) {
|
|
6606
|
+
try {
|
|
6607
|
+
return /^\s*\bfunction\b/.test(f);
|
|
6608
|
+
} catch (x) {
|
|
6609
|
+
return false;
|
|
6610
|
+
}
|
|
6611
|
+
};
|
|
6286
6612
|
|
|
6287
|
-
|
|
6613
|
+
_.isArguments = function(obj) {
|
|
6614
|
+
return !!(obj && hasOwnProperty$9.call(obj, 'callee'));
|
|
6615
|
+
};
|
|
6288
6616
|
|
|
6289
|
-
|
|
6290
|
-
|
|
6291
|
-
|
|
6292
|
-
|
|
6293
|
-
|
|
6294
|
-
|
|
6295
|
-
|
|
6296
|
-
|
|
6617
|
+
_.toArray = function(iterable) {
|
|
6618
|
+
if (!iterable) {
|
|
6619
|
+
return [];
|
|
6620
|
+
}
|
|
6621
|
+
if (iterable.toArray) {
|
|
6622
|
+
return iterable.toArray();
|
|
6623
|
+
}
|
|
6624
|
+
if (_.isArray(iterable)) {
|
|
6625
|
+
return slice.call(iterable);
|
|
6626
|
+
}
|
|
6627
|
+
if (_.isArguments(iterable)) {
|
|
6628
|
+
return slice.call(iterable);
|
|
6629
|
+
}
|
|
6630
|
+
return _.values(iterable);
|
|
6631
|
+
};
|
|
6297
6632
|
|
|
6298
|
-
|
|
6299
|
-
|
|
6300
|
-
|
|
6633
|
+
_.map = function(arr, callback, context) {
|
|
6634
|
+
if (nativeMap && arr.map === nativeMap) {
|
|
6635
|
+
return arr.map(callback, context);
|
|
6636
|
+
} else {
|
|
6637
|
+
var results = [];
|
|
6638
|
+
_.each(arr, function(item) {
|
|
6639
|
+
results.push(callback.call(context, item));
|
|
6640
|
+
});
|
|
6641
|
+
return results;
|
|
6642
|
+
}
|
|
6643
|
+
};
|
|
6301
6644
|
|
|
6302
|
-
|
|
6303
|
-
|
|
6304
|
-
|
|
6305
|
-
|
|
6645
|
+
_.keys = function(obj) {
|
|
6646
|
+
var results = [];
|
|
6647
|
+
if (obj === null) {
|
|
6648
|
+
return results;
|
|
6649
|
+
}
|
|
6650
|
+
_.each(obj, function(value, key) {
|
|
6651
|
+
results[results.length] = key;
|
|
6652
|
+
});
|
|
6653
|
+
return results;
|
|
6654
|
+
};
|
|
6306
6655
|
|
|
6307
|
-
|
|
6308
|
-
|
|
6309
|
-
|
|
6310
|
-
|
|
6656
|
+
_.values = function(obj) {
|
|
6657
|
+
var results = [];
|
|
6658
|
+
if (obj === null) {
|
|
6659
|
+
return results;
|
|
6660
|
+
}
|
|
6661
|
+
_.each(obj, function(value) {
|
|
6662
|
+
results[results.length] = value;
|
|
6663
|
+
});
|
|
6664
|
+
return results;
|
|
6665
|
+
};
|
|
6311
6666
|
|
|
6312
|
-
|
|
6313
|
-
|
|
6314
|
-
|
|
6315
|
-
|
|
6316
|
-
|
|
6317
|
-
|
|
6318
|
-
|
|
6319
|
-
|
|
6320
|
-
|
|
6321
|
-
|
|
6667
|
+
_.include = function(obj, target) {
|
|
6668
|
+
var found = false;
|
|
6669
|
+
if (obj === null) {
|
|
6670
|
+
return found;
|
|
6671
|
+
}
|
|
6672
|
+
if (nativeIndexOf && obj.indexOf === nativeIndexOf) {
|
|
6673
|
+
return obj.indexOf(target) != -1;
|
|
6674
|
+
}
|
|
6675
|
+
_.each(obj, function(value) {
|
|
6676
|
+
if (found || (found = (value === target))) {
|
|
6677
|
+
return breaker;
|
|
6678
|
+
}
|
|
6679
|
+
});
|
|
6680
|
+
return found;
|
|
6681
|
+
};
|
|
6322
6682
|
|
|
6323
|
-
|
|
6324
|
-
|
|
6325
|
-
|
|
6326
|
-
v = str(k, value);
|
|
6327
|
-
if (v) {
|
|
6328
|
-
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
|
6329
|
-
}
|
|
6330
|
-
}
|
|
6331
|
-
}
|
|
6683
|
+
_.includes = function(str, needle) {
|
|
6684
|
+
return str.indexOf(needle) !== -1;
|
|
6685
|
+
};
|
|
6332
6686
|
|
|
6333
|
-
|
|
6334
|
-
|
|
6335
|
-
|
|
6336
|
-
|
|
6337
|
-
|
|
6338
|
-
|
|
6339
|
-
|
|
6340
|
-
}
|
|
6341
|
-
};
|
|
6687
|
+
// Underscore Addons
|
|
6688
|
+
_.inherit = function(subclass, superclass) {
|
|
6689
|
+
subclass.prototype = new superclass();
|
|
6690
|
+
subclass.prototype.constructor = subclass;
|
|
6691
|
+
subclass.superclass = superclass.prototype;
|
|
6692
|
+
return subclass;
|
|
6693
|
+
};
|
|
6342
6694
|
|
|
6343
|
-
|
|
6344
|
-
|
|
6345
|
-
|
|
6346
|
-
'': value
|
|
6347
|
-
});
|
|
6348
|
-
};
|
|
6349
|
-
})();
|
|
6695
|
+
_.isObject = function(obj) {
|
|
6696
|
+
return (obj === Object(obj) && !_.isArray(obj));
|
|
6697
|
+
};
|
|
6350
6698
|
|
|
6351
|
-
|
|
6352
|
-
|
|
6353
|
-
|
|
6354
|
-
|
|
6355
|
-
|
|
6356
|
-
var at, // The index of the current character
|
|
6357
|
-
ch, // The current character
|
|
6358
|
-
escapee = {
|
|
6359
|
-
'"': '"',
|
|
6360
|
-
'\\': '\\',
|
|
6361
|
-
'/': '/',
|
|
6362
|
-
'b': '\b',
|
|
6363
|
-
'f': '\f',
|
|
6364
|
-
'n': '\n',
|
|
6365
|
-
'r': '\r',
|
|
6366
|
-
't': '\t'
|
|
6367
|
-
},
|
|
6368
|
-
text,
|
|
6369
|
-
error = function(m) {
|
|
6370
|
-
var e = new SyntaxError(m);
|
|
6371
|
-
e.at = at;
|
|
6372
|
-
e.text = text;
|
|
6373
|
-
throw e;
|
|
6374
|
-
},
|
|
6375
|
-
next = function(c) {
|
|
6376
|
-
// If a c parameter is provided, verify that it matches the current character.
|
|
6377
|
-
if (c && c !== ch) {
|
|
6378
|
-
error('Expected \'' + c + '\' instead of \'' + ch + '\'');
|
|
6699
|
+
_.isEmptyObject = function(obj) {
|
|
6700
|
+
if (_.isObject(obj)) {
|
|
6701
|
+
for (var key in obj) {
|
|
6702
|
+
if (hasOwnProperty$9.call(obj, key)) {
|
|
6703
|
+
return false;
|
|
6379
6704
|
}
|
|
6380
|
-
|
|
6705
|
+
}
|
|
6706
|
+
return true;
|
|
6707
|
+
}
|
|
6708
|
+
return false;
|
|
6709
|
+
};
|
|
6710
|
+
|
|
6711
|
+
_.isUndefined = function(obj) {
|
|
6712
|
+
return obj === void 0;
|
|
6713
|
+
};
|
|
6714
|
+
|
|
6715
|
+
_.isString = function(obj) {
|
|
6716
|
+
return toString.call(obj) == '[object String]';
|
|
6717
|
+
};
|
|
6718
|
+
|
|
6719
|
+
_.isDate = function(obj) {
|
|
6720
|
+
return toString.call(obj) == '[object Date]';
|
|
6721
|
+
};
|
|
6722
|
+
|
|
6723
|
+
_.isNumber = function(obj) {
|
|
6724
|
+
return toString.call(obj) == '[object Number]';
|
|
6725
|
+
};
|
|
6726
|
+
|
|
6727
|
+
_.isElement = function(obj) {
|
|
6728
|
+
return !!(obj && obj.nodeType === 1);
|
|
6729
|
+
};
|
|
6730
|
+
|
|
6731
|
+
_.encodeDates = function(obj) {
|
|
6732
|
+
_.each(obj, function(v, k) {
|
|
6733
|
+
if (_.isDate(v)) {
|
|
6734
|
+
obj[k] = _.formatDate(v);
|
|
6735
|
+
} else if (_.isObject(v)) {
|
|
6736
|
+
obj[k] = _.encodeDates(v); // recurse
|
|
6737
|
+
}
|
|
6738
|
+
});
|
|
6739
|
+
return obj;
|
|
6740
|
+
};
|
|
6741
|
+
|
|
6742
|
+
_.timestamp = function() {
|
|
6743
|
+
Date.now = Date.now || function() {
|
|
6744
|
+
return +new Date;
|
|
6745
|
+
};
|
|
6746
|
+
return Date.now();
|
|
6747
|
+
};
|
|
6748
|
+
|
|
6749
|
+
_.formatDate = function(d) {
|
|
6750
|
+
// YYYY-MM-DDTHH:MM:SS in UTC
|
|
6751
|
+
function pad(n) {
|
|
6752
|
+
return n < 10 ? '0' + n : n;
|
|
6753
|
+
}
|
|
6754
|
+
return d.getUTCFullYear() + '-' +
|
|
6755
|
+
pad(d.getUTCMonth() + 1) + '-' +
|
|
6756
|
+
pad(d.getUTCDate()) + 'T' +
|
|
6757
|
+
pad(d.getUTCHours()) + ':' +
|
|
6758
|
+
pad(d.getUTCMinutes()) + ':' +
|
|
6759
|
+
pad(d.getUTCSeconds());
|
|
6760
|
+
};
|
|
6761
|
+
|
|
6762
|
+
_.strip_empty_properties = function(p) {
|
|
6763
|
+
var ret = {};
|
|
6764
|
+
_.each(p, function(v, k) {
|
|
6765
|
+
if (_.isString(v) && v.length > 0) {
|
|
6766
|
+
ret[k] = v;
|
|
6767
|
+
}
|
|
6768
|
+
});
|
|
6769
|
+
return ret;
|
|
6770
|
+
};
|
|
6771
|
+
|
|
6772
|
+
/*
|
|
6773
|
+
* this function returns a copy of object after truncating it. If
|
|
6774
|
+
* passed an Array or Object it will iterate through obj and
|
|
6775
|
+
* truncate all the values recursively.
|
|
6776
|
+
*/
|
|
6777
|
+
_.truncate = function(obj, length) {
|
|
6778
|
+
var ret;
|
|
6779
|
+
|
|
6780
|
+
if (typeof(obj) === 'string') {
|
|
6781
|
+
ret = obj.slice(0, length);
|
|
6782
|
+
} else if (_.isArray(obj)) {
|
|
6783
|
+
ret = [];
|
|
6784
|
+
_.each(obj, function(val) {
|
|
6785
|
+
ret.push(_.truncate(val, length));
|
|
6786
|
+
});
|
|
6787
|
+
} else if (_.isObject(obj)) {
|
|
6788
|
+
ret = {};
|
|
6789
|
+
_.each(obj, function(val, key) {
|
|
6790
|
+
ret[key] = _.truncate(val, length);
|
|
6791
|
+
});
|
|
6792
|
+
} else {
|
|
6793
|
+
ret = obj;
|
|
6794
|
+
}
|
|
6795
|
+
|
|
6796
|
+
return ret;
|
|
6797
|
+
};
|
|
6798
|
+
|
|
6799
|
+
_.JSONEncode = (function() {
|
|
6800
|
+
return function(mixed_val) {
|
|
6801
|
+
var value = mixed_val;
|
|
6802
|
+
var quote = function(string) {
|
|
6803
|
+
var escapable = /[\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; // eslint-disable-line no-control-regex
|
|
6804
|
+
var meta = { // table of character substitutions
|
|
6805
|
+
'\b': '\\b',
|
|
6806
|
+
'\t': '\\t',
|
|
6807
|
+
'\n': '\\n',
|
|
6808
|
+
'\f': '\\f',
|
|
6809
|
+
'\r': '\\r',
|
|
6810
|
+
'"': '\\"',
|
|
6811
|
+
'\\': '\\\\'
|
|
6812
|
+
};
|
|
6813
|
+
|
|
6814
|
+
escapable.lastIndex = 0;
|
|
6815
|
+
return escapable.test(string) ?
|
|
6816
|
+
'"' + string.replace(escapable, function(a) {
|
|
6817
|
+
var c = meta[a];
|
|
6818
|
+
return typeof c === 'string' ? c :
|
|
6819
|
+
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
|
6820
|
+
}) + '"' :
|
|
6821
|
+
'"' + string + '"';
|
|
6822
|
+
};
|
|
6823
|
+
|
|
6824
|
+
var str = function(key, holder) {
|
|
6825
|
+
var gap = '';
|
|
6826
|
+
var indent = ' ';
|
|
6827
|
+
var i = 0; // The loop counter.
|
|
6828
|
+
var k = ''; // The member key.
|
|
6829
|
+
var v = ''; // The member value.
|
|
6830
|
+
var length = 0;
|
|
6831
|
+
var mind = gap;
|
|
6832
|
+
var partial = [];
|
|
6833
|
+
var value = holder[key];
|
|
6834
|
+
|
|
6835
|
+
// If the value has a toJSON method, call it to obtain a replacement value.
|
|
6836
|
+
if (value && typeof value === 'object' &&
|
|
6837
|
+
typeof value.toJSON === 'function') {
|
|
6838
|
+
value = value.toJSON(key);
|
|
6839
|
+
}
|
|
6840
|
+
|
|
6841
|
+
// What happens next depends on the value's type.
|
|
6842
|
+
switch (typeof value) {
|
|
6843
|
+
case 'string':
|
|
6844
|
+
return quote(value);
|
|
6845
|
+
|
|
6846
|
+
case 'number':
|
|
6847
|
+
// JSON numbers must be finite. Encode non-finite numbers as null.
|
|
6848
|
+
return isFinite(value) ? String(value) : 'null';
|
|
6849
|
+
|
|
6850
|
+
case 'boolean':
|
|
6851
|
+
case 'null':
|
|
6852
|
+
// If the value is a boolean or null, convert it to a string. Note:
|
|
6853
|
+
// typeof null does not produce 'null'. The case is included here in
|
|
6854
|
+
// the remote chance that this gets fixed someday.
|
|
6855
|
+
|
|
6856
|
+
return String(value);
|
|
6857
|
+
|
|
6858
|
+
case 'object':
|
|
6859
|
+
// If the type is 'object', we might be dealing with an object or an array or
|
|
6860
|
+
// null.
|
|
6861
|
+
// Due to a specification blunder in ECMAScript, typeof null is 'object',
|
|
6862
|
+
// so watch out for that case.
|
|
6863
|
+
if (!value) {
|
|
6864
|
+
return 'null';
|
|
6865
|
+
}
|
|
6866
|
+
|
|
6867
|
+
// Make an array to hold the partial results of stringifying this object value.
|
|
6868
|
+
gap += indent;
|
|
6869
|
+
partial = [];
|
|
6870
|
+
|
|
6871
|
+
// Is the value an array?
|
|
6872
|
+
if (toString.apply(value) === '[object Array]') {
|
|
6873
|
+
// The value is an array. Stringify every element. Use null as a placeholder
|
|
6874
|
+
// for non-JSON values.
|
|
6875
|
+
|
|
6876
|
+
length = value.length;
|
|
6877
|
+
for (i = 0; i < length; i += 1) {
|
|
6878
|
+
partial[i] = str(i, value) || 'null';
|
|
6879
|
+
}
|
|
6880
|
+
|
|
6881
|
+
// Join all of the elements together, separated with commas, and wrap them in
|
|
6882
|
+
// brackets.
|
|
6883
|
+
v = partial.length === 0 ? '[]' :
|
|
6884
|
+
gap ? '[\n' + gap +
|
|
6885
|
+
partial.join(',\n' + gap) + '\n' +
|
|
6886
|
+
mind + ']' :
|
|
6887
|
+
'[' + partial.join(',') + ']';
|
|
6888
|
+
gap = mind;
|
|
6889
|
+
return v;
|
|
6890
|
+
}
|
|
6891
|
+
|
|
6892
|
+
// Iterate through all of the keys in the object.
|
|
6893
|
+
for (k in value) {
|
|
6894
|
+
if (hasOwnProperty$9.call(value, k)) {
|
|
6895
|
+
v = str(k, value);
|
|
6896
|
+
if (v) {
|
|
6897
|
+
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
|
6898
|
+
}
|
|
6899
|
+
}
|
|
6900
|
+
}
|
|
6901
|
+
|
|
6902
|
+
// Join all of the member texts together, separated with commas,
|
|
6903
|
+
// and wrap them in braces.
|
|
6904
|
+
v = partial.length === 0 ? '{}' :
|
|
6905
|
+
gap ? '{' + partial.join(',') + '' +
|
|
6906
|
+
mind + '}' : '{' + partial.join(',') + '}';
|
|
6907
|
+
gap = mind;
|
|
6908
|
+
return v;
|
|
6909
|
+
}
|
|
6910
|
+
};
|
|
6911
|
+
|
|
6912
|
+
// Make a fake root object containing our value under the key of ''.
|
|
6913
|
+
// Return the result of stringifying the value.
|
|
6914
|
+
return str('', {
|
|
6915
|
+
'': value
|
|
6916
|
+
});
|
|
6917
|
+
};
|
|
6918
|
+
})();
|
|
6919
|
+
|
|
6920
|
+
/**
|
|
6921
|
+
* From https://github.com/douglascrockford/JSON-js/blob/master/json_parse.js
|
|
6922
|
+
* Slightly modified to throw a real Error rather than a POJO
|
|
6923
|
+
*/
|
|
6924
|
+
_.JSONDecode = (function() {
|
|
6925
|
+
var at, // The index of the current character
|
|
6926
|
+
ch, // The current character
|
|
6927
|
+
escapee = {
|
|
6928
|
+
'"': '"',
|
|
6929
|
+
'\\': '\\',
|
|
6930
|
+
'/': '/',
|
|
6931
|
+
'b': '\b',
|
|
6932
|
+
'f': '\f',
|
|
6933
|
+
'n': '\n',
|
|
6934
|
+
'r': '\r',
|
|
6935
|
+
't': '\t'
|
|
6936
|
+
},
|
|
6937
|
+
text,
|
|
6938
|
+
error = function(m) {
|
|
6939
|
+
var e = new SyntaxError(m);
|
|
6940
|
+
e.at = at;
|
|
6941
|
+
e.text = text;
|
|
6942
|
+
throw e;
|
|
6943
|
+
},
|
|
6944
|
+
next = function(c) {
|
|
6945
|
+
// If a c parameter is provided, verify that it matches the current character.
|
|
6946
|
+
if (c && c !== ch) {
|
|
6947
|
+
error('Expected \'' + c + '\' instead of \'' + ch + '\'');
|
|
6948
|
+
}
|
|
6949
|
+
// Get the next character. When there are no more characters,
|
|
6381
6950
|
// return the empty string.
|
|
6382
6951
|
ch = text.charAt(at);
|
|
6383
6952
|
at += 1;
|
|
@@ -11829,6 +12398,7 @@ const MIXPANEL_EVENT = {
|
|
|
11829
12398
|
VISUAL_SDK_ON: 'visual-sdk-on',
|
|
11830
12399
|
VISUAL_SDK_IFRAME_LOAD_PERFORMANCE: 'visual-sdk-iframe-load-performance',
|
|
11831
12400
|
VISUAL_SDK_EMBED_CREATE: 'visual-sdk-embed-create',
|
|
12401
|
+
VERCEL_INTEGRATION_COMPLETED: 'vercel-integration-completed',
|
|
11832
12402
|
};
|
|
11833
12403
|
let isMixpanelInitialized = false;
|
|
11834
12404
|
let eventQueue = [];
|
|
@@ -11891,1086 +12461,158 @@ function initMixpanel(sessionInfo) {
|
|
|
11891
12461
|
}
|
|
11892
12462
|
}
|
|
11893
12463
|
|
|
11894
|
-
|
|
11895
|
-
|
|
11896
|
-
|
|
11897
|
-
|
|
11898
|
-
|
|
11899
|
-
|
|
11900
|
-
*
|
|
11901
|
-
|
|
11902
|
-
|
|
11903
|
-
|
|
11904
|
-
*
|
|
11905
|
-
|
|
11906
|
-
|
|
11907
|
-
|
|
11908
|
-
|
|
11909
|
-
|
|
11910
|
-
|
|
11911
|
-
|
|
11912
|
-
|
|
11913
|
-
|
|
12464
|
+
var eventemitter3 = createCommonjsModule(function (module) {
|
|
12465
|
+
|
|
12466
|
+
var has = Object.prototype.hasOwnProperty
|
|
12467
|
+
, prefix = '~';
|
|
12468
|
+
|
|
12469
|
+
/**
|
|
12470
|
+
* Constructor to create a storage for our `EE` objects.
|
|
12471
|
+
* An `Events` instance is a plain object whose properties are event names.
|
|
12472
|
+
*
|
|
12473
|
+
* @constructor
|
|
12474
|
+
* @private
|
|
12475
|
+
*/
|
|
12476
|
+
function Events() {}
|
|
12477
|
+
|
|
12478
|
+
//
|
|
12479
|
+
// We try to not inherit from `Object.prototype`. In some engines creating an
|
|
12480
|
+
// instance in this way is faster than calling `Object.create(null)` directly.
|
|
12481
|
+
// If `Object.create(null)` is not supported we prefix the event names with a
|
|
12482
|
+
// character to make sure that the built-in object properties are not
|
|
12483
|
+
// overridden or used as an attack vector.
|
|
12484
|
+
//
|
|
12485
|
+
if (Object.create) {
|
|
12486
|
+
Events.prototype = Object.create(null);
|
|
12487
|
+
|
|
12488
|
+
//
|
|
12489
|
+
// This hack is needed because the `__proto__` property is still inherited in
|
|
12490
|
+
// some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.
|
|
12491
|
+
//
|
|
12492
|
+
if (!new Events().__proto__) prefix = false;
|
|
12493
|
+
}
|
|
12494
|
+
|
|
12495
|
+
/**
|
|
12496
|
+
* Representation of a single event listener.
|
|
12497
|
+
*
|
|
12498
|
+
* @param {Function} fn The listener function.
|
|
12499
|
+
* @param {*} context The context to invoke the listener with.
|
|
12500
|
+
* @param {Boolean} [once=false] Specify if the listener is a one-time listener.
|
|
12501
|
+
* @constructor
|
|
12502
|
+
* @private
|
|
12503
|
+
*/
|
|
12504
|
+
function EE(fn, context, once) {
|
|
12505
|
+
this.fn = fn;
|
|
12506
|
+
this.context = context;
|
|
12507
|
+
this.once = once || false;
|
|
12508
|
+
}
|
|
12509
|
+
|
|
12510
|
+
/**
|
|
12511
|
+
* Add a listener for a given event.
|
|
12512
|
+
*
|
|
12513
|
+
* @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
|
|
12514
|
+
* @param {(String|Symbol)} event The event name.
|
|
12515
|
+
* @param {Function} fn The listener function.
|
|
12516
|
+
* @param {*} context The context to invoke the listener with.
|
|
12517
|
+
* @param {Boolean} once Specify if the listener is a one-time listener.
|
|
12518
|
+
* @returns {EventEmitter}
|
|
12519
|
+
* @private
|
|
12520
|
+
*/
|
|
12521
|
+
function addListener(emitter, event, fn, context, once) {
|
|
12522
|
+
if (typeof fn !== 'function') {
|
|
12523
|
+
throw new TypeError('The listener must be a function');
|
|
12524
|
+
}
|
|
12525
|
+
|
|
12526
|
+
var listener = new EE(fn, context || emitter, once)
|
|
12527
|
+
, evt = prefix ? prefix + event : event;
|
|
12528
|
+
|
|
12529
|
+
if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;
|
|
12530
|
+
else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);
|
|
12531
|
+
else emitter._events[evt] = [emitter._events[evt], listener];
|
|
12532
|
+
|
|
12533
|
+
return emitter;
|
|
12534
|
+
}
|
|
12535
|
+
|
|
12536
|
+
/**
|
|
12537
|
+
* Clear event by name.
|
|
12538
|
+
*
|
|
12539
|
+
* @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
|
|
12540
|
+
* @param {(String|Symbol)} evt The Event name.
|
|
12541
|
+
* @private
|
|
12542
|
+
*/
|
|
12543
|
+
function clearEvent(emitter, evt) {
|
|
12544
|
+
if (--emitter._eventsCount === 0) emitter._events = new Events();
|
|
12545
|
+
else delete emitter._events[evt];
|
|
12546
|
+
}
|
|
12547
|
+
|
|
12548
|
+
/**
|
|
12549
|
+
* Minimal `EventEmitter` interface that is molded against the Node.js
|
|
12550
|
+
* `EventEmitter` interface.
|
|
12551
|
+
*
|
|
12552
|
+
* @constructor
|
|
12553
|
+
* @public
|
|
12554
|
+
*/
|
|
12555
|
+
function EventEmitter() {
|
|
12556
|
+
this._events = new Events();
|
|
12557
|
+
this._eventsCount = 0;
|
|
12558
|
+
}
|
|
12559
|
+
|
|
12560
|
+
/**
|
|
12561
|
+
* Return an array listing the events for which the emitter has registered
|
|
12562
|
+
* listeners.
|
|
12563
|
+
*
|
|
12564
|
+
* @returns {Array}
|
|
12565
|
+
* @public
|
|
12566
|
+
*/
|
|
12567
|
+
EventEmitter.prototype.eventNames = function eventNames() {
|
|
12568
|
+
var names = []
|
|
12569
|
+
, events
|
|
12570
|
+
, name;
|
|
12571
|
+
|
|
12572
|
+
if (this._eventsCount === 0) return names;
|
|
12573
|
+
|
|
12574
|
+
for (name in (events = this._events)) {
|
|
12575
|
+
if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
|
|
12576
|
+
}
|
|
12577
|
+
|
|
12578
|
+
if (Object.getOwnPropertySymbols) {
|
|
12579
|
+
return names.concat(Object.getOwnPropertySymbols(events));
|
|
12580
|
+
}
|
|
12581
|
+
|
|
12582
|
+
return names;
|
|
11914
12583
|
};
|
|
11915
12584
|
|
|
11916
|
-
|
|
11917
|
-
|
|
11918
|
-
|
|
11919
|
-
|
|
11920
|
-
|
|
11921
|
-
|
|
11922
|
-
|
|
11923
|
-
|
|
11924
|
-
|
|
11925
|
-
|
|
11926
|
-
|
|
12585
|
+
/**
|
|
12586
|
+
* Return the listeners registered for a given event.
|
|
12587
|
+
*
|
|
12588
|
+
* @param {(String|Symbol)} event The event name.
|
|
12589
|
+
* @returns {Array} The registered listeners.
|
|
12590
|
+
* @public
|
|
12591
|
+
*/
|
|
12592
|
+
EventEmitter.prototype.listeners = function listeners(event) {
|
|
12593
|
+
var evt = prefix ? prefix + event : event
|
|
12594
|
+
, handlers = this._events[evt];
|
|
12595
|
+
|
|
12596
|
+
if (!handlers) return [];
|
|
12597
|
+
if (handlers.fn) return [handlers.fn];
|
|
12598
|
+
|
|
12599
|
+
for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {
|
|
12600
|
+
ee[i] = handlers[i].fn;
|
|
12601
|
+
}
|
|
12602
|
+
|
|
12603
|
+
return ee;
|
|
11927
12604
|
};
|
|
11928
12605
|
|
|
11929
|
-
/**
|
|
11930
|
-
*
|
|
11931
|
-
*
|
|
11932
|
-
* @param
|
|
11933
|
-
|
|
11934
|
-
|
|
11935
|
-
|
|
11936
|
-
|
|
11937
|
-
|
|
11938
|
-
|
|
11939
|
-
}
|
|
11940
|
-
return r;
|
|
11941
|
-
});
|
|
11942
|
-
}
|
|
11943
|
-
/**
|
|
11944
|
-
*
|
|
11945
|
-
* @param authVerificationUrl
|
|
11946
|
-
*/
|
|
11947
|
-
function fetchSessionInfoService(authVerificationUrl) {
|
|
11948
|
-
return tokenisedFailureLoggedFetch(authVerificationUrl, {
|
|
11949
|
-
credentials: 'include',
|
|
11950
|
-
});
|
|
11951
|
-
}
|
|
11952
|
-
/**
|
|
11953
|
-
*
|
|
11954
|
-
* @param thoughtSpotHost
|
|
11955
|
-
*/
|
|
11956
|
-
async function fetchLogoutService(thoughtSpotHost) {
|
|
11957
|
-
return tokenisedFailureLoggedFetch(`${thoughtSpotHost}${EndPoints.LOGOUT}`, {
|
|
11958
|
-
credentials: 'include',
|
|
11959
|
-
method: 'POST',
|
|
11960
|
-
headers: {
|
|
11961
|
-
'x-requested-by': 'ThoughtSpot',
|
|
11962
|
-
},
|
|
11963
|
-
});
|
|
11964
|
-
}
|
|
11965
|
-
|
|
11966
|
-
// eslint-disable-next-line import/no-mutable-exports
|
|
11967
|
-
let loggedInStatus = false;
|
|
11968
|
-
// eslint-disable-next-line import/no-mutable-exports
|
|
11969
|
-
let samlAuthWindow = null;
|
|
11970
|
-
// eslint-disable-next-line import/no-mutable-exports
|
|
11971
|
-
let samlCompletionPromise = null;
|
|
11972
|
-
let sessionInfo = null;
|
|
11973
|
-
let sessionInfoResolver = null;
|
|
11974
|
-
const sessionInfoPromise = new Promise((resolve) => {
|
|
11975
|
-
sessionInfoResolver = resolve;
|
|
11976
|
-
});
|
|
11977
|
-
let releaseVersion = '';
|
|
11978
|
-
const SSO_REDIRECTION_MARKER_GUID = '5e16222e-ef02-43e9-9fbd-24226bf3ce5b';
|
|
11979
|
-
/**
|
|
11980
|
-
* Enum for auth failure types. This is the parameter passed to the listner
|
|
11981
|
-
* of {@link AuthStatus.FAILURE}.
|
|
11982
|
-
*
|
|
11983
|
-
* @group Authentication / Init
|
|
11984
|
-
*/
|
|
11985
|
-
var AuthFailureType;
|
|
11986
|
-
(function (AuthFailureType) {
|
|
11987
|
-
AuthFailureType["SDK"] = "SDK";
|
|
11988
|
-
AuthFailureType["NO_COOKIE_ACCESS"] = "NO_COOKIE_ACCESS";
|
|
11989
|
-
AuthFailureType["EXPIRY"] = "EXPIRY";
|
|
11990
|
-
AuthFailureType["OTHER"] = "OTHER";
|
|
11991
|
-
})(AuthFailureType || (AuthFailureType = {}));
|
|
11992
|
-
/**
|
|
11993
|
-
* Enum for auth status emitted by the emitter returned from {@link init}.
|
|
11994
|
-
*
|
|
11995
|
-
* @group Authentication / Init
|
|
11996
|
-
*/
|
|
11997
|
-
var AuthStatus;
|
|
11998
|
-
(function (AuthStatus) {
|
|
11999
|
-
/**
|
|
12000
|
-
* Emits when the SDK fails to authenticate
|
|
12001
|
-
*/
|
|
12002
|
-
AuthStatus["FAILURE"] = "FAILURE";
|
|
12003
|
-
/**
|
|
12004
|
-
* Emits when the SDK authenticates successfully
|
|
12005
|
-
*/
|
|
12006
|
-
AuthStatus["SDK_SUCCESS"] = "SDK_SUCCESS";
|
|
12007
|
-
/**
|
|
12008
|
-
* Emits when the app sends an authentication success message
|
|
12009
|
-
*/
|
|
12010
|
-
AuthStatus["SUCCESS"] = "SUCCESS";
|
|
12011
|
-
/**
|
|
12012
|
-
* Emits when a user logs out
|
|
12013
|
-
*/
|
|
12014
|
-
AuthStatus["LOGOUT"] = "LOGOUT";
|
|
12015
|
-
/**
|
|
12016
|
-
* Emitted when inPopup is true in the SAMLRedirect flow and the
|
|
12017
|
-
* popup is waiting to be triggered either programmatically
|
|
12018
|
-
* or by the trigger button.
|
|
12019
|
-
*
|
|
12020
|
-
* @version SDK: 1.19.0
|
|
12021
|
-
*/
|
|
12022
|
-
AuthStatus["WAITING_FOR_POPUP"] = "WAITING_FOR_POPUP";
|
|
12023
|
-
})(AuthStatus || (AuthStatus = {}));
|
|
12024
|
-
/**
|
|
12025
|
-
* Events which can be triggered on the emitter returned from {@link init}.
|
|
12026
|
-
*
|
|
12027
|
-
* @group Authentication / Init
|
|
12028
|
-
*/
|
|
12029
|
-
var AuthEvent;
|
|
12030
|
-
(function (AuthEvent) {
|
|
12031
|
-
/**
|
|
12032
|
-
* Manually trigger the SSO popup. This is useful when
|
|
12033
|
-
* authStatus is SAMLRedirect/OIDCRedirect and inPopup is set to true
|
|
12034
|
-
*/
|
|
12035
|
-
AuthEvent["TRIGGER_SSO_POPUP"] = "TRIGGER_SSO_POPUP";
|
|
12036
|
-
})(AuthEvent || (AuthEvent = {}));
|
|
12037
|
-
let authEE;
|
|
12038
|
-
/**
|
|
12039
|
-
*
|
|
12040
|
-
* @param eventEmitter
|
|
12041
|
-
*/
|
|
12042
|
-
function setAuthEE(eventEmitter) {
|
|
12043
|
-
authEE = eventEmitter;
|
|
12044
|
-
}
|
|
12045
|
-
/**
|
|
12046
|
-
*
|
|
12047
|
-
*/
|
|
12048
|
-
function notifyAuthSDKSuccess() {
|
|
12049
|
-
if (!authEE) {
|
|
12050
|
-
logger.error('SDK not initialized');
|
|
12051
|
-
return;
|
|
12052
|
-
}
|
|
12053
|
-
authEE.emit(AuthStatus.SDK_SUCCESS);
|
|
12054
|
-
}
|
|
12055
|
-
/**
|
|
12056
|
-
*
|
|
12057
|
-
*/
|
|
12058
|
-
function notifyAuthSuccess() {
|
|
12059
|
-
if (!authEE) {
|
|
12060
|
-
logger.error('SDK not initialized');
|
|
12061
|
-
return;
|
|
12062
|
-
}
|
|
12063
|
-
authEE.emit(AuthStatus.SUCCESS, sessionInfo);
|
|
12064
|
-
}
|
|
12065
|
-
/**
|
|
12066
|
-
*
|
|
12067
|
-
* @param failureType
|
|
12068
|
-
*/
|
|
12069
|
-
function notifyAuthFailure(failureType) {
|
|
12070
|
-
if (!authEE) {
|
|
12071
|
-
logger.error('SDK not initialized');
|
|
12072
|
-
return;
|
|
12073
|
-
}
|
|
12074
|
-
authEE.emit(AuthStatus.FAILURE, failureType);
|
|
12075
|
-
}
|
|
12076
|
-
/**
|
|
12077
|
-
*
|
|
12078
|
-
*/
|
|
12079
|
-
function notifyLogout() {
|
|
12080
|
-
if (!authEE) {
|
|
12081
|
-
logger.error('SDK not initialized');
|
|
12082
|
-
return;
|
|
12083
|
-
}
|
|
12084
|
-
authEE.emit(AuthStatus.LOGOUT);
|
|
12085
|
-
}
|
|
12086
|
-
const initSession = (sessionDetails) => {
|
|
12087
|
-
if (sessionInfo == null) {
|
|
12088
|
-
sessionInfo = sessionDetails;
|
|
12089
|
-
initMixpanel(sessionInfo);
|
|
12090
|
-
sessionInfoResolver(sessionInfo);
|
|
12091
|
-
}
|
|
12092
|
-
};
|
|
12093
|
-
const getSessionDetails = (sessionInfoResp) => {
|
|
12094
|
-
const devMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.devSdkKey;
|
|
12095
|
-
const prodMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.prodSdkKey;
|
|
12096
|
-
const mixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.production
|
|
12097
|
-
? prodMixpanelToken
|
|
12098
|
-
: devMixpanelToken;
|
|
12099
|
-
return {
|
|
12100
|
-
userGUID: sessionInfoResp.userGUID,
|
|
12101
|
-
mixpanelToken,
|
|
12102
|
-
isPublicUser: sessionInfoResp.configInfo.isPublicUser,
|
|
12103
|
-
releaseVersion: sessionInfoResp.releaseVersion,
|
|
12104
|
-
clusterId: sessionInfoResp.configInfo.selfClusterId,
|
|
12105
|
-
clusterName: sessionInfoResp.configInfo.selfClusterName,
|
|
12106
|
-
...sessionInfoResp,
|
|
12107
|
-
};
|
|
12108
|
-
};
|
|
12109
|
-
/**
|
|
12110
|
-
* Check if we are logged into the ThoughtSpot cluster
|
|
12111
|
-
*
|
|
12112
|
-
* @param thoughtSpotHost The ThoughtSpot cluster hostname or IP
|
|
12113
|
-
*/
|
|
12114
|
-
async function isLoggedIn(thoughtSpotHost) {
|
|
12115
|
-
const authVerificationUrl = `${thoughtSpotHost}${EndPoints.AUTH_VERIFICATION}`;
|
|
12116
|
-
let response = null;
|
|
12117
|
-
try {
|
|
12118
|
-
response = await fetchSessionInfoService(authVerificationUrl);
|
|
12119
|
-
const sessionInfoResp = await response.json();
|
|
12120
|
-
const sessionDetails = getSessionDetails(sessionInfoResp);
|
|
12121
|
-
// Store user session details from session info
|
|
12122
|
-
initSession(sessionDetails);
|
|
12123
|
-
releaseVersion = sessionInfoResp.releaseVersion;
|
|
12124
|
-
}
|
|
12125
|
-
catch (e) {
|
|
12126
|
-
return false;
|
|
12127
|
-
}
|
|
12128
|
-
return response.status === 200;
|
|
12129
|
-
}
|
|
12130
|
-
/**
|
|
12131
|
-
* Return releaseVersion if available
|
|
12132
|
-
*/
|
|
12133
|
-
function getReleaseVersion() {
|
|
12134
|
-
return releaseVersion;
|
|
12135
|
-
}
|
|
12136
|
-
/**
|
|
12137
|
-
* Return a promise that resolves with the session information when
|
|
12138
|
-
* authentication is successful. And info is available.
|
|
12139
|
-
*
|
|
12140
|
-
* @group Global methods
|
|
12141
|
-
*/
|
|
12142
|
-
function getSessionInfo() {
|
|
12143
|
-
return sessionInfoPromise;
|
|
12144
|
-
}
|
|
12145
|
-
/**
|
|
12146
|
-
* Check if we are stuck at the SSO redirect URL
|
|
12147
|
-
*/
|
|
12148
|
-
function isAtSSORedirectUrl() {
|
|
12149
|
-
return window.location.href.indexOf(SSO_REDIRECTION_MARKER_GUID) >= 0;
|
|
12150
|
-
}
|
|
12151
|
-
/**
|
|
12152
|
-
* Remove the SSO redirect URL marker
|
|
12153
|
-
*/
|
|
12154
|
-
function removeSSORedirectUrlMarker() {
|
|
12155
|
-
// Note (sunny): This will leave a # around even if it was not in the URL
|
|
12156
|
-
// to begin with. Trying to remove the hash by changing window.location will
|
|
12157
|
-
// reload the page which we don't want. We'll live with adding an
|
|
12158
|
-
// unnecessary hash to the parent page URL until we find any use case where
|
|
12159
|
-
// that creates an issue.
|
|
12160
|
-
window.location.hash = window.location.hash.replace(SSO_REDIRECTION_MARKER_GUID, '');
|
|
12161
|
-
}
|
|
12162
|
-
/**
|
|
12163
|
-
* Perform token based authentication
|
|
12164
|
-
*
|
|
12165
|
-
* @param embedConfig The embed configuration
|
|
12166
|
-
*/
|
|
12167
|
-
const doTokenAuth = async (embedConfig) => {
|
|
12168
|
-
const { thoughtSpotHost, username, authEndpoint, getAuthToken, } = embedConfig;
|
|
12169
|
-
if (!authEndpoint && !getAuthToken) {
|
|
12170
|
-
throw new Error('Either auth endpoint or getAuthToken function must be provided');
|
|
12171
|
-
}
|
|
12172
|
-
loggedInStatus = await isLoggedIn(thoughtSpotHost);
|
|
12173
|
-
if (!loggedInStatus) {
|
|
12174
|
-
const authToken = await getAuthenticationToken(embedConfig);
|
|
12175
|
-
let resp;
|
|
12176
|
-
try {
|
|
12177
|
-
resp = await fetchAuthPostService(thoughtSpotHost, username, authToken);
|
|
12178
|
-
}
|
|
12179
|
-
catch (e) {
|
|
12180
|
-
resp = await fetchAuthService(thoughtSpotHost, username, authToken);
|
|
12181
|
-
}
|
|
12182
|
-
// token login issues a 302 when successful
|
|
12183
|
-
loggedInStatus = resp.ok || resp.type === 'opaqueredirect';
|
|
12184
|
-
if (loggedInStatus && embedConfig.detectCookieAccessSlow) {
|
|
12185
|
-
// When 3rd party cookie access is blocked, this will fail because
|
|
12186
|
-
// cookies will not be sent with the call.
|
|
12187
|
-
loggedInStatus = await isLoggedIn(thoughtSpotHost);
|
|
12188
|
-
}
|
|
12189
|
-
}
|
|
12190
|
-
return loggedInStatus;
|
|
12191
|
-
};
|
|
12192
|
-
/**
|
|
12193
|
-
* Validate embedConfig parameters required for cookielessTokenAuth
|
|
12194
|
-
*
|
|
12195
|
-
* @param embedConfig The embed configuration
|
|
12196
|
-
*/
|
|
12197
|
-
const doCookielessTokenAuth = async (embedConfig) => {
|
|
12198
|
-
const { authEndpoint, getAuthToken } = embedConfig;
|
|
12199
|
-
if (!authEndpoint && !getAuthToken) {
|
|
12200
|
-
throw new Error('Either auth endpoint or getAuthToken function must be provided');
|
|
12201
|
-
}
|
|
12202
|
-
let authSuccess = false;
|
|
12203
|
-
try {
|
|
12204
|
-
const authToken = await getAuthenticationToken(embedConfig);
|
|
12205
|
-
if (authToken) {
|
|
12206
|
-
authSuccess = true;
|
|
12207
|
-
}
|
|
12208
|
-
}
|
|
12209
|
-
catch {
|
|
12210
|
-
authSuccess = false;
|
|
12211
|
-
}
|
|
12212
|
-
return authSuccess;
|
|
12213
|
-
};
|
|
12214
|
-
/**
|
|
12215
|
-
* Perform basic authentication to the ThoughtSpot cluster using the cluster
|
|
12216
|
-
* credentials.
|
|
12217
|
-
*
|
|
12218
|
-
* Warning: This feature is primarily intended for developer testing. It is
|
|
12219
|
-
* strongly advised not to use this authentication method in production.
|
|
12220
|
-
*
|
|
12221
|
-
* @param embedConfig The embed configuration
|
|
12222
|
-
*/
|
|
12223
|
-
const doBasicAuth = async (embedConfig) => {
|
|
12224
|
-
const { thoughtSpotHost, username, password } = embedConfig;
|
|
12225
|
-
const loggedIn = await isLoggedIn(thoughtSpotHost);
|
|
12226
|
-
if (!loggedIn) {
|
|
12227
|
-
const response = await fetchBasicAuthService(thoughtSpotHost, username, password);
|
|
12228
|
-
loggedInStatus = response.ok;
|
|
12229
|
-
if (embedConfig.detectCookieAccessSlow) {
|
|
12230
|
-
loggedInStatus = await isLoggedIn(thoughtSpotHost);
|
|
12231
|
-
}
|
|
12232
|
-
}
|
|
12233
|
-
else {
|
|
12234
|
-
loggedInStatus = true;
|
|
12235
|
-
}
|
|
12236
|
-
return loggedInStatus;
|
|
12237
|
-
};
|
|
12238
|
-
/**
|
|
12239
|
-
*
|
|
12240
|
-
* @param ssoURL
|
|
12241
|
-
* @param triggerContainer
|
|
12242
|
-
* @param triggerText
|
|
12243
|
-
*/
|
|
12244
|
-
async function samlPopupFlow(ssoURL, triggerContainer, triggerText) {
|
|
12245
|
-
const openPopup = () => {
|
|
12246
|
-
if (samlAuthWindow === null || samlAuthWindow.closed) {
|
|
12247
|
-
samlAuthWindow = window.open(ssoURL, '_blank', 'location=no,height=570,width=520,scrollbars=yes,status=yes');
|
|
12248
|
-
}
|
|
12249
|
-
else {
|
|
12250
|
-
samlAuthWindow.focus();
|
|
12251
|
-
}
|
|
12252
|
-
};
|
|
12253
|
-
authEE === null || authEE === void 0 ? void 0 : authEE.emit(AuthStatus.WAITING_FOR_POPUP);
|
|
12254
|
-
const containerEl = getDOMNode(triggerContainer);
|
|
12255
|
-
if (containerEl) {
|
|
12256
|
-
containerEl.innerHTML = '<button id="ts-auth-btn" class="ts-auth-btn" style="margin: auto;"></button>';
|
|
12257
|
-
const authElem = document.getElementById('ts-auth-btn');
|
|
12258
|
-
authElem.textContent = triggerText;
|
|
12259
|
-
authElem.addEventListener('click', openPopup, { once: true });
|
|
12260
|
-
}
|
|
12261
|
-
samlCompletionPromise = samlCompletionPromise
|
|
12262
|
-
|| new Promise((resolve, reject) => {
|
|
12263
|
-
window.addEventListener('message', (e) => {
|
|
12264
|
-
if (e.data.type === EmbedEvent.SAMLComplete) {
|
|
12265
|
-
e.source.close();
|
|
12266
|
-
resolve();
|
|
12267
|
-
}
|
|
12268
|
-
});
|
|
12269
|
-
});
|
|
12270
|
-
authEE === null || authEE === void 0 ? void 0 : authEE.once(AuthEvent.TRIGGER_SSO_POPUP, openPopup);
|
|
12271
|
-
return samlCompletionPromise;
|
|
12272
|
-
}
|
|
12273
|
-
/**
|
|
12274
|
-
* Perform SAML authentication
|
|
12275
|
-
*
|
|
12276
|
-
* @param embedConfig The embed configuration
|
|
12277
|
-
* @param ssoEndPoint
|
|
12278
|
-
*/
|
|
12279
|
-
const doSSOAuth = async (embedConfig, ssoEndPoint) => {
|
|
12280
|
-
const { thoughtSpotHost } = embedConfig;
|
|
12281
|
-
const loggedIn = await isLoggedIn(thoughtSpotHost);
|
|
12282
|
-
if (loggedIn) {
|
|
12283
|
-
if (isAtSSORedirectUrl()) {
|
|
12284
|
-
removeSSORedirectUrlMarker();
|
|
12285
|
-
}
|
|
12286
|
-
loggedInStatus = true;
|
|
12287
|
-
return;
|
|
12288
|
-
}
|
|
12289
|
-
// we have already tried authentication and it did not succeed, restore
|
|
12290
|
-
// the current URL to the original one and invoke the callback.
|
|
12291
|
-
if (isAtSSORedirectUrl()) {
|
|
12292
|
-
removeSSORedirectUrlMarker();
|
|
12293
|
-
loggedInStatus = false;
|
|
12294
|
-
return;
|
|
12295
|
-
}
|
|
12296
|
-
const ssoURL = `${thoughtSpotHost}${ssoEndPoint}`;
|
|
12297
|
-
if (embedConfig.inPopup) {
|
|
12298
|
-
await samlPopupFlow(ssoURL, embedConfig.authTriggerContainer, embedConfig.authTriggerText);
|
|
12299
|
-
loggedInStatus = await isLoggedIn(thoughtSpotHost);
|
|
12300
|
-
return;
|
|
12301
|
-
}
|
|
12302
|
-
window.location.href = ssoURL;
|
|
12303
|
-
};
|
|
12304
|
-
const doSamlAuth = async (embedConfig) => {
|
|
12305
|
-
const { thoughtSpotHost } = embedConfig;
|
|
12306
|
-
// redirect for SSO, when the SSO authentication is done, this page will be
|
|
12307
|
-
// loaded again and the same JS will execute again.
|
|
12308
|
-
const ssoRedirectUrl = embedConfig.inPopup
|
|
12309
|
-
? `${thoughtSpotHost}/v2/#/embed/saml-complete`
|
|
12310
|
-
: getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
|
|
12311
|
-
// bring back the page to the same URL
|
|
12312
|
-
const ssoEndPoint = `${EndPoints.SAML_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
|
|
12313
|
-
await doSSOAuth(embedConfig, ssoEndPoint);
|
|
12314
|
-
return loggedInStatus;
|
|
12315
|
-
};
|
|
12316
|
-
const doOIDCAuth = async (embedConfig) => {
|
|
12317
|
-
const { thoughtSpotHost } = embedConfig;
|
|
12318
|
-
// redirect for SSO, when the SSO authentication is done, this page will be
|
|
12319
|
-
// loaded again and the same JS will execute again.
|
|
12320
|
-
const ssoRedirectUrl = embedConfig.noRedirect || embedConfig.inPopup
|
|
12321
|
-
? `${thoughtSpotHost}/v2/#/embed/saml-complete`
|
|
12322
|
-
: getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
|
|
12323
|
-
// bring back the page to the same URL
|
|
12324
|
-
const ssoEndPoint = `${EndPoints.OIDC_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
|
|
12325
|
-
await doSSOAuth(embedConfig, ssoEndPoint);
|
|
12326
|
-
return loggedInStatus;
|
|
12327
|
-
};
|
|
12328
|
-
const logout = async (embedConfig) => {
|
|
12329
|
-
const { thoughtSpotHost } = embedConfig;
|
|
12330
|
-
await fetchLogoutService(thoughtSpotHost);
|
|
12331
|
-
resetCachedAuthToken();
|
|
12332
|
-
const thoughtspotIframes = document.querySelectorAll("[data-ts-iframe='true']");
|
|
12333
|
-
if (thoughtspotIframes === null || thoughtspotIframes === void 0 ? void 0 : thoughtspotIframes.length) {
|
|
12334
|
-
thoughtspotIframes.forEach((el) => {
|
|
12335
|
-
el.parentElement.innerHTML = embedConfig.loginFailedMessage;
|
|
12336
|
-
});
|
|
12337
|
-
}
|
|
12338
|
-
loggedInStatus = false;
|
|
12339
|
-
return loggedInStatus;
|
|
12340
|
-
};
|
|
12341
|
-
/**
|
|
12342
|
-
* Perform authentication on the ThoughtSpot cluster
|
|
12343
|
-
*
|
|
12344
|
-
* @param embedConfig The embed configuration
|
|
12345
|
-
*/
|
|
12346
|
-
const authenticate = async (embedConfig) => {
|
|
12347
|
-
const { authType } = embedConfig;
|
|
12348
|
-
switch (authType) {
|
|
12349
|
-
case AuthType.SSO:
|
|
12350
|
-
case AuthType.SAMLRedirect:
|
|
12351
|
-
case AuthType.SAML:
|
|
12352
|
-
return doSamlAuth(embedConfig);
|
|
12353
|
-
case AuthType.OIDC:
|
|
12354
|
-
case AuthType.OIDCRedirect:
|
|
12355
|
-
return doOIDCAuth(embedConfig);
|
|
12356
|
-
case AuthType.AuthServer:
|
|
12357
|
-
case AuthType.TrustedAuthToken:
|
|
12358
|
-
return doTokenAuth(embedConfig);
|
|
12359
|
-
case AuthType.TrustedAuthTokenCookieless:
|
|
12360
|
-
return doCookielessTokenAuth(embedConfig);
|
|
12361
|
-
case AuthType.Basic:
|
|
12362
|
-
return doBasicAuth(embedConfig);
|
|
12363
|
-
default:
|
|
12364
|
-
return Promise.resolve(true);
|
|
12365
|
-
}
|
|
12366
|
-
};
|
|
12367
|
-
|
|
12368
|
-
const ERROR_MESSAGE = {
|
|
12369
|
-
INVALID_THOUGHTSPOT_HOST: 'Error parsing ThoughtSpot host. Please provide a valid URL.',
|
|
12370
|
-
LIVEBOARD_VIZ_ID_VALIDATION: 'Please provide either liveboardId or pinboardId',
|
|
12371
|
-
TRIGGER_TIMED_OUT: 'Trigger timedout in getting response',
|
|
12372
|
-
SEARCHEMBED_BETA_WRANING_MESSAGE: 'Search Embed is in Beta in this release.',
|
|
12373
|
-
SAGE_EMBED_BETA_WARNING_MESSAGE: 'Sage Embed is in Beta in this release.',
|
|
12374
|
-
};
|
|
12375
|
-
|
|
12376
|
-
/**
|
|
12377
|
-
* Copyright (c) 2023
|
|
12378
|
-
*
|
|
12379
|
-
* Utilities related to reading configuration objects
|
|
12380
|
-
*
|
|
12381
|
-
* @summary Config-related utils
|
|
12382
|
-
* @author Ayon Ghosh <ayon.ghosh@thoughtspot.com>
|
|
12383
|
-
*/
|
|
12384
|
-
const urlRegex = new RegExp([
|
|
12385
|
-
'(^(https?:)//)?',
|
|
12386
|
-
'(([^:/?#]*)(?::([0-9]+))?)',
|
|
12387
|
-
'(/{0,1}[^?#]*)',
|
|
12388
|
-
'(\\?[^#]*|)',
|
|
12389
|
-
'(#.*|)$', // hash
|
|
12390
|
-
].join(''));
|
|
12391
|
-
/**
|
|
12392
|
-
* Parse and construct the ThoughtSpot hostname or IP address
|
|
12393
|
-
* from the embed configuration object.
|
|
12394
|
-
*
|
|
12395
|
-
* @param config
|
|
12396
|
-
*/
|
|
12397
|
-
const getThoughtSpotHost = (config) => {
|
|
12398
|
-
if (!config.thoughtSpotHost) {
|
|
12399
|
-
throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
|
|
12400
|
-
}
|
|
12401
|
-
const urlParts = config.thoughtSpotHost.match(urlRegex);
|
|
12402
|
-
if (!urlParts) {
|
|
12403
|
-
throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
|
|
12404
|
-
}
|
|
12405
|
-
const protocol = urlParts[2] || window.location.protocol;
|
|
12406
|
-
const host = urlParts[3];
|
|
12407
|
-
let path = urlParts[6];
|
|
12408
|
-
// Lose the trailing / if any
|
|
12409
|
-
if (path.charAt(path.length - 1) === '/') {
|
|
12410
|
-
path = path.substring(0, path.length - 1);
|
|
12411
|
-
}
|
|
12412
|
-
// const urlParams = urlParts[7];
|
|
12413
|
-
// const hash = urlParts[8];
|
|
12414
|
-
return `${protocol}//${host}${path}`;
|
|
12415
|
-
};
|
|
12416
|
-
const getV2BasePath = (config) => {
|
|
12417
|
-
if (config.basepath) {
|
|
12418
|
-
return config.basepath;
|
|
12419
|
-
}
|
|
12420
|
-
const tsHost = getThoughtSpotHost(config);
|
|
12421
|
-
// This is to handle when e2e's. Search is run on pods for
|
|
12422
|
-
// comp-blink-test-pipeline with baseUrl=https://localhost:8443.
|
|
12423
|
-
// This is to handle when the developer is developing in their local
|
|
12424
|
-
// environment.
|
|
12425
|
-
if (tsHost.includes('://localhost') && !tsHost.includes(':8443')) {
|
|
12426
|
-
return '';
|
|
12427
|
-
}
|
|
12428
|
-
return 'v2';
|
|
12429
|
-
};
|
|
12430
|
-
/**
|
|
12431
|
-
* It is a good idea to keep URLs under 2000 chars.
|
|
12432
|
-
* If this is ever breached, since we pass view configuration through
|
|
12433
|
-
* URL params, we would like to log a warning.
|
|
12434
|
-
* Reference: https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
|
|
12435
|
-
*/
|
|
12436
|
-
const URL_MAX_LENGTH = 2000;
|
|
12437
|
-
/**
|
|
12438
|
-
* The default CSS dimensions of the embedded app
|
|
12439
|
-
*/
|
|
12440
|
-
const DEFAULT_EMBED_WIDTH = '100%';
|
|
12441
|
-
const DEFAULT_EMBED_HEIGHT = '100%';
|
|
12442
|
-
|
|
12443
|
-
/**
|
|
12444
|
-
*
|
|
12445
|
-
* @param root0
|
|
12446
|
-
* @param root0.query
|
|
12447
|
-
* @param root0.variables
|
|
12448
|
-
* @param root0.thoughtSpotHost
|
|
12449
|
-
* @param root0.isCompositeQuery
|
|
12450
|
-
*/
|
|
12451
|
-
async function graphqlQuery({ query, variables, thoughtSpotHost, isCompositeQuery = false, }) {
|
|
12452
|
-
const operationName = getOperationNameFromQuery(query);
|
|
12453
|
-
try {
|
|
12454
|
-
const response = await fetch(`${thoughtSpotHost}/prism/?op=${operationName}`, {
|
|
12455
|
-
method: 'POST',
|
|
12456
|
-
headers: {
|
|
12457
|
-
'content-type': 'application/json;charset=UTF-8',
|
|
12458
|
-
'x-requested-by': 'ThoughtSpot',
|
|
12459
|
-
accept: '*/*',
|
|
12460
|
-
'accept-language': 'en-us',
|
|
12461
|
-
},
|
|
12462
|
-
body: JSON.stringify({
|
|
12463
|
-
operationName,
|
|
12464
|
-
query,
|
|
12465
|
-
variables,
|
|
12466
|
-
}),
|
|
12467
|
-
credentials: 'include',
|
|
12468
|
-
});
|
|
12469
|
-
const result = await response.json();
|
|
12470
|
-
const dataValues = Object.values(result.data);
|
|
12471
|
-
return (isCompositeQuery) ? result.data : dataValues[0];
|
|
12472
|
-
}
|
|
12473
|
-
catch (error) {
|
|
12474
|
-
return error;
|
|
12475
|
-
}
|
|
12476
|
-
}
|
|
12477
|
-
|
|
12478
|
-
const getSourceDetailQuery = `
|
|
12479
|
-
query GetSourceDetail($ids: [GUID!]!) {
|
|
12480
|
-
getSourceDetailById(ids: $ids, type: LOGICAL_TABLE) {
|
|
12481
|
-
id
|
|
12482
|
-
name
|
|
12483
|
-
description
|
|
12484
|
-
authorName
|
|
12485
|
-
authorDisplayName
|
|
12486
|
-
isExternal
|
|
12487
|
-
type
|
|
12488
|
-
created
|
|
12489
|
-
modified
|
|
12490
|
-
columns {
|
|
12491
|
-
id
|
|
12492
|
-
name
|
|
12493
|
-
author
|
|
12494
|
-
authorDisplayName
|
|
12495
|
-
description
|
|
12496
|
-
dataType
|
|
12497
|
-
type
|
|
12498
|
-
modified
|
|
12499
|
-
ownerName
|
|
12500
|
-
owner
|
|
12501
|
-
dataRecency
|
|
12502
|
-
sources {
|
|
12503
|
-
tableId
|
|
12504
|
-
tableName
|
|
12505
|
-
columnId
|
|
12506
|
-
columnName
|
|
12507
|
-
__typename
|
|
12508
|
-
}
|
|
12509
|
-
synonyms
|
|
12510
|
-
cohortAnswerId
|
|
12511
|
-
__typename
|
|
12512
|
-
}
|
|
12513
|
-
relationships
|
|
12514
|
-
destinationRelationships
|
|
12515
|
-
dataSourceId
|
|
12516
|
-
__typename
|
|
12517
|
-
}
|
|
12518
|
-
}
|
|
12519
|
-
`;
|
|
12520
|
-
const sourceDetailCache = new Map();
|
|
12521
|
-
/**
|
|
12522
|
-
*
|
|
12523
|
-
* @param thoughtSpotHost
|
|
12524
|
-
* @param sourceId
|
|
12525
|
-
*/
|
|
12526
|
-
async function getSourceDetail(thoughtSpotHost, sourceId) {
|
|
12527
|
-
if (sourceDetailCache.get(sourceId)) {
|
|
12528
|
-
return sourceDetailCache.get(sourceId);
|
|
12529
|
-
}
|
|
12530
|
-
const details = await graphqlQuery({
|
|
12531
|
-
query: getSourceDetailQuery,
|
|
12532
|
-
variables: {
|
|
12533
|
-
ids: [sourceId],
|
|
12534
|
-
},
|
|
12535
|
-
thoughtSpotHost,
|
|
12536
|
-
});
|
|
12537
|
-
const souceDetails = details[0];
|
|
12538
|
-
if (souceDetails) {
|
|
12539
|
-
sourceDetailCache.set(sourceId, souceDetails);
|
|
12540
|
-
}
|
|
12541
|
-
return souceDetails;
|
|
12542
|
-
}
|
|
12543
|
-
|
|
12544
|
-
const bachSessionId = `
|
|
12545
|
-
id {
|
|
12546
|
-
sessionId
|
|
12547
|
-
genNo
|
|
12548
|
-
acSession {
|
|
12549
|
-
sessionId
|
|
12550
|
-
genNo
|
|
12551
|
-
}
|
|
12552
|
-
}
|
|
12553
|
-
`;
|
|
12554
|
-
const getUnaggregatedAnswerSession = `
|
|
12555
|
-
mutation GetUnAggregatedAnswerSession($session: BachSessionIdInput!, $columns: [UserPointSelectionInput!]!) {
|
|
12556
|
-
Answer__getUnaggregatedAnswer(session: $session, columns: $columns) {
|
|
12557
|
-
${bachSessionId}
|
|
12558
|
-
answer {
|
|
12559
|
-
visualizations {
|
|
12560
|
-
... on TableViz {
|
|
12561
|
-
columns {
|
|
12562
|
-
column {
|
|
12563
|
-
id
|
|
12564
|
-
name
|
|
12565
|
-
referencedColumns {
|
|
12566
|
-
guid
|
|
12567
|
-
displayName
|
|
12568
|
-
}
|
|
12569
|
-
}
|
|
12570
|
-
}
|
|
12571
|
-
}
|
|
12572
|
-
}
|
|
12573
|
-
}
|
|
12574
|
-
}
|
|
12575
|
-
}
|
|
12576
|
-
`;
|
|
12577
|
-
const removeColumns = `
|
|
12578
|
-
mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!], $columnIds: [GUID!]) {
|
|
12579
|
-
Answer__removeColumns(
|
|
12580
|
-
session: $session
|
|
12581
|
-
logicalColumnIds: $logicalColumnIds
|
|
12582
|
-
columnIds: $columnIds
|
|
12583
|
-
) {
|
|
12584
|
-
${bachSessionId}
|
|
12585
|
-
}
|
|
12586
|
-
}
|
|
12587
|
-
`;
|
|
12588
|
-
const addColumns = `
|
|
12589
|
-
mutation AddColumns($session: BachSessionIdInput!, $columns: [AnswerColumnInfo!]!) {
|
|
12590
|
-
Answer__addColumn(session: $session, columns: $columns) {
|
|
12591
|
-
${bachSessionId}
|
|
12592
|
-
}
|
|
12593
|
-
}
|
|
12594
|
-
`;
|
|
12595
|
-
const getAnswerData = `
|
|
12596
|
-
query GetTableWithHeadlineData($session: BachSessionIdInput!, $deadline: Int!, $dataPaginationParams: DataPaginationParamsInput!) {
|
|
12597
|
-
getAnswer(session: $session) {
|
|
12598
|
-
${bachSessionId}
|
|
12599
|
-
answer {
|
|
12600
|
-
id
|
|
12601
|
-
visualizations {
|
|
12602
|
-
id
|
|
12603
|
-
... on TableViz {
|
|
12604
|
-
columns {
|
|
12605
|
-
column {
|
|
12606
|
-
id
|
|
12607
|
-
name
|
|
12608
|
-
type
|
|
12609
|
-
aggregationType
|
|
12610
|
-
dataType
|
|
12611
|
-
}
|
|
12612
|
-
}
|
|
12613
|
-
data(deadline: $deadline, pagination: $dataPaginationParams)
|
|
12614
|
-
}
|
|
12615
|
-
}
|
|
12616
|
-
}
|
|
12617
|
-
}
|
|
12618
|
-
}
|
|
12619
|
-
`;
|
|
12620
|
-
|
|
12621
|
-
// eslint-disable-next-line no-shadow
|
|
12622
|
-
var OperationType;
|
|
12623
|
-
(function (OperationType) {
|
|
12624
|
-
OperationType["GetChartWithData"] = "GetChartWithData";
|
|
12625
|
-
OperationType["GetTableWithHeadlineData"] = "GetTableWithHeadlineData";
|
|
12626
|
-
})(OperationType || (OperationType = {}));
|
|
12627
|
-
/**
|
|
12628
|
-
* Class representing the answer service provided with the
|
|
12629
|
-
* custom action payload. This service could be used to run
|
|
12630
|
-
* graphql queries in the context of the answer on which the
|
|
12631
|
-
* custom action was triggered.
|
|
12632
|
-
*
|
|
12633
|
-
* @example
|
|
12634
|
-
* ```js
|
|
12635
|
-
* embed.on(EmbedEvent.CustomAction, e => {
|
|
12636
|
-
* const underlying = await e.answerService.getUnderlyingDataForPoint([
|
|
12637
|
-
* 'col name 1'
|
|
12638
|
-
* ]);
|
|
12639
|
-
* const data = await underlying.fetchData(0, 100);
|
|
12640
|
-
* })
|
|
12641
|
-
* ```
|
|
12642
|
-
* @version SDK: 1.25.0| ThoughtSpot: 9.10.0.cl
|
|
12643
|
-
* @group Events
|
|
12644
|
-
*/
|
|
12645
|
-
class AnswerService {
|
|
12646
|
-
constructor(session, answer, thoughtSpotHost, selectedPoints) {
|
|
12647
|
-
this.session = session;
|
|
12648
|
-
this.answer = answer;
|
|
12649
|
-
this.thoughtSpotHost = thoughtSpotHost;
|
|
12650
|
-
this.selectedPoints = selectedPoints;
|
|
12651
|
-
this.session = removeTypename(session);
|
|
12652
|
-
}
|
|
12653
|
-
async getSourceDetail() {
|
|
12654
|
-
const sourceId = this.answer.sources[0].header.guid;
|
|
12655
|
-
return getSourceDetail(this.thoughtSpotHost, sourceId);
|
|
12656
|
-
}
|
|
12657
|
-
async removeColumns(columnIds) {
|
|
12658
|
-
return this.executeQuery(removeColumns, {
|
|
12659
|
-
logicalColumnIds: columnIds,
|
|
12660
|
-
});
|
|
12661
|
-
}
|
|
12662
|
-
async addColumns(columnIds) {
|
|
12663
|
-
return this.executeQuery(addColumns, {
|
|
12664
|
-
columns: columnIds.map((colId) => ({ logicalColumnId: colId })),
|
|
12665
|
-
});
|
|
12666
|
-
}
|
|
12667
|
-
async fetchData(offset = 0, size = 1000) {
|
|
12668
|
-
const { answer } = await this.executeQuery(getAnswerData, {
|
|
12669
|
-
deadline: 0,
|
|
12670
|
-
dataPaginationParams: {
|
|
12671
|
-
isClientPaginated: true,
|
|
12672
|
-
offset,
|
|
12673
|
-
size,
|
|
12674
|
-
},
|
|
12675
|
-
});
|
|
12676
|
-
const { columns, data } = answer.visualizations.find((viz) => !!viz.data) || {};
|
|
12677
|
-
return {
|
|
12678
|
-
columns,
|
|
12679
|
-
data,
|
|
12680
|
-
};
|
|
12681
|
-
}
|
|
12682
|
-
/**
|
|
12683
|
-
*
|
|
12684
|
-
* @param userLocale
|
|
12685
|
-
* @param includeInfo Include the CSV header in the output
|
|
12686
|
-
* @returns Response
|
|
12687
|
-
*/
|
|
12688
|
-
async fetchCSVBlob(userLocale = 'en-us', includeInfo = false) {
|
|
12689
|
-
const fetchUrl = this.getFetchCSVBlobUrl(userLocale, includeInfo);
|
|
12690
|
-
return tokenizedFetch(fetchUrl, {
|
|
12691
|
-
credentials: 'include',
|
|
12692
|
-
});
|
|
12693
|
-
}
|
|
12694
|
-
getFetchCSVBlobUrl(userLocale = 'en-us', includeInfo = false) {
|
|
12695
|
-
return `${this.thoughtSpotHost}/prism/download/answer/csv?sessionId=${this.session.sessionId}&genNo=${this.session.genNo}&userLocale=${userLocale}&exportFileName=data&hideCsvHeader=${!includeInfo}`;
|
|
12696
|
-
}
|
|
12697
|
-
/**
|
|
12698
|
-
* Get underlying data given a point and the output column names.
|
|
12699
|
-
*
|
|
12700
|
-
* @param outputColumnNames
|
|
12701
|
-
* @param selectedPoints
|
|
12702
|
-
* @example
|
|
12703
|
-
* ```js
|
|
12704
|
-
* embed.on(EmbedEvent.CustomAction, e => {
|
|
12705
|
-
* const underlying = await e.answerService.getUnderlyingDataForPoint([
|
|
12706
|
-
* 'col name 1' // The column should exist in the data source.
|
|
12707
|
-
* ]);
|
|
12708
|
-
* const data = await underlying.fetchData(0, 100);
|
|
12709
|
-
* })
|
|
12710
|
-
* ```
|
|
12711
|
-
* @version SDK: 1.25.0| ThoughtSpot: 9.10.0.cl
|
|
12712
|
-
*/
|
|
12713
|
-
async getUnderlyingDataForPoint(outputColumnNames, selectedPoints) {
|
|
12714
|
-
if (!selectedPoints && !this.selectedPoints) {
|
|
12715
|
-
throw new Error('Needs to be triggered in context of a point');
|
|
12716
|
-
}
|
|
12717
|
-
if (!selectedPoints) {
|
|
12718
|
-
selectedPoints = getSelectedPointsForUnderlyingDataQuery(this.selectedPoints);
|
|
12719
|
-
}
|
|
12720
|
-
const sourceDetail = await this.getSourceDetail();
|
|
12721
|
-
const ouputColumnGuids = getGuidsFromColumnNames(sourceDetail, outputColumnNames);
|
|
12722
|
-
const unAggAnswer = await graphqlQuery({
|
|
12723
|
-
query: getUnaggregatedAnswerSession,
|
|
12724
|
-
variables: {
|
|
12725
|
-
session: this.session,
|
|
12726
|
-
columns: selectedPoints,
|
|
12727
|
-
},
|
|
12728
|
-
thoughtSpotHost: this.thoughtSpotHost,
|
|
12729
|
-
});
|
|
12730
|
-
const unaggAnswerSession = new AnswerService(unAggAnswer.id, unAggAnswer.answer, this.thoughtSpotHost);
|
|
12731
|
-
const currentColumns = new Set(unAggAnswer.answer.visualizations[0].columns
|
|
12732
|
-
.map((c) => c.column.referencedColumns[0].guid));
|
|
12733
|
-
const columnsToAdd = [...ouputColumnGuids].filter((col) => !currentColumns.has(col));
|
|
12734
|
-
if (columnsToAdd.length) {
|
|
12735
|
-
await unaggAnswerSession.addColumns(columnsToAdd);
|
|
12736
|
-
}
|
|
12737
|
-
const columnsToRemove = [...currentColumns].filter((col) => !ouputColumnGuids.has(col));
|
|
12738
|
-
if (columnsToRemove.length) {
|
|
12739
|
-
await unaggAnswerSession.removeColumns(columnsToRemove);
|
|
12740
|
-
}
|
|
12741
|
-
return unaggAnswerSession;
|
|
12742
|
-
}
|
|
12743
|
-
async executeQuery(query, variables) {
|
|
12744
|
-
const data = await graphqlQuery({
|
|
12745
|
-
query,
|
|
12746
|
-
variables: {
|
|
12747
|
-
session: this.session,
|
|
12748
|
-
...variables,
|
|
12749
|
-
},
|
|
12750
|
-
thoughtSpotHost: this.thoughtSpotHost,
|
|
12751
|
-
isCompositeQuery: false,
|
|
12752
|
-
});
|
|
12753
|
-
this.session = deepMerge(this.session, (data === null || data === void 0 ? void 0 : data.id) || {});
|
|
12754
|
-
return data;
|
|
12755
|
-
}
|
|
12756
|
-
getSession() {
|
|
12757
|
-
return this.session;
|
|
12758
|
-
}
|
|
12759
|
-
}
|
|
12760
|
-
/**
|
|
12761
|
-
*
|
|
12762
|
-
* @param sourceDetail
|
|
12763
|
-
* @param colNames
|
|
12764
|
-
*/
|
|
12765
|
-
function getGuidsFromColumnNames(sourceDetail, colNames) {
|
|
12766
|
-
const cols = sourceDetail.columns.reduce((colSet, col) => {
|
|
12767
|
-
colSet[col.name] = col;
|
|
12768
|
-
return colSet;
|
|
12769
|
-
}, {});
|
|
12770
|
-
return new Set(colNames.map((colName) => {
|
|
12771
|
-
const col = cols[colName];
|
|
12772
|
-
return col.id;
|
|
12773
|
-
}));
|
|
12774
|
-
}
|
|
12775
|
-
/**
|
|
12776
|
-
*
|
|
12777
|
-
* @param selectedPoints
|
|
12778
|
-
*/
|
|
12779
|
-
function getSelectedPointsForUnderlyingDataQuery(selectedPoints) {
|
|
12780
|
-
const underlyingDataPoint = [];
|
|
12781
|
-
/**
|
|
12782
|
-
*
|
|
12783
|
-
* @param colVal
|
|
12784
|
-
*/
|
|
12785
|
-
function addPointFromColVal(colVal) {
|
|
12786
|
-
var _a;
|
|
12787
|
-
const dataType = colVal.column.dataType;
|
|
12788
|
-
const id = colVal.column.id;
|
|
12789
|
-
let dataValue;
|
|
12790
|
-
if (dataType === 'DATE') {
|
|
12791
|
-
if (Number.isFinite(colVal.value)) {
|
|
12792
|
-
dataValue = [{
|
|
12793
|
-
epochRange: {
|
|
12794
|
-
startEpoch: colVal.value,
|
|
12795
|
-
},
|
|
12796
|
-
}];
|
|
12797
|
-
// Case for custom calendar.
|
|
12798
|
-
}
|
|
12799
|
-
else if ((_a = colVal.value) === null || _a === void 0 ? void 0 : _a.v) {
|
|
12800
|
-
dataValue = [{
|
|
12801
|
-
epochRange: {
|
|
12802
|
-
startEpoch: colVal.value.v.s,
|
|
12803
|
-
endEpoch: colVal.value.v.e,
|
|
12804
|
-
},
|
|
12805
|
-
}];
|
|
12806
|
-
}
|
|
12807
|
-
}
|
|
12808
|
-
else {
|
|
12809
|
-
dataValue = [{ value: colVal.value }];
|
|
12810
|
-
}
|
|
12811
|
-
underlyingDataPoint.push({
|
|
12812
|
-
columnId: colVal.column.id,
|
|
12813
|
-
dataValue,
|
|
12814
|
-
});
|
|
12815
|
-
}
|
|
12816
|
-
selectedPoints.forEach((p) => {
|
|
12817
|
-
p.selectedAttributes.forEach(addPointFromColVal);
|
|
12818
|
-
});
|
|
12819
|
-
return underlyingDataPoint;
|
|
12820
|
-
}
|
|
12821
|
-
|
|
12822
|
-
var eventemitter3 = createCommonjsModule(function (module) {
|
|
12823
|
-
|
|
12824
|
-
var has = Object.prototype.hasOwnProperty
|
|
12825
|
-
, prefix = '~';
|
|
12826
|
-
|
|
12827
|
-
/**
|
|
12828
|
-
* Constructor to create a storage for our `EE` objects.
|
|
12829
|
-
* An `Events` instance is a plain object whose properties are event names.
|
|
12830
|
-
*
|
|
12831
|
-
* @constructor
|
|
12832
|
-
* @private
|
|
12833
|
-
*/
|
|
12834
|
-
function Events() {}
|
|
12835
|
-
|
|
12836
|
-
//
|
|
12837
|
-
// We try to not inherit from `Object.prototype`. In some engines creating an
|
|
12838
|
-
// instance in this way is faster than calling `Object.create(null)` directly.
|
|
12839
|
-
// If `Object.create(null)` is not supported we prefix the event names with a
|
|
12840
|
-
// character to make sure that the built-in object properties are not
|
|
12841
|
-
// overridden or used as an attack vector.
|
|
12842
|
-
//
|
|
12843
|
-
if (Object.create) {
|
|
12844
|
-
Events.prototype = Object.create(null);
|
|
12845
|
-
|
|
12846
|
-
//
|
|
12847
|
-
// This hack is needed because the `__proto__` property is still inherited in
|
|
12848
|
-
// some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.
|
|
12849
|
-
//
|
|
12850
|
-
if (!new Events().__proto__) prefix = false;
|
|
12851
|
-
}
|
|
12852
|
-
|
|
12853
|
-
/**
|
|
12854
|
-
* Representation of a single event listener.
|
|
12855
|
-
*
|
|
12856
|
-
* @param {Function} fn The listener function.
|
|
12857
|
-
* @param {*} context The context to invoke the listener with.
|
|
12858
|
-
* @param {Boolean} [once=false] Specify if the listener is a one-time listener.
|
|
12859
|
-
* @constructor
|
|
12860
|
-
* @private
|
|
12861
|
-
*/
|
|
12862
|
-
function EE(fn, context, once) {
|
|
12863
|
-
this.fn = fn;
|
|
12864
|
-
this.context = context;
|
|
12865
|
-
this.once = once || false;
|
|
12866
|
-
}
|
|
12867
|
-
|
|
12868
|
-
/**
|
|
12869
|
-
* Add a listener for a given event.
|
|
12870
|
-
*
|
|
12871
|
-
* @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
|
|
12872
|
-
* @param {(String|Symbol)} event The event name.
|
|
12873
|
-
* @param {Function} fn The listener function.
|
|
12874
|
-
* @param {*} context The context to invoke the listener with.
|
|
12875
|
-
* @param {Boolean} once Specify if the listener is a one-time listener.
|
|
12876
|
-
* @returns {EventEmitter}
|
|
12877
|
-
* @private
|
|
12878
|
-
*/
|
|
12879
|
-
function addListener(emitter, event, fn, context, once) {
|
|
12880
|
-
if (typeof fn !== 'function') {
|
|
12881
|
-
throw new TypeError('The listener must be a function');
|
|
12882
|
-
}
|
|
12883
|
-
|
|
12884
|
-
var listener = new EE(fn, context || emitter, once)
|
|
12885
|
-
, evt = prefix ? prefix + event : event;
|
|
12886
|
-
|
|
12887
|
-
if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;
|
|
12888
|
-
else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);
|
|
12889
|
-
else emitter._events[evt] = [emitter._events[evt], listener];
|
|
12890
|
-
|
|
12891
|
-
return emitter;
|
|
12892
|
-
}
|
|
12893
|
-
|
|
12894
|
-
/**
|
|
12895
|
-
* Clear event by name.
|
|
12896
|
-
*
|
|
12897
|
-
* @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
|
|
12898
|
-
* @param {(String|Symbol)} evt The Event name.
|
|
12899
|
-
* @private
|
|
12900
|
-
*/
|
|
12901
|
-
function clearEvent(emitter, evt) {
|
|
12902
|
-
if (--emitter._eventsCount === 0) emitter._events = new Events();
|
|
12903
|
-
else delete emitter._events[evt];
|
|
12904
|
-
}
|
|
12905
|
-
|
|
12906
|
-
/**
|
|
12907
|
-
* Minimal `EventEmitter` interface that is molded against the Node.js
|
|
12908
|
-
* `EventEmitter` interface.
|
|
12909
|
-
*
|
|
12910
|
-
* @constructor
|
|
12911
|
-
* @public
|
|
12912
|
-
*/
|
|
12913
|
-
function EventEmitter() {
|
|
12914
|
-
this._events = new Events();
|
|
12915
|
-
this._eventsCount = 0;
|
|
12916
|
-
}
|
|
12917
|
-
|
|
12918
|
-
/**
|
|
12919
|
-
* Return an array listing the events for which the emitter has registered
|
|
12920
|
-
* listeners.
|
|
12921
|
-
*
|
|
12922
|
-
* @returns {Array}
|
|
12923
|
-
* @public
|
|
12924
|
-
*/
|
|
12925
|
-
EventEmitter.prototype.eventNames = function eventNames() {
|
|
12926
|
-
var names = []
|
|
12927
|
-
, events
|
|
12928
|
-
, name;
|
|
12929
|
-
|
|
12930
|
-
if (this._eventsCount === 0) return names;
|
|
12931
|
-
|
|
12932
|
-
for (name in (events = this._events)) {
|
|
12933
|
-
if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
|
|
12934
|
-
}
|
|
12935
|
-
|
|
12936
|
-
if (Object.getOwnPropertySymbols) {
|
|
12937
|
-
return names.concat(Object.getOwnPropertySymbols(events));
|
|
12938
|
-
}
|
|
12939
|
-
|
|
12940
|
-
return names;
|
|
12941
|
-
};
|
|
12942
|
-
|
|
12943
|
-
/**
|
|
12944
|
-
* Return the listeners registered for a given event.
|
|
12945
|
-
*
|
|
12946
|
-
* @param {(String|Symbol)} event The event name.
|
|
12947
|
-
* @returns {Array} The registered listeners.
|
|
12948
|
-
* @public
|
|
12949
|
-
*/
|
|
12950
|
-
EventEmitter.prototype.listeners = function listeners(event) {
|
|
12951
|
-
var evt = prefix ? prefix + event : event
|
|
12952
|
-
, handlers = this._events[evt];
|
|
12953
|
-
|
|
12954
|
-
if (!handlers) return [];
|
|
12955
|
-
if (handlers.fn) return [handlers.fn];
|
|
12956
|
-
|
|
12957
|
-
for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {
|
|
12958
|
-
ee[i] = handlers[i].fn;
|
|
12959
|
-
}
|
|
12960
|
-
|
|
12961
|
-
return ee;
|
|
12962
|
-
};
|
|
12963
|
-
|
|
12964
|
-
/**
|
|
12965
|
-
* Return the number of listeners listening to a given event.
|
|
12966
|
-
*
|
|
12967
|
-
* @param {(String|Symbol)} event The event name.
|
|
12968
|
-
* @returns {Number} The number of listeners.
|
|
12969
|
-
* @public
|
|
12970
|
-
*/
|
|
12971
|
-
EventEmitter.prototype.listenerCount = function listenerCount(event) {
|
|
12972
|
-
var evt = prefix ? prefix + event : event
|
|
12973
|
-
, listeners = this._events[evt];
|
|
12606
|
+
/**
|
|
12607
|
+
* Return the number of listeners listening to a given event.
|
|
12608
|
+
*
|
|
12609
|
+
* @param {(String|Symbol)} event The event name.
|
|
12610
|
+
* @returns {Number} The number of listeners.
|
|
12611
|
+
* @public
|
|
12612
|
+
*/
|
|
12613
|
+
EventEmitter.prototype.listenerCount = function listenerCount(event) {
|
|
12614
|
+
var evt = prefix ? prefix + event : event
|
|
12615
|
+
, listeners = this._events[evt];
|
|
12974
12616
|
|
|
12975
12617
|
if (!listeners) return 0;
|
|
12976
12618
|
if (listeners.fn) return 1;
|
|
@@ -13278,109 +12920,548 @@ var _arrayIncludesWith = arrayIncludesWith;
|
|
|
13278
12920
|
/** Used as references for various `Number` constants. */
|
|
13279
12921
|
var INFINITY = 1 / 0;
|
|
13280
12922
|
|
|
13281
|
-
/**
|
|
13282
|
-
* Creates a set object of `values`.
|
|
13283
|
-
*
|
|
13284
|
-
* @private
|
|
13285
|
-
* @param {Array} values The values to add to the set.
|
|
13286
|
-
* @returns {Object} Returns the new set.
|
|
13287
|
-
*/
|
|
13288
|
-
var createSet = !(_Set && (1 / _setToArray(new _Set([,-0]))[1]) == INFINITY) ? noop_1 : function(values) {
|
|
13289
|
-
return new _Set(values);
|
|
12923
|
+
/**
|
|
12924
|
+
* Creates a set object of `values`.
|
|
12925
|
+
*
|
|
12926
|
+
* @private
|
|
12927
|
+
* @param {Array} values The values to add to the set.
|
|
12928
|
+
* @returns {Object} Returns the new set.
|
|
12929
|
+
*/
|
|
12930
|
+
var createSet = !(_Set && (1 / _setToArray(new _Set([,-0]))[1]) == INFINITY) ? noop_1 : function(values) {
|
|
12931
|
+
return new _Set(values);
|
|
12932
|
+
};
|
|
12933
|
+
|
|
12934
|
+
var _createSet = createSet;
|
|
12935
|
+
|
|
12936
|
+
/** Used as the size to enable large array optimizations. */
|
|
12937
|
+
var LARGE_ARRAY_SIZE$1 = 200;
|
|
12938
|
+
|
|
12939
|
+
/**
|
|
12940
|
+
* The base implementation of `_.uniqBy` without support for iteratee shorthands.
|
|
12941
|
+
*
|
|
12942
|
+
* @private
|
|
12943
|
+
* @param {Array} array The array to inspect.
|
|
12944
|
+
* @param {Function} [iteratee] The iteratee invoked per element.
|
|
12945
|
+
* @param {Function} [comparator] The comparator invoked per element.
|
|
12946
|
+
* @returns {Array} Returns the new duplicate free array.
|
|
12947
|
+
*/
|
|
12948
|
+
function baseUniq(array, iteratee, comparator) {
|
|
12949
|
+
var index = -1,
|
|
12950
|
+
includes = _arrayIncludes,
|
|
12951
|
+
length = array.length,
|
|
12952
|
+
isCommon = true,
|
|
12953
|
+
result = [],
|
|
12954
|
+
seen = result;
|
|
12955
|
+
|
|
12956
|
+
if (comparator) {
|
|
12957
|
+
isCommon = false;
|
|
12958
|
+
includes = _arrayIncludesWith;
|
|
12959
|
+
}
|
|
12960
|
+
else if (length >= LARGE_ARRAY_SIZE$1) {
|
|
12961
|
+
var set = iteratee ? null : _createSet(array);
|
|
12962
|
+
if (set) {
|
|
12963
|
+
return _setToArray(set);
|
|
12964
|
+
}
|
|
12965
|
+
isCommon = false;
|
|
12966
|
+
includes = _cacheHas;
|
|
12967
|
+
seen = new _SetCache;
|
|
12968
|
+
}
|
|
12969
|
+
else {
|
|
12970
|
+
seen = iteratee ? [] : result;
|
|
12971
|
+
}
|
|
12972
|
+
outer:
|
|
12973
|
+
while (++index < length) {
|
|
12974
|
+
var value = array[index],
|
|
12975
|
+
computed = iteratee ? iteratee(value) : value;
|
|
12976
|
+
|
|
12977
|
+
value = (comparator || value !== 0) ? value : 0;
|
|
12978
|
+
if (isCommon && computed === computed) {
|
|
12979
|
+
var seenIndex = seen.length;
|
|
12980
|
+
while (seenIndex--) {
|
|
12981
|
+
if (seen[seenIndex] === computed) {
|
|
12982
|
+
continue outer;
|
|
12983
|
+
}
|
|
12984
|
+
}
|
|
12985
|
+
if (iteratee) {
|
|
12986
|
+
seen.push(computed);
|
|
12987
|
+
}
|
|
12988
|
+
result.push(value);
|
|
12989
|
+
}
|
|
12990
|
+
else if (!includes(seen, computed, comparator)) {
|
|
12991
|
+
if (seen !== result) {
|
|
12992
|
+
seen.push(computed);
|
|
12993
|
+
}
|
|
12994
|
+
result.push(value);
|
|
12995
|
+
}
|
|
12996
|
+
}
|
|
12997
|
+
return result;
|
|
12998
|
+
}
|
|
12999
|
+
|
|
13000
|
+
var _baseUniq = baseUniq;
|
|
13001
|
+
|
|
13002
|
+
/**
|
|
13003
|
+
* Creates a duplicate-free version of an array, using
|
|
13004
|
+
* [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
|
|
13005
|
+
* for equality comparisons, in which only the first occurrence of each element
|
|
13006
|
+
* is kept. The order of result values is determined by the order they occur
|
|
13007
|
+
* in the array.
|
|
13008
|
+
*
|
|
13009
|
+
* @static
|
|
13010
|
+
* @memberOf _
|
|
13011
|
+
* @since 0.1.0
|
|
13012
|
+
* @category Array
|
|
13013
|
+
* @param {Array} array The array to inspect.
|
|
13014
|
+
* @returns {Array} Returns the new duplicate free array.
|
|
13015
|
+
* @example
|
|
13016
|
+
*
|
|
13017
|
+
* _.uniq([2, 1, 2]);
|
|
13018
|
+
* // => [2, 1]
|
|
13019
|
+
*/
|
|
13020
|
+
function uniq(array) {
|
|
13021
|
+
return (array && array.length) ? _baseUniq(array) : [];
|
|
13022
|
+
}
|
|
13023
|
+
|
|
13024
|
+
var uniq_1 = uniq;
|
|
13025
|
+
|
|
13026
|
+
/**
|
|
13027
|
+
*
|
|
13028
|
+
* @param url
|
|
13029
|
+
* @param options
|
|
13030
|
+
*/
|
|
13031
|
+
function tokenisedFailureLoggedFetch(url, options = {}) {
|
|
13032
|
+
return tokenizedFetch(url, options).then(async (r) => {
|
|
13033
|
+
var _a;
|
|
13034
|
+
if (!r.ok && r.type !== 'opaqueredirect' && r.type !== 'opaque') {
|
|
13035
|
+
logger.error('Failure', await ((_a = r.text) === null || _a === void 0 ? void 0 : _a.call(r)));
|
|
13036
|
+
}
|
|
13037
|
+
return r;
|
|
13038
|
+
});
|
|
13039
|
+
}
|
|
13040
|
+
/**
|
|
13041
|
+
*
|
|
13042
|
+
* @param authVerificationUrl
|
|
13043
|
+
*/
|
|
13044
|
+
function fetchSessionInfoService(authVerificationUrl) {
|
|
13045
|
+
return tokenisedFailureLoggedFetch(authVerificationUrl, {
|
|
13046
|
+
credentials: 'include',
|
|
13047
|
+
});
|
|
13048
|
+
}
|
|
13049
|
+
/**
|
|
13050
|
+
*
|
|
13051
|
+
* @param thoughtSpotHost
|
|
13052
|
+
*/
|
|
13053
|
+
async function fetchLogoutService(thoughtSpotHost) {
|
|
13054
|
+
return tokenisedFailureLoggedFetch(`${thoughtSpotHost}${EndPoints.LOGOUT}`, {
|
|
13055
|
+
credentials: 'include',
|
|
13056
|
+
method: 'POST',
|
|
13057
|
+
headers: {
|
|
13058
|
+
'x-requested-by': 'ThoughtSpot',
|
|
13059
|
+
},
|
|
13060
|
+
});
|
|
13061
|
+
}
|
|
13062
|
+
|
|
13063
|
+
// eslint-disable-next-line import/no-mutable-exports
|
|
13064
|
+
let loggedInStatus = false;
|
|
13065
|
+
// eslint-disable-next-line import/no-mutable-exports
|
|
13066
|
+
let samlAuthWindow = null;
|
|
13067
|
+
// eslint-disable-next-line import/no-mutable-exports
|
|
13068
|
+
let samlCompletionPromise = null;
|
|
13069
|
+
let sessionInfo = null;
|
|
13070
|
+
let sessionInfoResolver = null;
|
|
13071
|
+
const sessionInfoPromise = new Promise((resolve) => {
|
|
13072
|
+
sessionInfoResolver = resolve;
|
|
13073
|
+
});
|
|
13074
|
+
let releaseVersion = '';
|
|
13075
|
+
const SSO_REDIRECTION_MARKER_GUID = '5e16222e-ef02-43e9-9fbd-24226bf3ce5b';
|
|
13076
|
+
/**
|
|
13077
|
+
* Enum for auth failure types. This is the parameter passed to the listner
|
|
13078
|
+
* of {@link AuthStatus.FAILURE}.
|
|
13079
|
+
*
|
|
13080
|
+
* @group Authentication / Init
|
|
13081
|
+
*/
|
|
13082
|
+
var AuthFailureType;
|
|
13083
|
+
(function (AuthFailureType) {
|
|
13084
|
+
AuthFailureType["SDK"] = "SDK";
|
|
13085
|
+
AuthFailureType["NO_COOKIE_ACCESS"] = "NO_COOKIE_ACCESS";
|
|
13086
|
+
AuthFailureType["EXPIRY"] = "EXPIRY";
|
|
13087
|
+
AuthFailureType["OTHER"] = "OTHER";
|
|
13088
|
+
})(AuthFailureType || (AuthFailureType = {}));
|
|
13089
|
+
/**
|
|
13090
|
+
* Enum for auth status emitted by the emitter returned from {@link init}.
|
|
13091
|
+
*
|
|
13092
|
+
* @group Authentication / Init
|
|
13093
|
+
*/
|
|
13094
|
+
var AuthStatus;
|
|
13095
|
+
(function (AuthStatus) {
|
|
13096
|
+
/**
|
|
13097
|
+
* Emits when the SDK fails to authenticate
|
|
13098
|
+
*/
|
|
13099
|
+
AuthStatus["FAILURE"] = "FAILURE";
|
|
13100
|
+
/**
|
|
13101
|
+
* Emits when the SDK authenticates successfully
|
|
13102
|
+
*/
|
|
13103
|
+
AuthStatus["SDK_SUCCESS"] = "SDK_SUCCESS";
|
|
13104
|
+
/**
|
|
13105
|
+
* Emits when the app sends an authentication success message
|
|
13106
|
+
*/
|
|
13107
|
+
AuthStatus["SUCCESS"] = "SUCCESS";
|
|
13108
|
+
/**
|
|
13109
|
+
* Emits when a user logs out
|
|
13110
|
+
*/
|
|
13111
|
+
AuthStatus["LOGOUT"] = "LOGOUT";
|
|
13112
|
+
/**
|
|
13113
|
+
* Emitted when inPopup is true in the SAMLRedirect flow and the
|
|
13114
|
+
* popup is waiting to be triggered either programmatically
|
|
13115
|
+
* or by the trigger button.
|
|
13116
|
+
*
|
|
13117
|
+
* @version SDK: 1.19.0
|
|
13118
|
+
*/
|
|
13119
|
+
AuthStatus["WAITING_FOR_POPUP"] = "WAITING_FOR_POPUP";
|
|
13120
|
+
})(AuthStatus || (AuthStatus = {}));
|
|
13121
|
+
/**
|
|
13122
|
+
* Events which can be triggered on the emitter returned from {@link init}.
|
|
13123
|
+
*
|
|
13124
|
+
* @group Authentication / Init
|
|
13125
|
+
*/
|
|
13126
|
+
var AuthEvent;
|
|
13127
|
+
(function (AuthEvent) {
|
|
13128
|
+
/**
|
|
13129
|
+
* Manually trigger the SSO popup. This is useful when
|
|
13130
|
+
* authStatus is SAMLRedirect/OIDCRedirect and inPopup is set to true
|
|
13131
|
+
*/
|
|
13132
|
+
AuthEvent["TRIGGER_SSO_POPUP"] = "TRIGGER_SSO_POPUP";
|
|
13133
|
+
})(AuthEvent || (AuthEvent = {}));
|
|
13134
|
+
let authEE;
|
|
13135
|
+
/**
|
|
13136
|
+
*
|
|
13137
|
+
* @param eventEmitter
|
|
13138
|
+
*/
|
|
13139
|
+
function setAuthEE(eventEmitter) {
|
|
13140
|
+
authEE = eventEmitter;
|
|
13141
|
+
}
|
|
13142
|
+
/**
|
|
13143
|
+
*
|
|
13144
|
+
*/
|
|
13145
|
+
function notifyAuthSDKSuccess() {
|
|
13146
|
+
if (!authEE) {
|
|
13147
|
+
logger.error('SDK not initialized');
|
|
13148
|
+
return;
|
|
13149
|
+
}
|
|
13150
|
+
authEE.emit(AuthStatus.SDK_SUCCESS);
|
|
13151
|
+
}
|
|
13152
|
+
/**
|
|
13153
|
+
*
|
|
13154
|
+
*/
|
|
13155
|
+
function notifyAuthSuccess() {
|
|
13156
|
+
if (!authEE) {
|
|
13157
|
+
logger.error('SDK not initialized');
|
|
13158
|
+
return;
|
|
13159
|
+
}
|
|
13160
|
+
authEE.emit(AuthStatus.SUCCESS, sessionInfo);
|
|
13161
|
+
}
|
|
13162
|
+
/**
|
|
13163
|
+
*
|
|
13164
|
+
* @param failureType
|
|
13165
|
+
*/
|
|
13166
|
+
function notifyAuthFailure(failureType) {
|
|
13167
|
+
if (!authEE) {
|
|
13168
|
+
logger.error('SDK not initialized');
|
|
13169
|
+
return;
|
|
13170
|
+
}
|
|
13171
|
+
authEE.emit(AuthStatus.FAILURE, failureType);
|
|
13172
|
+
}
|
|
13173
|
+
/**
|
|
13174
|
+
*
|
|
13175
|
+
*/
|
|
13176
|
+
function notifyLogout() {
|
|
13177
|
+
if (!authEE) {
|
|
13178
|
+
logger.error('SDK not initialized');
|
|
13179
|
+
return;
|
|
13180
|
+
}
|
|
13181
|
+
authEE.emit(AuthStatus.LOGOUT);
|
|
13182
|
+
}
|
|
13183
|
+
const initSession = (sessionDetails) => {
|
|
13184
|
+
if (sessionInfo == null) {
|
|
13185
|
+
sessionInfo = sessionDetails;
|
|
13186
|
+
initMixpanel(sessionInfo);
|
|
13187
|
+
sessionInfoResolver(sessionInfo);
|
|
13188
|
+
}
|
|
13189
|
+
};
|
|
13190
|
+
const getSessionDetails = (sessionInfoResp) => {
|
|
13191
|
+
const devMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.devSdkKey;
|
|
13192
|
+
const prodMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.prodSdkKey;
|
|
13193
|
+
const mixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.production
|
|
13194
|
+
? prodMixpanelToken
|
|
13195
|
+
: devMixpanelToken;
|
|
13196
|
+
return {
|
|
13197
|
+
userGUID: sessionInfoResp.userGUID,
|
|
13198
|
+
mixpanelToken,
|
|
13199
|
+
isPublicUser: sessionInfoResp.configInfo.isPublicUser,
|
|
13200
|
+
releaseVersion: sessionInfoResp.releaseVersion,
|
|
13201
|
+
clusterId: sessionInfoResp.configInfo.selfClusterId,
|
|
13202
|
+
clusterName: sessionInfoResp.configInfo.selfClusterName,
|
|
13203
|
+
...sessionInfoResp,
|
|
13204
|
+
};
|
|
13205
|
+
};
|
|
13206
|
+
/**
|
|
13207
|
+
* Check if we are logged into the ThoughtSpot cluster
|
|
13208
|
+
*
|
|
13209
|
+
* @param thoughtSpotHost The ThoughtSpot cluster hostname or IP
|
|
13210
|
+
*/
|
|
13211
|
+
async function isLoggedIn(thoughtSpotHost) {
|
|
13212
|
+
const authVerificationUrl = `${thoughtSpotHost}${EndPoints.AUTH_VERIFICATION}`;
|
|
13213
|
+
let response = null;
|
|
13214
|
+
try {
|
|
13215
|
+
response = await fetchSessionInfoService(authVerificationUrl);
|
|
13216
|
+
const sessionInfoResp = await response.json();
|
|
13217
|
+
const sessionDetails = getSessionDetails(sessionInfoResp);
|
|
13218
|
+
// Store user session details from session info
|
|
13219
|
+
initSession(sessionDetails);
|
|
13220
|
+
releaseVersion = sessionInfoResp.releaseVersion;
|
|
13221
|
+
}
|
|
13222
|
+
catch (e) {
|
|
13223
|
+
return false;
|
|
13224
|
+
}
|
|
13225
|
+
return response.status === 200;
|
|
13226
|
+
}
|
|
13227
|
+
/**
|
|
13228
|
+
* Return releaseVersion if available
|
|
13229
|
+
*/
|
|
13230
|
+
function getReleaseVersion() {
|
|
13231
|
+
return releaseVersion;
|
|
13232
|
+
}
|
|
13233
|
+
/**
|
|
13234
|
+
* Return a promise that resolves with the session information when
|
|
13235
|
+
* authentication is successful. And info is available.
|
|
13236
|
+
*
|
|
13237
|
+
* @group Global methods
|
|
13238
|
+
*/
|
|
13239
|
+
function getSessionInfo() {
|
|
13240
|
+
return sessionInfoPromise;
|
|
13241
|
+
}
|
|
13242
|
+
/**
|
|
13243
|
+
* Check if we are stuck at the SSO redirect URL
|
|
13244
|
+
*/
|
|
13245
|
+
function isAtSSORedirectUrl() {
|
|
13246
|
+
return window.location.href.indexOf(SSO_REDIRECTION_MARKER_GUID) >= 0;
|
|
13247
|
+
}
|
|
13248
|
+
/**
|
|
13249
|
+
* Remove the SSO redirect URL marker
|
|
13250
|
+
*/
|
|
13251
|
+
function removeSSORedirectUrlMarker() {
|
|
13252
|
+
// Note (sunny): This will leave a # around even if it was not in the URL
|
|
13253
|
+
// to begin with. Trying to remove the hash by changing window.location will
|
|
13254
|
+
// reload the page which we don't want. We'll live with adding an
|
|
13255
|
+
// unnecessary hash to the parent page URL until we find any use case where
|
|
13256
|
+
// that creates an issue.
|
|
13257
|
+
window.location.hash = window.location.hash.replace(SSO_REDIRECTION_MARKER_GUID, '');
|
|
13258
|
+
}
|
|
13259
|
+
/**
|
|
13260
|
+
* Perform token based authentication
|
|
13261
|
+
*
|
|
13262
|
+
* @param embedConfig The embed configuration
|
|
13263
|
+
*/
|
|
13264
|
+
const doTokenAuth = async (embedConfig) => {
|
|
13265
|
+
const { thoughtSpotHost, username, authEndpoint, getAuthToken, } = embedConfig;
|
|
13266
|
+
if (!authEndpoint && !getAuthToken) {
|
|
13267
|
+
throw new Error('Either auth endpoint or getAuthToken function must be provided');
|
|
13268
|
+
}
|
|
13269
|
+
loggedInStatus = await isLoggedIn(thoughtSpotHost);
|
|
13270
|
+
if (!loggedInStatus) {
|
|
13271
|
+
const authToken = await getAuthenticationToken(embedConfig);
|
|
13272
|
+
let resp;
|
|
13273
|
+
try {
|
|
13274
|
+
resp = await fetchAuthPostService(thoughtSpotHost, username, authToken);
|
|
13275
|
+
}
|
|
13276
|
+
catch (e) {
|
|
13277
|
+
resp = await fetchAuthService(thoughtSpotHost, username, authToken);
|
|
13278
|
+
}
|
|
13279
|
+
// token login issues a 302 when successful
|
|
13280
|
+
loggedInStatus = resp.ok || resp.type === 'opaqueredirect';
|
|
13281
|
+
if (loggedInStatus && embedConfig.detectCookieAccessSlow) {
|
|
13282
|
+
// When 3rd party cookie access is blocked, this will fail because
|
|
13283
|
+
// cookies will not be sent with the call.
|
|
13284
|
+
loggedInStatus = await isLoggedIn(thoughtSpotHost);
|
|
13285
|
+
}
|
|
13286
|
+
}
|
|
13287
|
+
return loggedInStatus;
|
|
13288
|
+
};
|
|
13289
|
+
/**
|
|
13290
|
+
* Validate embedConfig parameters required for cookielessTokenAuth
|
|
13291
|
+
*
|
|
13292
|
+
* @param embedConfig The embed configuration
|
|
13293
|
+
*/
|
|
13294
|
+
const doCookielessTokenAuth = async (embedConfig) => {
|
|
13295
|
+
const { authEndpoint, getAuthToken } = embedConfig;
|
|
13296
|
+
if (!authEndpoint && !getAuthToken) {
|
|
13297
|
+
throw new Error('Either auth endpoint or getAuthToken function must be provided');
|
|
13298
|
+
}
|
|
13299
|
+
let authSuccess = false;
|
|
13300
|
+
try {
|
|
13301
|
+
const authToken = await getAuthenticationToken(embedConfig);
|
|
13302
|
+
if (authToken) {
|
|
13303
|
+
authSuccess = true;
|
|
13304
|
+
}
|
|
13305
|
+
}
|
|
13306
|
+
catch {
|
|
13307
|
+
authSuccess = false;
|
|
13308
|
+
}
|
|
13309
|
+
return authSuccess;
|
|
13310
|
+
};
|
|
13311
|
+
/**
|
|
13312
|
+
* Perform basic authentication to the ThoughtSpot cluster using the cluster
|
|
13313
|
+
* credentials.
|
|
13314
|
+
*
|
|
13315
|
+
* Warning: This feature is primarily intended for developer testing. It is
|
|
13316
|
+
* strongly advised not to use this authentication method in production.
|
|
13317
|
+
*
|
|
13318
|
+
* @param embedConfig The embed configuration
|
|
13319
|
+
*/
|
|
13320
|
+
const doBasicAuth = async (embedConfig) => {
|
|
13321
|
+
const { thoughtSpotHost, username, password } = embedConfig;
|
|
13322
|
+
const loggedIn = await isLoggedIn(thoughtSpotHost);
|
|
13323
|
+
if (!loggedIn) {
|
|
13324
|
+
const response = await fetchBasicAuthService(thoughtSpotHost, username, password);
|
|
13325
|
+
loggedInStatus = response.ok;
|
|
13326
|
+
if (embedConfig.detectCookieAccessSlow) {
|
|
13327
|
+
loggedInStatus = await isLoggedIn(thoughtSpotHost);
|
|
13328
|
+
}
|
|
13329
|
+
}
|
|
13330
|
+
else {
|
|
13331
|
+
loggedInStatus = true;
|
|
13332
|
+
}
|
|
13333
|
+
return loggedInStatus;
|
|
13334
|
+
};
|
|
13335
|
+
/**
|
|
13336
|
+
*
|
|
13337
|
+
* @param ssoURL
|
|
13338
|
+
* @param triggerContainer
|
|
13339
|
+
* @param triggerText
|
|
13340
|
+
*/
|
|
13341
|
+
async function samlPopupFlow(ssoURL, triggerContainer, triggerText) {
|
|
13342
|
+
const openPopup = () => {
|
|
13343
|
+
if (samlAuthWindow === null || samlAuthWindow.closed) {
|
|
13344
|
+
samlAuthWindow = window.open(ssoURL, '_blank', 'location=no,height=570,width=520,scrollbars=yes,status=yes');
|
|
13345
|
+
}
|
|
13346
|
+
else {
|
|
13347
|
+
samlAuthWindow.focus();
|
|
13348
|
+
}
|
|
13349
|
+
};
|
|
13350
|
+
authEE === null || authEE === void 0 ? void 0 : authEE.emit(AuthStatus.WAITING_FOR_POPUP);
|
|
13351
|
+
const containerEl = getDOMNode(triggerContainer);
|
|
13352
|
+
if (containerEl) {
|
|
13353
|
+
containerEl.innerHTML = '<button id="ts-auth-btn" class="ts-auth-btn" style="margin: auto;"></button>';
|
|
13354
|
+
const authElem = document.getElementById('ts-auth-btn');
|
|
13355
|
+
authElem.textContent = triggerText;
|
|
13356
|
+
authElem.addEventListener('click', openPopup, { once: true });
|
|
13357
|
+
}
|
|
13358
|
+
samlCompletionPromise = samlCompletionPromise
|
|
13359
|
+
|| new Promise((resolve, reject) => {
|
|
13360
|
+
window.addEventListener('message', (e) => {
|
|
13361
|
+
if (e.data.type === EmbedEvent.SAMLComplete) {
|
|
13362
|
+
e.source.close();
|
|
13363
|
+
resolve();
|
|
13364
|
+
}
|
|
13365
|
+
});
|
|
13366
|
+
});
|
|
13367
|
+
authEE === null || authEE === void 0 ? void 0 : authEE.once(AuthEvent.TRIGGER_SSO_POPUP, openPopup);
|
|
13368
|
+
return samlCompletionPromise;
|
|
13369
|
+
}
|
|
13370
|
+
/**
|
|
13371
|
+
* Perform SAML authentication
|
|
13372
|
+
*
|
|
13373
|
+
* @param embedConfig The embed configuration
|
|
13374
|
+
* @param ssoEndPoint
|
|
13375
|
+
*/
|
|
13376
|
+
const doSSOAuth = async (embedConfig, ssoEndPoint) => {
|
|
13377
|
+
const { thoughtSpotHost } = embedConfig;
|
|
13378
|
+
const loggedIn = await isLoggedIn(thoughtSpotHost);
|
|
13379
|
+
if (loggedIn) {
|
|
13380
|
+
if (isAtSSORedirectUrl()) {
|
|
13381
|
+
removeSSORedirectUrlMarker();
|
|
13382
|
+
}
|
|
13383
|
+
loggedInStatus = true;
|
|
13384
|
+
return;
|
|
13385
|
+
}
|
|
13386
|
+
// we have already tried authentication and it did not succeed, restore
|
|
13387
|
+
// the current URL to the original one and invoke the callback.
|
|
13388
|
+
if (isAtSSORedirectUrl()) {
|
|
13389
|
+
removeSSORedirectUrlMarker();
|
|
13390
|
+
loggedInStatus = false;
|
|
13391
|
+
return;
|
|
13392
|
+
}
|
|
13393
|
+
const ssoURL = `${thoughtSpotHost}${ssoEndPoint}`;
|
|
13394
|
+
if (embedConfig.inPopup) {
|
|
13395
|
+
await samlPopupFlow(ssoURL, embedConfig.authTriggerContainer, embedConfig.authTriggerText);
|
|
13396
|
+
loggedInStatus = await isLoggedIn(thoughtSpotHost);
|
|
13397
|
+
return;
|
|
13398
|
+
}
|
|
13399
|
+
window.location.href = ssoURL;
|
|
13400
|
+
};
|
|
13401
|
+
const doSamlAuth = async (embedConfig) => {
|
|
13402
|
+
const { thoughtSpotHost } = embedConfig;
|
|
13403
|
+
// redirect for SSO, when the SSO authentication is done, this page will be
|
|
13404
|
+
// loaded again and the same JS will execute again.
|
|
13405
|
+
const ssoRedirectUrl = embedConfig.inPopup
|
|
13406
|
+
? `${thoughtSpotHost}/v2/#/embed/saml-complete`
|
|
13407
|
+
: getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
|
|
13408
|
+
// bring back the page to the same URL
|
|
13409
|
+
const ssoEndPoint = `${EndPoints.SAML_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
|
|
13410
|
+
await doSSOAuth(embedConfig, ssoEndPoint);
|
|
13411
|
+
return loggedInStatus;
|
|
13412
|
+
};
|
|
13413
|
+
const doOIDCAuth = async (embedConfig) => {
|
|
13414
|
+
const { thoughtSpotHost } = embedConfig;
|
|
13415
|
+
// redirect for SSO, when the SSO authentication is done, this page will be
|
|
13416
|
+
// loaded again and the same JS will execute again.
|
|
13417
|
+
const ssoRedirectUrl = embedConfig.noRedirect || embedConfig.inPopup
|
|
13418
|
+
? `${thoughtSpotHost}/v2/#/embed/saml-complete`
|
|
13419
|
+
: getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
|
|
13420
|
+
// bring back the page to the same URL
|
|
13421
|
+
const ssoEndPoint = `${EndPoints.OIDC_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
|
|
13422
|
+
await doSSOAuth(embedConfig, ssoEndPoint);
|
|
13423
|
+
return loggedInStatus;
|
|
13424
|
+
};
|
|
13425
|
+
const logout = async (embedConfig) => {
|
|
13426
|
+
const { thoughtSpotHost } = embedConfig;
|
|
13427
|
+
await fetchLogoutService(thoughtSpotHost);
|
|
13428
|
+
resetCachedAuthToken();
|
|
13429
|
+
const thoughtspotIframes = document.querySelectorAll('[data-ts-iframe=\'true\']');
|
|
13430
|
+
if (thoughtspotIframes === null || thoughtspotIframes === void 0 ? void 0 : thoughtspotIframes.length) {
|
|
13431
|
+
thoughtspotIframes.forEach((el) => {
|
|
13432
|
+
el.parentElement.innerHTML = embedConfig.loginFailedMessage;
|
|
13433
|
+
});
|
|
13434
|
+
}
|
|
13435
|
+
loggedInStatus = false;
|
|
13436
|
+
return loggedInStatus;
|
|
13437
|
+
};
|
|
13438
|
+
/**
|
|
13439
|
+
* Perform authentication on the ThoughtSpot cluster
|
|
13440
|
+
*
|
|
13441
|
+
* @param embedConfig The embed configuration
|
|
13442
|
+
*/
|
|
13443
|
+
const authenticate = async (embedConfig) => {
|
|
13444
|
+
const { authType } = embedConfig;
|
|
13445
|
+
switch (authType) {
|
|
13446
|
+
case AuthType.SSO:
|
|
13447
|
+
case AuthType.SAMLRedirect:
|
|
13448
|
+
case AuthType.SAML:
|
|
13449
|
+
return doSamlAuth(embedConfig);
|
|
13450
|
+
case AuthType.OIDC:
|
|
13451
|
+
case AuthType.OIDCRedirect:
|
|
13452
|
+
return doOIDCAuth(embedConfig);
|
|
13453
|
+
case AuthType.AuthServer:
|
|
13454
|
+
case AuthType.TrustedAuthToken:
|
|
13455
|
+
return doTokenAuth(embedConfig);
|
|
13456
|
+
case AuthType.TrustedAuthTokenCookieless:
|
|
13457
|
+
return doCookielessTokenAuth(embedConfig);
|
|
13458
|
+
case AuthType.Basic:
|
|
13459
|
+
return doBasicAuth(embedConfig);
|
|
13460
|
+
default:
|
|
13461
|
+
return Promise.resolve(true);
|
|
13462
|
+
}
|
|
13290
13463
|
};
|
|
13291
13464
|
|
|
13292
|
-
var _createSet = createSet;
|
|
13293
|
-
|
|
13294
|
-
/** Used as the size to enable large array optimizations. */
|
|
13295
|
-
var LARGE_ARRAY_SIZE$1 = 200;
|
|
13296
|
-
|
|
13297
|
-
/**
|
|
13298
|
-
* The base implementation of `_.uniqBy` without support for iteratee shorthands.
|
|
13299
|
-
*
|
|
13300
|
-
* @private
|
|
13301
|
-
* @param {Array} array The array to inspect.
|
|
13302
|
-
* @param {Function} [iteratee] The iteratee invoked per element.
|
|
13303
|
-
* @param {Function} [comparator] The comparator invoked per element.
|
|
13304
|
-
* @returns {Array} Returns the new duplicate free array.
|
|
13305
|
-
*/
|
|
13306
|
-
function baseUniq(array, iteratee, comparator) {
|
|
13307
|
-
var index = -1,
|
|
13308
|
-
includes = _arrayIncludes,
|
|
13309
|
-
length = array.length,
|
|
13310
|
-
isCommon = true,
|
|
13311
|
-
result = [],
|
|
13312
|
-
seen = result;
|
|
13313
|
-
|
|
13314
|
-
if (comparator) {
|
|
13315
|
-
isCommon = false;
|
|
13316
|
-
includes = _arrayIncludesWith;
|
|
13317
|
-
}
|
|
13318
|
-
else if (length >= LARGE_ARRAY_SIZE$1) {
|
|
13319
|
-
var set = iteratee ? null : _createSet(array);
|
|
13320
|
-
if (set) {
|
|
13321
|
-
return _setToArray(set);
|
|
13322
|
-
}
|
|
13323
|
-
isCommon = false;
|
|
13324
|
-
includes = _cacheHas;
|
|
13325
|
-
seen = new _SetCache;
|
|
13326
|
-
}
|
|
13327
|
-
else {
|
|
13328
|
-
seen = iteratee ? [] : result;
|
|
13329
|
-
}
|
|
13330
|
-
outer:
|
|
13331
|
-
while (++index < length) {
|
|
13332
|
-
var value = array[index],
|
|
13333
|
-
computed = iteratee ? iteratee(value) : value;
|
|
13334
|
-
|
|
13335
|
-
value = (comparator || value !== 0) ? value : 0;
|
|
13336
|
-
if (isCommon && computed === computed) {
|
|
13337
|
-
var seenIndex = seen.length;
|
|
13338
|
-
while (seenIndex--) {
|
|
13339
|
-
if (seen[seenIndex] === computed) {
|
|
13340
|
-
continue outer;
|
|
13341
|
-
}
|
|
13342
|
-
}
|
|
13343
|
-
if (iteratee) {
|
|
13344
|
-
seen.push(computed);
|
|
13345
|
-
}
|
|
13346
|
-
result.push(value);
|
|
13347
|
-
}
|
|
13348
|
-
else if (!includes(seen, computed, comparator)) {
|
|
13349
|
-
if (seen !== result) {
|
|
13350
|
-
seen.push(computed);
|
|
13351
|
-
}
|
|
13352
|
-
result.push(value);
|
|
13353
|
-
}
|
|
13354
|
-
}
|
|
13355
|
-
return result;
|
|
13356
|
-
}
|
|
13357
|
-
|
|
13358
|
-
var _baseUniq = baseUniq;
|
|
13359
|
-
|
|
13360
|
-
/**
|
|
13361
|
-
* Creates a duplicate-free version of an array, using
|
|
13362
|
-
* [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
|
|
13363
|
-
* for equality comparisons, in which only the first occurrence of each element
|
|
13364
|
-
* is kept. The order of result values is determined by the order they occur
|
|
13365
|
-
* in the array.
|
|
13366
|
-
*
|
|
13367
|
-
* @static
|
|
13368
|
-
* @memberOf _
|
|
13369
|
-
* @since 0.1.0
|
|
13370
|
-
* @category Array
|
|
13371
|
-
* @param {Array} array The array to inspect.
|
|
13372
|
-
* @returns {Array} Returns the new duplicate free array.
|
|
13373
|
-
* @example
|
|
13374
|
-
*
|
|
13375
|
-
* _.uniq([2, 1, 2]);
|
|
13376
|
-
* // => [2, 1]
|
|
13377
|
-
*/
|
|
13378
|
-
function uniq(array) {
|
|
13379
|
-
return (array && array.length) ? _baseUniq(array) : [];
|
|
13380
|
-
}
|
|
13381
|
-
|
|
13382
|
-
var uniq_1 = uniq;
|
|
13383
|
-
|
|
13384
13465
|
/* eslint-disable camelcase */
|
|
13385
13466
|
const CONFIG_DEFAULTS = {
|
|
13386
13467
|
loginFailedMessage: 'Not logged in',
|
|
@@ -13841,6 +13922,8 @@ function processTrigger(iFrame, messageType, thoughtSpotHost, data) {
|
|
|
13841
13922
|
});
|
|
13842
13923
|
}
|
|
13843
13924
|
|
|
13925
|
+
var name="@thoughtspot/visual-embed-sdk";var version="1.28.0-alpha.2";var description="ThoughtSpot Embed SDK";var module="lib/src/index.js";var main="dist/tsembed.js";var types="lib/src/index.d.ts";var files=["dist/**","lib/**","src/**","cjs/**"];var exports={".":{"import":"./lib/src/index.js",require:"./cjs/src/index.js",types:"./lib/src/index.d.ts"},"./react":{"import":"./lib/src/react/all-types-export.js",require:"./cjs/src/react/all-types-export.js",types:"./lib/src/react/all-types-export.d.ts"},"./lib/src/react":{"import":"./lib/src/react/all-types-export.js",require:"./cjs/src/react/all-types-export.js",types:"./lib/src/react/all-types-export.d.ts"}};var typesVersions={"*":{react:["./lib/src/react/all-types-export.d.ts"]}};var scripts={lint:"eslint 'src/**'","lint:fix":"eslint 'src/**/*.*' --fix",tsc:"tsc -p . --incremental false; tsc -p . --incremental false --module commonjs --outDir cjs",start:"gatsby develop","build:gatsby":"npm run clean:gatsby && gatsby build --prefix-paths","build:gatsby:noprefix":"npm run clean:gatsby && gatsby build","serve:gatsby":"gatsby serve","clean:gatsby":"gatsby clean","build-and-publish":"npm run build:gatsby && npm run publish","bundle-dts-file":"dts-bundle --name @thoughtspot/visual-embed-sdk --out visual-embed-sdk.d.ts --main lib/src/index.d.ts","bundle-dts":"dts-bundle --name ../../dist/visual-embed-sdk --main lib/src/index.d.ts --outputAsModuleFolder=true","bundle-dts-react":"dts-bundle --name ../../../dist/visual-embed-sdk-react --main lib/src/react/index.d.ts --outputAsModuleFolder=true","bundle-dts-react-full":"dts-bundle --name ../../../dist/visual-embed-sdk-react-full --main lib/src/react/all-types-export.d.ts --outputAsModuleFolder=true",build:"rollup -c",watch:"rollup -cw","docs-cmd":"node scripts/gatsby-commands.js",docgen:"typedoc --tsconfig tsconfig.json --theme typedoc-theme","test-sdk":"jest -c jest.config.sdk.js --runInBand","test-docs":"jest -c jest.config.docs.js",test:"npm run test-sdk && npm run test-docs",posttest:"cat ./coverage/sdk/lcov.info | coveralls","is-publish-allowed":"node scripts/is-publish-allowed.js",prepublishOnly:"npm run is-publish-allowed && npm run test && npm run tsc && npm run bundle-dts-file && npm run bundle-dts && npm run bundle-dts-react && npm run bundle-dts-react-full && npm run build","check-size":"npm run build && size-limit","publish-dev":"npm publish --tag dev","publish-prod":"npm publish --tag latest"};var peerDependencies={react:"> 16.8.0","react-dom":"> 16.8.0"};var dependencies={algoliasearch:"^4.10.5",classnames:"^2.3.1",dompurify:"^2.3.4","eslint-plugin-comment-length":"^0.9.2","eslint-plugin-jsdoc":"^46.9.0",eventemitter3:"^4.0.7","gatsby-plugin-vercel":"^1.0.3","html-react-parser":"^1.4.12",lodash:"^4.17.21","mixpanel-browser":"^2.45.0","ts-deepmerge":"^6.0.2",tslib:"^2.5.3","use-deep-compare-effect":"^1.8.1"};var devDependencies={"@mdx-js/mdx":"^1.6.22","@mdx-js/react":"^1.6.22","@react-icons/all-files":"^4.1.0","@rollup/plugin-commonjs":"^18.0.0","@rollup/plugin-json":"^4.1.0","@rollup/plugin-node-resolve":"^11.2.1","@rollup/plugin-replace":"^5.0.2","@size-limit/preset-big-lib":"^8.2.6","@testing-library/dom":"^7.31.0","@testing-library/jest-dom":"^5.14.1","@testing-library/react":"^11.2.7","@testing-library/user-event":"^13.1.8","@types/jest":"^22.2.3","@types/mixpanel-browser":"^2.35.6","@types/react-test-renderer":"^17.0.1","@typescript-eslint/eslint-plugin":"^4.6.0","@typescript-eslint/parser":"^4.6.0",asciidoctor:"^2.2.1","babel-jest":"^26.6.3","babel-preset-gatsby":"^1.10.0","command-line-args":"^5.1.1",coveralls:"^3.1.0","current-git-branch":"^1.1.0","dts-bundle":"^0.7.3",eslint:"^7.12.1","eslint-config-airbnb-base":"^14.2.0","eslint-config-prettier":"^6.15.0","eslint-import-resolver-typescript":"^2.3.0","eslint-plugin-import":"^2.22.1","eslint-plugin-prettier":"^3.1.4","eslint-plugin-react-hooks":"^4.2.0","fs-extra":"^10.0.0",gatsby:"3.13.1","gatsby-plugin-algolia":"^0.22.2","gatsby-plugin-catch-links":"^3.1.0","gatsby-plugin-env-variables":"^2.1.0","gatsby-plugin-intl":"^0.3.3","gatsby-plugin-manifest":"^3.2.0","gatsby-plugin-output":"^0.1.3","gatsby-plugin-sass":"6.7.0","gatsby-plugin-sitemap":"^4.10.0","gatsby-source-filesystem":"3.1.0","gatsby-transformer-asciidoc":"2.1.0","gatsby-transformer-rehype":"2.0.0","gh-pages":"^3.1.0","highlight.js":"^10.6.0","html-to-text":"^8.0.0","identity-obj-proxy":"^3.0.0","istanbul-merge":"^1.1.1",jest:"^26.6.3","jest-fetch-mock":"^3.0.3",jsdom:"^17.0.0","node-sass":"^8.0.0",prettier:"2.1.2",react:"^16.14.0","react-dom":"^16.14.0","react-resizable":"^1.11.0","react-resize-detector":"^6.6.0","react-test-renderer":"^17.0.2","react-use-flexsearch":"^0.1.1",rollup:"2.30.0","rollup-plugin-typescript2":"0.27.3","ts-jest":"^26.5.5","ts-loader":"8.0.4",typedoc:"0.21.6","typedoc-plugin-toc-group":"thoughtspot/typedoc-plugin-toc-group",typescript:"^4.9.4","url-search-params-polyfill":"^8.1.0",util:"^0.12.4"};var author="ThoughtSpot";var email="support@thoughtspot.com";var license="ThoughtSpot Development Tools End User License Agreement";var directories={lib:"lib"};var repository={type:"git",url:"git+https://github.com/thoughtspot/visual-embed-sdk.git"};var publishConfig={registry:"https://registry.npmjs.org"};var keywords=["thoughtspot","everywhere","embed","sdk","analytics"];var bugs={url:"https://github.com/thoughtspot/visual-embed-sdk/issues"};var homepage="https://github.com/thoughtspot/visual-embed-sdk#readme";var globals={window:{}};var pkgInfo = {name:name,version:version,description:description,module:module,main:main,types:types,files:files,exports:exports,typesVersions:typesVersions,"size-limit":[{path:"dist/tsembed.js",limit:"44 kB"}],scripts:scripts,peerDependencies:peerDependencies,dependencies:dependencies,devDependencies:devDependencies,author:author,email:email,license:license,directories:directories,repository:repository,publishConfig:publishConfig,keywords:keywords,bugs:bugs,homepage:homepage,globals:globals};
|
|
13926
|
+
|
|
13844
13927
|
/**
|
|
13845
13928
|
* Copyright (c) 2022
|
|
13846
13929
|
*
|
|
@@ -15345,7 +15428,7 @@ class SearchEmbed extends TsEmbed {
|
|
|
15345
15428
|
}
|
|
15346
15429
|
getEmbedParams() {
|
|
15347
15430
|
var _a;
|
|
15348
|
-
const { hideResults,
|
|
15431
|
+
const { hideResults, enableSearchAssist, forceTable, searchOptions, runtimeFilters, dataSource, dataSources, excludeRuntimeFiltersfromURL, hideSearchBar, dataPanelV2 = false, useLastSelectedSources = false, runtimeParameters, } = this.viewConfig;
|
|
15349
15432
|
const queryParams = this.getBaseQueryParams();
|
|
15350
15433
|
queryParams[Param.HideActions] = [
|
|
15351
15434
|
...((_a = queryParams[Param.HideActions]) !== null && _a !== void 0 ? _a : []),
|
|
@@ -15495,16 +15578,6 @@ class SearchBarEmbed extends TsEmbed {
|
|
|
15495
15578
|
* @summary TS Sage embed
|
|
15496
15579
|
* @author Mourya Balabhadra <mourya.balabhadra@thoughtspot.com>
|
|
15497
15580
|
*/
|
|
15498
|
-
const HiddenActionItemByDefaultForSageEmbed = [
|
|
15499
|
-
Action.Save,
|
|
15500
|
-
Action.Pin,
|
|
15501
|
-
Action.EditACopy,
|
|
15502
|
-
Action.SaveAsView,
|
|
15503
|
-
Action.UpdateTML,
|
|
15504
|
-
Action.EditTML,
|
|
15505
|
-
Action.AnswerDelete,
|
|
15506
|
-
Action.Share,
|
|
15507
|
-
];
|
|
15508
15581
|
/**
|
|
15509
15582
|
* Embed ThoughtSpot LLM and GPT-based Natural Language Search component.
|
|
15510
15583
|
*
|
|
@@ -15524,7 +15597,6 @@ class SageEmbed extends V1Embed {
|
|
|
15524
15597
|
* @returns {string} query string
|
|
15525
15598
|
*/
|
|
15526
15599
|
getEmbedParams() {
|
|
15527
|
-
var _a;
|
|
15528
15600
|
const { disableWorksheetChange, hideWorksheetSelector, showObjectSuggestions, hideSampleQuestions, isProductTour, hideSearchBarTitle, hideSageAnswerHeader, hideAutocompleteSuggestions, } = this.viewConfig;
|
|
15529
15601
|
const params = this.getBaseQueryParams();
|
|
15530
15602
|
params[Param.EmbedApp] = true;
|
|
@@ -15540,10 +15612,6 @@ class SageEmbed extends V1Embed {
|
|
|
15540
15612
|
params[Param.IsProductTour] = !!isProductTour;
|
|
15541
15613
|
params[Param.HideSearchBarTitle] = !!hideSearchBarTitle;
|
|
15542
15614
|
params[Param.HideSageAnswerHeader] = !!hideSageAnswerHeader;
|
|
15543
|
-
params[Param.HideActions] = [
|
|
15544
|
-
...((_a = params[Param.HideActions]) !== null && _a !== void 0 ? _a : []),
|
|
15545
|
-
...HiddenActionItemByDefaultForSageEmbed,
|
|
15546
|
-
];
|
|
15547
15615
|
return getQueryParamString(params, true);
|
|
15548
15616
|
}
|
|
15549
15617
|
/**
|
|
@@ -15584,4 +15652,4 @@ class SageEmbed extends V1Embed {
|
|
|
15584
15652
|
}
|
|
15585
15653
|
}
|
|
15586
15654
|
|
|
15587
|
-
export { Action, AnswerService, AppEmbed, AuthEvent, AuthFailureType, AuthStatus, AuthType, ContextMenuTriggerOptions, DataSourceVisualMode, EmbedEvent, HomeLeftNavItem, HomepageModule, HostEvent, LiveboardEmbed, LogLevel, Page, PinboardEmbed, PrefetchFeatures, RuntimeFilterOp, SageEmbed, SearchBarEmbed, SearchEmbed, executeTML, exportTML, getEmbedConfig as getInitConfig, getSessionInfo, init, logout$1 as logout, prefetch };
|
|
15655
|
+
export { Action, AnswerService, AppEmbed, AuthEvent, AuthFailureType, AuthStatus, AuthType, ContextMenuTriggerOptions, DataSourceVisualMode, EmbedEvent, HomeLeftNavItem, HomepageModule, HostEvent, LiveboardEmbed, LogLevel, MIXPANEL_EVENT, Page, PinboardEmbed, PrefetchFeatures, RuntimeFilterOp, SageEmbed, SearchBarEmbed, SearchEmbed, executeTML, exportTML, getEmbedConfig as getInitConfig, getSessionInfo, init, logout$1 as logout, prefetch, uploadMixpanelEvent };
|