@microsoft/teamsfx 2.2.3-alpha.9b38c38b5.0 → 2.2.3-alpha.a0d5ed36e.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.
@@ -10,7 +10,6 @@ import axios from 'axios';
10
10
  import { Agent } from 'https';
11
11
  import * as path from 'path';
12
12
  import * as fs from 'fs';
13
- import { __rest } from 'tslib';
14
13
  import { AdaptiveCards } from '@microsoft/adaptivecards-tools';
15
14
 
16
15
  // Copyright (c) Microsoft Corporation.
@@ -396,6 +395,7 @@ function getAuthority(authorityHost, tenantId) {
396
395
  return normalizedAuthorityHost + "/" + tenantId;
397
396
  }
398
397
 
398
+ // Copyright (c) Microsoft Corporation.
399
399
  /**
400
400
  * @internal
401
401
  */
@@ -713,16 +713,16 @@ class TeamsUserCredential {
713
713
  * @remarks
714
714
  * Can only be used within Teams.
715
715
  */
716
- async login(scopes, resources) {
717
- throw new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), ErrorCode.RuntimeNotSupported);
716
+ login(scopes, resources) {
717
+ return Promise.reject(new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), ErrorCode.RuntimeNotSupported));
718
718
  }
719
719
  /**
720
720
  * Get access token from credential.
721
721
  * @remarks
722
722
  * Can only be used within Teams.
723
723
  */
724
- async getToken(scopes, options) {
725
- throw new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), ErrorCode.RuntimeNotSupported);
724
+ getToken(scopes, options) {
725
+ return Promise.reject(new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), ErrorCode.RuntimeNotSupported));
726
726
  }
727
727
  /**
728
728
  * Get basic user info from SSO token
@@ -733,14 +733,16 @@ class TeamsUserCredential {
733
733
  * Can only be used within Teams.
734
734
  */
735
735
  getUserInfo(resources) {
736
- throw new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), ErrorCode.RuntimeNotSupported);
736
+ return Promise.reject(new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), ErrorCode.RuntimeNotSupported));
737
737
  }
738
738
  }
739
739
 
740
740
  // Copyright (c) Microsoft Corporation.
741
741
  const defaultScope = "https://graph.microsoft.com/.default";
742
+ // eslint-disable-next-line no-secrets/no-secrets
742
743
  /**
743
744
  * Microsoft Graph auth provider for Teams Framework
745
+ * @deprecated Use `TokenCredentialAuthenticationProvider` from `@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials` instead.
744
746
  */
745
747
  class MsGraphAuthProvider {
746
748
  constructor(credentialOrTeamsFx, scopes) {
@@ -769,7 +771,7 @@ class MsGraphAuthProvider {
769
771
  *
770
772
  */
771
773
  async getAccessToken() {
772
- internalLogger.info(`Get Graph Access token with scopes: '${this.scopes}'`);
774
+ internalLogger.info(`Get Graph Access token with scopes: '${this.scopes.toString()}'`);
773
775
  let accessToken;
774
776
  if (this.credentialOrTeamsFx.getCredential) {
775
777
  accessToken = await this.credentialOrTeamsFx
@@ -795,6 +797,14 @@ class MsGraphAuthProvider {
795
797
  // Copyright (c) Microsoft Corporation.
796
798
  /**
797
799
  * Get Microsoft graph client.
800
+ * @deprecated Use `TokenCredentialAuthenticationProvider` and `Client.initWithMiddleware` instead.
801
+ * ```typescript
802
+ * const authProvider = new TokenCredentialAuthenticationProvider(credential, { scopes: scope });
803
+ * const graph = Client.initWithMiddleware({
804
+ * authProvider: authProvider,
805
+ * });
806
+ * ```
807
+ *
798
808
  * @example
799
809
  * Get Microsoft graph client by TokenCredential
800
810
  * ```typescript
@@ -852,6 +862,14 @@ function createMicrosoftGraphClient(teamsfx, scopes) {
852
862
  // eslint-disable-next-line no-secrets/no-secrets
853
863
  /**
854
864
  * Get Microsoft graph client.
865
+ * @deprecated Use `TokenCredentialAuthenticationProvider` and `Client.initWithMiddleware` instead.
866
+ * ```typescript
867
+ * const authProvider = new TokenCredentialAuthenticationProvider(credential, { scopes: scope });
868
+ * const graph = Client.initWithMiddleware({
869
+ * authProvider: authProvider,
870
+ * });
871
+ * ```
872
+ *
855
873
  * @example
856
874
  * Get Microsoft graph client by TokenCredential
857
875
  * ```typescript
@@ -1007,7 +1025,7 @@ function isMsiAuthentication(teamsfx) {
1007
1025
  function generateDefaultConfig(teamsfx, databaseName) {
1008
1026
  internalLogger.verbose(`SQL server ${teamsfx.getConfig("sqlServerEndpoint")}
1009
1027
  , user name ${teamsfx.getConfig("sqlUsername")}
1010
- , database name ${databaseName}`);
1028
+ , database name ${databaseName ? databaseName : ""}`);
1011
1029
  const config = {
1012
1030
  server: teamsfx.getConfig("sqlServerEndpoint"),
1013
1031
  authentication: {
@@ -1060,7 +1078,7 @@ async function generateTokenConfig(teamsfx, databaseName) {
1060
1078
  };
1061
1079
  internalLogger.verbose(`Generate token configuration success
1062
1080
  , server endpoint is ${teamsfx.getConfig("sqlServerEndpoint")}
1063
- , database name is ${databaseName}`);
1081
+ , database name is ${databaseName ? databaseName : ""}`);
1064
1082
  return config;
1065
1083
  }
1066
1084
  internalLogger.error(`Generate token configuration
@@ -1328,7 +1346,8 @@ class TeamsBotSsoPrompt extends Dialog {
1328
1346
  async sendOAuthCardAsync(context) {
1329
1347
  internalLogger.verbose("Send OAuth card to get SSO token");
1330
1348
  const account = await TeamsInfo.getMember(context, context.activity.from.id);
1331
- internalLogger.verbose("Get Teams member account user principal name: " + account.userPrincipalName);
1349
+ internalLogger.verbose("Get Teams member account user principal name: " +
1350
+ (account.userPrincipalName ? account.userPrincipalName : ""));
1332
1351
  const loginHint = account.userPrincipalName ? account.userPrincipalName : "";
1333
1352
  const signInResource = this.getSignInResource(loginHint);
1334
1353
  const card = CardFactory.oauthCard("", "Teams SSO Sign In", "Sign In", signInResource.signInLink, signInResource.tokenExchangeResource);
@@ -1528,18 +1547,18 @@ class BasicAuthProvider {
1528
1547
  * @throws {@link ErrorCode|AuthorizationInfoAlreadyExists} - when Authorization header or auth property already exists in request configuration.
1529
1548
  * @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
1530
1549
  */
1531
- async AddAuthenticationInfo(config) {
1550
+ AddAuthenticationInfo(config) {
1532
1551
  if (config.headers && config.headers["Authorization"]) {
1533
- throw new ErrorWithCode(ErrorMessage.AuthorizationHeaderAlreadyExists, ErrorCode.AuthorizationInfoAlreadyExists);
1552
+ return Promise.reject(new ErrorWithCode(ErrorMessage.AuthorizationHeaderAlreadyExists, ErrorCode.AuthorizationInfoAlreadyExists));
1534
1553
  }
1535
1554
  if (config.auth) {
1536
- throw new ErrorWithCode(ErrorMessage.BasicCredentialAlreadyExists, ErrorCode.AuthorizationInfoAlreadyExists);
1555
+ return Promise.reject(new ErrorWithCode(ErrorMessage.BasicCredentialAlreadyExists, ErrorCode.AuthorizationInfoAlreadyExists));
1537
1556
  }
1538
1557
  config.auth = {
1539
1558
  username: this.userName,
1540
1559
  password: this.password,
1541
1560
  };
1542
- return config;
1561
+ return Promise.resolve(config);
1543
1562
  }
1544
1563
  }
1545
1564
 
@@ -1579,14 +1598,14 @@ class ApiKeyProvider {
1579
1598
  * @throws {@link ErrorCode|AuthorizationInfoAlreadyExists} - when API key already exists in request header or url query parameter.
1580
1599
  * @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
1581
1600
  */
1582
- async AddAuthenticationInfo(config) {
1601
+ AddAuthenticationInfo(config) {
1583
1602
  switch (this.keyLocation) {
1584
1603
  case ApiKeyLocation.Header:
1585
1604
  if (!config.headers) {
1586
1605
  config.headers = {};
1587
1606
  }
1588
1607
  if (config.headers[this.keyName]) {
1589
- throw new ErrorWithCode(formatString(ErrorMessage.DuplicateApiKeyInHeader, this.keyName), ErrorCode.AuthorizationInfoAlreadyExists);
1608
+ return Promise.reject(new ErrorWithCode(formatString(ErrorMessage.DuplicateApiKeyInHeader, this.keyName), ErrorCode.AuthorizationInfoAlreadyExists));
1590
1609
  }
1591
1610
  config.headers[this.keyName] = this.keyValue;
1592
1611
  break;
@@ -1600,12 +1619,12 @@ class ApiKeyProvider {
1600
1619
  urlHasDefinedApiKey = url.searchParams.has(this.keyName);
1601
1620
  }
1602
1621
  if (config.params[this.keyName] || urlHasDefinedApiKey) {
1603
- throw new ErrorWithCode(formatString(ErrorMessage.DuplicateApiKeyInQueryParam, this.keyName), ErrorCode.AuthorizationInfoAlreadyExists);
1622
+ return Promise.reject(new ErrorWithCode(formatString(ErrorMessage.DuplicateApiKeyInQueryParam, this.keyName), ErrorCode.AuthorizationInfoAlreadyExists));
1604
1623
  }
1605
1624
  config.params[this.keyName] = this.keyValue;
1606
1625
  break;
1607
1626
  }
1608
- return config;
1627
+ return Promise.resolve(config);
1609
1628
  }
1610
1629
  }
1611
1630
  /**
@@ -1652,7 +1671,7 @@ class CertificateAuthProvider {
1652
1671
  *
1653
1672
  * @throws {@link ErrorCode|InvalidParameter} - when custom httpsAgent in the request has duplicate properties with certOption provided in constructor.
1654
1673
  */
1655
- async AddAuthenticationInfo(config) {
1674
+ AddAuthenticationInfo(config) {
1656
1675
  if (!config.httpsAgent) {
1657
1676
  config.httpsAgent = new Agent(this.certOption);
1658
1677
  }
@@ -1660,12 +1679,12 @@ class CertificateAuthProvider {
1660
1679
  const existingProperties = new Set(Object.keys(config.httpsAgent.options));
1661
1680
  for (const property of Object.keys(this.certOption)) {
1662
1681
  if (existingProperties.has(property)) {
1663
- throw new ErrorWithCode(formatString(ErrorMessage.DuplicateHttpsOptionProperty, property), ErrorCode.InvalidParameter);
1682
+ return Promise.reject(new ErrorWithCode(formatString(ErrorMessage.DuplicateHttpsOptionProperty, property), ErrorCode.InvalidParameter));
1664
1683
  }
1665
1684
  }
1666
1685
  Object.assign(config.httpsAgent.options, this.certOption);
1667
1686
  }
1668
- return config;
1687
+ return Promise.resolve(config);
1669
1688
  }
1670
1689
  }
1671
1690
  /**
@@ -1734,6 +1753,8 @@ const ReservedKey = new Set([
1734
1753
  ]);
1735
1754
  /**
1736
1755
  * A class providing credential and configuration.
1756
+ * @deprecated Please use {@link TeamsUserCredential}
1757
+ * in browser environment and {@link OnBehalfOfUserCredential} or {@link AppCredential} in NodeJS.
1737
1758
  */
1738
1759
  class TeamsFx {
1739
1760
  /**
@@ -1963,6 +1984,7 @@ var InvokeResponseErrorCode;
1963
1984
  InvokeResponseErrorCode[InvokeResponseErrorCode["InternalServerError"] = 500] = "InternalServerError";
1964
1985
  })(InvokeResponseErrorCode || (InvokeResponseErrorCode = {}));
1965
1986
 
1987
+ // Copyright (c) Microsoft Corporation.
1966
1988
  /**
1967
1989
  * Available response type for an adaptive card invoke response.
1968
1990
  * @internal
@@ -1977,7 +1999,7 @@ var InvokeResponseType;
1977
1999
  * Provides methods for formatting various invoke responses a bot can send to respond to an invoke request.
1978
2000
  *
1979
2001
  * @remarks
1980
- * All of these functions return an {@link InvokeResponse} object, which can be
2002
+ * All of these functions return an `InvokeResponse` object, which can be
1981
2003
  * passed as input to generate a new `invokeResponse` activity.
1982
2004
  *
1983
2005
  * This example sends an invoke response that contains an adaptive card.
@@ -2402,6 +2424,7 @@ function cloneConversation(conversation) {
2402
2424
  */
2403
2425
  function getKey(reference) {
2404
2426
  var _a, _b;
2427
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
2405
2428
  return `_${(_a = reference.conversation) === null || _a === void 0 ? void 0 : _a.tenantId}_${(_b = reference.conversation) === null || _b === void 0 ? void 0 : _b.id}`;
2406
2429
  }
2407
2430
  /**
@@ -2719,7 +2742,7 @@ class Channel$1 {
2719
2742
  async sendMessage(text, onError) {
2720
2743
  const response = {};
2721
2744
  await this.parent.adapter.continueConversation(this.parent.conversationReference, async (context) => {
2722
- const conversation = await this.newConversation(context);
2745
+ const conversation = this.newConversation(context);
2723
2746
  await this.parent.adapter.continueConversation(conversation, async (ctx) => {
2724
2747
  try {
2725
2748
  const res = await ctx.sendActivity(text);
@@ -2748,7 +2771,7 @@ class Channel$1 {
2748
2771
  async sendAdaptiveCard(card, onError) {
2749
2772
  const response = {};
2750
2773
  await this.parent.adapter.continueConversation(this.parent.conversationReference, async (context) => {
2751
- const conversation = await this.newConversation(context);
2774
+ const conversation = this.newConversation(context);
2752
2775
  await this.parent.adapter.continueConversation(conversation, async (ctx) => {
2753
2776
  try {
2754
2777
  const res = await ctx.sendActivity({
@@ -2771,7 +2794,7 @@ class Channel$1 {
2771
2794
  /**
2772
2795
  * @internal
2773
2796
  */
2774
- async newConversation(context) {
2797
+ newConversation(context) {
2775
2798
  const reference = TurnContext.getConversationReference(context.activity);
2776
2799
  const channelConversation = cloneConversation(reference);
2777
2800
  channelConversation.conversation.id = this.info.id || "";
@@ -3200,6 +3223,38 @@ var SearchScope$1;
3200
3223
  SearchScope[SearchScope["All"] = 7] = "All";
3201
3224
  })(SearchScope$1 || (SearchScope$1 = {}));
3202
3225
 
3226
+ /******************************************************************************
3227
+ Copyright (c) Microsoft Corporation.
3228
+
3229
+ Permission to use, copy, modify, and/or distribute this software for any
3230
+ purpose with or without fee is hereby granted.
3231
+
3232
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
3233
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
3234
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
3235
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
3236
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
3237
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
3238
+ PERFORMANCE OF THIS SOFTWARE.
3239
+ ***************************************************************************** */
3240
+
3241
+ function __rest(s, e) {
3242
+ var t = {};
3243
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
3244
+ t[p] = s[p];
3245
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
3246
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
3247
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
3248
+ t[p[i]] = s[p[i]];
3249
+ }
3250
+ return t;
3251
+ }
3252
+
3253
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
3254
+ var e = new Error(message);
3255
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
3256
+ };
3257
+
3203
3258
  // Copyright (c) Microsoft Corporation.
3204
3259
  let DIALOG_NAME = "BotSsoExecutionDialog";
3205
3260
  let TEAMS_SSO_PROMPT_ID = "TeamsFxSsoPrompt";
@@ -3481,8 +3536,7 @@ class DefaultBotSsoExecutionActivityHandler extends TeamsActivityHandler {
3481
3536
  timeout: (_h = (_g = ssoConfig.dialog) === null || _g === void 0 ? void 0 : _g.ssoPromptConfig) === null || _h === void 0 ? void 0 : _h.timeout,
3482
3537
  endOnInvalidMessage: (_k = (_j = ssoConfig.dialog) === null || _j === void 0 ? void 0 : _j.ssoPromptConfig) === null || _k === void 0 ? void 0 : _k.endOnInvalidMessage,
3483
3538
  };
3484
- const teamsfx = new TeamsFx(IdentityType.User, Object.assign({}, customConfig));
3485
- this.ssoExecutionDialog = new BotSsoExecutionDialog(dedupStorage, settings, teamsfx);
3539
+ this.ssoExecutionDialog = new BotSsoExecutionDialog(dedupStorage, settings, customConfig, customConfig.initiateLoginEndpoint);
3486
3540
  this.conversationState = conversationState;
3487
3541
  this.dialogState = conversationState.createProperty("DialogState");
3488
3542
  this.userState = userState;
@@ -3533,7 +3587,7 @@ class DefaultBotSsoExecutionActivityHandler extends TeamsActivityHandler {
3533
3587
  * @param query Signin state (part of signin action auth flow) verification invoke query
3534
3588
  * @returns A promise that represents the work queued.
3535
3589
  *
3536
- * @remark
3590
+ * @remarks
3537
3591
  * It should trigger {@link BotSsoExecutionDialog} instance to handle signin process
3538
3592
  */
3539
3593
  async handleTeamsSigninTokenExchange(context, query) {
@@ -3643,9 +3697,12 @@ class ConversationBot$1 {
3643
3697
  // the default error handler
3644
3698
  adapter.onTurnError = async (context, error) => {
3645
3699
  // This check writes out errors to console.
3700
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
3646
3701
  console.error(`[onTurnError] unhandled error: ${error}`);
3647
3702
  // Send a trace activity, which will be displayed in Bot Framework Emulator
3648
- await context.sendTraceActivity("OnTurnError Trace", `${error}`, "https://www.botframework.com/schemas/error", "TurnError");
3703
+ await context.sendTraceActivity("OnTurnError Trace",
3704
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
3705
+ `${error}`, "https://www.botframework.com/schemas/error", "TurnError");
3649
3706
  // Send a message to the user
3650
3707
  await context.sendActivity(`The bot encountered unhandled error: ${error.message}`);
3651
3708
  await context.sendActivity("To continue to run this bot, please fix the bot source code.");
@@ -3924,6 +3981,7 @@ async function executionWithTokenAndConfig(context, authConfig, initiateLoginEnd
3924
3981
  }
3925
3982
  /**
3926
3983
  * execution in message extension with SSO token.
3984
+ * @deprecated Use {@link executionWithTokenAndConfig} instead.
3927
3985
  *
3928
3986
  * @param {TurnContext} context - The context object for the current turn.
3929
3987
  * @param {AuthenticationConfiguration} config - User custom the message extension authentication configuration.
@@ -3972,7 +4030,7 @@ async function executionWithToken(context, config, scopes, logic) {
3972
4030
  // eslint-disable-next-line no-secrets/no-secrets
3973
4031
  /**
3974
4032
  * Users execute query in message extension with SSO or access token.
3975
- *
4033
+ * @deprecated Use {@link handleMessageExtensionQueryWithSSO} instead.
3976
4034
  *
3977
4035
  * @param {TurnContext} context - The context object for the current turn.
3978
4036
  * @param {AuthenticationConfiguration} config - User custom the message extension authentication configuration.
@@ -4245,11 +4303,11 @@ class Channel {
4245
4303
  /**
4246
4304
  * @internal
4247
4305
  */
4248
- async newConversation(context) {
4306
+ newConversation(context) {
4249
4307
  const reference = TurnContext.getConversationReference(context.activity);
4250
4308
  const channelConversation = cloneConversation(reference);
4251
4309
  channelConversation.conversation.id = this.info.id || "";
4252
- return channelConversation;
4310
+ return Promise.resolve(channelConversation);
4253
4311
  }
4254
4312
  }
4255
4313
  /**
@@ -4556,6 +4614,27 @@ class NotificationBot {
4556
4614
  }
4557
4615
  return new TeamsBotInstallation(this.adapter, conversationReference, this.botAppId);
4558
4616
  }
4617
+ /**
4618
+ * Validate the installation by getting paged memebers.
4619
+ *
4620
+ * @param conversationReference The bound `ConversationReference`.
4621
+ * @returns Returns false if recieves `BotNotInConversationRoster` error, otherwise returns true.
4622
+ */
4623
+ async validateInstallation(conversationReference) {
4624
+ let isValid = true;
4625
+ await this.adapter.continueConversationAsync(this.botAppId, conversationReference, async (context) => {
4626
+ try {
4627
+ // try get member to see if the installation is still valid
4628
+ await TeamsInfo.getPagedMembers(context, 1);
4629
+ }
4630
+ catch (error) {
4631
+ if (error.code === "BotNotInConversationRoster") {
4632
+ isValid = false;
4633
+ }
4634
+ }
4635
+ });
4636
+ return isValid;
4637
+ }
4559
4638
  /**
4560
4639
  * Gets a pagined list of targets where the bot is installed.
4561
4640
  *
@@ -4567,7 +4646,7 @@ class NotificationBot {
4567
4646
  *
4568
4647
  * @returns An array of {@link TeamsBotInstallation} with paged data and continuation token.
4569
4648
  */
4570
- async getPagedInstallations(pageSize, continuationToken) {
4649
+ async getPagedInstallations(pageSize, continuationToken, validationEnabled = true) {
4571
4650
  if (this.conversationReferenceStore === undefined || this.adapter === undefined) {
4572
4651
  throw new Error("NotificationBot has not been initialized.");
4573
4652
  }
@@ -4575,19 +4654,12 @@ class NotificationBot {
4575
4654
  const targets = [];
4576
4655
  for (const reference of references.data) {
4577
4656
  // validate connection
4578
- let valid = true;
4579
- await this.adapter.continueConversationAsync(this.botAppId, reference, async (context) => {
4580
- try {
4581
- // try get member to see if the installation is still valid
4582
- await TeamsInfo.getPagedMembers(context, 1);
4583
- }
4584
- catch (error) {
4585
- if (error.code === "BotNotInConversationRoster") {
4586
- valid = false;
4587
- }
4588
- }
4589
- });
4590
- if (valid) {
4657
+ let valid;
4658
+ if (validationEnabled) {
4659
+ // try get member to see if the installation is still valid
4660
+ valid = await this.validateInstallation(reference);
4661
+ }
4662
+ if (!validationEnabled || (validationEnabled && valid)) {
4591
4663
  targets.push(new TeamsBotInstallation(this.adapter, reference, this.botAppId));
4592
4664
  }
4593
4665
  else {
@@ -4849,9 +4921,9 @@ class ConversationBot {
4849
4921
  // the default error handler
4850
4922
  adapter.onTurnError = async (context, error) => {
4851
4923
  // This check writes out errors to console.
4852
- console.error(`[onTurnError] unhandled error: ${error}`);
4924
+ console.error(`[onTurnError] unhandled error`, error);
4853
4925
  // Send a trace activity, which will be displayed in Bot Framework Emulator
4854
- await context.sendTraceActivity("OnTurnError Trace", `${error}`, "https://www.botframework.com/schemas/error", "TurnError");
4926
+ await context.sendTraceActivity("OnTurnError Trace", error instanceof Error ? error.message : error, "https://www.botframework.com/schemas/error", "TurnError");
4855
4927
  // Send a message to the user
4856
4928
  await context.sendActivity(`The bot encountered unhandled error: ${error.message}`);
4857
4929
  await context.sendActivity("To continue to run this bot, please fix the bot source code.");