@microsoft/teamsfx 2.0.0-experimental.0 → 2.0.1-alpha.264d12800.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -46,7 +46,6 @@ var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
46
46
  // Licensed under the MIT license.
47
47
  /**
48
48
  * Error code to trace the error types.
49
- * @beta
50
49
  */
51
50
  exports.ErrorCode = void 0;
52
51
  (function (ErrorCode) {
@@ -70,6 +69,30 @@ exports.ErrorCode = void 0;
70
69
  * Channel is not supported error.
71
70
  */
72
71
  ErrorCode["ChannelNotSupported"] = "ChannelNotSupported";
72
+ /**
73
+ * Failed to retrieve sso token
74
+ */
75
+ ErrorCode["FailedToRetrieveSsoToken"] = "FailedToRetrieveSsoToken";
76
+ /**
77
+ * Failed to process sso handler
78
+ */
79
+ ErrorCode["FailedToProcessSsoHandler"] = "FailedToProcessSsoHandler";
80
+ /**
81
+ * Cannot find command
82
+ */
83
+ ErrorCode["CannotFindCommand"] = "CannotFindCommand";
84
+ /**
85
+ * Failed to run sso step
86
+ */
87
+ ErrorCode["FailedToRunSsoStep"] = "FailedToRunSsoStep";
88
+ /**
89
+ * Failed to run dedup step
90
+ */
91
+ ErrorCode["FailedToRunDedupStep"] = "FailedToRunDedupStep";
92
+ /**
93
+ * Sso activity handler is undefined
94
+ */
95
+ ErrorCode["SsoActivityHandlerIsUndefined"] = "SsoActivityHandlerIsUndefined";
73
96
  /**
74
97
  * Runtime is not supported error.
75
98
  */
@@ -125,6 +148,15 @@ ErrorMessage.NodejsRuntimeNotSupported = "{0} is not supported in Node.";
125
148
  ErrorMessage.FailToAcquireTokenOnBehalfOfUser = "Failed to acquire access token on behalf of user: {0}";
126
149
  // ChannelNotSupported Error
127
150
  ErrorMessage.OnlyMSTeamsChannelSupported = "{0} is only supported in MS Teams Channel";
151
+ ErrorMessage.FailedToProcessSsoHandler = "Failed to process sso handler: {0}";
152
+ // FailedToRetrieveSsoToken Error
153
+ ErrorMessage.FailedToRetrieveSsoToken = "Failed to retrieve sso token, user failed to finish the AAD consent flow.";
154
+ // CannotFindCommand Error
155
+ ErrorMessage.CannotFindCommand = "Cannot find command: {0}";
156
+ ErrorMessage.FailedToRunSsoStep = "Failed to run dialog to retrieve sso token: {0}";
157
+ ErrorMessage.FailedToRunDedupStep = "Failed to run dialog to remove duplicated messages: {0}";
158
+ // SsoActivityHandlerIsUndefined Error
159
+ ErrorMessage.SsoActivityHandlerIsNull = "Sso command can only be used or added when sso activity handler is not undefined";
128
160
  // IdentityTypeNotSupported Error
129
161
  ErrorMessage.IdentityTypeNotSupported = "{0} identity is not supported in {1}";
130
162
  // AuthorizationInfoError
@@ -135,10 +167,9 @@ ErrorMessage.EmptyParameter = "Parameter {0} is empty";
135
167
  ErrorMessage.DuplicateHttpsOptionProperty = "Axios HTTPS agent already defined value for property {0}";
136
168
  ErrorMessage.DuplicateApiKeyInHeader = "The request already defined api key in request header with name {0}.";
137
169
  ErrorMessage.DuplicateApiKeyInQueryParam = "The request already defined api key in query parameter with name {0}.";
170
+ ErrorMessage.OnlySupportInQueryActivity = "The handleMessageExtensionQueryWithToken only support in handleTeamsMessagingExtensionQuery with composeExtension/query type.";
138
171
  /**
139
172
  * Error class with code and message thrown by the SDK.
140
- *
141
- * @beta
142
173
  */
143
174
  class ErrorWithCode extends Error {
144
175
  /**
@@ -146,8 +177,6 @@ class ErrorWithCode extends Error {
146
177
  *
147
178
  * @param {string} message - error message.
148
179
  * @param {ErrorCode} code - error code.
149
- *
150
- * @beta
151
180
  */
152
181
  constructor(message, code) {
153
182
  if (!code) {
@@ -165,8 +194,6 @@ class ErrorWithCode extends Error {
165
194
  // Licensed under the MIT license.
166
195
  /**
167
196
  * Log level.
168
- *
169
- * @beta
170
197
  */
171
198
  exports.LogLevel = void 0;
172
199
  (function (LogLevel) {
@@ -191,8 +218,6 @@ exports.LogLevel = void 0;
191
218
  * Update log level helper.
192
219
  *
193
220
  * @param { LogLevel } level - log level in configuration
194
- *
195
- * @beta
196
221
  */
197
222
  function setLogLevel(level) {
198
223
  internalLogger.level = level;
@@ -201,8 +226,6 @@ function setLogLevel(level) {
201
226
  * Get log level.
202
227
  *
203
228
  * @returns Log level
204
- *
205
- * @beta
206
229
  */
207
230
  function getLogLevel() {
208
231
  return internalLogger.level;
@@ -277,8 +300,6 @@ const internalLogger = new InternalLogger();
277
300
  * error: console.error,
278
301
  * });
279
302
  * ```
280
- *
281
- * @beta
282
303
  */
283
304
  function setLogger(logger) {
284
305
  internalLogger.customLogger = logger;
@@ -296,8 +317,6 @@ function setLogger(logger) {
296
317
  * }
297
318
  * });
298
319
  * ```
299
- *
300
- * @beta
301
320
  */
302
321
  function setLogFunction(logFunction) {
303
322
  internalLogger.customLogFunction = logFunction;
@@ -340,6 +359,7 @@ function getUserInfoFromSsoToken(ssoToken) {
340
359
  const userInfo = {
341
360
  displayName: tokenObject.name,
342
361
  objectId: tokenObject.oid,
362
+ tenantId: tokenObject.tid,
343
363
  preferredUserName: "",
344
364
  };
345
365
  if (tokenObject.ver === "2.0") {
@@ -461,8 +481,6 @@ function parseCertificate(certificateContent) {
461
481
  *
462
482
  * @remarks
463
483
  * Only works in in server side.
464
- *
465
- * @beta
466
484
  */
467
485
  class AppCredential {
468
486
  /**
@@ -475,8 +493,6 @@ class AppCredential {
475
493
  *
476
494
  * @throws {@link ErrorCode|InvalidConfiguration} when client id, client secret or tenant id is not found in config.
477
495
  * @throws {@link ErrorCode|RuntimeNotSupported} when runtime is nodeJS.
478
- *
479
- * @beta
480
496
  */
481
497
  constructor(authConfig) {
482
498
  internalLogger.info("Create M365 tenant credential");
@@ -506,8 +522,6 @@ class AppCredential {
506
522
  *
507
523
  * @returns Access token with expected scopes.
508
524
  * Throw error if get access token failed.
509
- *
510
- * @beta
511
525
  */
512
526
  getToken(scopes, options) {
513
527
  return tslib.__awaiter(this, void 0, void 0, function* () {
@@ -549,7 +563,10 @@ class AppCredential {
549
563
  */
550
564
  loadAndValidateConfig(config) {
551
565
  internalLogger.verbose("Validate authentication configuration");
552
- if (config.clientId && (config.clientSecret || config.certificateContent) && config.tenantId) {
566
+ if (config.clientId &&
567
+ (config.clientSecret || config.certificateContent) &&
568
+ config.tenantId &&
569
+ config.authorityHost) {
553
570
  return config;
554
571
  }
555
572
  const missingValues = [];
@@ -562,6 +579,9 @@ class AppCredential {
562
579
  if (!config.tenantId) {
563
580
  missingValues.push("tenantId");
564
581
  }
582
+ if (!config.authorityHost) {
583
+ missingValues.push("authorityHost");
584
+ }
565
585
  const errorMsg = formatString(ErrorMessage.InvalidConfiguration, missingValues.join(", "), "undefined");
566
586
  internalLogger.error(errorMsg);
567
587
  throw new ErrorWithCode(errorMsg, exports.ErrorCode.InvalidConfiguration);
@@ -579,8 +599,6 @@ class AppCredential {
579
599
  *
580
600
  * @remarks
581
601
  * Can only be used in server side.
582
- *
583
- * @beta
584
602
  */
585
603
  class OnBehalfOfUserCredential {
586
604
  /**
@@ -595,8 +613,6 @@ class OnBehalfOfUserCredential {
595
613
  * @throws {@link ErrorCode|InvalidConfiguration} when client id, client secret, certificate content, authority host or tenant id is not found in config.
596
614
  * @throws {@link ErrorCode|InternalError} when SSO token is not valid.
597
615
  * @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
598
- *
599
- * @beta
600
616
  */
601
617
  constructor(ssoToken, config) {
602
618
  internalLogger.info("Get on behalf of user credential");
@@ -657,8 +673,6 @@ class OnBehalfOfUserCredential {
657
673
  * @remarks
658
674
  * If scopes is empty string or array, it returns SSO token.
659
675
  * If scopes is non-empty, it returns access token for target scope.
660
- *
661
- * @beta
662
676
  */
663
677
  getToken(scopes, options) {
664
678
  return tslib.__awaiter(this, void 0, void 0, function* () {
@@ -711,8 +725,6 @@ class OnBehalfOfUserCredential {
711
725
  * @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
712
726
  *
713
727
  * @returns Basic user info with user displayName, objectId and preferredUserName.
714
- *
715
- * @beta
716
728
  */
717
729
  getUserInfo() {
718
730
  internalLogger.info("Get basic user info from SSO token");
@@ -744,26 +756,25 @@ class OnBehalfOfUserCredential {
744
756
  *
745
757
  * @remarks
746
758
  * Can only be used within Teams.
747
- *
748
- * @beta
749
759
  */
750
760
  class TeamsUserCredential {
751
761
  /**
752
762
  * Constructor of TeamsUserCredential.
753
763
  * @remarks
754
764
  * Can only be used within Teams.
755
- * @beta
756
765
  */
757
766
  constructor(authConfig) {
758
767
  throw new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), exports.ErrorCode.RuntimeNotSupported);
759
768
  }
760
769
  /**
761
770
  * Popup login page to get user's access token with specific scopes.
771
+ *
772
+ * @param {string[]} resources - The optional list of resources for full trust Teams apps.
773
+ *
762
774
  * @remarks
763
775
  * Can only be used within Teams.
764
- * @beta
765
776
  */
766
- login(scopes) {
777
+ login(scopes, resources) {
767
778
  return tslib.__awaiter(this, void 0, void 0, function* () {
768
779
  throw new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), exports.ErrorCode.RuntimeNotSupported);
769
780
  });
@@ -772,7 +783,6 @@ class TeamsUserCredential {
772
783
  * Get access token from credential.
773
784
  * @remarks
774
785
  * Can only be used within Teams.
775
- * @beta
776
786
  */
777
787
  getToken(scopes, options) {
778
788
  return tslib.__awaiter(this, void 0, void 0, function* () {
@@ -781,11 +791,13 @@ class TeamsUserCredential {
781
791
  }
782
792
  /**
783
793
  * Get basic user info from SSO token
794
+ *
795
+ * @param {string[]} resources - The optional list of resources for full trust Teams apps.
796
+ *
784
797
  * @remarks
785
798
  * Can only be used within Teams.
786
- * @beta
787
799
  */
788
- getUserInfo() {
800
+ getUserInfo(resources) {
789
801
  throw new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), exports.ErrorCode.RuntimeNotSupported);
790
802
  }
791
803
  }
@@ -794,8 +806,6 @@ class TeamsUserCredential {
794
806
  const defaultScope = "https://graph.microsoft.com/.default";
795
807
  /**
796
808
  * Microsoft Graph auth provider for Teams Framework
797
- *
798
- * @beta
799
809
  */
800
810
  class MsGraphAuthProvider {
801
811
  /**
@@ -807,8 +817,6 @@ class MsGraphAuthProvider {
807
817
  * @throws {@link ErrorCode|InvalidParameter} when scopes is not a valid string or string array.
808
818
  *
809
819
  * @returns An instance of MsGraphAuthProvider.
810
- *
811
- * @beta
812
820
  */
813
821
  constructor(teamsfx, scopes) {
814
822
  this.teamsfx = teamsfx;
@@ -902,8 +910,6 @@ class MsGraphAuthProvider {
902
910
  * @throws {@link ErrorCode|InvalidParameter} when scopes is not a valid string or string array.
903
911
  *
904
912
  * @returns Graph client with specified scopes.
905
- *
906
- * @beta
907
913
  */
908
914
  function createMicrosoftGraphClient(teamsfx, scopes) {
909
915
  internalLogger.info("Create Microsoft Graph Client");
@@ -931,8 +937,6 @@ const defaultSQLScope = "https://database.windows.net/";
931
937
  * @throws {@link ErrorCode|InvalidConfiguration} when SQL config resource configuration is invalid.
932
938
  * @throws {@link ErrorCode|InternalError} when get user MSI token failed or MSI token is invalid.
933
939
  * @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
934
- *
935
- * @beta
936
940
  */
937
941
  function getTediousConnectionConfig(teamsfx, databaseName) {
938
942
  return tslib.__awaiter(this, void 0, void 0, function* () {
@@ -1091,8 +1095,6 @@ var TediousAuthenticationType;
1091
1095
  // Licensed under the MIT license.
1092
1096
  /**
1093
1097
  * Identity type to use in authentication.
1094
- *
1095
- * @beta
1096
1098
  */
1097
1099
  exports.IdentityType = void 0;
1098
1100
  (function (IdentityType) {
@@ -1110,8 +1112,6 @@ exports.IdentityType = void 0;
1110
1112
  const invokeResponseType = "invokeResponse";
1111
1113
  /**
1112
1114
  * Response body returned for a token exchange invoke activity.
1113
- *
1114
- * @beta
1115
1115
  */
1116
1116
  class TokenExchangeInvokeResponse {
1117
1117
  constructor(id, failureDetail) {
@@ -1166,8 +1166,6 @@ class TokenExchangeInvokeResponse {
1166
1166
  * }
1167
1167
  * ]));
1168
1168
  * ```
1169
- *
1170
- * @beta
1171
1169
  */
1172
1170
  class TeamsBotSsoPrompt extends botbuilderDialogs.Dialog {
1173
1171
  /**
@@ -1179,8 +1177,6 @@ class TeamsBotSsoPrompt extends botbuilderDialogs.Dialog {
1179
1177
  *
1180
1178
  * @throws {@link ErrorCode|InvalidParameter} when scopes is not a valid string or string array.
1181
1179
  * @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
1182
- *
1183
- * @beta
1184
1180
  */
1185
1181
  constructor(teamsfx, dialogId, settings) {
1186
1182
  super(dialogId);
@@ -1203,8 +1199,6 @@ class TeamsBotSsoPrompt extends botbuilderDialogs.Dialog {
1203
1199
  * @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
1204
1200
  *
1205
1201
  * @returns A `Promise` representing the asynchronous operation.
1206
- *
1207
- * @beta
1208
1202
  */
1209
1203
  beginDialog(dc) {
1210
1204
  var _a;
@@ -1254,8 +1248,6 @@ class TeamsBotSsoPrompt extends botbuilderDialogs.Dialog {
1254
1248
  *
1255
1249
  * @throws {@link ErrorCode|ChannelNotSupported} when bot channel is not MS Teams.
1256
1250
  * @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
1257
- *
1258
- * @beta
1259
1251
  */
1260
1252
  continueDialog(dc) {
1261
1253
  var _a;
@@ -1308,9 +1300,6 @@ class TeamsBotSsoPrompt extends botbuilderDialogs.Dialog {
1308
1300
  if (!this.teamsfx.hasConfig("tenantId")) {
1309
1301
  missingConfigurations.push("tenantId");
1310
1302
  }
1311
- if (!this.teamsfx.hasConfig("applicationIdUri")) {
1312
- missingConfigurations.push("applicationIdUri");
1313
- }
1314
1303
  if (missingConfigurations.length != 0) {
1315
1304
  const errorMsg = formatString(ErrorMessage.InvalidConfiguration, missingConfigurations.join(", "), "undefined");
1316
1305
  internalLogger.error(errorMsg);
@@ -1363,9 +1352,7 @@ class TeamsBotSsoPrompt extends botbuilderDialogs.Dialog {
1363
1352
  internalLogger.verbose("Sign in link: " + signInLink);
1364
1353
  const tokenExchangeResource = {
1365
1354
  id: uuid.v4(),
1366
- uri: this.teamsfx.getConfig("applicationIdUri").replace(/\/$/, "") + "/access_as_user",
1367
1355
  };
1368
- internalLogger.verbose("Token exchange resource uri: " + tokenExchangeResource.uri);
1369
1356
  return {
1370
1357
  signInLink: signInLink,
1371
1358
  tokenExchangeResource: tokenExchangeResource,
@@ -1466,8 +1453,6 @@ class TeamsBotSsoPrompt extends botbuilderDialogs.Dialog {
1466
1453
  * ```typescript
1467
1454
  * const client = createApiClient("https://my-api-endpoint-base-url", new BasicAuthProvider("xxx","xxx"));
1468
1455
  * ```
1469
- *
1470
- * @beta
1471
1456
  */
1472
1457
  function createApiClient(apiEndpoint, authProvider) {
1473
1458
  // Add a request interceptor
@@ -1485,14 +1470,10 @@ function createApiClient(apiEndpoint, authProvider) {
1485
1470
  // Copyright (c) Microsoft Corporation.
1486
1471
  /**
1487
1472
  * Provider that handles Bearer Token authentication
1488
- *
1489
- * @beta
1490
1473
  */
1491
1474
  class BearerTokenAuthProvider {
1492
1475
  /**
1493
1476
  * @param { () => Promise<string> } getToken - Function that returns the content of bearer token used in http request
1494
- *
1495
- * @beta
1496
1477
  */
1497
1478
  constructor(getToken) {
1498
1479
  this.getToken = getToken;
@@ -1506,8 +1487,6 @@ class BearerTokenAuthProvider {
1506
1487
  * @returns Updated axios request config.
1507
1488
  *
1508
1489
  * @throws {@link ErrorCode|AuthorizationInfoAlreadyExists} - when Authorization header already exists in request configuration.
1509
- *
1510
- * @beta
1511
1490
  */
1512
1491
  AddAuthenticationInfo(config) {
1513
1492
  return tslib.__awaiter(this, void 0, void 0, function* () {
@@ -1527,8 +1506,6 @@ class BearerTokenAuthProvider {
1527
1506
  // Copyright (c) Microsoft Corporation.
1528
1507
  /**
1529
1508
  * Provider that handles Basic authentication
1530
- *
1531
- * @beta
1532
1509
  */
1533
1510
  class BasicAuthProvider {
1534
1511
  /**
@@ -1538,8 +1515,6 @@ class BasicAuthProvider {
1538
1515
  *
1539
1516
  * @throws {@link ErrorCode|InvalidParameter} - when username or password is empty.
1540
1517
  * @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
1541
- *
1542
- * @beta
1543
1518
  */
1544
1519
  constructor(userName, password) {
1545
1520
  if (!userName) {
@@ -1561,8 +1536,6 @@ class BasicAuthProvider {
1561
1536
  *
1562
1537
  * @throws {@link ErrorCode|AuthorizationInfoAlreadyExists} - when Authorization header or auth property already exists in request configuration.
1563
1538
  * @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
1564
- *
1565
- * @beta
1566
1539
  */
1567
1540
  AddAuthenticationInfo(config) {
1568
1541
  return tslib.__awaiter(this, void 0, void 0, function* () {
@@ -1584,8 +1557,6 @@ class BasicAuthProvider {
1584
1557
  // Copyright (c) Microsoft Corporation.
1585
1558
  /**
1586
1559
  * Provider that handles API Key authentication
1587
- *
1588
- * @beta
1589
1560
  */
1590
1561
  class ApiKeyProvider {
1591
1562
  /**
@@ -1596,8 +1567,6 @@ class ApiKeyProvider {
1596
1567
  *
1597
1568
  * @throws {@link ErrorCode|InvalidParameter} - when key name or key value is empty.
1598
1569
  * @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
1599
- *
1600
- * @beta
1601
1570
  */
1602
1571
  constructor(keyName, keyValue, keyLocation) {
1603
1572
  if (!keyName) {
@@ -1620,8 +1589,6 @@ class ApiKeyProvider {
1620
1589
  *
1621
1590
  * @throws {@link ErrorCode|AuthorizationInfoAlreadyExists} - when API key already exists in request header or url query parameter.
1622
1591
  * @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
1623
- *
1624
- * @beta
1625
1592
  */
1626
1593
  AddAuthenticationInfo(config) {
1627
1594
  return tslib.__awaiter(this, void 0, void 0, function* () {
@@ -1639,8 +1606,12 @@ class ApiKeyProvider {
1639
1606
  if (!config.params) {
1640
1607
  config.params = {};
1641
1608
  }
1642
- const url = new URL(config.url, config.baseURL);
1643
- if (config.params[this.keyName] || url.searchParams.has(this.keyName)) {
1609
+ let urlHasDefinedApiKey = false;
1610
+ if (config.url) {
1611
+ const url = new URL(config.url, config.baseURL);
1612
+ urlHasDefinedApiKey = url.searchParams.has(this.keyName);
1613
+ }
1614
+ if (config.params[this.keyName] || urlHasDefinedApiKey) {
1644
1615
  throw new ErrorWithCode(formatString(ErrorMessage.DuplicateApiKeyInQueryParam, this.keyName), exports.ErrorCode.AuthorizationInfoAlreadyExists);
1645
1616
  }
1646
1617
  config.params[this.keyName] = this.keyValue;
@@ -1652,8 +1623,6 @@ class ApiKeyProvider {
1652
1623
  }
1653
1624
  /**
1654
1625
  * Define available location for API Key location
1655
- *
1656
- * @beta
1657
1626
  */
1658
1627
  exports.ApiKeyLocation = void 0;
1659
1628
  (function (ApiKeyLocation) {
@@ -1670,8 +1639,6 @@ exports.ApiKeyLocation = void 0;
1670
1639
  // Copyright (c) Microsoft Corporation.
1671
1640
  /**
1672
1641
  * Provider that handles Certificate authentication
1673
- *
1674
- * @beta
1675
1642
  */
1676
1643
  class CertificateAuthProvider {
1677
1644
  /**
@@ -1679,8 +1646,6 @@ class CertificateAuthProvider {
1679
1646
  * @param { SecureContextOptions } certOption - information about the cert used in http requests
1680
1647
  *
1681
1648
  * @throws {@link ErrorCode|InvalidParameter} - when cert option is empty.
1682
- *
1683
- * @beta
1684
1649
  */
1685
1650
  constructor(certOption) {
1686
1651
  if (certOption && Object.keys(certOption).length !== 0) {
@@ -1699,8 +1664,6 @@ class CertificateAuthProvider {
1699
1664
  * @returns Updated axios request config.
1700
1665
  *
1701
1666
  * @throws {@link ErrorCode|InvalidParameter} - when custom httpsAgent in the request has duplicate properties with certOption provided in constructor.
1702
- *
1703
- * @beta
1704
1667
  */
1705
1668
  AddAuthenticationInfo(config) {
1706
1669
  return tslib.__awaiter(this, void 0, void 0, function* () {
@@ -1786,7 +1749,6 @@ const ReservedKey = new Set([
1786
1749
  ]);
1787
1750
  /**
1788
1751
  * A class providing credential and configuration.
1789
- * @beta
1790
1752
  */
1791
1753
  class TeamsFx {
1792
1754
  /**
@@ -1796,16 +1758,15 @@ class TeamsFx {
1796
1758
  * @param customConfig - key/value pairs of customized configuration that overrides default ones.
1797
1759
  *
1798
1760
  * @throws {@link ErrorCode|IdentityTypeNotSupported} when setting app identity in browser.
1799
- *
1800
- * @beta
1801
1761
  */
1802
1762
  constructor(identityType, customConfig) {
1803
1763
  this.identityType = identityType !== null && identityType !== void 0 ? identityType : exports.IdentityType.User;
1804
1764
  this.configuration = new Map();
1805
1765
  this.loadFromEnv();
1806
1766
  if (customConfig) {
1807
- for (const key of Object.keys(customConfig)) {
1808
- const value = customConfig[key];
1767
+ const myConfig = Object.assign({}, customConfig);
1768
+ for (const key of Object.keys(myConfig)) {
1769
+ const value = myConfig[key];
1809
1770
  if (value) {
1810
1771
  this.configuration.set(key, value);
1811
1772
  }
@@ -1816,7 +1777,6 @@ class TeamsFx {
1816
1777
  * Identity type set by user.
1817
1778
  *
1818
1779
  * @returns identity type.
1819
- * @beta
1820
1780
  */
1821
1781
  getIdentityType() {
1822
1782
  return this.identityType;
@@ -1829,7 +1789,6 @@ class TeamsFx {
1829
1789
  * identity is chose, will return {@link AppCredential}.
1830
1790
  *
1831
1791
  * @returns instance implements TokenCredential interface.
1832
- * @beta
1833
1792
  */
1834
1793
  getCredential() {
1835
1794
  if (this.identityType === exports.IdentityType.User) {
@@ -1849,10 +1808,10 @@ class TeamsFx {
1849
1808
  }
1850
1809
  /**
1851
1810
  * Get user information.
1811
+ * @param {string[]} resources - The optional list of resources for full trust Teams apps.
1852
1812
  * @returns UserInfo object.
1853
- * @beta
1854
1813
  */
1855
- getUserInfo() {
1814
+ getUserInfo(resources) {
1856
1815
  return tslib.__awaiter(this, void 0, void 0, function* () {
1857
1816
  if (this.identityType !== exports.IdentityType.User) {
1858
1817
  const errorMsg = formatString(ErrorMessage.IdentityTypeNotSupported, this.identityType.toString(), "TeamsFx");
@@ -1876,15 +1835,14 @@ class TeamsFx {
1876
1835
  * await teamsfx.login("https://graph.microsoft.com/User.Read Calendars.Read"); // multiple scopes using string
1877
1836
  * ```
1878
1837
  * @param scopes - The list of scopes for which the token will have access, before that, we will request user to consent.
1838
+ * @param {string[]} resources - The optional list of resources for full trust Teams apps.
1879
1839
  *
1880
1840
  * @throws {@link ErrorCode|InternalError} when failed to login with unknown error.
1881
1841
  * @throws {@link ErrorCode|ConsentFailed} when user canceled or failed to consent.
1882
1842
  * @throws {@link ErrorCode|InvalidParameter} when scopes is not a valid string or string array.
1883
1843
  * @throws {@link ErrorCode|RuntimeNotSupported} when runtime is nodeJS.
1884
- *
1885
- * @beta
1886
1844
  */
1887
- login(scopes) {
1845
+ login(scopes, resources) {
1888
1846
  return tslib.__awaiter(this, void 0, void 0, function* () {
1889
1847
  throw new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "login"), exports.ErrorCode.RuntimeNotSupported);
1890
1848
  });
@@ -1893,7 +1851,6 @@ class TeamsFx {
1893
1851
  * Set SSO token when using user identity in NodeJS.
1894
1852
  * @param {string} ssoToken - used for on behalf of user flow.
1895
1853
  * @returns self instance.
1896
- * @beta
1897
1854
  */
1898
1855
  setSsoToken(ssoToken) {
1899
1856
  if (this.identityType !== exports.IdentityType.User) {
@@ -1906,7 +1863,6 @@ class TeamsFx {
1906
1863
  * Usually used by service plugins to retrieve specific config
1907
1864
  * @param {string} key - configuration key.
1908
1865
  * @returns value in configuration.
1909
- * @beta
1910
1866
  */
1911
1867
  getConfig(key) {
1912
1868
  const value = this.configuration.get(key);
@@ -1921,7 +1877,6 @@ class TeamsFx {
1921
1877
  * Check the value of specific key.
1922
1878
  * @param {string} key - configuration key.
1923
1879
  * @returns true if corresponding value is not empty string.
1924
- * @beta
1925
1880
  */
1926
1881
  hasConfig(key) {
1927
1882
  const value = this.configuration.get(key);
@@ -1930,7 +1885,6 @@ class TeamsFx {
1930
1885
  /**
1931
1886
  * Get all configurations.
1932
1887
  * @returns key value mappings.
1933
- * @beta
1934
1888
  */
1935
1889
  getConfigs() {
1936
1890
  const config = {};
@@ -1972,166 +1926,385 @@ class TeamsFx {
1972
1926
  // Copyright (c) Microsoft Corporation.
1973
1927
  // Licensed under the MIT license.
1974
1928
  /**
1975
- * @internal
1929
+ * The target type where the notification will be sent to.
1930
+ *
1931
+ * @remarks
1932
+ * - "Channel" means to a team channel. (By default, notification to a team will be sent to its "General" channel.)
1933
+ * - "Group" means to a group chat.
1934
+ * - "Person" means to a personal chat.
1976
1935
  */
1977
- function cloneConversation(conversation) {
1978
- return JSON.parse(JSON.stringify(conversation));
1979
- }
1936
+ exports.NotificationTargetType = void 0;
1937
+ (function (NotificationTargetType) {
1938
+ /**
1939
+ * The notification will be sent to a team channel.
1940
+ * (By default, notification to a team will be sent to its "General" channel.)
1941
+ */
1942
+ NotificationTargetType["Channel"] = "Channel";
1943
+ /**
1944
+ * The notification will be sent to a group chat.
1945
+ */
1946
+ NotificationTargetType["Group"] = "Group";
1947
+ /**
1948
+ * The notification will be sent to a personal chat.
1949
+ */
1950
+ NotificationTargetType["Person"] = "Person";
1951
+ })(exports.NotificationTargetType || (exports.NotificationTargetType = {}));
1952
+ /**
1953
+ * Options used to control how the response card will be sent to users.
1954
+ */
1955
+ exports.AdaptiveCardResponse = void 0;
1956
+ (function (AdaptiveCardResponse) {
1957
+ /**
1958
+ * The response card will be replaced the current one for the interactor who trigger the action.
1959
+ */
1960
+ AdaptiveCardResponse[AdaptiveCardResponse["ReplaceForInteractor"] = 0] = "ReplaceForInteractor";
1961
+ /**
1962
+ * The response card will be replaced the current one for all users in the chat.
1963
+ */
1964
+ AdaptiveCardResponse[AdaptiveCardResponse["ReplaceForAll"] = 1] = "ReplaceForAll";
1965
+ /**
1966
+ * The response card will be sent as a new message for all users in the chat.
1967
+ */
1968
+ AdaptiveCardResponse[AdaptiveCardResponse["NewForAll"] = 2] = "NewForAll";
1969
+ })(exports.AdaptiveCardResponse || (exports.AdaptiveCardResponse = {}));
1970
+ /**
1971
+ * Status code for an `application/vnd.microsoft.error` invoke response.
1972
+ */
1973
+ exports.InvokeResponseErrorCode = void 0;
1974
+ (function (InvokeResponseErrorCode) {
1975
+ /**
1976
+ * Invalid request.
1977
+ */
1978
+ InvokeResponseErrorCode[InvokeResponseErrorCode["BadRequest"] = 400] = "BadRequest";
1979
+ /**
1980
+ * Internal server error.
1981
+ */
1982
+ InvokeResponseErrorCode[InvokeResponseErrorCode["InternalServerError"] = 500] = "InternalServerError";
1983
+ })(exports.InvokeResponseErrorCode || (exports.InvokeResponseErrorCode = {}));
1984
+
1980
1985
  /**
1986
+ * Available response type for an adaptive card invoke response.
1981
1987
  * @internal
1982
1988
  */
1983
- function getTargetType(conversationReference) {
1984
- var _a;
1985
- const conversationType = (_a = conversationReference.conversation) === null || _a === void 0 ? void 0 : _a.conversationType;
1986
- if (conversationType === "personal") {
1987
- return "Person";
1989
+ var InvokeResponseType;
1990
+ (function (InvokeResponseType) {
1991
+ InvokeResponseType["AdaptiveCard"] = "application/vnd.microsoft.card.adaptive";
1992
+ InvokeResponseType["Message"] = "application/vnd.microsoft.activity.message";
1993
+ InvokeResponseType["Error"] = "application/vnd.microsoft.error";
1994
+ })(InvokeResponseType || (InvokeResponseType = {}));
1995
+ /**
1996
+ * Provides methods for formatting various invoke responses a bot can send to respond to an invoke request.
1997
+ *
1998
+ * @remarks
1999
+ * All of these functions return an {@link InvokeResponse} object, which can be
2000
+ * passed as input to generate a new `invokeResponse` activity.
2001
+ *
2002
+ * This example sends an invoke response that contains an adaptive card.
2003
+ *
2004
+ * ```typescript
2005
+ *
2006
+ * const myCard = {
2007
+ * type: "AdaptiveCard",
2008
+ * body: [
2009
+ * {
2010
+ * "type": "TextBlock",
2011
+ * "text": "This is a sample card"
2012
+ * }],
2013
+ * $schema: "http://adaptivecards.io/schemas/adaptive-card.json",
2014
+ * version: "1.4"
2015
+ * };
2016
+ *
2017
+ * const invokeResponse = InvokeResponseFactory.adaptiveCard(myCard);
2018
+ * await context.sendActivity({
2019
+ * type: ActivityTypes.InvokeResponse,
2020
+ * value: invokeResponse,
2021
+ * });
2022
+ * ```
2023
+ */
2024
+ class InvokeResponseFactory {
2025
+ /**
2026
+ * Create an invoke response from a text message.
2027
+ * The type of the invoke response is `application/vnd.microsoft.activity.message`
2028
+ * indicates the request was successfully processed.
2029
+ *
2030
+ * @param message A text message included in a invoke response.
2031
+ *
2032
+ * @returns {InvokeResponse} An InvokeResponse object.
2033
+ */
2034
+ static textMessage(message) {
2035
+ if (!message) {
2036
+ throw new Error("The text message cannot be null or empty");
2037
+ }
2038
+ return {
2039
+ status: botbuilder.StatusCodes.OK,
2040
+ body: {
2041
+ statusCode: botbuilder.StatusCodes.OK,
2042
+ type: InvokeResponseType.Message,
2043
+ value: message,
2044
+ },
2045
+ };
1988
2046
  }
1989
- else if (conversationType === "groupChat") {
1990
- return "Group";
2047
+ /**
2048
+ * Create an invoke response from an adaptive card.
2049
+ *
2050
+ * The type of the invoke response is `application/vnd.microsoft.card.adaptive` indicates
2051
+ * the request was successfully processed, and the response includes an adaptive card
2052
+ * that the client should display in place of the current one.
2053
+ *
2054
+ * @param card The adaptive card JSON payload.
2055
+ *
2056
+ * @returns {InvokeResponse} An InvokeResponse object.
2057
+ */
2058
+ static adaptiveCard(card) {
2059
+ if (!card) {
2060
+ throw new Error("The adaptive card content cannot be null or undefined");
2061
+ }
2062
+ return {
2063
+ status: botbuilder.StatusCodes.OK,
2064
+ body: {
2065
+ statusCode: botbuilder.StatusCodes.OK,
2066
+ type: InvokeResponseType.AdaptiveCard,
2067
+ value: card,
2068
+ },
2069
+ };
1991
2070
  }
1992
- else if (conversationType === "channel") {
1993
- return "Channel";
2071
+ /**
2072
+ * Create an invoke response with error code and message.
2073
+ *
2074
+ * The type of the invoke response is `application/vnd.microsoft.error` indicates
2075
+ * the request was failed to processed.
2076
+ *
2077
+ * @param errorCode The status code indicates error, available values:
2078
+ * - 400 (BadRequest): indicate the incoming request was invalid.
2079
+ * - 500 (InternalServerError): indicate an unexpected error occurred.
2080
+ * @param errorMessage The error message.
2081
+ *
2082
+ * @returns {InvokeResponse} An InvokeResponse object.
2083
+ */
2084
+ static errorResponse(errorCode, errorMessage) {
2085
+ return {
2086
+ status: botbuilder.StatusCodes.OK,
2087
+ body: {
2088
+ statusCode: errorCode,
2089
+ type: InvokeResponseType.Error,
2090
+ value: {
2091
+ code: errorCode.toString(),
2092
+ message: errorMessage,
2093
+ },
2094
+ },
2095
+ };
1994
2096
  }
1995
- else {
1996
- return undefined;
2097
+ /**
2098
+ * Create an invoke response with status code and response value.
2099
+ * @param statusCode The status code.
2100
+ * @param body The value of the response body.
2101
+ *
2102
+ * @returns {InvokeResponse} An InvokeResponse object.
2103
+ */
2104
+ static createInvokeResponse(statusCode, body) {
2105
+ return {
2106
+ status: statusCode,
2107
+ body: body,
2108
+ };
1997
2109
  }
1998
- }
2110
+ }
2111
+
1999
2112
  /**
2000
2113
  * @internal
2001
2114
  */
2002
- function getTeamsBotInstallationId(context) {
2003
- var _a, _b, _c, _d;
2004
- return (_d = (_c = (_b = (_a = context.activity) === null || _a === void 0 ? void 0 : _a.channelData) === null || _b === void 0 ? void 0 : _b.team) === null || _c === void 0 ? void 0 : _c.id) !== null && _d !== void 0 ? _d : context.activity.conversation.id;
2115
+ class CardActionMiddleware {
2116
+ constructor(handlers) {
2117
+ this.actionHandlers = [];
2118
+ this.defaultMessage = "Your response was sent to the app";
2119
+ if (handlers && handlers.length > 0) {
2120
+ this.actionHandlers.push(...handlers);
2121
+ }
2122
+ }
2123
+ onTurn(context, next) {
2124
+ var _a, _b, _c;
2125
+ return tslib.__awaiter(this, void 0, void 0, function* () {
2126
+ if (context.activity.name === "adaptiveCard/action") {
2127
+ const action = context.activity.value.action;
2128
+ const actionVerb = action.verb;
2129
+ for (const handler of this.actionHandlers) {
2130
+ if (((_a = handler.triggerVerb) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === (actionVerb === null || actionVerb === void 0 ? void 0 : actionVerb.toLowerCase())) {
2131
+ let response;
2132
+ try {
2133
+ response = yield handler.handleActionInvoked(context, action.data);
2134
+ }
2135
+ catch (error) {
2136
+ const errorResponse = InvokeResponseFactory.errorResponse(exports.InvokeResponseErrorCode.InternalServerError, error.message);
2137
+ yield this.sendInvokeResponse(context, errorResponse);
2138
+ throw error;
2139
+ }
2140
+ const responseType = (_b = response.body) === null || _b === void 0 ? void 0 : _b.type;
2141
+ switch (responseType) {
2142
+ case InvokeResponseType.AdaptiveCard:
2143
+ const card = (_c = response.body) === null || _c === void 0 ? void 0 : _c.value;
2144
+ if (!card) {
2145
+ const errorMessage = "Adaptive card content cannot be found in the response body";
2146
+ yield this.sendInvokeResponse(context, InvokeResponseFactory.errorResponse(exports.InvokeResponseErrorCode.InternalServerError, errorMessage));
2147
+ throw new Error(errorMessage);
2148
+ }
2149
+ if (card.refresh && handler.adaptiveCardResponse !== exports.AdaptiveCardResponse.NewForAll) {
2150
+ // Card won't be refreshed with AdaptiveCardResponse.ReplaceForInteractor.
2151
+ // So set to AdaptiveCardResponse.ReplaceForAll here.
2152
+ handler.adaptiveCardResponse = exports.AdaptiveCardResponse.ReplaceForAll;
2153
+ }
2154
+ const activity = botbuilder.MessageFactory.attachment(botbuilder.CardFactory.adaptiveCard(card));
2155
+ if (handler.adaptiveCardResponse === exports.AdaptiveCardResponse.NewForAll) {
2156
+ yield this.sendInvokeResponse(context, InvokeResponseFactory.textMessage(this.defaultMessage));
2157
+ yield context.sendActivity(activity);
2158
+ }
2159
+ else if (handler.adaptiveCardResponse === exports.AdaptiveCardResponse.ReplaceForAll) {
2160
+ activity.id = context.activity.replyToId;
2161
+ yield context.updateActivity(activity);
2162
+ yield this.sendInvokeResponse(context, response);
2163
+ }
2164
+ else {
2165
+ yield this.sendInvokeResponse(context, response);
2166
+ }
2167
+ break;
2168
+ case InvokeResponseType.Message:
2169
+ case InvokeResponseType.Error:
2170
+ default:
2171
+ yield this.sendInvokeResponse(context, response);
2172
+ break;
2173
+ }
2174
+ break;
2175
+ }
2176
+ }
2177
+ }
2178
+ yield next();
2179
+ });
2180
+ }
2181
+ sendInvokeResponse(context, response) {
2182
+ return tslib.__awaiter(this, void 0, void 0, function* () {
2183
+ yield context.sendActivity({
2184
+ type: botbuilder.ActivityTypes.InvokeResponse,
2185
+ value: response,
2186
+ });
2187
+ });
2188
+ }
2005
2189
  }
2006
2190
 
2007
- // Copyright (c) Microsoft Corporation.
2008
2191
  /**
2009
- * @internal
2192
+ * A card action bot to respond to adaptive card universal actions.
2010
2193
  */
2011
- var ActivityType;
2012
- (function (ActivityType) {
2013
- ActivityType[ActivityType["CurrentBotInstalled"] = 0] = "CurrentBotInstalled";
2014
- ActivityType[ActivityType["CurrentBotMessaged"] = 1] = "CurrentBotMessaged";
2015
- ActivityType[ActivityType["CurrentBotUninstalled"] = 2] = "CurrentBotUninstalled";
2016
- ActivityType[ActivityType["TeamDeleted"] = 3] = "TeamDeleted";
2017
- ActivityType[ActivityType["TeamRestored"] = 4] = "TeamRestored";
2018
- ActivityType[ActivityType["Unknown"] = 5] = "Unknown";
2019
- })(ActivityType || (ActivityType = {}));
2194
+ class CardActionBot {
2195
+ /**
2196
+ * Creates a new instance of the `CardActionBot`.
2197
+ *
2198
+ * @param adapter The bound `BotFrameworkAdapter`.
2199
+ * @param options - initialize options
2200
+ */
2201
+ constructor(adapter, options) {
2202
+ this.middleware = new CardActionMiddleware(options === null || options === void 0 ? void 0 : options.actions);
2203
+ this.adapter = adapter.use(this.middleware);
2204
+ }
2205
+ /**
2206
+ * Registers a card action handler to the bot.
2207
+ * @param actionHandler A card action handler to be registered.
2208
+ */
2209
+ registerHandler(actionHandler) {
2210
+ if (actionHandler) {
2211
+ this.middleware.actionHandlers.push(actionHandler);
2212
+ }
2213
+ }
2214
+ /**
2215
+ * Registers card action handlers to the bot.
2216
+ * @param actionHandlers A set of card action handlers to be registered.
2217
+ */
2218
+ registerHandlers(actionHandlers) {
2219
+ if (actionHandlers) {
2220
+ this.middleware.actionHandlers.push(...actionHandlers);
2221
+ }
2222
+ }
2223
+ }
2224
+
2225
+ // Copyright (c) Microsoft Corporation.
2020
2226
  /**
2021
2227
  * @internal
2022
2228
  */
2023
- class NotificationMiddleware {
2024
- constructor(options) {
2025
- this.conversationReferenceStore = options.conversationReferenceStore;
2229
+ class CommandResponseMiddleware {
2230
+ constructor(handlers, ssoHandlers, activityHandler) {
2231
+ this.commandHandlers = [];
2232
+ this.ssoCommandHandlers = [];
2233
+ handlers = handlers !== null && handlers !== void 0 ? handlers : [];
2234
+ ssoHandlers = ssoHandlers !== null && ssoHandlers !== void 0 ? ssoHandlers : [];
2235
+ this.hasSsoCommand = ssoHandlers.length > 0;
2236
+ this.ssoActivityHandler = activityHandler;
2237
+ if (this.hasSsoCommand && !this.ssoActivityHandler) {
2238
+ internalLogger.error(ErrorMessage.SsoActivityHandlerIsNull);
2239
+ throw new ErrorWithCode(ErrorMessage.SsoActivityHandlerIsNull, exports.ErrorCode.SsoActivityHandlerIsUndefined);
2240
+ }
2241
+ this.commandHandlers.push(...handlers);
2242
+ for (const ssoHandler of ssoHandlers) {
2243
+ this.addSsoCommand(ssoHandler);
2244
+ }
2245
+ }
2246
+ addSsoCommand(ssoHandler) {
2247
+ var _a;
2248
+ (_a = this.ssoActivityHandler) === null || _a === void 0 ? void 0 : _a.addCommand((context, tokenResponse, message) => tslib.__awaiter(this, void 0, void 0, function* () {
2249
+ const matchResult = this.shouldTrigger(ssoHandler.triggerPatterns, message.text);
2250
+ message.matches = Array.isArray(matchResult) ? matchResult : void 0;
2251
+ const response = yield ssoHandler.handleCommandReceived(context, message, tokenResponse);
2252
+ yield this.processResponse(context, response);
2253
+ }), ssoHandler.triggerPatterns);
2254
+ this.ssoCommandHandlers.push(ssoHandler);
2255
+ this.hasSsoCommand = true;
2026
2256
  }
2027
2257
  onTurn(context, next) {
2258
+ var _a, _b;
2028
2259
  return tslib.__awaiter(this, void 0, void 0, function* () {
2029
- const type = this.classifyActivity(context.activity);
2030
- switch (type) {
2031
- case ActivityType.CurrentBotInstalled:
2032
- case ActivityType.TeamRestored: {
2033
- const reference = botbuilder.TurnContext.getConversationReference(context.activity);
2034
- yield this.conversationReferenceStore.set(reference);
2035
- break;
2260
+ if (context.activity.type === botbuilder.ActivityTypes.Message) {
2261
+ // Invoke corresponding command handler for the command response
2262
+ const commandText = this.getActivityText(context.activity);
2263
+ let alreadyProcessed = false;
2264
+ for (const handler of this.commandHandlers) {
2265
+ const matchResult = this.shouldTrigger(handler.triggerPatterns, commandText);
2266
+ // It is important to note that the command bot will stop processing handlers
2267
+ // when the first command handler is matched.
2268
+ if (!!matchResult) {
2269
+ const message = {
2270
+ text: commandText,
2271
+ };
2272
+ message.matches = Array.isArray(matchResult) ? matchResult : void 0;
2273
+ const response = yield handler.handleCommandReceived(context, message);
2274
+ yield this.processResponse(context, response);
2275
+ alreadyProcessed = true;
2276
+ break;
2277
+ }
2036
2278
  }
2037
- case ActivityType.CurrentBotMessaged: {
2038
- yield this.tryAddMessagedReference(context);
2039
- break;
2279
+ if (!alreadyProcessed) {
2280
+ for (const handler of this.ssoCommandHandlers) {
2281
+ const matchResult = this.shouldTrigger(handler.triggerPatterns, commandText);
2282
+ if (!!matchResult) {
2283
+ yield ((_a = this.ssoActivityHandler) === null || _a === void 0 ? void 0 : _a.run(context));
2284
+ break;
2285
+ }
2286
+ }
2040
2287
  }
2041
- case ActivityType.CurrentBotUninstalled:
2042
- case ActivityType.TeamDeleted: {
2043
- const reference = botbuilder.TurnContext.getConversationReference(context.activity);
2044
- yield this.conversationReferenceStore.delete(reference);
2045
- break;
2288
+ }
2289
+ else {
2290
+ if (this.hasSsoCommand) {
2291
+ yield ((_b = this.ssoActivityHandler) === null || _b === void 0 ? void 0 : _b.run(context));
2046
2292
  }
2047
2293
  }
2048
2294
  yield next();
2049
2295
  });
2050
2296
  }
2051
- classifyActivity(activity) {
2052
- var _a, _b;
2053
- const activityType = activity.type;
2054
- if (activityType === "installationUpdate") {
2055
- const action = (_a = activity.action) === null || _a === void 0 ? void 0 : _a.toLowerCase();
2056
- if (action === "add") {
2057
- return ActivityType.CurrentBotInstalled;
2297
+ processResponse(context, response) {
2298
+ return tslib.__awaiter(this, void 0, void 0, function* () {
2299
+ if (typeof response === "string") {
2300
+ yield context.sendActivity(response);
2058
2301
  }
2059
2302
  else {
2060
- return ActivityType.CurrentBotUninstalled;
2061
- }
2062
- }
2063
- else if (activityType === "conversationUpdate") {
2064
- const eventType = (_b = activity.channelData) === null || _b === void 0 ? void 0 : _b.eventType;
2065
- if (eventType === "teamDeleted") {
2066
- return ActivityType.TeamDeleted;
2067
- }
2068
- else if (eventType === "teamRestored") {
2069
- return ActivityType.TeamRestored;
2303
+ const replyActivity = response;
2304
+ if (replyActivity) {
2305
+ yield context.sendActivity(replyActivity);
2306
+ }
2070
2307
  }
2071
- }
2072
- else if (activityType === "message") {
2073
- return ActivityType.CurrentBotMessaged;
2074
- }
2075
- return ActivityType.Unknown;
2076
- }
2077
- tryAddMessagedReference(context) {
2078
- var _a, _b, _c, _d;
2079
- return tslib.__awaiter(this, void 0, void 0, function* () {
2080
- const reference = botbuilder.TurnContext.getConversationReference(context.activity);
2081
- const conversationType = (_a = reference === null || reference === void 0 ? void 0 : reference.conversation) === null || _a === void 0 ? void 0 : _a.conversationType;
2082
- if (conversationType === "personal" || conversationType === "groupChat") {
2083
- if (!(yield this.conversationReferenceStore.check(reference))) {
2084
- yield this.conversationReferenceStore.set(reference);
2085
- }
2086
- }
2087
- else if (conversationType === "channel") {
2088
- const teamId = (_d = (_c = (_b = context.activity) === null || _b === void 0 ? void 0 : _b.channelData) === null || _c === void 0 ? void 0 : _c.team) === null || _d === void 0 ? void 0 : _d.id;
2089
- if (teamId !== undefined) {
2090
- const teamReference = cloneConversation(reference);
2091
- teamReference.conversation.id = teamId;
2092
- if (!(yield this.conversationReferenceStore.check(teamReference))) {
2093
- yield this.conversationReferenceStore.set(teamReference);
2094
- }
2095
- }
2096
- }
2097
- });
2098
- }
2099
- }
2100
- class CommandResponseMiddleware {
2101
- constructor(handlers) {
2102
- this.commandHandlers = [];
2103
- if (handlers && handlers.length > 0) {
2104
- this.commandHandlers.push(...handlers);
2105
- }
2106
- }
2107
- onTurn(context, next) {
2108
- return tslib.__awaiter(this, void 0, void 0, function* () {
2109
- if (context.activity.type === botbuilder.ActivityTypes.Message) {
2110
- // Invoke corresponding command handler for the command response
2111
- const commandText = this.getActivityText(context.activity);
2112
- const message = {
2113
- text: commandText,
2114
- };
2115
- for (const handler of this.commandHandlers) {
2116
- const matchResult = this.shouldTrigger(handler.triggerPatterns, commandText);
2117
- // It is important to note that the command bot will stop processing handlers
2118
- // when the first command handler is matched.
2119
- if (!!matchResult) {
2120
- message.matches = Array.isArray(matchResult) ? matchResult : void 0;
2121
- const response = yield handler.handleCommandReceived(context, message);
2122
- if (typeof response === "string") {
2123
- yield context.sendActivity(response);
2124
- }
2125
- else {
2126
- const replyActivity = response;
2127
- if (replyActivity) {
2128
- yield context.sendActivity(replyActivity);
2129
- }
2130
- }
2131
- }
2132
- }
2133
- }
2134
- yield next();
2135
2308
  });
2136
2309
  }
2137
2310
  matchPattern(pattern, text) {
@@ -2175,8 +2348,6 @@ class CommandResponseMiddleware {
2175
2348
  *
2176
2349
  * @remarks
2177
2350
  * Ensure each command should ONLY be registered with the command once, otherwise it'll cause unexpected behavior if you register the same command more than once.
2178
- *
2179
- * @beta
2180
2351
  */
2181
2352
  class CommandBot {
2182
2353
  /**
@@ -2184,19 +2355,16 @@ class CommandBot {
2184
2355
  *
2185
2356
  * @param adapter The bound `BotFrameworkAdapter`.
2186
2357
  * @param options - initialize options
2187
- *
2188
- * @beta
2189
2358
  */
2190
- constructor(adapter, options) {
2191
- this.middleware = new CommandResponseMiddleware(options === null || options === void 0 ? void 0 : options.commands);
2359
+ constructor(adapter, options, ssoCommandActivityHandler, ssoConfig) {
2360
+ this.ssoConfig = ssoConfig;
2361
+ this.middleware = new CommandResponseMiddleware(options === null || options === void 0 ? void 0 : options.commands, options === null || options === void 0 ? void 0 : options.ssoCommands, ssoCommandActivityHandler);
2192
2362
  this.adapter = adapter.use(this.middleware);
2193
2363
  }
2194
2364
  /**
2195
2365
  * Registers a command into the command bot.
2196
2366
  *
2197
- * @param command The command to registered.
2198
- *
2199
- * @beta
2367
+ * @param command The command to register.
2200
2368
  */
2201
2369
  registerCommand(command) {
2202
2370
  if (command) {
@@ -2206,15 +2374,169 @@ class CommandBot {
2206
2374
  /**
2207
2375
  * Registers commands into the command bot.
2208
2376
  *
2209
- * @param commands The command to registered.
2210
- *
2211
- * @beta
2377
+ * @param commands The commands to register.
2212
2378
  */
2213
2379
  registerCommands(commands) {
2214
2380
  if (commands) {
2215
2381
  this.middleware.commandHandlers.push(...commands);
2216
2382
  }
2217
2383
  }
2384
+ /**
2385
+ * Registers a sso command into the command bot.
2386
+ *
2387
+ * @param command The command to register.
2388
+ */
2389
+ registerSsoCommand(ssoCommand) {
2390
+ this.validateSsoActivityHandler();
2391
+ this.middleware.addSsoCommand(ssoCommand);
2392
+ }
2393
+ /**
2394
+ * Registers commands into the command bot.
2395
+ *
2396
+ * @param commands The commands to register.
2397
+ */
2398
+ registerSsoCommands(ssoCommands) {
2399
+ if (ssoCommands.length > 0) {
2400
+ this.validateSsoActivityHandler();
2401
+ for (const ssoCommand of ssoCommands) {
2402
+ this.middleware.addSsoCommand(ssoCommand);
2403
+ }
2404
+ }
2405
+ }
2406
+ validateSsoActivityHandler() {
2407
+ if (!this.middleware.ssoActivityHandler) {
2408
+ internalLogger.error(ErrorMessage.SsoActivityHandlerIsNull);
2409
+ throw new ErrorWithCode(ErrorMessage.SsoActivityHandlerIsNull, exports.ErrorCode.SsoActivityHandlerIsUndefined);
2410
+ }
2411
+ }
2412
+ }
2413
+
2414
+ // Copyright (c) Microsoft Corporation.
2415
+ /**
2416
+ * @internal
2417
+ */
2418
+ function cloneConversation(conversation) {
2419
+ return JSON.parse(JSON.stringify(conversation));
2420
+ }
2421
+ /**
2422
+ * @internal
2423
+ */
2424
+ function getTargetType(conversationReference) {
2425
+ var _a;
2426
+ const conversationType = (_a = conversationReference.conversation) === null || _a === void 0 ? void 0 : _a.conversationType;
2427
+ if (conversationType === "personal") {
2428
+ return exports.NotificationTargetType.Person;
2429
+ }
2430
+ else if (conversationType === "groupChat") {
2431
+ return exports.NotificationTargetType.Group;
2432
+ }
2433
+ else if (conversationType === "channel") {
2434
+ return exports.NotificationTargetType.Channel;
2435
+ }
2436
+ else {
2437
+ return undefined;
2438
+ }
2439
+ }
2440
+ /**
2441
+ * @internal
2442
+ */
2443
+ function getTeamsBotInstallationId(context) {
2444
+ var _a, _b, _c, _d;
2445
+ return (_d = (_c = (_b = (_a = context.activity) === null || _a === void 0 ? void 0 : _a.channelData) === null || _b === void 0 ? void 0 : _b.team) === null || _c === void 0 ? void 0 : _c.id) !== null && _d !== void 0 ? _d : context.activity.conversation.id;
2446
+ }
2447
+
2448
+ // Copyright (c) Microsoft Corporation.
2449
+ /**
2450
+ * @internal
2451
+ */
2452
+ var ActivityType;
2453
+ (function (ActivityType) {
2454
+ ActivityType[ActivityType["CurrentBotInstalled"] = 0] = "CurrentBotInstalled";
2455
+ ActivityType[ActivityType["CurrentBotMessaged"] = 1] = "CurrentBotMessaged";
2456
+ ActivityType[ActivityType["CurrentBotUninstalled"] = 2] = "CurrentBotUninstalled";
2457
+ ActivityType[ActivityType["TeamDeleted"] = 3] = "TeamDeleted";
2458
+ ActivityType[ActivityType["TeamRestored"] = 4] = "TeamRestored";
2459
+ ActivityType[ActivityType["Unknown"] = 5] = "Unknown";
2460
+ })(ActivityType || (ActivityType = {}));
2461
+ /**
2462
+ * @internal
2463
+ */
2464
+ class NotificationMiddleware {
2465
+ constructor(options) {
2466
+ this.conversationReferenceStore = options.conversationReferenceStore;
2467
+ }
2468
+ onTurn(context, next) {
2469
+ return tslib.__awaiter(this, void 0, void 0, function* () {
2470
+ const type = this.classifyActivity(context.activity);
2471
+ switch (type) {
2472
+ case ActivityType.CurrentBotInstalled:
2473
+ case ActivityType.TeamRestored: {
2474
+ const reference = botbuilder.TurnContext.getConversationReference(context.activity);
2475
+ yield this.conversationReferenceStore.set(reference);
2476
+ break;
2477
+ }
2478
+ case ActivityType.CurrentBotMessaged: {
2479
+ yield this.tryAddMessagedReference(context);
2480
+ break;
2481
+ }
2482
+ case ActivityType.CurrentBotUninstalled:
2483
+ case ActivityType.TeamDeleted: {
2484
+ const reference = botbuilder.TurnContext.getConversationReference(context.activity);
2485
+ yield this.conversationReferenceStore.delete(reference);
2486
+ break;
2487
+ }
2488
+ }
2489
+ yield next();
2490
+ });
2491
+ }
2492
+ classifyActivity(activity) {
2493
+ var _a, _b;
2494
+ const activityType = activity.type;
2495
+ if (activityType === "installationUpdate") {
2496
+ const action = (_a = activity.action) === null || _a === void 0 ? void 0 : _a.toLowerCase();
2497
+ if (action === "add") {
2498
+ return ActivityType.CurrentBotInstalled;
2499
+ }
2500
+ else {
2501
+ return ActivityType.CurrentBotUninstalled;
2502
+ }
2503
+ }
2504
+ else if (activityType === "conversationUpdate") {
2505
+ const eventType = (_b = activity.channelData) === null || _b === void 0 ? void 0 : _b.eventType;
2506
+ if (eventType === "teamDeleted") {
2507
+ return ActivityType.TeamDeleted;
2508
+ }
2509
+ else if (eventType === "teamRestored") {
2510
+ return ActivityType.TeamRestored;
2511
+ }
2512
+ }
2513
+ else if (activityType === "message") {
2514
+ return ActivityType.CurrentBotMessaged;
2515
+ }
2516
+ return ActivityType.Unknown;
2517
+ }
2518
+ tryAddMessagedReference(context) {
2519
+ var _a, _b, _c, _d;
2520
+ return tslib.__awaiter(this, void 0, void 0, function* () {
2521
+ const reference = botbuilder.TurnContext.getConversationReference(context.activity);
2522
+ const conversationType = (_a = reference === null || reference === void 0 ? void 0 : reference.conversation) === null || _a === void 0 ? void 0 : _a.conversationType;
2523
+ if (conversationType === "personal" || conversationType === "groupChat") {
2524
+ if (!(yield this.conversationReferenceStore.check(reference))) {
2525
+ yield this.conversationReferenceStore.set(reference);
2526
+ }
2527
+ }
2528
+ else if (conversationType === "channel") {
2529
+ const teamId = (_d = (_c = (_b = context.activity) === null || _b === void 0 ? void 0 : _b.channelData) === null || _c === void 0 ? void 0 : _c.team) === null || _d === void 0 ? void 0 : _d.id;
2530
+ if (teamId !== undefined) {
2531
+ const teamReference = cloneConversation(reference);
2532
+ teamReference.conversation.id = teamId;
2533
+ if (!(yield this.conversationReferenceStore.check(teamReference))) {
2534
+ yield this.conversationReferenceStore.set(teamReference);
2535
+ }
2536
+ }
2537
+ }
2538
+ });
2539
+ }
2218
2540
  }
2219
2541
 
2220
2542
  // Copyright (c) Microsoft Corporation.
@@ -2354,32 +2676,30 @@ class ConversationReferenceStore {
2354
2676
  *
2355
2677
  * @param target - the notification target.
2356
2678
  * @param text - the plain text message.
2357
- * @returns A `Promise` representing the asynchronous operation.
2358
- *
2359
- * @beta
2679
+ * @param onError - an optional error handler that can catch exceptions during message sending.
2680
+ * If not defined, error will be handled by `BotAdapter.onTurnError`.
2681
+ * @returns the response of sending message.
2360
2682
  */
2361
- function sendMessage(target, text) {
2362
- return target.sendMessage(text);
2683
+ function sendMessage(target, text, onError) {
2684
+ return target.sendMessage(text, onError);
2363
2685
  }
2364
2686
  /**
2365
2687
  * Send an adaptive card message to a notification target.
2366
2688
  *
2367
2689
  * @param target - the notification target.
2368
2690
  * @param card - the adaptive card raw JSON.
2369
- * @returns A `Promise` representing the asynchronous operation.
2370
- *
2371
- * @beta
2691
+ * @param onError - an optional error handler that can catch exceptions during adaptive card sending.
2692
+ * If not defined, error will be handled by `BotAdapter.onTurnError`.
2693
+ * @returns the response of sending adaptive card message.
2372
2694
  */
2373
- function sendAdaptiveCard(target, card) {
2374
- return target.sendAdaptiveCard(card);
2695
+ function sendAdaptiveCard(target, card, onError) {
2696
+ return target.sendAdaptiveCard(card, onError);
2375
2697
  }
2376
2698
  /**
2377
2699
  * A {@link NotificationTarget} that represents a team channel.
2378
2700
  *
2379
2701
  * @remarks
2380
2702
  * It's recommended to get channels from {@link TeamsBotInstallation.channels()}.
2381
- *
2382
- * @beta
2383
2703
  */
2384
2704
  class Channel {
2385
2705
  /**
@@ -2390,16 +2710,12 @@ class Channel {
2390
2710
  *
2391
2711
  * @param parent - The parent {@link TeamsBotInstallation} where this channel is created from.
2392
2712
  * @param info - Detailed channel information.
2393
- *
2394
- * @beta
2395
2713
  */
2396
2714
  constructor(parent, info) {
2397
2715
  /**
2398
2716
  * Notification target type. For channel it's always "Channel".
2399
- *
2400
- * @beta
2401
2717
  */
2402
- this.type = "Channel";
2718
+ this.type = exports.NotificationTargetType.Channel;
2403
2719
  this.parent = parent;
2404
2720
  this.info = info;
2405
2721
  }
@@ -2407,36 +2723,64 @@ class Channel {
2407
2723
  * Send a plain text message.
2408
2724
  *
2409
2725
  * @param text - the plain text message.
2410
- * @returns A `Promise` representing the asynchronous operation.
2411
- *
2412
- * @beta
2726
+ * @param onError - an optional error handler that can catch exceptions during message sending.
2727
+ * If not defined, error will be handled by `BotAdapter.onTurnError`.
2728
+ * @returns the response of sending message.
2413
2729
  */
2414
- sendMessage(text) {
2415
- return this.parent.adapter.continueConversation(this.parent.conversationReference, (context) => tslib.__awaiter(this, void 0, void 0, function* () {
2416
- const conversation = yield this.newConversation(context);
2417
- yield this.parent.adapter.continueConversation(conversation, (ctx) => tslib.__awaiter(this, void 0, void 0, function* () {
2418
- yield ctx.sendActivity(text);
2730
+ sendMessage(text, onError) {
2731
+ return tslib.__awaiter(this, void 0, void 0, function* () {
2732
+ const response = {};
2733
+ yield this.parent.adapter.continueConversation(this.parent.conversationReference, (context) => tslib.__awaiter(this, void 0, void 0, function* () {
2734
+ const conversation = yield this.newConversation(context);
2735
+ yield this.parent.adapter.continueConversation(conversation, (ctx) => tslib.__awaiter(this, void 0, void 0, function* () {
2736
+ try {
2737
+ const res = yield ctx.sendActivity(text);
2738
+ response.id = res === null || res === void 0 ? void 0 : res.id;
2739
+ }
2740
+ catch (error) {
2741
+ if (onError) {
2742
+ yield onError(ctx, error);
2743
+ }
2744
+ else {
2745
+ throw error;
2746
+ }
2747
+ }
2748
+ }));
2419
2749
  }));
2420
- }));
2750
+ return response;
2751
+ });
2421
2752
  }
2422
2753
  /**
2423
2754
  * Send an adaptive card message.
2424
2755
  *
2425
2756
  * @param card - the adaptive card raw JSON.
2426
- * @returns A `Promise` representing the asynchronous operation.
2427
- *
2428
- * @beta
2757
+ * @param onError - an optional error handler that can catch exceptions during adaptive card sending.
2758
+ * If not defined, error will be handled by `BotAdapter.onTurnError`.
2759
+ * @returns the response of sending adaptive card message.
2429
2760
  */
2430
- sendAdaptiveCard(card) {
2761
+ sendAdaptiveCard(card, onError) {
2431
2762
  return tslib.__awaiter(this, void 0, void 0, function* () {
2432
- return this.parent.adapter.continueConversation(this.parent.conversationReference, (context) => tslib.__awaiter(this, void 0, void 0, function* () {
2763
+ const response = {};
2764
+ yield this.parent.adapter.continueConversation(this.parent.conversationReference, (context) => tslib.__awaiter(this, void 0, void 0, function* () {
2433
2765
  const conversation = yield this.newConversation(context);
2434
2766
  yield this.parent.adapter.continueConversation(conversation, (ctx) => tslib.__awaiter(this, void 0, void 0, function* () {
2435
- yield ctx.sendActivity({
2436
- attachments: [botbuilder.CardFactory.adaptiveCard(card)],
2437
- });
2767
+ try {
2768
+ const res = yield ctx.sendActivity({
2769
+ attachments: [botbuilder.CardFactory.adaptiveCard(card)],
2770
+ });
2771
+ response.id = res === null || res === void 0 ? void 0 : res.id;
2772
+ }
2773
+ catch (error) {
2774
+ if (onError) {
2775
+ yield onError(ctx, error);
2776
+ }
2777
+ else {
2778
+ throw error;
2779
+ }
2780
+ }
2438
2781
  }));
2439
2782
  }));
2783
+ return response;
2440
2784
  });
2441
2785
  }
2442
2786
  /**
@@ -2456,8 +2800,6 @@ class Channel {
2456
2800
  *
2457
2801
  * @remarks
2458
2802
  * It's recommended to get members from {@link TeamsBotInstallation.members()}.
2459
- *
2460
- * @beta
2461
2803
  */
2462
2804
  class Member {
2463
2805
  /**
@@ -2468,16 +2810,12 @@ class Member {
2468
2810
  *
2469
2811
  * @param parent - The parent {@link TeamsBotInstallation} where this member is created from.
2470
2812
  * @param account - Detailed member account information.
2471
- *
2472
- * @beta
2473
2813
  */
2474
2814
  constructor(parent, account) {
2475
2815
  /**
2476
2816
  * Notification target type. For member it's always "Person".
2477
- *
2478
- * @beta
2479
2817
  */
2480
- this.type = "Person";
2818
+ this.type = exports.NotificationTargetType.Person;
2481
2819
  this.parent = parent;
2482
2820
  this.account = account;
2483
2821
  }
@@ -2485,36 +2823,64 @@ class Member {
2485
2823
  * Send a plain text message.
2486
2824
  *
2487
2825
  * @param text - the plain text message.
2488
- * @returns A `Promise` representing the asynchronous operation.
2489
- *
2490
- * @beta
2826
+ * @param onError - an optional error handler that can catch exceptions during message sending.
2827
+ * If not defined, error will be handled by `BotAdapter.onTurnError`.
2828
+ * @returns the response of sending message.
2491
2829
  */
2492
- sendMessage(text) {
2493
- return this.parent.adapter.continueConversation(this.parent.conversationReference, (context) => tslib.__awaiter(this, void 0, void 0, function* () {
2494
- const conversation = yield this.newConversation(context);
2495
- yield this.parent.adapter.continueConversation(conversation, (ctx) => tslib.__awaiter(this, void 0, void 0, function* () {
2496
- yield ctx.sendActivity(text);
2830
+ sendMessage(text, onError) {
2831
+ return tslib.__awaiter(this, void 0, void 0, function* () {
2832
+ const response = {};
2833
+ yield this.parent.adapter.continueConversation(this.parent.conversationReference, (context) => tslib.__awaiter(this, void 0, void 0, function* () {
2834
+ const conversation = yield this.newConversation(context);
2835
+ yield this.parent.adapter.continueConversation(conversation, (ctx) => tslib.__awaiter(this, void 0, void 0, function* () {
2836
+ try {
2837
+ const res = yield ctx.sendActivity(text);
2838
+ response.id = res === null || res === void 0 ? void 0 : res.id;
2839
+ }
2840
+ catch (error) {
2841
+ if (onError) {
2842
+ yield onError(ctx, error);
2843
+ }
2844
+ else {
2845
+ throw error;
2846
+ }
2847
+ }
2848
+ }));
2497
2849
  }));
2498
- }));
2850
+ return response;
2851
+ });
2499
2852
  }
2500
2853
  /**
2501
2854
  * Send an adaptive card message.
2502
2855
  *
2503
2856
  * @param card - the adaptive card raw JSON.
2504
- * @returns A `Promise` representing the asynchronous operation.
2505
- *
2506
- * @beta
2857
+ * @param onError - an optional error handler that can catch exceptions during adaptive card sending.
2858
+ * If not defined, error will be handled by `BotAdapter.onTurnError`.
2859
+ * @returns the response of sending adaptive card message.
2507
2860
  */
2508
- sendAdaptiveCard(card) {
2861
+ sendAdaptiveCard(card, onError) {
2509
2862
  return tslib.__awaiter(this, void 0, void 0, function* () {
2510
- return this.parent.adapter.continueConversation(this.parent.conversationReference, (context) => tslib.__awaiter(this, void 0, void 0, function* () {
2863
+ const response = {};
2864
+ yield this.parent.adapter.continueConversation(this.parent.conversationReference, (context) => tslib.__awaiter(this, void 0, void 0, function* () {
2511
2865
  const conversation = yield this.newConversation(context);
2512
2866
  yield this.parent.adapter.continueConversation(conversation, (ctx) => tslib.__awaiter(this, void 0, void 0, function* () {
2513
- yield ctx.sendActivity({
2514
- attachments: [botbuilder.CardFactory.adaptiveCard(card)],
2515
- });
2867
+ try {
2868
+ const res = yield ctx.sendActivity({
2869
+ attachments: [botbuilder.CardFactory.adaptiveCard(card)],
2870
+ });
2871
+ response.id = res === null || res === void 0 ? void 0 : res.id;
2872
+ }
2873
+ catch (error) {
2874
+ if (onError) {
2875
+ yield onError(ctx, error);
2876
+ }
2877
+ else {
2878
+ throw error;
2879
+ }
2880
+ }
2516
2881
  }));
2517
2882
  }));
2883
+ return response;
2518
2884
  });
2519
2885
  }
2520
2886
  /**
@@ -2545,8 +2911,6 @@ class Member {
2545
2911
  *
2546
2912
  * @remarks
2547
2913
  * It's recommended to get bot installations from {@link ConversationBot.installations()}.
2548
- *
2549
- * @beta
2550
2914
  */
2551
2915
  class TeamsBotInstallation {
2552
2916
  /**
@@ -2557,8 +2921,6 @@ class TeamsBotInstallation {
2557
2921
  *
2558
2922
  * @param adapter - the bound `BotFrameworkAdapter`.
2559
2923
  * @param conversationReference - the bound `ConversationReference`.
2560
- *
2561
- * @beta
2562
2924
  */
2563
2925
  constructor(adapter, conversationReference) {
2564
2926
  this.adapter = adapter;
@@ -2569,39 +2931,71 @@ class TeamsBotInstallation {
2569
2931
  * Send a plain text message.
2570
2932
  *
2571
2933
  * @param text - the plain text message.
2572
- * @returns A `Promise` representing the asynchronous operation.
2573
- *
2574
- * @beta
2934
+ * @param onError - an optional error handler that can catch exceptions during message sending.
2935
+ * If not defined, error will be handled by `BotAdapter.onTurnError`.
2936
+ * @returns the response of sending message.
2575
2937
  */
2576
- sendMessage(text) {
2577
- return this.adapter.continueConversation(this.conversationReference, (context) => tslib.__awaiter(this, void 0, void 0, function* () {
2578
- yield context.sendActivity(text);
2579
- }));
2938
+ sendMessage(text, onError) {
2939
+ return tslib.__awaiter(this, void 0, void 0, function* () {
2940
+ const response = {};
2941
+ yield this.adapter.continueConversation(this.conversationReference, (context) => tslib.__awaiter(this, void 0, void 0, function* () {
2942
+ try {
2943
+ const res = yield context.sendActivity(text);
2944
+ response.id = res === null || res === void 0 ? void 0 : res.id;
2945
+ }
2946
+ catch (error) {
2947
+ if (onError) {
2948
+ yield onError(context, error);
2949
+ }
2950
+ else {
2951
+ throw error;
2952
+ }
2953
+ }
2954
+ }));
2955
+ return response;
2956
+ });
2580
2957
  }
2581
2958
  /**
2582
2959
  * Send an adaptive card message.
2583
2960
  *
2584
2961
  * @param card - the adaptive card raw JSON.
2585
- * @returns A `Promise` representing the asynchronous operation.
2586
- *
2587
- * @beta
2962
+ * @param onError - an optional error handler that can catch exceptions during adaptive card sending.
2963
+ * If not defined, error will be handled by `BotAdapter.onTurnError`.
2964
+ * @returns the response of sending adaptive card message.
2588
2965
  */
2589
- sendAdaptiveCard(card) {
2590
- return this.adapter.continueConversation(this.conversationReference, (context) => tslib.__awaiter(this, void 0, void 0, function* () {
2591
- yield context.sendActivity({
2592
- attachments: [botbuilder.CardFactory.adaptiveCard(card)],
2593
- });
2594
- }));
2966
+ sendAdaptiveCard(card, onError) {
2967
+ return tslib.__awaiter(this, void 0, void 0, function* () {
2968
+ const response = {};
2969
+ yield this.adapter.continueConversation(this.conversationReference, (context) => tslib.__awaiter(this, void 0, void 0, function* () {
2970
+ try {
2971
+ const res = yield context.sendActivity({
2972
+ attachments: [botbuilder.CardFactory.adaptiveCard(card)],
2973
+ });
2974
+ response.id = res === null || res === void 0 ? void 0 : res.id;
2975
+ }
2976
+ catch (error) {
2977
+ if (onError) {
2978
+ yield onError(context, error);
2979
+ }
2980
+ else {
2981
+ throw error;
2982
+ }
2983
+ }
2984
+ }));
2985
+ return response;
2986
+ });
2595
2987
  }
2596
2988
  /**
2597
2989
  * Get channels from this bot installation.
2598
2990
  *
2599
2991
  * @returns an array of channels if bot is installed into a team, otherwise returns an empty array.
2600
- *
2601
- * @beta
2602
2992
  */
2603
2993
  channels() {
2604
2994
  return tslib.__awaiter(this, void 0, void 0, function* () {
2995
+ const channels = [];
2996
+ if (this.type !== exports.NotificationTargetType.Channel) {
2997
+ return channels;
2998
+ }
2605
2999
  let teamsChannels = [];
2606
3000
  yield this.adapter.continueConversation(this.conversationReference, (context) => tslib.__awaiter(this, void 0, void 0, function* () {
2607
3001
  const teamId = getTeamsBotInstallationId(context);
@@ -2609,7 +3003,6 @@ class TeamsBotInstallation {
2609
3003
  teamsChannels = yield botbuilder.TeamsInfo.getTeamChannels(context, teamId);
2610
3004
  }
2611
3005
  }));
2612
- const channels = [];
2613
3006
  for (const channel of teamsChannels) {
2614
3007
  channels.push(new Channel(this, channel));
2615
3008
  }
@@ -2620,8 +3013,6 @@ class TeamsBotInstallation {
2620
3013
  * Get members from this bot installation.
2621
3014
  *
2622
3015
  * @returns an array of members from where the bot is installed.
2623
- *
2624
- * @beta
2625
3016
  */
2626
3017
  members() {
2627
3018
  return tslib.__awaiter(this, void 0, void 0, function* () {
@@ -2639,11 +3030,29 @@ class TeamsBotInstallation {
2639
3030
  return members;
2640
3031
  });
2641
3032
  }
3033
+ /**
3034
+ * Get team details from this bot installation
3035
+ *
3036
+ * @returns the team details if bot is installed into a team, otherwise returns undefined.
3037
+ */
3038
+ getTeamDetails() {
3039
+ return tslib.__awaiter(this, void 0, void 0, function* () {
3040
+ if (this.type !== exports.NotificationTargetType.Channel) {
3041
+ return undefined;
3042
+ }
3043
+ let teamDetails;
3044
+ yield this.adapter.continueConversation(this.conversationReference, (context) => tslib.__awaiter(this, void 0, void 0, function* () {
3045
+ const teamId = getTeamsBotInstallationId(context);
3046
+ if (teamId !== undefined) {
3047
+ teamDetails = yield botbuilder.TeamsInfo.getTeamDetails(context, teamId);
3048
+ }
3049
+ }));
3050
+ return teamDetails;
3051
+ });
3052
+ }
2642
3053
  }
2643
3054
  /**
2644
3055
  * Provide utilities to send notification to varies targets (e.g., member, group, channel).
2645
- *
2646
- * @beta
2647
3056
  */
2648
3057
  class NotificationBot {
2649
3058
  /**
@@ -2654,8 +3063,6 @@ class NotificationBot {
2654
3063
  *
2655
3064
  * @param adapter - the bound `BotFrameworkAdapter`
2656
3065
  * @param options - initialize options
2657
- *
2658
- * @beta
2659
3066
  */
2660
3067
  constructor(adapter, options) {
2661
3068
  var _a, _b;
@@ -2672,8 +3079,6 @@ class NotificationBot {
2672
3079
  * The result is retrieving from the persisted storage.
2673
3080
  *
2674
3081
  * @returns - an array of {@link TeamsBotInstallation}.
2675
- *
2676
- * @beta
2677
3082
  */
2678
3083
  installations() {
2679
3084
  return tslib.__awaiter(this, void 0, void 0, function* () {
@@ -2706,6 +3111,488 @@ class NotificationBot {
2706
3111
  return targets;
2707
3112
  });
2708
3113
  }
3114
+ /**
3115
+ * Returns the first {@link Member} where predicate is true, and undefined otherwise.
3116
+ *
3117
+ * @param predicate find calls predicate once for each member of the installation,
3118
+ * until it finds one where predicate returns true. If such a member is found, find
3119
+ * immediately returns that member. Otherwise, find returns undefined.
3120
+ * @param scope the scope to find members from the installations
3121
+ * (personal chat, group chat, Teams channel).
3122
+ * @returns the first {@link Member} where predicate is true, and undefined otherwise.
3123
+ */
3124
+ findMember(predicate, scope) {
3125
+ return tslib.__awaiter(this, void 0, void 0, function* () {
3126
+ for (const target of yield this.installations()) {
3127
+ if (this.matchSearchScope(target, scope)) {
3128
+ for (const member of yield target.members()) {
3129
+ if (yield predicate(member)) {
3130
+ return member;
3131
+ }
3132
+ }
3133
+ }
3134
+ }
3135
+ return;
3136
+ });
3137
+ }
3138
+ /**
3139
+ * Returns the first {@link Channel} where predicate is true, and undefined otherwise.
3140
+ *
3141
+ * @param predicate find calls predicate once for each channel of the installation,
3142
+ * until it finds one where predicate returns true. If such a channel is found, find
3143
+ * immediately returns that channel. Otherwise, find returns undefined.
3144
+ * @returns the first {@link Channel} where predicate is true, and undefined otherwise.
3145
+ */
3146
+ findChannel(predicate) {
3147
+ return tslib.__awaiter(this, void 0, void 0, function* () {
3148
+ for (const target of yield this.installations()) {
3149
+ if (target.type === exports.NotificationTargetType.Channel) {
3150
+ const teamDetails = yield target.getTeamDetails();
3151
+ for (const channel of yield target.channels()) {
3152
+ if (yield predicate(channel, teamDetails)) {
3153
+ return channel;
3154
+ }
3155
+ }
3156
+ }
3157
+ }
3158
+ return;
3159
+ });
3160
+ }
3161
+ /**
3162
+ * Returns all {@link Member} where predicate is true, and empty array otherwise.
3163
+ *
3164
+ * @param predicate find calls predicate for each member of the installation.
3165
+ * @param scope the scope to find members from the installations
3166
+ * (personal chat, group chat, Teams channel).
3167
+ * @returns an array of {@link Member} where predicate is true, and empty array otherwise.
3168
+ */
3169
+ findAllMembers(predicate, scope) {
3170
+ return tslib.__awaiter(this, void 0, void 0, function* () {
3171
+ const members = [];
3172
+ for (const target of yield this.installations()) {
3173
+ if (this.matchSearchScope(target, scope)) {
3174
+ for (const member of yield target.members()) {
3175
+ if (yield predicate(member)) {
3176
+ members.push(member);
3177
+ }
3178
+ }
3179
+ }
3180
+ }
3181
+ return members;
3182
+ });
3183
+ }
3184
+ /**
3185
+ * Returns all {@link Channel} where predicate is true, and empty array otherwise.
3186
+ *
3187
+ * @param predicate find calls predicate for each channel of the installation.
3188
+ * @returns an array of {@link Channel} where predicate is true, and empty array otherwise.
3189
+ */
3190
+ findAllChannels(predicate) {
3191
+ return tslib.__awaiter(this, void 0, void 0, function* () {
3192
+ const channels = [];
3193
+ for (const target of yield this.installations()) {
3194
+ if (target.type === exports.NotificationTargetType.Channel) {
3195
+ const teamDetails = yield target.getTeamDetails();
3196
+ for (const channel of yield target.channels()) {
3197
+ if (yield predicate(channel, teamDetails)) {
3198
+ channels.push(channel);
3199
+ }
3200
+ }
3201
+ }
3202
+ }
3203
+ return channels;
3204
+ });
3205
+ }
3206
+ matchSearchScope(target, scope) {
3207
+ scope = scope !== null && scope !== void 0 ? scope : exports.SearchScope.All;
3208
+ return ((target.type === exports.NotificationTargetType.Channel && (scope & exports.SearchScope.Channel) !== 0) ||
3209
+ (target.type === exports.NotificationTargetType.Group && (scope & exports.SearchScope.Group) !== 0) ||
3210
+ (target.type === exports.NotificationTargetType.Person && (scope & exports.SearchScope.Person) !== 0));
3211
+ }
3212
+ }
3213
+ /**
3214
+ * The search scope when calling {@link NotificationBot.findMember} and {@link NotificationBot.findAllMembers}.
3215
+ * The search scope is a flagged enum and it can be combined with `|`.
3216
+ * For example, to search from personal chat and group chat, use `SearchScope.Person | SearchScope.Group`.
3217
+ */
3218
+ exports.SearchScope = void 0;
3219
+ (function (SearchScope) {
3220
+ /**
3221
+ * Search members from the installations in personal chat only.
3222
+ */
3223
+ SearchScope[SearchScope["Person"] = 1] = "Person";
3224
+ /**
3225
+ * Search members from the installations in group chat only.
3226
+ */
3227
+ SearchScope[SearchScope["Group"] = 2] = "Group";
3228
+ /**
3229
+ * Search members from the installations in Teams channel only.
3230
+ */
3231
+ SearchScope[SearchScope["Channel"] = 4] = "Channel";
3232
+ /**
3233
+ * Search members from all installations including personal chat, group chat and Teams channel.
3234
+ */
3235
+ SearchScope[SearchScope["All"] = 7] = "All";
3236
+ })(exports.SearchScope || (exports.SearchScope = {}));
3237
+
3238
+ // Copyright (c) Microsoft Corporation.
3239
+ let DIALOG_NAME = "BotSsoExecutionDialog";
3240
+ let TEAMS_SSO_PROMPT_ID = "TeamsFxSsoPrompt";
3241
+ let COMMAND_ROUTE_DIALOG = "CommandRouteDialog";
3242
+ /**
3243
+ * Sso execution dialog, use to handle sso command
3244
+ */
3245
+ class BotSsoExecutionDialog extends botbuilderDialogs.ComponentDialog {
3246
+ /**
3247
+ * Creates a new instance of the BotSsoExecutionDialog.
3248
+ * @param dedupStorage Helper storage to remove duplicated messages
3249
+ * @param settings The list of scopes for which the token will have access
3250
+ * @param teamsfx {@link TeamsFx} instance for authentication
3251
+ */
3252
+ constructor(dedupStorage, ssoPromptSettings, teamsfx, dialogName) {
3253
+ super(dialogName !== null && dialogName !== void 0 ? dialogName : DIALOG_NAME);
3254
+ this.dedupStorageKeys = [];
3255
+ // Map to store the commandId and triggerPatterns, key: commandId, value: triggerPatterns
3256
+ this.commandMapping = new Map();
3257
+ if (dialogName) {
3258
+ DIALOG_NAME = dialogName;
3259
+ TEAMS_SSO_PROMPT_ID = dialogName + TEAMS_SSO_PROMPT_ID;
3260
+ COMMAND_ROUTE_DIALOG = dialogName + COMMAND_ROUTE_DIALOG;
3261
+ }
3262
+ this.initialDialogId = COMMAND_ROUTE_DIALOG;
3263
+ this.dedupStorage = dedupStorage;
3264
+ this.dedupStorageKeys = [];
3265
+ const ssoDialog = new TeamsBotSsoPrompt(teamsfx, TEAMS_SSO_PROMPT_ID, ssoPromptSettings);
3266
+ this.addDialog(ssoDialog);
3267
+ const commandRouteDialog = new botbuilderDialogs.WaterfallDialog(COMMAND_ROUTE_DIALOG, [
3268
+ this.commandRouteStep.bind(this),
3269
+ ]);
3270
+ this.addDialog(commandRouteDialog);
3271
+ }
3272
+ /**
3273
+ * Add TeamsFxBotSsoCommandHandler instance
3274
+ * @param handler {@link BotSsoExecutionDialogHandler} callback function
3275
+ * @param triggerPatterns The trigger pattern
3276
+ */
3277
+ addCommand(handler, triggerPatterns) {
3278
+ const commandId = this.getCommandHash(triggerPatterns);
3279
+ const dialog = new botbuilderDialogs.WaterfallDialog(commandId, [
3280
+ this.ssoStep.bind(this),
3281
+ this.dedupStep.bind(this),
3282
+ (stepContext) => tslib.__awaiter(this, void 0, void 0, function* () {
3283
+ const tokenResponse = stepContext.result.tokenResponse;
3284
+ const context = stepContext.context;
3285
+ const message = stepContext.result.message;
3286
+ try {
3287
+ if (tokenResponse) {
3288
+ yield handler(context, tokenResponse, message);
3289
+ }
3290
+ else {
3291
+ throw new Error(ErrorMessage.FailedToRetrieveSsoToken);
3292
+ }
3293
+ return yield stepContext.endDialog();
3294
+ }
3295
+ catch (error) {
3296
+ const errorMsg = formatString(ErrorMessage.FailedToProcessSsoHandler, error.message);
3297
+ internalLogger.error(errorMsg);
3298
+ return yield stepContext.endDialog(new ErrorWithCode(errorMsg, exports.ErrorCode.FailedToProcessSsoHandler));
3299
+ }
3300
+ }),
3301
+ ]);
3302
+ this.commandMapping.set(commandId, triggerPatterns);
3303
+ this.addDialog(dialog);
3304
+ }
3305
+ getCommandHash(patterns) {
3306
+ const expressions = Array.isArray(patterns) ? patterns : [patterns];
3307
+ const patternStr = expressions.join();
3308
+ const patternStrWithoutSpecialChar = patternStr.replace(/[^a-zA-Z0-9]/g, "");
3309
+ const hash = crypto.createHash("sha256").update(patternStr).digest("hex").toLowerCase();
3310
+ return patternStrWithoutSpecialChar + hash;
3311
+ }
3312
+ /**
3313
+ * The run method handles the incoming activity (in the form of a DialogContext) and passes it through the dialog system.
3314
+ *
3315
+ * @param context The context object for the current turn.
3316
+ * @param accessor The instance of StatePropertyAccessor for dialog system.
3317
+ */
3318
+ run(context, accessor) {
3319
+ return tslib.__awaiter(this, void 0, void 0, function* () {
3320
+ const dialogSet = new botbuilderDialogs.DialogSet(accessor);
3321
+ dialogSet.add(this);
3322
+ const dialogContext = yield dialogSet.createContext(context);
3323
+ this.ensureMsTeamsChannel(dialogContext);
3324
+ const results = yield dialogContext.continueDialog();
3325
+ if (results && results.status === botbuilderDialogs.DialogTurnStatus.empty) {
3326
+ yield dialogContext.beginDialog(this.id);
3327
+ }
3328
+ else if (results &&
3329
+ results.status === botbuilderDialogs.DialogTurnStatus.complete &&
3330
+ results.result instanceof Error) {
3331
+ throw results.result;
3332
+ }
3333
+ });
3334
+ }
3335
+ getActivityText(activity) {
3336
+ let text = activity.text;
3337
+ const removedMentionText = botbuilder.TurnContext.removeRecipientMention(activity);
3338
+ if (removedMentionText) {
3339
+ text = removedMentionText
3340
+ .toLowerCase()
3341
+ .replace(/\n|\r\n/g, "")
3342
+ .trim();
3343
+ }
3344
+ return text;
3345
+ }
3346
+ commandRouteStep(stepContext) {
3347
+ return tslib.__awaiter(this, void 0, void 0, function* () {
3348
+ const turnContext = stepContext.context;
3349
+ const text = this.getActivityText(turnContext.activity);
3350
+ const commandId = this.getMatchesCommandId(text);
3351
+ if (commandId) {
3352
+ return yield stepContext.beginDialog(commandId);
3353
+ }
3354
+ const errorMsg = formatString(ErrorMessage.CannotFindCommand, turnContext.activity.text);
3355
+ internalLogger.error(errorMsg);
3356
+ throw new ErrorWithCode(errorMsg, exports.ErrorCode.CannotFindCommand);
3357
+ });
3358
+ }
3359
+ ssoStep(stepContext) {
3360
+ return tslib.__awaiter(this, void 0, void 0, function* () {
3361
+ try {
3362
+ const turnContext = stepContext.context;
3363
+ const text = this.getActivityText(turnContext.activity);
3364
+ const message = {
3365
+ text,
3366
+ };
3367
+ stepContext.options.commandMessage = message;
3368
+ return yield stepContext.beginDialog(TEAMS_SSO_PROMPT_ID);
3369
+ }
3370
+ catch (error) {
3371
+ const errorMsg = formatString(ErrorMessage.FailedToRunSsoStep, error.message);
3372
+ internalLogger.error(errorMsg);
3373
+ return yield stepContext.endDialog(new ErrorWithCode(errorMsg, exports.ErrorCode.FailedToRunSsoStep));
3374
+ }
3375
+ });
3376
+ }
3377
+ dedupStep(stepContext) {
3378
+ return tslib.__awaiter(this, void 0, void 0, function* () {
3379
+ const tokenResponse = stepContext.result;
3380
+ if (!tokenResponse) {
3381
+ internalLogger.error(ErrorMessage.FailedToRetrieveSsoToken);
3382
+ return yield stepContext.endDialog(new ErrorWithCode(ErrorMessage.FailedToRetrieveSsoToken, exports.ErrorCode.FailedToRunSsoStep));
3383
+ }
3384
+ try {
3385
+ // Only dedup after ssoStep to make sure that all Teams client would receive the login request
3386
+ if (tokenResponse && (yield this.shouldDedup(stepContext.context))) {
3387
+ return botbuilderDialogs.Dialog.EndOfTurn;
3388
+ }
3389
+ return yield stepContext.next({
3390
+ tokenResponse,
3391
+ message: stepContext.options.commandMessage,
3392
+ });
3393
+ }
3394
+ catch (error) {
3395
+ const errorMsg = formatString(ErrorMessage.FailedToRunDedupStep, error.message);
3396
+ internalLogger.error(errorMsg);
3397
+ return yield stepContext.endDialog(new ErrorWithCode(errorMsg, exports.ErrorCode.FailedToRunDedupStep));
3398
+ }
3399
+ });
3400
+ }
3401
+ /**
3402
+ * Called when the component is ending.
3403
+ *
3404
+ * @param context Context for the current turn of conversation.
3405
+ */
3406
+ onEndDialog(context) {
3407
+ return tslib.__awaiter(this, void 0, void 0, function* () {
3408
+ const conversationId = context.activity.conversation.id;
3409
+ const currentDedupKeys = this.dedupStorageKeys.filter((key) => key.indexOf(conversationId) > 0);
3410
+ yield this.dedupStorage.delete(currentDedupKeys);
3411
+ this.dedupStorageKeys = this.dedupStorageKeys.filter((key) => key.indexOf(conversationId) < 0);
3412
+ });
3413
+ }
3414
+ /**
3415
+ * If a user is signed into multiple Teams clients, the Bot might receive a "signin/tokenExchange" from each client.
3416
+ * Each token exchange request for a specific user login will have an identical activity.value.Id.
3417
+ * Only one of these token exchange requests should be processed by the bot. For a distributed bot in production,
3418
+ * this requires a distributed storage to ensure only one token exchange is processed.
3419
+ * @param context Context for the current turn of conversation.
3420
+ * @returns boolean value indicate whether the message should be removed
3421
+ */
3422
+ shouldDedup(context) {
3423
+ return tslib.__awaiter(this, void 0, void 0, function* () {
3424
+ const storeItem = {
3425
+ eTag: context.activity.value.id,
3426
+ };
3427
+ const key = this.getStorageKey(context);
3428
+ const storeItems = { [key]: storeItem };
3429
+ try {
3430
+ yield this.dedupStorage.write(storeItems);
3431
+ this.dedupStorageKeys.push(key);
3432
+ }
3433
+ catch (err) {
3434
+ if (err instanceof Error && err.message.indexOf("eTag conflict")) {
3435
+ return true;
3436
+ }
3437
+ throw err;
3438
+ }
3439
+ return false;
3440
+ });
3441
+ }
3442
+ getStorageKey(context) {
3443
+ if (!context || !context.activity || !context.activity.conversation) {
3444
+ throw new Error("Invalid context, can not get storage key!");
3445
+ }
3446
+ const activity = context.activity;
3447
+ const channelId = activity.channelId;
3448
+ const conversationId = activity.conversation.id;
3449
+ if (activity.type !== botbuilder.ActivityTypes.Invoke || activity.name !== botbuilder.tokenExchangeOperationName) {
3450
+ throw new Error("TokenExchangeState can only be used with Invokes of signin/tokenExchange.");
3451
+ }
3452
+ const value = activity.value;
3453
+ if (!value || !value.id) {
3454
+ throw new Error("Invalid signin/tokenExchange. Missing activity.value.id.");
3455
+ }
3456
+ return `${channelId}/${conversationId}/${value.id}`;
3457
+ }
3458
+ matchPattern(pattern, text) {
3459
+ if (text) {
3460
+ if (typeof pattern === "string") {
3461
+ const regExp = new RegExp(pattern, "i");
3462
+ return regExp.test(text);
3463
+ }
3464
+ if (pattern instanceof RegExp) {
3465
+ const matches = text.match(pattern);
3466
+ return matches !== null && matches !== void 0 ? matches : false;
3467
+ }
3468
+ }
3469
+ return false;
3470
+ }
3471
+ isPatternMatched(patterns, text) {
3472
+ const expressions = Array.isArray(patterns) ? patterns : [patterns];
3473
+ for (const ex of expressions) {
3474
+ const matches = this.matchPattern(ex, text);
3475
+ return !!matches;
3476
+ }
3477
+ return false;
3478
+ }
3479
+ getMatchesCommandId(text) {
3480
+ for (const command of this.commandMapping) {
3481
+ const pattern = command[1];
3482
+ if (this.isPatternMatched(pattern, text)) {
3483
+ return command[0];
3484
+ }
3485
+ }
3486
+ return undefined;
3487
+ }
3488
+ /**
3489
+ * Ensure bot is running in MS Teams since TeamsBotSsoPrompt is only supported in MS Teams channel.
3490
+ * @param dc dialog context
3491
+ * @throws {@link ErrorCode|ChannelNotSupported} if bot channel is not MS Teams
3492
+ * @internal
3493
+ */
3494
+ ensureMsTeamsChannel(dc) {
3495
+ if (dc.context.activity.channelId != botbuilder.Channels.Msteams) {
3496
+ const errorMsg = formatString(ErrorMessage.OnlyMSTeamsChannelSupported, "SSO execution dialog");
3497
+ internalLogger.error(errorMsg);
3498
+ throw new ErrorWithCode(errorMsg, exports.ErrorCode.ChannelNotSupported);
3499
+ }
3500
+ }
3501
+ }
3502
+
3503
+ // Copyright (c) Microsoft Corporation.
3504
+ /**
3505
+ * Default SSO execution activity handler
3506
+ */
3507
+ class DefaultBotSsoExecutionActivityHandler extends botbuilder.TeamsActivityHandler {
3508
+ /**
3509
+ * Creates a new instance of the DefaultBotSsoExecutionActivityHandler.
3510
+ * @param ssoConfig configuration for SSO command bot
3511
+ *
3512
+ * @remarks
3513
+ * In the constructor, it uses BotSsoConfig parameter which from {@link ConversationBot} options to initialize {@link BotSsoExecutionDialog}.
3514
+ * It also need to register an event handler for the message event which trigger {@link BotSsoExecutionDialog} instance.
3515
+ */
3516
+ constructor(ssoConfig) {
3517
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
3518
+ super();
3519
+ const memoryStorage = new botbuilder.MemoryStorage();
3520
+ const userState = (_b = (_a = ssoConfig.dialog) === null || _a === void 0 ? void 0 : _a.userState) !== null && _b !== void 0 ? _b : new botbuilder.UserState(memoryStorage);
3521
+ const conversationState = (_d = (_c = ssoConfig.dialog) === null || _c === void 0 ? void 0 : _c.conversationState) !== null && _d !== void 0 ? _d : new botbuilder.ConversationState(memoryStorage);
3522
+ const dedupStorage = (_f = (_e = ssoConfig.dialog) === null || _e === void 0 ? void 0 : _e.dedupStorage) !== null && _f !== void 0 ? _f : memoryStorage;
3523
+ const _l = ssoConfig.aad, { scopes } = _l, customConfig = tslib.__rest(_l, ["scopes"]);
3524
+ const settings = {
3525
+ scopes: scopes,
3526
+ timeout: (_h = (_g = ssoConfig.dialog) === null || _g === void 0 ? void 0 : _g.ssoPromptConfig) === null || _h === void 0 ? void 0 : _h.timeout,
3527
+ endOnInvalidMessage: (_k = (_j = ssoConfig.dialog) === null || _j === void 0 ? void 0 : _j.ssoPromptConfig) === null || _k === void 0 ? void 0 : _k.endOnInvalidMessage,
3528
+ };
3529
+ const teamsfx = new TeamsFx(exports.IdentityType.User, Object.assign({}, customConfig));
3530
+ this.ssoExecutionDialog = new BotSsoExecutionDialog(dedupStorage, settings, teamsfx);
3531
+ this.conversationState = conversationState;
3532
+ this.dialogState = conversationState.createProperty("DialogState");
3533
+ this.userState = userState;
3534
+ this.onMessage((context, next) => tslib.__awaiter(this, void 0, void 0, function* () {
3535
+ yield this.ssoExecutionDialog.run(context, this.dialogState);
3536
+ yield next();
3537
+ }));
3538
+ }
3539
+ /**
3540
+ * Add TeamsFxBotSsoCommandHandler instance to SSO execution dialog
3541
+ * @param handler {@link BotSsoExecutionDialogHandler} callback function
3542
+ * @param triggerPatterns The trigger pattern
3543
+ *
3544
+ * @remarks
3545
+ * This function is used to add SSO command to {@link BotSsoExecutionDialog} instance.
3546
+ */
3547
+ addCommand(handler, triggerPatterns) {
3548
+ this.ssoExecutionDialog.addCommand(handler, triggerPatterns);
3549
+ }
3550
+ /**
3551
+ * Called to initiate the event emission process.
3552
+ * @param context The context object for the current turn.
3553
+ */
3554
+ run(context) {
3555
+ const _super = Object.create(null, {
3556
+ run: { get: () => super.run }
3557
+ });
3558
+ return tslib.__awaiter(this, void 0, void 0, function* () {
3559
+ try {
3560
+ yield _super.run.call(this, context);
3561
+ }
3562
+ finally {
3563
+ yield this.conversationState.saveChanges(context, false);
3564
+ yield this.userState.saveChanges(context, false);
3565
+ }
3566
+ });
3567
+ }
3568
+ /**
3569
+ * Receives invoke activities with Activity name of 'signin/verifyState'.
3570
+ * @param context A context object for this turn.
3571
+ * @param query Signin state (part of signin action auth flow) verification invoke query.
3572
+ * @returns A promise that represents the work queued.
3573
+ *
3574
+ * @remarks
3575
+ * It should trigger {@link BotSsoExecutionDialog} instance to handle signin process
3576
+ */
3577
+ handleTeamsSigninVerifyState(context, query) {
3578
+ return tslib.__awaiter(this, void 0, void 0, function* () {
3579
+ yield this.ssoExecutionDialog.run(context, this.dialogState);
3580
+ });
3581
+ }
3582
+ /**
3583
+ * Receives invoke activities with Activity name of 'signin/tokenExchange'
3584
+ * @param context A context object for this turn.
3585
+ * @param query Signin state (part of signin action auth flow) verification invoke query
3586
+ * @returns A promise that represents the work queued.
3587
+ *
3588
+ * @remark
3589
+ * It should trigger {@link BotSsoExecutionDialog} instance to handle signin process
3590
+ */
3591
+ handleTeamsSigninTokenExchange(context, query) {
3592
+ return tslib.__awaiter(this, void 0, void 0, function* () {
3593
+ yield this.ssoExecutionDialog.run(context, this.dialogState);
3594
+ });
3595
+ }
2709
3596
  }
2710
3597
 
2711
3598
  // Copyright (c) Microsoft Corporation.
@@ -2759,8 +3646,6 @@ class NotificationBot {
2759
3646
  * For command and response, ensure each command should ONLY be registered with the command once, otherwise it'll cause unexpected behavior if you register the same command more than once.
2760
3647
  *
2761
3648
  * For notification, set `notification.storage` in {@link ConversationOptions} to use your own storage implementation.
2762
- *
2763
- * @beta
2764
3649
  */
2765
3650
  class ConversationBot {
2766
3651
  /**
@@ -2770,23 +3655,34 @@ class ConversationBot {
2770
3655
  * It's recommended to create your own adapter and storage for production environment instead of the default one.
2771
3656
  *
2772
3657
  * @param options - initialize options
2773
- *
2774
- * @beta
2775
3658
  */
2776
3659
  constructor(options) {
2777
- var _a, _b;
3660
+ var _a, _b, _c, _d;
2778
3661
  if (options.adapter) {
2779
3662
  this.adapter = options.adapter;
2780
3663
  }
2781
3664
  else {
2782
3665
  this.adapter = this.createDefaultAdapter(options.adapterConfig);
2783
3666
  }
2784
- if ((_a = options.command) === null || _a === void 0 ? void 0 : _a.enabled) {
2785
- this.command = new CommandBot(this.adapter, options.command);
3667
+ let ssoCommandActivityHandler;
3668
+ if (options === null || options === void 0 ? void 0 : options.ssoConfig) {
3669
+ if ((_a = options.ssoConfig.dialog) === null || _a === void 0 ? void 0 : _a.CustomBotSsoExecutionActivityHandler) {
3670
+ ssoCommandActivityHandler =
3671
+ new options.ssoConfig.dialog.CustomBotSsoExecutionActivityHandler(options.ssoConfig);
3672
+ }
3673
+ else {
3674
+ ssoCommandActivityHandler = new DefaultBotSsoExecutionActivityHandler(options.ssoConfig);
3675
+ }
2786
3676
  }
2787
- if ((_b = options.notification) === null || _b === void 0 ? void 0 : _b.enabled) {
3677
+ if ((_b = options.command) === null || _b === void 0 ? void 0 : _b.enabled) {
3678
+ this.command = new CommandBot(this.adapter, options.command, ssoCommandActivityHandler, options.ssoConfig);
3679
+ }
3680
+ if ((_c = options.notification) === null || _c === void 0 ? void 0 : _c.enabled) {
2788
3681
  this.notification = new NotificationBot(this.adapter, options.notification);
2789
3682
  }
3683
+ if ((_d = options.cardAction) === null || _d === void 0 ? void 0 : _d.enabled) {
3684
+ this.cardAction = new CardActionBot(this.adapter, options.cardAction);
3685
+ }
2790
3686
  }
2791
3687
  createDefaultAdapter(adapterConfig) {
2792
3688
  const adapter = adapterConfig === undefined
@@ -2827,8 +3723,6 @@ class ConversationBot {
2827
3723
  * });
2828
3724
  * });
2829
3725
  * ```
2830
- *
2831
- * @beta
2832
3726
  */
2833
3727
  requestHandler(req, res, logic) {
2834
3728
  return tslib.__awaiter(this, void 0, void 0, function* () {
@@ -2881,8 +3775,6 @@ class MessageBuilder {
2881
3775
  * description: "sample card description"
2882
3776
  * });
2883
3777
  * ```
2884
- *
2885
- * @beta
2886
3778
  */
2887
3779
  static attachAdaptiveCard(cardTemplate, data) {
2888
3780
  return {
@@ -2894,8 +3786,6 @@ class MessageBuilder {
2894
3786
  *
2895
3787
  * @param card The adaptive card content.
2896
3788
  * @returns A bot message activity attached with an adaptive card.
2897
- *
2898
- * @beta
2899
3789
  */
2900
3790
  static attachAdaptiveCardWithoutData(card) {
2901
3791
  return {
@@ -2921,8 +3811,6 @@ class MessageBuilder {
2921
3811
  * ['action']
2922
3812
  * );
2923
3813
  * ```
2924
- *
2925
- * @beta
2926
3814
  */
2927
3815
  static attachHeroCard(title, images, buttons, other) {
2928
3816
  return MessageBuilder.attachContent(botbuilder.CardFactory.heroCard(title, images, buttons, other));
@@ -2938,8 +3826,6 @@ class MessageBuilder {
2938
3826
  *
2939
3827
  * @remarks
2940
3828
  * For channels that don't natively support sign-in cards, an alternative message is rendered.
2941
- *
2942
- * @beta
2943
3829
  */
2944
3830
  static attachSigninCard(title, url, text) {
2945
3831
  return MessageBuilder.attachContent(botbuilder.CardFactory.signinCard(title, url, text));
@@ -2949,8 +3835,6 @@ class MessageBuilder {
2949
3835
  *
2950
3836
  * @param card A description of the Office 365 connector card.
2951
3837
  * @returns A bot message activity attached with an Office 365 connector card.
2952
- *
2953
- * @beta
2954
3838
  */
2955
3839
  static attachO365ConnectorCard(card) {
2956
3840
  return MessageBuilder.attachContent(botbuilder.CardFactory.o365ConnectorCard(card));
@@ -2959,8 +3843,6 @@ class MessageBuilder {
2959
3843
  * Build a message activity attached with a receipt card.
2960
3844
  * @param card A description of the receipt card.
2961
3845
  * @returns A message activity attached with a receipt card.
2962
- *
2963
- * @beta
2964
3846
  */
2965
3847
  static AttachReceiptCard(card) {
2966
3848
  return MessageBuilder.attachContent(botbuilder.CardFactory.receiptCard(card));
@@ -2973,8 +3855,6 @@ class MessageBuilder {
2973
3855
  * is converted to an `imBack` button with a title and value set to the value of the string.
2974
3856
  * @param other Optional. Any additional properties to include on the card.
2975
3857
  * @returns A message activity attached with a thumbnail card
2976
- *
2977
- * @beta
2978
3858
  */
2979
3859
  static attachThumbnailCard(title, images, buttons, other) {
2980
3860
  return MessageBuilder.attachContent(botbuilder.CardFactory.thumbnailCard(title, images, buttons, other));
@@ -2983,8 +3863,6 @@ class MessageBuilder {
2983
3863
  * Add an attachement to a bot activity.
2984
3864
  * @param attachement The attachment object to attach.
2985
3865
  * @returns A message activity with an attachment.
2986
- *
2987
- * @beta
2988
3866
  */
2989
3867
  static attachContent(attachement) {
2990
3868
  return {
@@ -2993,15 +3871,122 @@ class MessageBuilder {
2993
3871
  }
2994
3872
  }
2995
3873
 
3874
+ // Copyright (c) Microsoft Corporation.
3875
+ /**
3876
+ * Retrieve the OAuth Sign in Link to use in the MessagingExtensionResult Suggested Actions.
3877
+ * This method only work on MessageExtension with Query now.
3878
+ *
3879
+ * @param {TeamsFx} teamsfx - Used to provide configuration and auth.
3880
+ * @param {string | string[]} scopes - The list of scopes for which the token will have access.
3881
+ *
3882
+ * @returns SignIn link CardAction with 200 status code.
3883
+ */
3884
+ function getSignInResponseForMessageExtension(teamsfx, scopes) {
3885
+ const scopesArray = getScopesArray(scopes);
3886
+ const signInLink = `${teamsfx.getConfig("initiateLoginEndpoint")}?scope=${encodeURI(scopesArray.join(" "))}&clientId=${teamsfx.getConfig("clientId")}&tenantId=${teamsfx.getConfig("tenantId")}`;
3887
+ return {
3888
+ composeExtension: {
3889
+ type: "silentAuth",
3890
+ suggestedActions: {
3891
+ actions: [
3892
+ {
3893
+ type: "openUrl",
3894
+ value: signInLink,
3895
+ title: "Message Extension OAuth",
3896
+ },
3897
+ ],
3898
+ },
3899
+ },
3900
+ };
3901
+ }
3902
+ /**
3903
+ * execution in message extension with SSO token.
3904
+ *
3905
+ * @param {TurnContext} context - The context object for the current turn.
3906
+ * @param {AuthenticationConfiguration} config - User custom the message extension authentication configuration.
3907
+ * @param {string[]} scopes - The list of scopes for which the token will have access.
3908
+ * @param {function} logic - Business logic when executing the query in message extension with SSO or access token.
3909
+ *
3910
+ * @throws {@link ErrorCode|InternalError} when failed to get access token with unknown error.
3911
+ * @throws {@link ErrorCode|TokenExpiredError} when SSO token has already expired.
3912
+ * @throws {@link ErrorCode|ServiceError} when failed to get access token from simple auth server.
3913
+ * @throws {@link ErrorCode|InvalidParameter} when scopes is not a valid string or string array.
3914
+ * @throws {@link ErrorCode|RuntimeNotSupported} when runtime is nodeJS.
3915
+ *
3916
+ * @returns A MessageExtension Response for the activity. If the logic not return any, return void instead.
3917
+ */
3918
+ function executionWithToken(context, config, scopes, logic) {
3919
+ return tslib.__awaiter(this, void 0, void 0, function* () {
3920
+ const valueObj = context.activity.value;
3921
+ if (!valueObj.authentication || !valueObj.authentication.token) {
3922
+ internalLogger.verbose("No AccessToken in request, return silentAuth for AccessToken");
3923
+ return getSignInResponseForMessageExtension(new TeamsFx(exports.IdentityType.User, config), scopes);
3924
+ }
3925
+ try {
3926
+ const teamsfx = new TeamsFx(exports.IdentityType.User, config).setSsoToken(valueObj.authentication.token);
3927
+ const token = yield teamsfx.getCredential().getToken(scopes);
3928
+ const ssoTokenExpiration = parseJwt(valueObj.authentication.token).exp;
3929
+ const tokenRes = {
3930
+ ssoToken: valueObj.authentication.token,
3931
+ ssoTokenExpiration: new Date(ssoTokenExpiration * 1000).toISOString(),
3932
+ token: token.token,
3933
+ expiration: token.expiresOnTimestamp.toString(),
3934
+ connectionName: "",
3935
+ };
3936
+ if (logic) {
3937
+ return yield logic(tokenRes);
3938
+ }
3939
+ }
3940
+ catch (err) {
3941
+ if (err instanceof ErrorWithCode && err.code === exports.ErrorCode.UiRequiredError) {
3942
+ internalLogger.verbose("User not consent yet, return 412 to user consent first.");
3943
+ const response = { status: 412 };
3944
+ yield context.sendActivity({ value: response, type: botbuilder.ActivityTypes.InvokeResponse });
3945
+ return;
3946
+ }
3947
+ throw err;
3948
+ }
3949
+ });
3950
+ }
3951
+ /**
3952
+ * Users execute query in message extension with SSO or access token.
3953
+ *
3954
+ * @param {TurnContext} context - The context object for the current turn.
3955
+ * @param {AuthenticationConfiguration} config - User custom the message extension authentication configuration.
3956
+ * @param {string| string[]} scopes - The list of scopes for which the token will have access.
3957
+ * @param {function} logic - Business logic when executing the query in message extension with SSO or access token.
3958
+ *
3959
+ * @throws {@link ErrorCode|InternalError} when User invoke not response to message extension query.
3960
+ * @throws {@link ErrorCode|InternalError} when failed to get access token with unknown error.
3961
+ * @throws {@link ErrorCode|TokenExpiredError} when SSO token has already expired.
3962
+ * @throws {@link ErrorCode|ServiceError} when failed to get access token from simple auth server.
3963
+ * @throws {@link ErrorCode|InvalidParameter} when scopes is not a valid string or string array.
3964
+ * @throws {@link ErrorCode|RuntimeNotSupported} when runtime is nodeJS.
3965
+ *
3966
+ * @returns A MessageExtension Response for the activity. If the logic not return any, return void instead.
3967
+ */
3968
+ function handleMessageExtensionQueryWithToken(context, config, scopes, logic) {
3969
+ return tslib.__awaiter(this, void 0, void 0, function* () {
3970
+ if (context.activity.name != "composeExtension/query") {
3971
+ internalLogger.error(ErrorMessage.OnlySupportInQueryActivity);
3972
+ throw new ErrorWithCode(formatString(ErrorMessage.OnlySupportInQueryActivity), exports.ErrorCode.FailedOperation);
3973
+ }
3974
+ return yield executionWithToken(context, config !== null && config !== void 0 ? config : {}, scopes, logic);
3975
+ });
3976
+ }
3977
+
2996
3978
  exports.ApiKeyProvider = ApiKeyProvider;
2997
3979
  exports.AppCredential = AppCredential;
2998
3980
  exports.BasicAuthProvider = BasicAuthProvider;
2999
3981
  exports.BearerTokenAuthProvider = BearerTokenAuthProvider;
3982
+ exports.BotSsoExecutionDialog = BotSsoExecutionDialog;
3983
+ exports.CardActionBot = CardActionBot;
3000
3984
  exports.CertificateAuthProvider = CertificateAuthProvider;
3001
3985
  exports.Channel = Channel;
3002
3986
  exports.CommandBot = CommandBot;
3003
3987
  exports.ConversationBot = ConversationBot;
3004
3988
  exports.ErrorWithCode = ErrorWithCode;
3989
+ exports.InvokeResponseFactory = InvokeResponseFactory;
3005
3990
  exports.Member = Member;
3006
3991
  exports.MessageBuilder = MessageBuilder;
3007
3992
  exports.MsGraphAuthProvider = MsGraphAuthProvider;
@@ -3017,6 +4002,7 @@ exports.createPemCertOption = createPemCertOption;
3017
4002
  exports.createPfxCertOption = createPfxCertOption;
3018
4003
  exports.getLogLevel = getLogLevel;
3019
4004
  exports.getTediousConnectionConfig = getTediousConnectionConfig;
4005
+ exports.handleMessageExtensionQueryWithToken = handleMessageExtensionQueryWithToken;
3020
4006
  exports.sendAdaptiveCard = sendAdaptiveCard;
3021
4007
  exports.sendMessage = sendMessage;
3022
4008
  exports.setLogFunction = setLogFunction;