@thoughtspot/visual-embed-sdk 1.45.2 → 1.45.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/cjs/package.json +1 -1
  2. package/cjs/src/css-variables.d.ts +48 -0
  3. package/cjs/src/css-variables.d.ts.map +1 -1
  4. package/cjs/src/embed/app.d.ts +37 -0
  5. package/cjs/src/embed/app.d.ts.map +1 -1
  6. package/cjs/src/embed/app.js +37 -1
  7. package/cjs/src/embed/app.js.map +1 -1
  8. package/cjs/src/embed/app.spec.js +24 -0
  9. package/cjs/src/embed/app.spec.js.map +1 -1
  10. package/cjs/src/embed/conversation.d.ts +127 -9
  11. package/cjs/src/embed/conversation.d.ts.map +1 -1
  12. package/cjs/src/embed/conversation.js +41 -18
  13. package/cjs/src/embed/conversation.js.map +1 -1
  14. package/cjs/src/embed/conversation.spec.js +96 -3
  15. package/cjs/src/embed/conversation.spec.js.map +1 -1
  16. package/cjs/src/embed/liveboard.d.ts +38 -1
  17. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  18. package/cjs/src/embed/liveboard.js +38 -10
  19. package/cjs/src/embed/liveboard.js.map +1 -1
  20. package/cjs/src/embed/liveboard.spec.js +179 -7
  21. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  22. package/cjs/src/errors.d.ts +1 -0
  23. package/cjs/src/errors.d.ts.map +1 -1
  24. package/cjs/src/errors.js +1 -0
  25. package/cjs/src/errors.js.map +1 -1
  26. package/cjs/src/index.d.ts +3 -3
  27. package/cjs/src/index.d.ts.map +1 -1
  28. package/cjs/src/index.js.map +1 -1
  29. package/cjs/src/types.d.ts +192 -40
  30. package/cjs/src/types.d.ts.map +1 -1
  31. package/cjs/src/types.js +184 -19
  32. package/cjs/src/types.js.map +1 -1
  33. package/cjs/src/utils/graphql/answerService/answer-queries.d.ts +1 -0
  34. package/cjs/src/utils/graphql/answerService/answer-queries.d.ts.map +1 -1
  35. package/cjs/src/utils/graphql/answerService/answer-queries.js +23 -1
  36. package/cjs/src/utils/graphql/answerService/answer-queries.js.map +1 -1
  37. package/cjs/src/utils/graphql/answerService/answerService.d.ts +2 -1
  38. package/cjs/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  39. package/cjs/src/utils/graphql/answerService/answerService.js +9 -1
  40. package/cjs/src/utils/graphql/answerService/answerService.js.map +1 -1
  41. package/cjs/src/utils/graphql/answerService/answerService.spec.js +73 -0
  42. package/cjs/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
  43. package/cjs/src/utils.d.ts +15 -0
  44. package/cjs/src/utils.d.ts.map +1 -1
  45. package/cjs/src/utils.js +33 -1
  46. package/cjs/src/utils.js.map +1 -1
  47. package/cjs/src/utils.spec.js +49 -0
  48. package/cjs/src/utils.spec.js.map +1 -1
  49. package/dist/{index-BdkKLLo1.js → index-BuwECGdm.js} +1 -1
  50. package/dist/src/css-variables.d.ts +48 -0
  51. package/dist/src/css-variables.d.ts.map +1 -1
  52. package/dist/src/embed/app.d.ts +37 -0
  53. package/dist/src/embed/app.d.ts.map +1 -1
  54. package/dist/src/embed/conversation.d.ts +127 -9
  55. package/dist/src/embed/conversation.d.ts.map +1 -1
  56. package/dist/src/embed/liveboard.d.ts +38 -1
  57. package/dist/src/embed/liveboard.d.ts.map +1 -1
  58. package/dist/src/errors.d.ts +1 -0
  59. package/dist/src/errors.d.ts.map +1 -1
  60. package/dist/src/index.d.ts +3 -3
  61. package/dist/src/index.d.ts.map +1 -1
  62. package/dist/src/types.d.ts +192 -40
  63. package/dist/src/types.d.ts.map +1 -1
  64. package/dist/src/utils/graphql/answerService/answer-queries.d.ts +1 -0
  65. package/dist/src/utils/graphql/answerService/answer-queries.d.ts.map +1 -1
  66. package/dist/src/utils/graphql/answerService/answerService.d.ts +2 -1
  67. package/dist/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  68. package/dist/src/utils.d.ts +15 -0
  69. package/dist/src/utils.d.ts.map +1 -1
  70. package/dist/tsembed-react.es.js +364 -52
  71. package/dist/tsembed-react.js +363 -51
  72. package/dist/tsembed.es.js +364 -52
  73. package/dist/tsembed.js +363 -51
  74. package/dist/visual-embed-sdk-react-full.d.ts +696 -342
  75. package/dist/visual-embed-sdk-react.d.ts +685 -331
  76. package/dist/visual-embed-sdk.d.ts +757 -379
  77. package/lib/package.json +1 -1
  78. package/lib/src/css-variables.d.ts +48 -0
  79. package/lib/src/css-variables.d.ts.map +1 -1
  80. package/lib/src/embed/app.d.ts +37 -0
  81. package/lib/src/embed/app.d.ts.map +1 -1
  82. package/lib/src/embed/app.js +39 -3
  83. package/lib/src/embed/app.js.map +1 -1
  84. package/lib/src/embed/app.spec.js +24 -0
  85. package/lib/src/embed/app.spec.js.map +1 -1
  86. package/lib/src/embed/conversation.d.ts +127 -9
  87. package/lib/src/embed/conversation.d.ts.map +1 -1
  88. package/lib/src/embed/conversation.js +42 -19
  89. package/lib/src/embed/conversation.js.map +1 -1
  90. package/lib/src/embed/conversation.spec.js +96 -3
  91. package/lib/src/embed/conversation.spec.js.map +1 -1
  92. package/lib/src/embed/liveboard.d.ts +38 -1
  93. package/lib/src/embed/liveboard.d.ts.map +1 -1
  94. package/lib/src/embed/liveboard.js +39 -11
  95. package/lib/src/embed/liveboard.js.map +1 -1
  96. package/lib/src/embed/liveboard.spec.js +179 -7
  97. package/lib/src/embed/liveboard.spec.js.map +1 -1
  98. package/lib/src/errors.d.ts +1 -0
  99. package/lib/src/errors.d.ts.map +1 -1
  100. package/lib/src/errors.js +1 -0
  101. package/lib/src/errors.js.map +1 -1
  102. package/lib/src/index.d.ts +3 -3
  103. package/lib/src/index.d.ts.map +1 -1
  104. package/lib/src/index.js.map +1 -1
  105. package/lib/src/types.d.ts +192 -40
  106. package/lib/src/types.d.ts.map +1 -1
  107. package/lib/src/types.js +184 -19
  108. package/lib/src/types.js.map +1 -1
  109. package/lib/src/utils/graphql/answerService/answer-queries.d.ts +1 -0
  110. package/lib/src/utils/graphql/answerService/answer-queries.d.ts.map +1 -1
  111. package/lib/src/utils/graphql/answerService/answer-queries.js +22 -0
  112. package/lib/src/utils/graphql/answerService/answer-queries.js.map +1 -1
  113. package/lib/src/utils/graphql/answerService/answerService.d.ts +2 -1
  114. package/lib/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  115. package/lib/src/utils/graphql/answerService/answerService.js +9 -1
  116. package/lib/src/utils/graphql/answerService/answerService.js.map +1 -1
  117. package/lib/src/utils/graphql/answerService/answerService.spec.js +73 -0
  118. package/lib/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
  119. package/lib/src/utils.d.ts +15 -0
  120. package/lib/src/utils.d.ts.map +1 -1
  121. package/lib/src/utils.js +30 -0
  122. package/lib/src/utils.js.map +1 -1
  123. package/lib/src/utils.spec.js +50 -1
  124. package/lib/src/utils.spec.js.map +1 -1
  125. package/package.json +1 -1
  126. package/src/css-variables.ts +60 -0
  127. package/src/embed/app.spec.ts +32 -0
  128. package/src/embed/app.ts +97 -1
  129. package/src/embed/conversation.spec.ts +117 -3
  130. package/src/embed/conversation.ts +188 -29
  131. package/src/embed/liveboard.spec.ts +264 -10
  132. package/src/embed/liveboard.ts +100 -11
  133. package/src/errors.ts +1 -0
  134. package/src/index.ts +5 -1
  135. package/src/types.ts +193 -40
  136. package/src/utils/graphql/answerService/answer-queries.ts +23 -0
  137. package/src/utils/graphql/answerService/answerService.spec.ts +87 -0
  138. package/src/utils/graphql/answerService/answerService.ts +13 -1
  139. package/src/utils.spec.ts +56 -0
  140. package/src/utils.ts +36 -0
package/src/types.ts CHANGED
@@ -1599,7 +1599,7 @@ export interface LiveboardAppEmbedViewConfig {
1599
1599
  * To enable this feature on your instance, contact ThoughtSpot Support.
1600
1600
  *
1601
1601
  * Supported embed types: `AppEmbed`, `LiveboardEmbed`
1602
- * @version SDK: 1.42.0 | ThoughtSpot: 10.15.0.cl
1602
+ * @version SDK: 1.46.0 | ThoughtSpot: 26.4.0.cl
1603
1603
  * @example
1604
1604
  * ```js
1605
1605
  * // Replace <EmbedComponent> with embed component name. For example, AppEmbed or LiveboardEmbed
@@ -3203,6 +3203,42 @@ export enum EmbedEvent {
3203
3203
  * @version SDK: 1.43.0 | ThoughtSpot: 10.15.0.cl
3204
3204
  */
3205
3205
  ApiIntercept = 'ApiIntercept',
3206
+ /**
3207
+ * Emitted when a Spotter conversation is renamed.
3208
+ * @example
3209
+ * ```js
3210
+ * spotterEmbed.on(EmbedEvent.SpotterConversationRenamed, (payload) => {
3211
+ * console.log('Conversation renamed', payload);
3212
+ * // payload: { convId: string, oldTitle: string, newTitle: string }
3213
+ * })
3214
+ * ```
3215
+ * @version SDK: 1.46.0 | ThoughtSpot: 26.3.0.cl
3216
+ */
3217
+ SpotterConversationRenamed = 'spotterConversationRenamed',
3218
+ /**
3219
+ * Emitted when a Spotter conversation is deleted.
3220
+ * @example
3221
+ * ```js
3222
+ * spotterEmbed.on(EmbedEvent.SpotterConversationDeleted, (payload) => {
3223
+ * console.log('Conversation deleted', payload);
3224
+ * // payload: { convId: string, title: string }
3225
+ * })
3226
+ * ```
3227
+ * @version SDK: 1.46.0 | ThoughtSpot: 26.3.0.cl
3228
+ */
3229
+ SpotterConversationDeleted = 'spotterConversationDeleted',
3230
+ /**
3231
+ * Emitted when a Spotter conversation is selected/clicked.
3232
+ * @example
3233
+ * ```js
3234
+ * spotterEmbed.on(EmbedEvent.SpotterConversationSelected, (payload) => {
3235
+ * console.log('Conversation selected', payload);
3236
+ * // payload: { convId: string, title: string, worksheetId: string }
3237
+ * })
3238
+ * ```
3239
+ * @version SDK: 1.46.0 | ThoughtSpot: 26.3.0.cl
3240
+ */
3241
+ SpotterConversationSelected = 'spotterConversationSelected',
3206
3242
 
3207
3243
  /**
3208
3244
  * @hidden
@@ -4771,7 +4807,19 @@ export enum Param {
4771
4807
  isLinkParametersEnabled = 'isLinkParametersEnabled',
4772
4808
  EnablePastConversationsSidebar = 'enablePastConversationsSidebar',
4773
4809
  UpdatedSpotterChatPrompt = 'updatedSpotterChatPrompt',
4810
+ SpotterSidebarTitle = 'spotterSidebarTitle',
4811
+ SpotterSidebarDefaultExpanded = 'spotterSidebarDefaultExpanded',
4812
+ SpotterChatRenameLabel = 'spotterChatRenameLabel',
4813
+ SpotterChatDeleteLabel = 'spotterChatDeleteLabel',
4814
+ SpotterDeleteConversationModalTitle = 'spotterDeleteConversationModalTitle',
4815
+ SpotterPastConversationAlertMessage = 'spotterPastConversationAlertMessage',
4816
+ SpotterDocumentationUrl = 'spotterDocumentationUrl',
4817
+ SpotterBestPracticesLabel = 'spotterBestPracticesLabel',
4818
+ SpotterConversationsBatchSize = 'spotterConversationsBatchSize',
4819
+ SpotterNewChatButtonTitle = 'spotterNewChatButtonTitle',
4774
4820
  IsThisPeriodInDateFiltersEnabled = 'isThisPeriodInDateFiltersEnabled',
4821
+ HideToolResponseCardBranding = 'hideToolResponseCardBranding',
4822
+ ToolResponseCardBrandingLabel = 'toolResponseCardBrandingLabel',
4775
4823
  }
4776
4824
 
4777
4825
  /**
@@ -6216,6 +6264,96 @@ export enum Action {
6216
6264
  * @version SDK: 1.44.0 | ThoughtSpot Cloud: 26.2.0.cl
6217
6265
  */
6218
6266
  UngroupLiveboardGroup = 'ungroupLiveboardGroup',
6267
+ /**
6268
+ * Controls visibility of the sidebar header (title and toggle button)
6269
+ * in the Spotter past conversations sidebar.
6270
+ * @example
6271
+ * ```js
6272
+ * hiddenActions: [Action.SpotterSidebarHeader]
6273
+ * ```
6274
+ * @version SDK: 1.46.0 | ThoughtSpot Cloud: 26.3.0.cl
6275
+ */
6276
+ SpotterSidebarHeader = 'spotterSidebarHeader',
6277
+ /**
6278
+ * Controls visibility of the sidebar footer (documentation link)
6279
+ * in the Spotter past conversations sidebar.
6280
+ * @example
6281
+ * ```js
6282
+ * hiddenActions: [Action.SpotterSidebarFooter]
6283
+ * ```
6284
+ * @version SDK: 1.46.0 | ThoughtSpot Cloud: 26.3.0.cl
6285
+ */
6286
+ SpotterSidebarFooter = 'spotterSidebarFooter',
6287
+ /**
6288
+ * Controls visibility and disable state of the sidebar toggle/expand button
6289
+ * in the Spotter past conversations sidebar.
6290
+ * @example
6291
+ * ```js
6292
+ * disabledActions: [Action.SpotterSidebarToggle]
6293
+ * ```
6294
+ * @version SDK: 1.46.0 | ThoughtSpot Cloud: 26.3.0.cl
6295
+ */
6296
+ SpotterSidebarToggle = 'spotterSidebarToggle',
6297
+ /**
6298
+ * Controls visibility and disable state of the "New Chat" button
6299
+ * in the Spotter past conversations sidebar.
6300
+ * @example
6301
+ * ```js
6302
+ * disabledActions: [Action.SpotterNewChat]
6303
+ * ```
6304
+ * @version SDK: 1.46.0 | ThoughtSpot Cloud: 26.3.0.cl
6305
+ */
6306
+ SpotterNewChat = 'spotterNewChat',
6307
+ /**
6308
+ * Controls visibility of the past conversation banner alert
6309
+ * in the Spotter interface.
6310
+ * @example
6311
+ * ```js
6312
+ * hiddenActions: [Action.SpotterPastChatBanner]
6313
+ * ```
6314
+ * @version SDK: 1.46.0 | ThoughtSpot Cloud: 26.3.0.cl
6315
+ */
6316
+ SpotterPastChatBanner = 'spotterPastChatBanner',
6317
+ /**
6318
+ * Controls visibility and disable state of the conversation edit menu
6319
+ * (three-dot menu) in the Spotter past conversations sidebar.
6320
+ * @example
6321
+ * ```js
6322
+ * disabledActions: [Action.SpotterChatMenu]
6323
+ * ```
6324
+ * @version SDK: 1.46.0 | ThoughtSpot Cloud: 26.3.0.cl
6325
+ */
6326
+ SpotterChatMenu = 'spotterChatMenu',
6327
+ /**
6328
+ * Controls visibility and disable state of the rename action
6329
+ * in the Spotter conversation edit menu.
6330
+ * @example
6331
+ * ```js
6332
+ * disabledActions: [Action.SpotterChatRename]
6333
+ * ```
6334
+ * @version SDK: 1.46.0 | ThoughtSpot Cloud: 26.3.0.cl
6335
+ */
6336
+ SpotterChatRename = 'spotterChatRename',
6337
+ /**
6338
+ * Controls visibility and disable state of the delete action
6339
+ * in the Spotter conversation edit menu.
6340
+ * @example
6341
+ * ```js
6342
+ * disabledActions: [Action.SpotterChatDelete]
6343
+ * ```
6344
+ * @version SDK: 1.46.0 | ThoughtSpot Cloud: 26.3.0.cl
6345
+ */
6346
+ SpotterChatDelete = 'spotterChatDelete',
6347
+ /**
6348
+ * Controls visibility and disable state of the documentation/best practices
6349
+ * link in the Spotter sidebar footer.
6350
+ * @example
6351
+ * ```js
6352
+ * disabledActions: [Action.SpotterDocs]
6353
+ * ```
6354
+ * @version SDK: 1.46.0 | ThoughtSpot Cloud: 26.3.0.cl
6355
+ */
6356
+ SpotterDocs = 'spotterDocs',
6219
6357
  /**
6220
6358
  * The **Include current period** checkbox for date filters.
6221
6359
  * Controls the visibility and availability of the option to include
@@ -6426,13 +6564,30 @@ export enum LogLevel {
6426
6564
  * Error types emitted by embedded components.
6427
6565
  *
6428
6566
  * These enum values categorize different types of errors that can occur during
6429
- * the lifecycle of an embedded ThoughtSpot component. Use these values to implement
6430
- * specific error handling logic based on the error category.
6431
- *
6432
- * @see {@link EmbedErrorDetailsEvent} - The error event object structure
6433
- * @see {@link EmbedEvent.Error} - The event that emits these errors
6567
+ * the lifecycle of an embedded ThoughtSpot component.
6568
+ * Use {@link EmbedErrorDetailsEvent} and {@link EmbedErrorCodes} to handle specific errors.
6434
6569
  * @version SDK: 1.44.2 | ThoughtSpot: 26.2.0.cl
6435
6570
  * @group Error Handling
6571
+ *
6572
+ * @example
6573
+ * Handle specific error types
6574
+ * ```js
6575
+ * embed.on(EmbedEvent.Error, (error) => {
6576
+ * switch (error.errorType) {
6577
+ * case ErrorDetailsTypes.API:
6578
+ * console.error('API error:', error.message);
6579
+ * break;
6580
+ * case ErrorDetailsTypes.VALIDATION_ERROR:
6581
+ * console.error('Validation error:', error.message);
6582
+ * break;
6583
+ * case ErrorDetailsTypes.NETWORK:
6584
+ * console.error('Network error:', error.message);
6585
+ * break;
6586
+ * default:
6587
+ * console.error('Unknown error:', error);
6588
+ * }
6589
+ * });
6590
+ * ```
6436
6591
  */
6437
6592
  export enum ErrorDetailsTypes {
6438
6593
  /** API call failure */
@@ -6444,26 +6599,34 @@ export enum ErrorDetailsTypes {
6444
6599
  }
6445
6600
 
6446
6601
  /**
6447
- * Error codes for identifying specific issues in embedded ThoughtSpot components.
6448
- *
6449
- * Use these codes for precise error handling and debugging. Each code maps to a
6450
- * distinct failure scenario, enabling targeted recovery strategies.
6602
+ * Error codes for identifying specific issues in embedded ThoughtSpot components. Use {@link EmbedErrorDetailsEvent} and {@link ErrorDetailsTypes} codes for precise error handling and debugging.
6451
6603
  *
6452
6604
  * @version SDK: 1.44.2 | ThoughtSpot: 26.2.0.cl
6453
6605
  * @group Error Handling
6454
- *
6455
- * @see {@link EmbedErrorDetailsEvent} - The error event object that includes these codes
6456
- * @see {@link ErrorDetailsTypes} - General error type categories
6457
- *
6606
+
6458
6607
  * @example
6459
6608
  * Handle specific error codes in the error event handler
6460
- *
6609
+ * ```js
6461
6610
  * embed.on(EmbedEvent.Error, (error) => {
6462
- * if (error.code === EmbedErrorCodes.WORKSHEET_ID_NOT_FOUND) {
6463
- * console.error('Worksheet ID not found:', error.message);
6611
+ * switch (error.code) {
6612
+ * case EmbedErrorCodes.WORKSHEET_ID_NOT_FOUND:
6613
+ * console.error('Worksheet ID not found:', error.message);
6614
+ * break;
6615
+ * case EmbedErrorCodes.LIVEBOARD_ID_MISSING:
6616
+ * console.error('Liveboard ID is missing:', error.message);
6617
+ * break;
6618
+ * case EmbedErrorCodes.CONFLICTING_ACTIONS_CONFIG:
6619
+ * console.error('Conflicting actions configuration:', error.message);
6620
+ * break;
6621
+ * case EmbedErrorCodes.CONFLICTING_TABS_CONFIG:
6622
+ * console.error('Conflicting tabs configuration:', error.message);
6623
+ * break;
6624
+ * default:
6625
+ * console.error('Unknown error:', error);
6464
6626
  * }
6465
6627
  * });
6466
- * */
6628
+ * ```
6629
+ * */
6467
6630
  export enum EmbedErrorCodes {
6468
6631
  /** Worksheet ID not found or does not exist */
6469
6632
  WORKSHEET_ID_NOT_FOUND = 'WORKSHEET_ID_NOT_FOUND',
@@ -6471,10 +6634,10 @@ export enum EmbedErrorCodes {
6471
6634
  /** Required Liveboard ID is missing from configuration */
6472
6635
  LIVEBOARD_ID_MISSING = 'LIVEBOARD_ID_MISSING',
6473
6636
 
6474
- /** Conflicting action configuration detected (e.g., both hiddenActions and visibleActions specified) */
6637
+ /** Conflicting action configuration detected */
6475
6638
  CONFLICTING_ACTIONS_CONFIG = 'CONFLICTING_ACTIONS_CONFIG',
6476
6639
 
6477
- /** Conflicting tab configuration detected (e.g., both hiddenTabs and visibleTabs specified) */
6640
+ /** Conflicting tab configuration detected */
6478
6641
  CONFLICTING_TABS_CONFIG = 'CONFLICTING_TABS_CONFIG',
6479
6642
 
6480
6643
  /** Error during component initialization */
@@ -6500,6 +6663,9 @@ export enum EmbedErrorCodes {
6500
6663
 
6501
6664
  /** Failed to update embed parameters during pre-render */
6502
6665
  UPDATE_PARAMS_FAILED = 'UPDATE_PARAMS_FAILED',
6666
+
6667
+ /** Invalid URL provided in configuration */
6668
+ INVALID_URL = 'INVALID_URL',
6503
6669
  }
6504
6670
 
6505
6671
  /**
@@ -6513,7 +6679,7 @@ export enum EmbedErrorCodes {
6513
6679
  *
6514
6680
  * - **errorType**: One of the predefined {@link ErrorDetailsTypes} values
6515
6681
  * - **message**: Human-readable error description (string or array of strings for multiple errors)
6516
- * - **code**: Machine-readable error identifier for programmatic handling
6682
+ * - **code**: Machine-readable error identifier {@link EmbedErrorCodes} values
6517
6683
  * - **[key: string]**: Additional context-specific for backward compatibility
6518
6684
  *
6519
6685
  * ## Usage
@@ -6523,12 +6689,11 @@ export enum EmbedErrorCodes {
6523
6689
  *
6524
6690
  * @version SDK: 1.44.2 | ThoughtSpot: 26.2.0.cl
6525
6691
  * @group Error Handling
6526
- * @see {@link ErrorDetailsTypes} - Available error type values
6527
- * @see {@link EmbedEvent.Error} - The event that emits this object
6528
6692
  *
6529
6693
  * @example
6530
6694
  * Handle specific error types
6531
- *
6695
+ *
6696
+ * ```js
6532
6697
  * embed.on(EmbedEvent.Error, (error) => {
6533
6698
  * switch (error.code) {
6534
6699
  * case EmbedErrorCodes.WORKSHEET_ID_NOT_FOUND:
@@ -6538,30 +6703,18 @@ export enum EmbedErrorCodes {
6538
6703
  * console.error('Unknown error:', error);
6539
6704
  * }
6540
6705
  * });
6541
- * *
6706
+ * ```
6542
6707
  * @example
6543
6708
  * Handle multiple error messages
6544
- *
6709
+ *
6710
+ * ```js
6545
6711
  * embed.on(EmbedEvent.Error, (error) => {
6546
6712
  * const messages = Array.isArray(error.message)
6547
6713
  * ? error.message
6548
6714
  * : [error.message];
6549
- *
6550
6715
  * messages.forEach(msg => console.error(msg));
6551
6716
  * });
6552
- * *
6553
- * @example
6554
- * Access additional error context
6555
- *
6556
- * embed.on(EmbedEvent.Error, (error) => {
6557
- * console.error('Error Details:', {
6558
- * type: error.errorType,
6559
- * message: error.message,
6560
- * code: error.code,
6561
- * // Additional context fields vary by error type
6562
- * ...error
6563
- * });
6564
- * });
6717
+ * ```
6565
6718
  * */
6566
6719
  export interface EmbedErrorDetailsEvent {
6567
6720
  /** The type of error that occurred */
@@ -176,6 +176,29 @@ export const getSQLQuery = `
176
176
  }
177
177
  `;
178
178
 
179
+ export const updateDisplayMode = `
180
+ mutation UpdateDisplayMode(
181
+ $session: BachSessionIdInput!
182
+ $displayMode: DisplayMode
183
+ ) {
184
+ Answer__updateProperties(session: $session, displayMode: $displayMode) {
185
+ id {
186
+ sessionId
187
+ genNo
188
+ acSession {
189
+ sessionId
190
+ genNo
191
+ }
192
+ }
193
+ answer {
194
+ id
195
+ displayMode
196
+ suggestedDisplayMode
197
+ }
198
+ }
199
+ }
200
+ `;
201
+
179
202
  export const getAnswerTML = `
180
203
  mutation GetUnsavedAnswerTML($session: BachSessionIdInput!, $exportDependencies: Boolean, $formatType: EDocFormatType, $exportPermissions: Boolean, $exportFqn: Boolean) {
181
204
  UnsavedAnswer_getTML(
@@ -473,6 +473,93 @@ describe('Answer service tests', () => {
473
473
  expect(sql).toBe('SELECT * FROM table');
474
474
  });
475
475
 
476
+ test('Get SQL query with all columns should update display mode', async () => {
477
+ fetchMock.mockResponses(
478
+ JSON.stringify({
479
+ data: {
480
+ Answer__updateProperties: {
481
+ id: {
482
+ ...defaultSession,
483
+ },
484
+ answer: {
485
+ id: 'answer1',
486
+ displayMode: 'TABLE_MODE',
487
+ suggestedDisplayMode: 'CHART_MODE',
488
+ },
489
+ },
490
+ },
491
+ }),
492
+ JSON.stringify({
493
+ data: {
494
+ Answer__getQuery: {
495
+ sql: 'SELECT * FROM table',
496
+ },
497
+ },
498
+ }),
499
+ );
500
+ const answerService = createAnswerService();
501
+ const sql = await answerService.getSQLQuery(true);
502
+ expect(fetchMock).toHaveBeenCalledWith(
503
+ 'https://tshost/prism/?op=UpdateDisplayMode',
504
+ expect.objectContaining({
505
+ body: JSON.stringify({
506
+ operationName: 'UpdateDisplayMode',
507
+ query: queries.updateDisplayMode,
508
+ variables: {
509
+ session: defaultSession,
510
+ displayMode: 'TABLE_MODE',
511
+ },
512
+ }),
513
+ }),
514
+ );
515
+ expect(fetchMock).toHaveBeenCalledWith(
516
+ 'https://tshost/prism/?op=GetSQLQuery',
517
+ expect.objectContaining({
518
+ body: JSON.stringify({
519
+ operationName: 'GetSQLQuery',
520
+ query: getSQLQuery,
521
+ variables: {
522
+ session: defaultSession,
523
+ },
524
+ }),
525
+ }),
526
+ );
527
+ expect(sql).toBe('SELECT * FROM table');
528
+ });
529
+
530
+ test('Update display mode should call the right API', async () => {
531
+ fetchMock.mockResponseOnce(JSON.stringify({
532
+ data: {
533
+ Answer__updateProperties: {
534
+ id: {
535
+ ...defaultSession,
536
+ },
537
+ answer: {
538
+ id: 'answer1',
539
+ displayMode: 'CHART_MODE',
540
+ suggestedDisplayMode: 'TABLE_MODE',
541
+ },
542
+ },
543
+ },
544
+ }));
545
+ const answerService = createAnswerService();
546
+ const response = await answerService.updateDisplayMode('CHART_MODE');
547
+ expect(fetchMock).toHaveBeenCalledWith(
548
+ 'https://tshost/prism/?op=UpdateDisplayMode',
549
+ expect.objectContaining({
550
+ body: JSON.stringify({
551
+ operationName: 'UpdateDisplayMode',
552
+ query: queries.updateDisplayMode,
553
+ variables: {
554
+ session: defaultSession,
555
+ displayMode: 'CHART_MODE',
556
+ },
557
+ }),
558
+ }),
559
+ );
560
+ expect(response.answer.displayMode).toBe('CHART_MODE');
561
+ });
562
+
476
563
  test('Add displayed Viz should call the right API', async () => {
477
564
  fetchMock.mockResponseOnce(JSON.stringify({
478
565
  data: {
@@ -190,7 +190,19 @@ export class AnswerService {
190
190
  );
191
191
  }
192
192
 
193
- public async getSQLQuery(): Promise<string> {
193
+ public async updateDisplayMode(displayMode = "TABLE_MODE") {
194
+ return this.executeQuery(
195
+ queries.updateDisplayMode,
196
+ {
197
+ displayMode,
198
+ },
199
+ );
200
+ }
201
+
202
+ public async getSQLQuery(fetchSQLWithAllColumns = false): Promise<string> {
203
+ if (fetchSQLWithAllColumns) {
204
+ await this.updateDisplayMode("TABLE_MODE");
205
+ }
194
206
  const { sql } = await this.executeQuery(
195
207
  queries.getSQLQuery,
196
208
  {},
package/src/utils.spec.ts CHANGED
@@ -21,6 +21,8 @@ import {
21
21
  formatTemplate,
22
22
  isValidCssMargin,
23
23
  resetValueFromWindow,
24
+ validateHttpUrl,
25
+ setParamIfDefined,
24
26
  } from './utils';
25
27
  import { RuntimeFilterOp } from './types';
26
28
  import { logger } from './utils/logger';
@@ -824,4 +826,58 @@ describe('getValueFromWindow and storeValueInWindow', () => {
824
826
  expect(getValueFromWindow('key2')).toBe('value2');
825
827
  });
826
828
  });
829
+
830
+ describe('validateHttpUrl', () => {
831
+ test.each([
832
+ ['http URL', 'http://example.com'],
833
+ ['https URL', 'https://example.com'],
834
+ ['https URL with path', 'https://docs.example.com/spotter'],
835
+ ['https URL with query params', 'https://example.com/path?foo=bar'],
836
+ ])('should return [true, null] for valid %s', (_, url) => {
837
+ const [isValid, error] = validateHttpUrl(url);
838
+ expect(isValid).toBe(true);
839
+ expect(error).toBeNull();
840
+ });
841
+
842
+ test.each([
843
+ ['ftp protocol', 'ftp://example.com', 'ftp:'],
844
+ ['file protocol', 'file:///path/to/file', 'file:'],
845
+ ['javascript protocol', 'javascript:alert(1)', 'javascript:'],
846
+ ])('should return [false, Error] for %s', (_, url, protocol) => {
847
+ const [isValid, error] = validateHttpUrl(url);
848
+ expect(isValid).toBe(false);
849
+ expect(error).toBeInstanceOf(Error);
850
+ expect(error?.message).toContain('Invalid protocol');
851
+ expect(error?.message).toContain(protocol);
852
+ });
853
+
854
+ test.each([
855
+ ['invalid URL format', 'not-a-valid-url'],
856
+ ['empty string', ''],
857
+ ['URL without protocol', 'example.com'],
858
+ ])('should return [false, Error] for %s', (_, url) => {
859
+ const [isValid, error] = validateHttpUrl(url);
860
+ expect(isValid).toBe(false);
861
+ expect(error).toBeInstanceOf(Error);
862
+ });
863
+ });
864
+
865
+ describe('setParamIfDefined', () => {
866
+ test.each([
867
+ ['string value', 'testParam', 'testValue', false, 'testValue'],
868
+ ['number value', 'numParam', 42, false, 42],
869
+ ['truthy value as boolean', 'boolParam', 'truthy', true, true],
870
+ ['falsy value as boolean', 'boolParam', 0, true, false],
871
+ ])('should set %s correctly', (_, param, value, asBoolean, expected) => {
872
+ const queryParams: Record<string, unknown> = {};
873
+ setParamIfDefined(queryParams, param, value, asBoolean);
874
+ expect(queryParams[param]).toBe(expected);
875
+ });
876
+
877
+ test('should not set param when value is undefined', () => {
878
+ const queryParams: Record<string, unknown> = {};
879
+ setParamIfDefined(queryParams, 'testParam', undefined);
880
+ expect(queryParams.testParam).toBeUndefined();
881
+ });
882
+ });
827
883
  });
package/src/utils.ts CHANGED
@@ -581,3 +581,39 @@ export const isWindowUndefined = (): boolean => {
581
581
  }
582
582
  return false;
583
583
  }
584
+
585
+ /**
586
+ * Validates that a URL uses only http: or https: protocols.
587
+ * Returns a tuple of [isValid, error] so the caller can handle validation errors.
588
+ * @param url - The URL string to validate
589
+ * @returns [true, null] if valid, [false, Error] if invalid
590
+ */
591
+ export const validateHttpUrl = (url: string): [boolean, Error | null] => {
592
+ try {
593
+ const parsedUrl = new URL(url);
594
+ if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {
595
+ return [false, new Error(`Invalid protocol: ${parsedUrl.protocol}. Only http: and https: are allowed.`)];
596
+ }
597
+ return [true, null];
598
+ } catch (error) {
599
+ return [false, error instanceof Error ? error : new Error(String(error))];
600
+ }
601
+ };
602
+
603
+ /**
604
+ * Sets a query parameter if the value is defined.
605
+ * @param queryParams - The query params object to modify
606
+ * @param param - The parameter key
607
+ * @param value - The value to set
608
+ * @param asBoolean - If true, coerces value to boolean
609
+ */
610
+ export const setParamIfDefined = <T>(
611
+ queryParams: Record<string, unknown>,
612
+ param: string,
613
+ value: T | undefined,
614
+ asBoolean = false,
615
+ ): void => {
616
+ if (value !== undefined) {
617
+ queryParams[param] = asBoolean ? !!value : value;
618
+ }
619
+ };