* Add CreateACSAdapter scenario markers

* Add urlResolvers util & Refactor

* Refactor

* Update test

* Add support on DirectLine version & CDN URL config properties & Update tests

* Add telemetry event

* Add DirectLine chat adapter optional params

* Add DirectLine property on CDNPackagesInfo

* Add ability to create DirectLine

* Throw Error on adapter load failure

* Clean up

* Add ChatSDKErrors enum

* Refactor & Add test

* Update CHANGELOG.md

* Refactor

* Add chatAdapterCreators util & Refactor creationg of DirectLine

* Refactor

* Refactor creation of ACSAdapter

* Clean up

* Refactor creation of IC3Adapter

* Fix lint
This commit is contained in:
xTEddie 2022-11-15 16:43:24 -08:00 коммит произвёл GitHub
Родитель 2a7572c4fc
Коммит 5f9a9ded5d
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
13 изменённых файлов: 363 добавлений и 134 удалений

Просмотреть файл

@ -2,6 +2,9 @@
All notable changes to this project will be documented in this file.
## [Unreleased]
### Added
- Add ability to use `ChatSDK.createChatAdapter()` for `DirectLine` protocol
- Add `CreateACSAdapter` telemetry event
## [1.2.0] - 2022-11-11
### Added

Просмотреть файл

@ -197,6 +197,58 @@ describe('Omnichannel Chat SDK', () => {
expect(url).toBe(libraries.getACSAdapterCDNUrl());
});
it('ChatSDK should be able to pick custom webChatDirectLineVersion if set', async () => {
const omnichannelConfig = {
orgUrl: '',
orgId: '',
widgetId: ''
};
const chatSDKConfig = {
chatAdapterConfig: {
webChatDirectLineVersion: 'version'
}
};
const chatSDK = new OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
const url = chatSDK.resolveChatAdapterUrl(ChatAdapterProtocols.DirectLine);
expect(url).toBe(libraries.getDirectLineCDNUrl(chatSDKConfig.chatAdapterConfig.webChatDirectLineVersion));
});
it('ChatSDK should be able to pick custom webChatDirectLineCDNUrl if set', async () => {
const omnichannelConfig = {
orgUrl: '',
orgId: '',
widgetId: ''
};
const chatSDKConfig = {
chatAdapterConfig: {
webChatDirectLineVersion: 'version',
webChatDirectLineCDNUrl: 'cdn'
}
};
const chatSDK = new OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
const url = chatSDK.resolveChatAdapterUrl(ChatAdapterProtocols.DirectLine);
expect(url).toBe(chatSDKConfig.chatAdapterConfig.webChatDirectLineCDNUrl);
});
it('ChatSDK should pick the default webChatDirectLineCDNUrl if no chatAdapterConfig is set', async () => {
const omnichannelConfig = {
orgUrl: '',
orgId: '',
widgetId: ''
};
const chatSDK = new OmnichannelChatSDK(omnichannelConfig);
const url = chatSDK.resolveChatAdapterUrl(ChatAdapterProtocols.DirectLine);
expect(url).toBe(libraries.getDirectLineCDNUrl());
});
it('ChatSDK should throw an error if ChatSDK.resolveChatAdapterUrl() is called with other protocol than supported protocols', async () => {
const omnichannelConfig = {
orgUrl: '',
@ -206,9 +258,10 @@ describe('Omnichannel Chat SDK', () => {
const chatSDK = new OmnichannelChatSDK(omnichannelConfig);
const protocol = ChatAdapterProtocols.DirectLine;
const protocol = "UnsupportedProtocol";
try {
chatSDK.resolveChatAdapterUrl(protocol);
fail();
} catch (error) {
expect(error.toString()).toContain(`ChatAdapter for protocol ${protocol} currently not supported`);
}

Просмотреть файл

@ -12,6 +12,7 @@ import CallingOptionsOptionSetNumber from "../src/core/CallingOptionsOptionSetNu
import AriaTelemetry from "../src/telemetry/AriaTelemetry";
import * as settings from '../src/config/settings';
import { AWTLogManager } from "../src/external/aria/webjs/AriaSDK";
import ChatSDKErrors from "../src/core/ChatSDKErrors";
describe('Omnichannel Chat SDK (Web)', () => {
(settings as any).ariaTelemetryKey = '';
@ -67,6 +68,40 @@ describe('Omnichannel Chat SDK (Web)', () => {
expect(chatSDK.OCClient.sessionInit.mock.calls[0][1]).toMatchObject(sessionInitOptionalParams);
});
it('ChatSDK.startChat() with sendDefaultInitContext should throw an error if not used on Web Platform', async () => {
const chatSDK = new OmnichannelChatSDK(omnichannelConfig);
chatSDK.getChatConfig = jest.fn();
await chatSDK.initialize();
chatSDK.IC3Client = {
initialize: jest.fn(),
joinConversation: jest.fn()
}
const optionalParams = {
sendDefaultInitContext: true
}
jest.spyOn(chatSDK.OCClient, 'getChatToken').mockResolvedValue(Promise.resolve({
ChatId: '',
Token: '',
RegionGtms: '{}'
}));
jest.spyOn(chatSDK.OCClient, 'sessionInit').mockResolvedValue(Promise.resolve());
jest.spyOn(platform, 'isNode').mockReturnValue(true);
jest.spyOn(platform, 'isReactNative').mockReturnValue(false);
jest.spyOn(platform, 'isBrowser').mockReturnValue(false);
try {
await chatSDK.startChat(optionalParams);
} catch (error) {
expect(error.message).toEqual(ChatSDKErrors.UnsupportedPlatform);
}
});
it('ChatSDK.createChatAdapter() should be returned succesfully on Web platform', async () => {
const chatSDK = new OmnichannelChatSDK(omnichannelConfig);
chatSDK.getChatConfig = jest.fn();
@ -109,7 +144,7 @@ describe('Omnichannel Chat SDK (Web)', () => {
jest.spyOn(platform, 'isReactNative').mockReturnValue(false);
jest.spyOn(platform, 'isBrowser').mockReturnValue(true);
const protocol = 'DirectLine';
const protocol = 'UnsupportedProtocol';
const optionalParams = {
protocol
}

Просмотреть файл

@ -15,13 +15,16 @@ import AuthSettings from "./core/AuthSettings";
import CallingOptionsOptionSetNumber from "./core/CallingOptionsOptionSetNumber";
import ChatAdapterOptionalParams from "./core/messaging/ChatAdapterOptionalParams";
import ChatAdapterProtocols from "./core/messaging/ChatAdapterProtocols";
import { ChatClient } from "@azure/communication-chat";
import ChatConfig from "./core/ChatConfig";
import ChatReconnectContext from "./core/ChatReconnectContext";
import ChatReconnectOptionalParams from "./core/ChatReconnectOptionalParams";
import ChatSDKConfig from "./core/ChatSDKConfig";
import ChatSDKErrors from "./core/ChatSDKErrors";
import ChatSDKExceptionDetails from "./core/ChatSDKExceptionDetails";
import ChatSDKMessage from "./core/messaging/ChatSDKMessage";
import ChatTranscriptBody from "./core/ChatTranscriptBody";
import { createACSAdapter, createDirectLine, createIC3Adapter } from "./utils/chatAdapterCreators";
import ConversationMode from "./core/ConversationMode";
import DeliveryMode from "@microsoft/omnichannel-ic3core/lib/model/DeliveryMode";
import FileMetadata from "@microsoft/omnichannel-amsclient/lib/FileMetadata";
@ -39,7 +42,6 @@ import IFileMetadata from "@microsoft/omnichannel-ic3core/lib/model/IFileMetadat
import IGetChatTokenOptionalParams from "@microsoft/ocsdk/lib/Interfaces/IGetChatTokenOptionalParams";
import IGetChatTranscriptsOptionalParams from "@microsoft/ocsdk/lib/Interfaces/IGetChatTranscriptsOptionalParams";
import IGetLWIDetailsOptionalParams from "@microsoft/ocsdk/lib/Interfaces/IGetLWIDetailsOptionalParams";
import IIC3AdapterOptions from "./external/IC3Adapter/IIC3AdapterOptions";
import IInitializationInfo from "@microsoft/omnichannel-ic3core/lib/model/IInitializationInfo";
import IMessage from "@microsoft/omnichannel-ic3core/lib/model/IMessage";
import InitializeOptionalParams from "./core/InitializeOptionalParams";
@ -71,15 +73,12 @@ import ScenarioMarker from "./telemetry/ScenarioMarker";
import StartChatOptionalParams from "./core/StartChatOptionalParams";
import TelemetryEvent from "./telemetry/TelemetryEvent";
import createAMSClient from "@microsoft/omnichannel-amsclient";
import createChannelDataEgressMiddleware from "./external/ACSAdapter/createChannelDataEgressMiddleware";
import createFormatEgressTagsMiddleware from "./external/ACSAdapter/createFormatEgressTagsMiddleware";
import createFormatIngressTagsMiddleware from "./external/ACSAdapter/createFormatIngressTagsMiddleware";
import createOmnichannelMessage from "./utils/createOmnichannelMessage";
import createTelemetry from "./utils/createTelemetry";
import createVoiceVideoCalling from "./api/createVoiceVideoCalling";
import { defaultMessageTags } from "./core/messaging/MessageTags";
import {isCustomerMessage} from "./utils/utilities";
import libraries from "./utils/libraries";
import urlResolvers from "./utils/urlResolvers";
import validateOmnichannelConfig from "./validators/OmnichannelConfigValidator";
class OmnichannelChatSDK {
@ -452,7 +451,7 @@ class OmnichannelChatSDK {
if (optionalParams.sendDefaultInitContext) {
if (platform.isNode() || platform.isReactNative()) {
const exceptionDetails: ChatSDKExceptionDetails = {
response: "UnsupportedPlatform",
response: ChatSDKErrors.UnsupportedPlatform,
message: "sendDefaultInitContext is only supported on browser"
};
@ -1447,7 +1446,6 @@ class OmnichannelChatSDK {
});
try {
if (this.authenticatedUserToken) {
emailTranscriptOptionalParams.authenticatedUserToken = this.authenticatedUserToken;
}
@ -1519,94 +1517,18 @@ class OmnichannelChatSDK {
}
const {protocol} = optionalParams;
const supportedChatAdapterProtocols = [ChatAdapterProtocols.ACS, ChatAdapterProtocols.IC3];
const supportedChatAdapterProtocols = [ChatAdapterProtocols.ACS, ChatAdapterProtocols.IC3, ChatAdapterProtocols.DirectLine];
if (protocol && !supportedChatAdapterProtocols.includes(protocol as string)) {
return Promise.reject(`ChatAdapter for protocol ${protocol} currently not supported`);
}
if (protocol === ChatAdapterProtocols.ACS || this.liveChatVersion === LiveChatVersion.V2) {
return new Promise (async (resolve, reject) => { // eslint-disable-line no-async-promise-executor
const options = optionalParams.ACSAdapter? optionalParams.ACSAdapter.options: {};
// Tags formatting middlewares are required to be the last in the pipeline to ensure tags are converted to the right format
const defaultEgressMiddlewares = [createChannelDataEgressMiddleware({widgetId: this.omnichannelConfig.widgetId}), createFormatEgressTagsMiddleware()];
const defaultIngressMiddlewares = [createFormatIngressTagsMiddleware()];
const egressMiddleware = options?.egressMiddleware? [...options.egressMiddleware, ...defaultEgressMiddlewares]: [...defaultEgressMiddlewares];
const ingressMiddleware = options?.ingressMiddleware? [...options.egressMiddleware, ...defaultIngressMiddlewares]: [...defaultIngressMiddlewares];
const featuresOption = {
enableAdaptiveCards: true, // Whether to enable adaptive card payload in adapter (payload in JSON string)
enableThreadMemberUpdateNotification: true, // Whether to enable chat thread member join/leave notification
enableLeaveThreadOnWindowClosed: false, // Whether to remove user on browser close event
...options, // overrides
ingressMiddleware,
egressMiddleware
};
const acsAdapterCDNUrl = this.resolveChatAdapterUrl(protocol || ChatAdapterProtocols.ACS);
this.telemetry?.setCDNPackages({
ACSAdapter: acsAdapterCDNUrl
});
await loadScript(acsAdapterCDNUrl, () => {
/* istanbul ignore next */
this.debug && console.debug('ACSAdapter loaded!');
try {
const { ChatAdapter } = window as any; // eslint-disable-line @typescript-eslint/no-explicit-any
const fileManager = new AMSFileManager(this.AMSClient as FramedClient, this.acsAdapterLogger);
const adapter = ChatAdapter.createACSAdapter(
this.chatToken.token as string,
this.chatToken.visitorId || 'teamsvisitor',
this.chatToken.chatId as string,
this.chatToken.acsEndpoint as string,
fileManager,
30000,
ACSParticipantDisplayName.Customer,
this.ACSClient?.getChatClient(),
this.acsAdapterLogger, // logger
featuresOption,
);
resolve(adapter);
} catch {
throw new Error('Failed to load ACSAdapter');
}
}, () => {
reject('Failed to load ACSADapter');
});
});
if (protocol === ChatAdapterProtocols.DirectLine) {
return createDirectLine(optionalParams, this.chatSDKConfig, this.liveChatVersion, ChatAdapterProtocols.DirectLine, this.telemetry as typeof AriaTelemetry, this.scenarioMarker);
} else if (protocol === ChatAdapterProtocols.ACS || this.liveChatVersion === LiveChatVersion.V2) {
const fileManager = new AMSFileManager(this.AMSClient as FramedClient, this.acsAdapterLogger);
return createACSAdapter(optionalParams, this.chatSDKConfig, this.liveChatVersion, ChatAdapterProtocols.ACS, this.telemetry as typeof AriaTelemetry, this.scenarioMarker, this.omnichannelConfig, this.chatToken, fileManager, this.ACSClient?.getChatClient() as ChatClient, this.acsAdapterLogger as ACSAdapterLogger);
} else if (protocol === ChatAdapterProtocols.IC3 || this.liveChatVersion === LiveChatVersion.V1) {
return new Promise (async (resolve, reject) => { // eslint-disable-line no-async-promise-executor
const options = optionalParams.IC3Adapter? optionalParams.IC3Adapter.options: {};
const ic3AdapterCDNUrl = this.resolveChatAdapterUrl(protocol || ChatAdapterProtocols.IC3);
this.telemetry?.setCDNPackages({
IC3Adapter: ic3AdapterCDNUrl
});
this.scenarioMarker.startScenario(TelemetryEvent.CreateIC3Adapter);
await loadScript(ic3AdapterCDNUrl, () => {
/* istanbul ignore next */
this.debug && console.debug('IC3Adapter loaded!');
const adapterConfig: IIC3AdapterOptions = {
chatToken: this.chatToken,
userDisplayName: 'Customer',
userId: this.chatToken.visitorId || 'teamsvisitor',
sdkURL: this.resolveIC3ClientUrl(),
sdk: this.IC3Client,
...options // overrides
};
const adapter = new window.Microsoft.BotFramework.WebChat.IC3Adapter(adapterConfig);
adapter.logger = this.ic3ClientLogger;
this.scenarioMarker.completeScenario(TelemetryEvent.CreateIC3Adapter);
resolve(adapter);
}, () => {
this.scenarioMarker.failScenario(TelemetryEvent.CreateIC3Adapter);
reject('Failed to load IC3Adapter');
});
});
return createIC3Adapter(optionalParams, this.chatSDKConfig, this.liveChatVersion, ChatAdapterProtocols.IC3, this.telemetry as typeof AriaTelemetry, this.scenarioMarker, this.chatToken, this.IC3Client, this.ic3ClientLogger as IC3ClientLogger);
}
return Promise.reject(`ChatAdapter for protocol ${protocol} currently not supported`);
@ -1912,46 +1834,11 @@ class OmnichannelChatSDK {
}
private resolveIC3ClientUrl(): string {
if (this.chatSDKConfig.ic3Config && 'ic3ClientCDNUrl' in this.chatSDKConfig.ic3Config) {
return this.chatSDKConfig.ic3Config.ic3ClientCDNUrl as string;
}
if (this.chatSDKConfig.ic3Config && 'ic3ClientVersion' in this.chatSDKConfig.ic3Config) {
return libraries.getIC3ClientCDNUrl(this.chatSDKConfig.ic3Config.ic3ClientVersion);
}
return libraries.getIC3ClientCDNUrl();
return urlResolvers.resolveIC3ClientUrl(this.chatSDKConfig);
}
private resolveChatAdapterUrl(protocol: string): string {
const supportedChatAdapterProtocols = [ChatAdapterProtocols.ACS, ChatAdapterProtocols.IC3];
if (protocol && !supportedChatAdapterProtocols.includes(protocol as string)) {
throw new Error(`ChatAdapter for protocol ${protocol} currently not supported`);
}
if (protocol === ChatAdapterProtocols.ACS || this.liveChatVersion === LiveChatVersion.V2) {
if (this.chatSDKConfig.chatAdapterConfig && 'webChatACSAdapterCDNUrl' in this.chatSDKConfig.chatAdapterConfig) {
return this.chatSDKConfig.chatAdapterConfig.webChatACSAdapterCDNUrl as string;
}
if (this.chatSDKConfig.chatAdapterConfig && 'webChatACSAdapterVersion' in this.chatSDKConfig.chatAdapterConfig) {
return libraries.getACSAdapterCDNUrl(this.chatSDKConfig.chatAdapterConfig.webChatACSAdapterVersion);
}
return libraries.getACSAdapterCDNUrl();
} else if (protocol === ChatAdapterProtocols.IC3 || this.liveChatVersion === LiveChatVersion.V1) {
if (this.chatSDKConfig.chatAdapterConfig && 'webChatIC3AdapterCDNUrl' in this.chatSDKConfig.chatAdapterConfig) {
return this.chatSDKConfig.chatAdapterConfig.webChatIC3AdapterCDNUrl as string;
}
if (this.chatSDKConfig.chatAdapterConfig && 'webChatIC3AdapterVersion' in this.chatSDKConfig.chatAdapterConfig) {
return libraries.getIC3AdapterCDNUrl(this.chatSDKConfig.chatAdapterConfig.webChatIC3AdapterVersion);
}
return libraries.getIC3AdapterCDNUrl();
}
return '';
return urlResolvers.resolveChatAdapterUrl(this.chatSDKConfig, this.liveChatVersion, protocol);
}
private async updateChatToken(newToken: string, newRegionGTMS: IRegionGtms): Promise<void> {

Просмотреть файл

@ -1,11 +1,13 @@
const ic3ClientVersion = '2021.08.14.1';
const webChatIC3AdapterVersion = '0.1.0-master.2dba07b';
const webChatACSAdapterVersion = '0.0.35-beta.12';
const webChatDirectLineVersion = '0.15.1';
const ariaTelemetryKey = 'c7655518acf1403f93ff6b9f77942f0a-d01a02fd-6b50-4de3-a566-62eda11f93bc-7083';
export {
ic3ClientVersion,
webChatIC3AdapterVersion,
webChatACSAdapterVersion,
webChatDirectLineVersion,
ariaTelemetryKey
};

Просмотреть файл

@ -0,0 +1,5 @@
enum ChatSDKErrors {
UnsupportedPlatform = "UnsupportedPlatform"
}
export default ChatSDKErrors;

Просмотреть файл

@ -3,4 +3,6 @@ export default interface ChatAdapterConfig {
webChatIC3AdapterCDNUrl?: string;
webChatACSAdapterVersion?: string;
webChatACSAdapterCDNUrl?: string;
webChatDirectLineVersion?: string;
webChatDirectLineCDNUrl?: string;
}

Просмотреть файл

@ -4,12 +4,17 @@ interface ChatAdapterOptionalParams {
options?: {
[key: string]: any // eslint-disable-line @typescript-eslint/no-explicit-any
}
}
};
ACSAdapter?: {
options?: {
[key: string]: any // eslint-disable-line @typescript-eslint/no-explicit-any
}
}
};
DirectLine?: {
options?: {
[key: string]: any // eslint-disable-line @typescript-eslint/no-explicit-any
}
};
}
export default ChatAdapterOptionalParams;

Просмотреть файл

@ -35,6 +35,7 @@ interface CDNPackagesInfo {
IC3Client?: string;
IC3Adapter?: string;
ACSAdapter?: string;
DirectLine?: string;
SpoolSDK?: string;
VoiceVideoCalling?: string;
}

Просмотреть файл

@ -22,6 +22,7 @@ enum TelemetryEvent {
GetLiveChatTranscript = "GetLiveChatTranscript",
CreateIC3Adapter = "CreateChatAdapter",
CreateACSAdapter = "CreateACSAdapter",
CreateDirectLine = "CreateDirectLine",
GetVoiceVideoCalling = "GetVoiceVideoCalling",
GetIC3Client = "GetIC3Client",
InitializeVoiceVideoCallingSDK = "InitializeVoiceVideoCallingSDK",

Просмотреть файл

@ -0,0 +1,149 @@
import { ACSAdapterLogger, IC3ClientLogger } from "./loggers";
import ACSParticipantDisplayName from "../core/messaging/ACSParticipantDisplayName";
import AMSFileManager from "../external/ACSAdapter/AMSFileManager";
import AriaTelemetry from "../telemetry/AriaTelemetry";
import ChatAdapterOptionalParams from "../core/messaging/ChatAdapterOptionalParams";
import { ChatClient } from "@azure/communication-chat";
import ChatSDKConfig from "../core/ChatSDKConfig";
import createChannelDataEgressMiddleware from "../external/ACSAdapter/createChannelDataEgressMiddleware";
import createFormatEgressTagsMiddleware from "../external/ACSAdapter/createFormatEgressTagsMiddleware";
import createFormatIngressTagsMiddleware from "../external/ACSAdapter/createFormatIngressTagsMiddleware";
import IChatToken from "../external/IC3Adapter/IChatToken";
import IIC3AdapterOptions from "../external/IC3Adapter/IIC3AdapterOptions";
import LiveChatVersion from "../core/LiveChatVersion";
import { loadScript } from "./WebUtils";
import OmnichannelConfig from "../core/OmnichannelConfig";
import ScenarioMarker from "../telemetry/ScenarioMarker";
import TelemetryEvent from "../telemetry/TelemetryEvent";
import urlResolvers from "./urlResolvers";
const createDirectLine = async (optionalParams: ChatAdapterOptionalParams, chatSDKConfig: ChatSDKConfig, liveChatVersion: LiveChatVersion, protocol: string, telemetry: typeof AriaTelemetry, scenarioMarker: ScenarioMarker): Promise<unknown> => {
const options = optionalParams.DirectLine? optionalParams.DirectLine.options: {};
const directLineCDNUrl = urlResolvers.resolveChatAdapterUrl(chatSDKConfig, liveChatVersion, protocol);
telemetry?.setCDNPackages({
DirectLine: directLineCDNUrl
});
scenarioMarker.startScenario(TelemetryEvent.CreateDirectLine);
try {
await loadScript(directLineCDNUrl);
} catch {
scenarioMarker.failScenario(TelemetryEvent.CreateDirectLine);
throw new Error('Failed to load DirectLine');
}
try {
const {DirectLine} = window as any; // eslint-disable-line @typescript-eslint/no-explicit-any
const adapter = new DirectLine.DirectLine({...options});
scenarioMarker.completeScenario(TelemetryEvent.CreateDirectLine);
return adapter;
} catch {
scenarioMarker.failScenario(TelemetryEvent.CreateDirectLine);
throw new Error('Failed to create DirectLine');
}
};
const createACSAdapter = async (optionalParams: ChatAdapterOptionalParams, chatSDKConfig: ChatSDKConfig, liveChatVersion: LiveChatVersion, protocol: string, telemetry: typeof AriaTelemetry, scenarioMarker: ScenarioMarker, omnichannelConfig: OmnichannelConfig, chatToken: IChatToken, fileManager: AMSFileManager, chatClient: ChatClient, logger: ACSAdapterLogger): Promise<unknown> => {
const options = optionalParams.ACSAdapter? optionalParams.ACSAdapter.options: {};
const acsAdapterCDNUrl = urlResolvers.resolveChatAdapterUrl(chatSDKConfig, liveChatVersion, protocol);
telemetry?.setCDNPackages({
ACSAdapter: acsAdapterCDNUrl
});
// Tags formatting middlewares are required to be the last in the pipeline to ensure tags are converted to the right format
const defaultEgressMiddlewares = [createChannelDataEgressMiddleware({widgetId: omnichannelConfig.widgetId}), createFormatEgressTagsMiddleware()];
const defaultIngressMiddlewares = [createFormatIngressTagsMiddleware()];
const egressMiddleware = options?.egressMiddleware? [...options.egressMiddleware, ...defaultEgressMiddlewares]: [...defaultEgressMiddlewares];
const ingressMiddleware = options?.ingressMiddleware? [...options.egressMiddleware, ...defaultIngressMiddlewares]: [...defaultIngressMiddlewares];
const featuresOption = {
enableAdaptiveCards: true, // Whether to enable adaptive card payload in adapter (payload in JSON string)
enableThreadMemberUpdateNotification: true, // Whether to enable chat thread member join/leave notification
enableLeaveThreadOnWindowClosed: false, // Whether to remove user on browser close event
...options, // overrides
ingressMiddleware,
egressMiddleware
};
scenarioMarker.startScenario(TelemetryEvent.CreateACSAdapter);
try {
await loadScript(acsAdapterCDNUrl);
} catch {
scenarioMarker.failScenario(TelemetryEvent.CreateACSAdapter);
throw new Error('Failed to load ACSAdapter');
}
try {
const { ChatAdapter } = window as any; // eslint-disable-line @typescript-eslint/no-explicit-any
const adapter = ChatAdapter.createACSAdapter(
chatToken.token as string,
chatToken.visitorId || 'teamsvisitor',
chatToken.chatId as string,
chatToken.acsEndpoint as string,
fileManager,
30000,
ACSParticipantDisplayName.Customer,
chatClient,
logger,
featuresOption,
);
scenarioMarker.completeScenario(TelemetryEvent.CreateACSAdapter);
return adapter;
} catch {
scenarioMarker.failScenario(TelemetryEvent.CreateACSAdapter);
throw new Error('Failed to create ACSAdapter');
}
};
const createIC3Adapter = async (optionalParams: ChatAdapterOptionalParams, chatSDKConfig: ChatSDKConfig, liveChatVersion: LiveChatVersion, protocol: string, telemetry: typeof AriaTelemetry, scenarioMarker: ScenarioMarker, chatToken: IChatToken, ic3Client: any, logger: IC3ClientLogger): Promise<unknown> => { // eslint-disable-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
const options = optionalParams.IC3Adapter? optionalParams.IC3Adapter.options: {};
const ic3AdapterCDNUrl = urlResolvers.resolveChatAdapterUrl(chatSDKConfig, liveChatVersion, protocol);
telemetry?.setCDNPackages({
IC3Adapter: ic3AdapterCDNUrl
});
scenarioMarker.startScenario(TelemetryEvent.CreateIC3Adapter);
try {
await loadScript(ic3AdapterCDNUrl);
} catch {
scenarioMarker.failScenario(TelemetryEvent.CreateIC3Adapter);
throw new Error('Failed to load IC3Adapter');
}
const adapterConfig: IIC3AdapterOptions = {
chatToken: chatToken,
userDisplayName: 'Customer',
userId: chatToken.visitorId || 'teamsvisitor',
sdkURL: urlResolvers.resolveIC3ClientUrl(chatSDKConfig),
sdk: ic3Client,
...options // overrides
};
try {
const adapter = new window.Microsoft.BotFramework.WebChat.IC3Adapter(adapterConfig);
adapter.logger = logger;
scenarioMarker.completeScenario(TelemetryEvent.CreateIC3Adapter);
return adapter;
} catch {
scenarioMarker.failScenario(TelemetryEvent.CreateIC3Adapter);
throw new Error('Failed to create IC3Adapter');
}
};
export default {
createDirectLine,
createACSAdapter,
createIC3Adapter
};
export {
createDirectLine,
createACSAdapter,
createIC3Adapter
};

Просмотреть файл

@ -1,4 +1,4 @@
import { ic3ClientVersion, webChatACSAdapterVersion, webChatIC3AdapterVersion } from "../config/settings";
import { ic3ClientVersion, webChatACSAdapterVersion, webChatDirectLineVersion, webChatIC3AdapterVersion } from "../config/settings";
const getIC3ClientCDNUrl = (version = ic3ClientVersion): string => {
const IC3ClientCDNUrl = `https://comms.omnichannelengagementhub.com/release/${version}/Scripts/SDK/SDK.min.js`;
@ -15,14 +15,21 @@ const getACSAdapterCDNUrl = (version = webChatACSAdapterVersion): string => {
return ACSAdapterCDNUrl;
}
const getDirectLineCDNUrl = (version = webChatDirectLineVersion): string => {
const DirectLineCDNUrl = `https://unpkg.com/botframework-directlinejs@${version}/dist/directline.js`;
return DirectLineCDNUrl;
}
export default {
getIC3ClientCDNUrl,
getIC3AdapterCDNUrl,
getACSAdapterCDNUrl
getACSAdapterCDNUrl,
getDirectLineCDNUrl
}
export {
getIC3ClientCDNUrl,
getIC3AdapterCDNUrl,
getACSAdapterCDNUrl
getACSAdapterCDNUrl,
getDirectLineCDNUrl
}

79
src/utils/urlResolvers.ts Normal file
Просмотреть файл

@ -0,0 +1,79 @@
import ChatSDKConfig from "../core/ChatSDKConfig";
import LiveChatVersion from "../core/LiveChatVersion";
import ChatAdapterProtocols from "../core/messaging/ChatAdapterProtocols";
import libraries from "./libraries";
const resolveIC3ClientUrl = (chatSDKConfig: ChatSDKConfig): string => {
if (chatSDKConfig.ic3Config && 'ic3ClientCDNUrl' in chatSDKConfig.ic3Config) {
return chatSDKConfig.ic3Config.ic3ClientCDNUrl as string;
}
if (chatSDKConfig.ic3Config && 'ic3ClientVersion' in chatSDKConfig.ic3Config) {
return libraries.getIC3ClientCDNUrl(chatSDKConfig.ic3Config.ic3ClientVersion);
}
return libraries.getIC3ClientCDNUrl();
};
const resolveDirectLineCDNUrl = (chatSDKConfig: ChatSDKConfig) => {
if (chatSDKConfig.chatAdapterConfig && 'webChatDirectLineCDNUrl' in chatSDKConfig.chatAdapterConfig) {
return chatSDKConfig.chatAdapterConfig.webChatDirectLineCDNUrl as string;
}
if (chatSDKConfig.chatAdapterConfig && 'webChatDirectLineVersion' in chatSDKConfig.chatAdapterConfig) {
return libraries.getDirectLineCDNUrl(chatSDKConfig.chatAdapterConfig.webChatDirectLineVersion);
}
return libraries.getDirectLineCDNUrl();
}
const resolveACSAdapterCDNUrl = (chatSDKConfig: ChatSDKConfig) => {
if (chatSDKConfig.chatAdapterConfig && 'webChatACSAdapterCDNUrl' in chatSDKConfig.chatAdapterConfig) {
return chatSDKConfig.chatAdapterConfig.webChatACSAdapterCDNUrl as string;
}
if (chatSDKConfig.chatAdapterConfig && 'webChatACSAdapterVersion' in chatSDKConfig.chatAdapterConfig) {
return libraries.getACSAdapterCDNUrl(chatSDKConfig.chatAdapterConfig.webChatACSAdapterVersion);
}
return libraries.getACSAdapterCDNUrl();
};
const resolveIC3AdapterCDNUrl = (chatSDKConfig: ChatSDKConfig) => {
if (chatSDKConfig.chatAdapterConfig && 'webChatIC3AdapterCDNUrl' in chatSDKConfig.chatAdapterConfig) {
return chatSDKConfig.chatAdapterConfig.webChatIC3AdapterCDNUrl as string;
}
if (chatSDKConfig.chatAdapterConfig && 'webChatIC3AdapterVersion' in chatSDKConfig.chatAdapterConfig) {
return libraries.getIC3AdapterCDNUrl(chatSDKConfig.chatAdapterConfig.webChatIC3AdapterVersion);
}
return libraries.getIC3AdapterCDNUrl();
};
const resolveChatAdapterUrl = (chatSDKConfig: ChatSDKConfig, liveChatVersion: LiveChatVersion, protocol: string): string => {
const supportedChatAdapterProtocols = [ChatAdapterProtocols.ACS, ChatAdapterProtocols.IC3, ChatAdapterProtocols.DirectLine];
if (protocol && !supportedChatAdapterProtocols.includes(protocol as string)) {
throw new Error(`ChatAdapter for protocol ${protocol} currently not supported`);
}
if (protocol === ChatAdapterProtocols.DirectLine) {
return resolveDirectLineCDNUrl(chatSDKConfig);
} else if (protocol === ChatAdapterProtocols.ACS || liveChatVersion === LiveChatVersion.V2) {
return resolveACSAdapterCDNUrl(chatSDKConfig);
} else if (protocol === ChatAdapterProtocols.IC3 || liveChatVersion === LiveChatVersion.V1) {
return resolveIC3AdapterCDNUrl(chatSDKConfig);
}
return '';
};
export default {
resolveIC3ClientUrl,
resolveChatAdapterUrl
}
export {
resolveIC3ClientUrl,
resolveChatAdapterUrl
}