Switch from TSLint to ESLint for TypeScript samples (#3969)

* Switch from TSLint to ESLint for TypeScript samples

* Update ci-javascript-samples.yml

Updating eslint for both file types i.e. .js and .ts

* eslint-plugin-import

* eslint-plugin-n

* Resolving dependencies

* jsonwebtoken
This commit is contained in:
gandiddi 2024-05-13 21:34:55 +05:30 коммит произвёл GitHub
Родитель df21f1a703
Коммит 62a768d02c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
46 изменённых файлов: 340 добавлений и 324 удалений

6
.github/workflows/ci-javascript-samples.yml поставляемый
Просмотреть файл

@ -94,9 +94,5 @@ jobs:
- name: yarn lint
run: |
if ${{ endsWith(matrix.files[0], '.js') }}; then
yarn eslint ${{ join(matrix.files, ' ') }}
else
yarn tslint ${{ join(matrix.files, ' ') }}
fi
yarn eslint ${{ join(matrix.files, ' ') }}
working-directory: ${{ matrix.folder }}

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

@ -0,0 +1,15 @@
module.exports = {
"extends": "standard",
"parser": "@typescript-eslint/parser",
"rules": {
"semi": [2, "always"],
"indent": [2, 4],
"no-return-await": 0,
"space-before-function-paren": [2, {
"named": "never",
"anonymous": "never",
"asyncArrow": "always"
}],
"template-curly-spacing": [2, "always"]
}
};

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

@ -7,7 +7,7 @@
"main": "./lib/index.js",
"scripts": {
"build": "tsc --build",
"lint": "tslint -c tslint.json 'src/**/*.ts'",
"lint": "eslint -c .eslintrc.js --ext .ts src",
"postinstall": "npm run build && node ./deploymentScripts/webConfigPrep.js",
"start": "tsc --build && node ./lib/index.js",
"test": "echo \"Error: no test specified\" && exit 1",
@ -24,8 +24,15 @@
},
"devDependencies": {
"@types/restify": "8.4.2",
"@typescript-eslint/eslint-plugin": "^7.8.0",
"@typescript-eslint/parser": "^7.8.0",
"eslint": "^8.57.0",
"eslint-config-standard": "^14.1.1",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"nodemon": "~2.0.4",
"tslint": "~6.1.2",
"typescript": "~4.3.2"
"typescript": "~4.9.3"
}
}
}

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

@ -7,7 +7,6 @@ import * as restify from 'restify';
// See https://aka.ms/bot-services to learn more about the different parts of a bot.
import {
CloudAdapter,
ConfigurationServiceClientCredentialFactory,
ConfigurationBotFrameworkAuthentication,
ConfigurationBotFrameworkAuthenticationOptions
} from 'botbuilder';
@ -54,5 +53,5 @@ const myBot = new EmptyBot();
// Listen for incoming requests.
server.post('/api/messages', async (req, res) => {
// Route received a request to adapter for processing
await adapter.process(req, res, (context) => myBot.run(context))
await adapter.process(req, res, (context) => myBot.run(context));
});

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

@ -1,18 +0,0 @@
{
"defaultSeverity": "error",
"extends": [
"tslint:recommended"
],
"jsRules": {},
"rules": {
"interface-name" : [true, "never-prefix"],
"max-line-length": [false],
"no-console": [false, "log", "error"],
"no-var-requires": false,
"quotemark": [true, "single"],
"one-variable-per-declaration": false,
"curly": [true, "ignore-same-line"],
"trailing-comma": [true, {"multiline": "never", "singleline": "never"}]
},
"rulesDirectory": []
}

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

@ -0,0 +1,15 @@
module.exports = {
"extends": "standard",
"parser": "@typescript-eslint/parser",
"rules": {
"semi": [2, "always"],
"indent": [2, 4],
"no-return-await": 0,
"space-before-function-paren": [2, {
"named": "never",
"anonymous": "never",
"asyncArrow": "always"
}],
"template-curly-spacing": [2, "always"]
}
};

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

@ -7,7 +7,7 @@
"main": "index.js",
"scripts": {
"build": "tsc --build",
"lint": "tslint -c tslint.json 'src/**/*.ts'",
"lint": "eslint -c .eslintrc.js --ext .ts src",
"start": "tsc --build && node ./lib/index.js",
"test": "echo \"Error: no test specified\" && exit 1",
"watch": "nodemon --watch ./src -e ts --exec \"npm run start\""
@ -17,8 +17,16 @@
"readline": "^1.3.0"
},
"devDependencies": {
"@types/jsonwebtoken": "^9.0.6",
"@typescript-eslint/eslint-plugin": "^7.8.0",
"@typescript-eslint/parser": "^7.8.0",
"eslint": "^8.57.0",
"eslint-config-standard": "^14.1.1",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"nodemon": "~1.19.4",
"tslint": "^5.20.0",
"typescript": "~4.3.2"
"typescript": "~4.9.3"
}
}

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

@ -7,7 +7,6 @@ import { ActivityTypes, TurnContext } from 'botbuilder';
* Simple bot that echoes received messages.
*/
export class ConsoleEchoBot {
/**
* Driver code for the bot. This bot only responds to "Message"-type
* Activities. If the user's message is "quit", the process will exit.
@ -26,5 +25,5 @@ export class ConsoleEchoBot {
await turnContext.sendActivity(`You sent '${ turnContext.activity.text }'`);
}
}
}
};
}

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

@ -38,7 +38,7 @@ export class ConsoleAdapter extends BotAdapter {
this.reference = {
bot: { id: 'bot', name: 'Bot' },
channelId: 'console',
conversation: { id: 'convo1', name: '', isGroup: false },
conversation: { id: 'convo1', name: '', isGroup: false },
serviceUrl: '',
user: { id: 'user', name: 'User1' },
...reference
@ -123,12 +123,12 @@ export class ConsoleAdapter extends BotAdapter {
* @param logic A function handler that will be called to perform the bots logic after the the adapters middleware has been run.
*/
public continueConversation(reference: ConversationReference, logic: (context: TurnContext) => Promise<void>): Promise<void> {
// Create context and run middleware pipe
const activity: Partial<Activity> = TurnContext.applyConversationReference({}, reference, true);
const context: TurnContext = new TurnContext(this, activity);
// Create context and run middleware pipe
const activity: Partial<Activity> = TurnContext.applyConversationReference({}, reference, true);
const context: TurnContext = new TurnContext(this, activity);
return this.runMiddleware(context, logic)
.catch((err: Error) => { this.printError(err.toString()); });
return this.runMiddleware(context, logic)
.catch((err: Error) => { this.printError(err.toString()); });
}
/**
@ -143,25 +143,26 @@ export class ConsoleAdapter extends BotAdapter {
*/
public async sendActivities(context: TurnContext, activities: Array <Partial<Activity>>): Promise<ResourceResponse[]> {
const responses: ResourceResponse[] = [];
for(const activity of activities) {
for (const activity of activities) {
responses.push({} as ResourceResponse);
switch (activity.type) {
case 'delay' as ActivityTypes:
await this.sleep(activity.value);
break;
case ActivityTypes.Message:
if (activity.attachments && activity.attachments.length > 0) {
const append: string = activity.attachments.length === 1
? `(1 attachment)` : `(${activity.attachments.length} attachments)`;
this.print(`${activity.text} ${append}`);
} else {
this.print(activity.text || '');
}
break;
default:
this.print(`[${activity.type}]`);
break;
case 'delay' as ActivityTypes:
await this.sleep(activity.value);
break;
case ActivityTypes.Message:
if (activity.attachments && activity.attachments.length > 0) {
const append: string = activity.attachments.length === 1
? '(1 attachment)'
: `(${ activity.attachments.length } attachments)`;
this.print(`${ activity.text } ${ append }`);
} else {
this.print(activity.text || '');
}
break;
default:
this.print(`[${ activity.type }]`);
break;
}
}
return responses;
@ -172,7 +173,7 @@ export class ConsoleAdapter extends BotAdapter {
* will result an error being returned.
*/
public updateActivity(context: TurnContext, activity: Partial<Activity>): Promise<void> {
return Promise.reject(new Error(`ConsoleAdapter.updateActivity(): not supported.`));
return Promise.reject(new Error('ConsoleAdapter.updateActivity(): not supported.'));
}
/**
@ -180,7 +181,7 @@ export class ConsoleAdapter extends BotAdapter {
* will result an error being returned.
*/
public deleteActivity(context: TurnContext, reference: Partial<ConversationReference>): Promise<void> {
return Promise.reject(new Error(`ConsoleAdapter.deleteActivity(): not supported.`));
return Promise.reject(new Error('ConsoleAdapter.deleteActivity(): not supported.'));
}
/**

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

@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
import { ConsoleAdapter} from './consoleAdapter';
import { ConsoleAdapter } from './consoleAdapter';
import { ConsoleEchoBot } from './bot';
@ -17,7 +17,7 @@ const echoBot: ConsoleEchoBot = new ConsoleEchoBot();
// `adapter.listen` tells the adapter to listen for incoming messages
// and events, known as "Activities."
// Activities are wrapped in TurnContext objects by the handler function.
const closeFn = adapter.listen(async (turnContext: TurnContext) => {
adapter.listen(async (turnContext: TurnContext) => {
await echoBot.onTurn(turnContext);
});

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

@ -1,18 +0,0 @@
{
"defaultSeverity": "error",
"extends": [
"tslint:recommended"
],
"jsRules": {},
"rules": {
"interface-name" : [true, "never-prefix"],
"max-line-length": [false],
"no-console": [false, "log", "error"],
"no-var-requires": false,
"quotemark": [true, "single"],
"one-variable-per-declaration": false,
"curly": [true, "ignore-same-line"],
"trailing-comma": [true, {"multiline": "never", "singleline": "never"}]
},
"rulesDirectory": []
}

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

@ -0,0 +1,15 @@
module.exports = {
"extends": "standard",
"parser": "@typescript-eslint/parser",
"rules": {
"semi": [2, "always"],
"indent": [2, 4],
"no-return-await": 0,
"space-before-function-paren": [2, {
"named": "never",
"anonymous": "never",
"asyncArrow": "always"
}],
"template-curly-spacing": [2, "always"]
}
};

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

@ -7,7 +7,7 @@
"main": "./lib/index.js",
"scripts": {
"build": "tsc --build",
"lint": "tslint -c tslint.json 'src/**/*.ts'",
"lint": "eslint -c .eslintrc.js --ext .ts src",
"postinstall": "npm run build && node ./deploymentScripts/webConfigPrep.js",
"start": "tsc --build && node ./lib/index.js",
"test": "echo \"Error: no test specified\" && exit 1",
@ -27,8 +27,15 @@
"@types/dotenv": "6.1.1",
"@types/node": "^16.11.6",
"@types/restify": "8.4.2",
"@typescript-eslint/eslint-plugin": "^7.8.0",
"@typescript-eslint/parser": "^7.8.0",
"eslint": "^8.57.0",
"eslint-config-standard": "^14.1.1",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"nodemon": "~2.0.4",
"tslint": "~6.1.2",
"typescript": "~4.3.2"
"typescript": "~4.9.3"
}
}

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

@ -3,10 +3,6 @@
import * as path from 'path';
import { config } from 'dotenv';
const ENV_FILE = path.join(__dirname, '..', '.env');
config({ path: ENV_FILE });
import * as restify from 'restify';
import { INodeSocket } from 'botframework-streaming';
@ -15,7 +11,6 @@ import { INodeSocket } from 'botframework-streaming';
// See https://aka.ms/bot-services to learn more about the different parts of a bot.
import {
CloudAdapter,
ConfigurationServiceClientCredentialFactory,
ConfigurationBotFrameworkAuthentication,
ConfigurationBotFrameworkAuthenticationOptions
} from 'botbuilder';
@ -23,11 +18,15 @@ import {
// This bot's main dialog.
import { EchoBot } from './bot';
import { config } from 'dotenv';
const ENV_FILE = path.join(__dirname, '..', '.env');
config({ path: ENV_FILE });
// Create HTTP server.
const server = restify.createServer();
server.use(restify.plugins.bodyParser());
server.listen(process.env.port || process.env.PORT || 3978, () => {
console.log(`\n${server.name} listening to ${server.url}`);
console.log(`\n${ server.name } listening to ${ server.url }`);
console.log('\nGet Bot Framework Emulator: https://aka.ms/botframework-emulator');
console.log('\nTo talk to your bot, open the emulator select "Open Bot"');
});

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

@ -1,18 +0,0 @@
{
"defaultSeverity": "error",
"extends": [
"tslint:recommended"
],
"jsRules": {},
"rules": {
"interface-name" : [true, "never-prefix"],
"max-line-length": [false],
"no-console": [false, "log", "error"],
"no-var-requires": false,
"quotemark": [true, "single"],
"one-variable-per-declaration": false,
"curly": [true, "ignore-same-line"],
"trailing-comma": [true, {"multiline": "never", "singleline": "never"}]
},
"rulesDirectory": []
}

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

@ -0,0 +1,15 @@
module.exports = {
"extends": "standard",
"parser": "@typescript-eslint/parser",
"rules": {
"semi": [2, "always"],
"indent": [2, 4],
"no-return-await": 0,
"space-before-function-paren": [2, {
"named": "never",
"anonymous": "never",
"asyncArrow": "always"
}],
"template-curly-spacing": [2, "always"]
}
};

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

@ -7,7 +7,7 @@
"main": "./lib/index.js",
"scripts": {
"build": "tsc --build",
"lint": "tslint -c tslint.json 'src/**/*.ts'",
"lint": "eslint -c .eslintrc.js --ext .ts src",
"postinstall": "npm run build && node ./deploymentScripts/webConfigPrep.js",
"start": "tsc --build && node ./lib/index.js",
"test": "echo \"Error: no test specified\" && exit 1",
@ -24,8 +24,15 @@
},
"devDependencies": {
"@types/restify": "8.4.2",
"@typescript-eslint/eslint-plugin": "^7.8.0",
"@typescript-eslint/parser": "^7.8.0",
"eslint": "^8.57.0",
"eslint-config-standard": "^14.1.1",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"nodemon": "~1.19.4",
"tslint": "~5.20.0",
"typescript": "~4.3.2"
"typescript": "~4.9.3"
}
}
}

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

@ -34,7 +34,7 @@ export class WelcomeBot extends ActivityHandler {
// The channel should send the user name in the 'From' object
const userName = context.activity.from.name;
await context.sendActivity('You are seeing this message because this was your first message ever sent to this bot.');
await context.sendActivity(`It is a good practice to welcome the user and provide personal greeting. For example, welcome ${userName}.`);
await context.sendActivity(`It is a good practice to welcome the user and provide personal greeting. For example, welcome ${ userName }.`);
// Set the flag indicating the bot handled the user's first message.
await this.welcomedUserProperty.set(context, true);
@ -43,18 +43,18 @@ export class WelcomeBot extends ActivityHandler {
// Consider using LUIS or QnA for Natural Language Processing.
const text = context.activity.text.toLowerCase();
switch (text) {
case 'hello':
case 'hi':
await context.sendActivity(`You said "${context.activity.text}"`);
break;
case 'intro':
case 'help':
await this.sendIntroCard(context);
break;
default:
await context.sendActivity(`This is a simple Welcome Bot sample. You can say 'intro' to
see the introduction card. If you are running this bot in the Bot
Framework Emulator, press the 'Start Over' button to simulate user joining a bot or a channel`);
case 'hello':
case 'hi':
await context.sendActivity(`You said "${ context.activity.text }"`);
break;
case 'intro':
case 'help':
await this.sendIntroCard(context);
break;
default:
await context.sendActivity(`This is a simple Welcome Bot sample. You can say 'intro' to
see the introduction card. If you are running this bot in the Bot
Framework Emulator, press the 'Start Over' button to simulate user joining a bot or a channel`);
}
}
// Save state changes
@ -75,7 +75,7 @@ export class WelcomeBot extends ActivityHandler {
// bot was added to the conversation, and the opposite indicates this is a user.
if (context.activity.membersAdded[idx].id !== context.activity.recipient.id) {
await context.sendActivity('Welcome to the \'Welcome User\' Bot. This bot will introduce you to welcoming and greeting users.');
await context.sendActivity(`You are seeing this message because the bot received at least one 'ConversationUpdate' ` +
await context.sendActivity('You are seeing this message because the bot received at least one \'ConversationUpdate\' ' +
'event, indicating you (and possibly others) joined the conversation. If you are using the emulator, ' +
'pressing the \'Start Over\' button to trigger this event again. The specifics of the \'ConversationUpdate\' ' +
'event depends on the channel. You can read more information at https://aka.ms/about-botframework-welcome-user');

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

@ -1,18 +0,0 @@
{
"defaultSeverity": "error",
"extends": [
"tslint:recommended"
],
"jsRules": {},
"rules": {
"interface-name" : [true, "never-prefix"],
"max-line-length": [false],
"no-console": [false, "log", "error"],
"no-var-requires": false,
"quotemark": [true, "single"],
"one-variable-per-declaration": false,
"curly": [true, "ignore-same-line"],
"trailing-comma": [true, {"multiline": "never", "singleline": "never"}]
},
"rulesDirectory": []
}

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

@ -0,0 +1,15 @@
module.exports = {
"extends": "standard",
"parser": "@typescript-eslint/parser",
"rules": {
"semi": [2, "always"],
"indent": [2, 4],
"no-return-await": 0,
"space-before-function-paren": [2, {
"named": "never",
"anonymous": "never",
"asyncArrow": "always"
}],
"template-curly-spacing": [2, "always"]
}
};

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

@ -7,7 +7,7 @@
"main": "./lib/index.js",
"scripts": {
"build": "tsc --build",
"lint": "tslint -c tslint.json 'src/**/*.ts'",
"lint": "eslint -c .eslintrc.js --ext .ts src",
"postinstall": "npm run build && node ./deploymentScripts/webConfigPrep.js",
"start": "tsc --build && node ./lib/index.js",
"test": "echo \"Error: no test specified\" && exit 1",
@ -26,8 +26,15 @@
},
"devDependencies": {
"@types/restify": "8.4.2",
"@typescript-eslint/eslint-plugin": "^7.8.0",
"@typescript-eslint/parser": "^7.8.0",
"eslint": "^8.57.0",
"eslint-config-standard": "^14.1.1",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"nodemon": "~1.19.4",
"tslint": "~5.20.0",
"typescript": "~4.3.2"
"typescript": "~4.9.3"
}
}
}

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

@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
import { ActivityHandler, BotState, ConversationState, StatePropertyAccessor, UserState } from 'botbuilder';
import { ActivityHandler, BotState, ConversationState, StatePropertyAccessor, UserState } from 'botbuilder';
import { Dialog, DialogState } from 'botbuilder-dialogs';
import { UserProfileDialog } from '../dialogs/userProfileDialog';
export class DialogBot extends ActivityHandler {

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

@ -83,7 +83,7 @@ export class UserProfileDialog extends ComponentDialog {
stepContext.options.name = stepContext.result;
// We can send messages to the user at any point in the WaterfallStep.
await stepContext.context.sendActivity(`Thanks ${stepContext.result}.`);
await stepContext.context.sendActivity(`Thanks ${ stepContext.result }.`);
// WaterfallStep always finishes with the end of the Waterfall or with another dialog; here it is a Prompt Dialog.
return await stepContext.prompt(CONFIRM_PROMPT, 'Do you want to give your age?', ['yes', 'no']);
@ -105,7 +105,7 @@ export class UserProfileDialog extends ComponentDialog {
private async confirmStep(stepContext: WaterfallStepContext<UserProfile>) {
stepContext.options.age = stepContext.result;
const msg = stepContext.options.age === -1 ? 'No age given.' : `I have your age as ${stepContext.options.age}.`;
const msg = stepContext.options.age === -1 ? 'No age given.' : `I have your age as ${ stepContext.options.age }.`;
// We can send messages to the user at any point in the WaterfallStep.
await stepContext.context.sendActivity(msg);
@ -123,9 +123,9 @@ export class UserProfileDialog extends ComponentDialog {
userProfile.name = stepContextOptions.name;
userProfile.age = stepContextOptions.age;
let msg = `I have your mode of transport as ${userProfile.transport} and your name as ${userProfile.name}.`;
let msg = `I have your mode of transport as ${ userProfile.transport } and your name as ${ userProfile.name }.`;
if (userProfile.age !== -1) {
msg += ` And age as ${userProfile.age}.`;
msg += ` And age as ${ userProfile.age }.`;
}
await stepContext.context.sendActivity(msg);

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

@ -35,12 +35,12 @@ adapter.onTurnError = async (context, error) => {
// This check writes out errors to console log .vs. app insights.
// NOTE: In production environment, you should consider logging this to Azure
// application insights.
console.error(`\n [onTurnError] unhandled error: ${error}`);
console.error(`\n [onTurnError] unhandled error: ${ error }`);
// Send a trace activity, which will be displayed in Bot Framework Emulator
await context.sendTraceActivity(
'OnTurnError Trace',
`${error}`,
`${ error }`,
'https://www.botframework.com/schemas/error',
'TurnError'
);
@ -70,7 +70,7 @@ const server = restify.createServer();
server.use(restify.plugins.bodyParser());
server.listen(process.env.port || process.env.PORT || 3978, () => {
console.log(`\n${server.name} listening to ${server.url}.`);
console.log(`\n${ server.name } listening to ${ server.url }.`);
console.log('\nGet Bot Framework Emulator: https://aka.ms/botframework-emulator');
console.log('\nTo talk to your bot, open the emulator select "Open Bot"');
});

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

@ -1,18 +0,0 @@
{
"defaultSeverity": "error",
"extends": [
"tslint:recommended"
],
"jsRules": {},
"rules": {
"interface-name" : [true, "never-prefix"],
"max-line-length": [false],
"no-console": [false, "log", "error"],
"no-var-requires": false,
"quotemark": [true, "single"],
"one-variable-per-declaration": false,
"curly": [true, "ignore-same-line"],
"trailing-comma": [true, {"multiline": "never", "singleline": "never"}]
},
"rulesDirectory": []
}

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

@ -0,0 +1,15 @@
module.exports = {
"extends": "standard",
"parser": "@typescript-eslint/parser",
"rules": {
"semi": [2, "always"],
"indent": [2, 4],
"no-return-await": 0,
"space-before-function-paren": [2, {
"named": "never",
"anonymous": "never",
"asyncArrow": "always"
}],
"template-curly-spacing": [2, "always"]
}
};

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

@ -7,7 +7,7 @@
"main": "./lib/index.js",
"scripts": {
"build": "tsc --build",
"lint": "tslint -c tslint.json 'src/**/*.ts'",
"lint": "eslint -c .eslintrc.js --ext .ts src",
"postinstall": "npm run build && node ./deploymentScripts/webConfigPrep.js",
"start": "tsc --build && node ./lib/index.js",
"test": "echo \"Error: no test specified\" && exit 1",
@ -26,8 +26,15 @@
},
"devDependencies": {
"@types/restify": "8.4.2",
"@typescript-eslint/eslint-plugin": "^7.8.0",
"@typescript-eslint/parser": "^7.8.0",
"eslint": "^8.57.0",
"eslint-config-standard": "^14.1.1",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"nodemon": "~1.19.4",
"tslint": "~5.20.0",
"typescript": "~4.3.2"
"typescript": "~4.9.3"
}
}
}

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

@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
import { ActivityHandler, BotState, ConversationState, StatePropertyAccessor, UserState } from 'botbuilder';
import { ActivityHandler, BotState, ConversationState, StatePropertyAccessor, UserState } from 'botbuilder';
import { Dialog, DialogState } from 'botbuilder-dialogs';
import { MainDialog } from '../dialogs/mainDialog';
export class DialogBot extends ActivityHandler {

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

@ -2,7 +2,7 @@
// Licensed under the MIT License.
import AdaptiveCard from '../resources/adaptiveCard.json';
import { AttachmentLayoutTypes, CardFactory, StatePropertyAccessor, TurnContext, UserState } from 'botbuilder';
import { AttachmentLayoutTypes, CardFactory, StatePropertyAccessor, TurnContext } from 'botbuilder';
import {
ChoicePrompt,
ComponentDialog,
@ -15,7 +15,6 @@ import {
const MAIN_WATERFALL_DIALOG = 'mainWaterfallDialog';
export class MainDialog extends ComponentDialog {
constructor() {
super('MainDialog');
@ -77,49 +76,49 @@ export class MainDialog extends ComponentDialog {
console.log('MainDialog.showCardStep');
switch (stepContext.result.value) {
case 'Adaptive Card':
await stepContext.context.sendActivity({ attachments: [this.createAdaptiveCard()] });
break;
case 'Animation Card':
await stepContext.context.sendActivity({ attachments: [this.createAnimationCard()] });
break;
case 'Audio Card':
await stepContext.context.sendActivity({ attachments: [this.createAudioCard()] });
break;
case 'OAuth Card':
await stepContext.context.sendActivity({ attachments: [this.createOAuthCard()] });
break;
case 'Hero Card':
await stepContext.context.sendActivity({ attachments: [this.createHeroCard()] });
break;
case 'Receipt Card':
await stepContext.context.sendActivity({ attachments: [this.createReceiptCard()] });
break;
case 'Signin Card':
await stepContext.context.sendActivity({ attachments: [this.createSignInCard()] });
break;
case 'Thumbnail Card':
await stepContext.context.sendActivity({ attachments: [this.createThumbnailCard()] });
break;
case 'Video Card':
await stepContext.context.sendActivity({ attachments: [this.createVideoCard()] });
break;
default:
await stepContext.context.sendActivity({
attachmentLayout: AttachmentLayoutTypes.Carousel,
attachments: [
this.createAdaptiveCard(),
this.createAnimationCard(),
this.createAudioCard(),
this.createOAuthCard(),
this.createHeroCard(),
this.createReceiptCard(),
this.createSignInCard(),
this.createThumbnailCard(),
this.createVideoCard()
]
});
break;
case 'Adaptive Card':
await stepContext.context.sendActivity({ attachments: [this.createAdaptiveCard()] });
break;
case 'Animation Card':
await stepContext.context.sendActivity({ attachments: [this.createAnimationCard()] });
break;
case 'Audio Card':
await stepContext.context.sendActivity({ attachments: [this.createAudioCard()] });
break;
case 'OAuth Card':
await stepContext.context.sendActivity({ attachments: [this.createOAuthCard()] });
break;
case 'Hero Card':
await stepContext.context.sendActivity({ attachments: [this.createHeroCard()] });
break;
case 'Receipt Card':
await stepContext.context.sendActivity({ attachments: [this.createReceiptCard()] });
break;
case 'Signin Card':
await stepContext.context.sendActivity({ attachments: [this.createSignInCard()] });
break;
case 'Thumbnail Card':
await stepContext.context.sendActivity({ attachments: [this.createThumbnailCard()] });
break;
case 'Video Card':
await stepContext.context.sendActivity({ attachments: [this.createVideoCard()] });
break;
default:
await stepContext.context.sendActivity({
attachmentLayout: AttachmentLayoutTypes.Carousel,
attachments: [
this.createAdaptiveCard(),
this.createAnimationCard(),
this.createAudioCard(),
this.createOAuthCard(),
this.createHeroCard(),
this.createReceiptCard(),
this.createSignInCard(),
this.createThumbnailCard(),
this.createVideoCard()
]
});
break;
}
// Give the user instructions about what to do next

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

@ -35,12 +35,12 @@ adapter.onTurnError = async (context, error) => {
// This check writes out errors to console log .vs. app insights.
// NOTE: In production environment, you should consider logging this to Azure
// application insights.
console.error(`\n [onTurnError] unhandled error: ${error}`);
console.error(`\n [onTurnError] unhandled error: ${ error }`);
// Send a trace activity, which will be displayed in Bot Framework Emulator
await context.sendTraceActivity(
'OnTurnError Trace',
`${error}`,
`${ error }`,
'https://www.botframework.com/schemas/error',
'TurnError'
);
@ -70,7 +70,7 @@ const server = restify.createServer();
server.use(restify.plugins.bodyParser());
server.listen(process.env.port || process.env.PORT || 3978, () => {
console.log(`\n${server.name} listening to ${server.url}.`);
console.log(`\n${ server.name } listening to ${ server.url }.`);
console.log('\nGet Bot Framework Emulator: https://aka.ms/botframework-emulator');
console.log('\nTo talk to your bot, open the emulator select "Open Bot"');
});

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

@ -1,18 +0,0 @@
{
"defaultSeverity": "error",
"extends": [
"tslint:recommended"
],
"jsRules": {},
"rules": {
"interface-name" : [true, "never-prefix"],
"max-line-length": [false],
"no-console": [false, "log", "error"],
"no-var-requires": false,
"quotemark": [true, "single"],
"one-variable-per-declaration": false,
"curly": [true, "ignore-same-line"],
"trailing-comma": [true, {"multiline": "never", "singleline": "never"}]
},
"rulesDirectory": []
}

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

@ -1,6 +1,7 @@
/* eslint-disable */
module.exports = {
"extends": "standard",
"parser": "@typescript-eslint/parser",
"rules": {
"semi": [2, "always"],
"indent": [2, 4],
@ -10,7 +11,10 @@ module.exports = {
"anonymous": "never",
"asyncArrow": "always"
}],
"template-curly-spacing": [2, "always"]
"template-curly-spacing": [2, "always"],
"no-useless-constructor": 0,
"prefer-const": 0,
"array-callback-return": 0
},
"env": {
"commonjs": true,

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

@ -7,7 +7,7 @@
"main": "index.js",
"scripts": {
"build": "tsc --build",
"lint": "tslint -c tslint.json 'src/**/*.ts'",
"lint": "eslint -c .eslintrc.js --ext .ts src",
"postinstall": "npm run build && node ./deploymentScripts/webConfigPrep.js",
"start": "tsc --build && node ./lib/index.js",
"test": "tsc --build && nyc mocha lib/tests/**/*.test.js",
@ -51,11 +51,18 @@
"@types/mocha": "^7.0.2",
"@types/node": "^16.11.6",
"@types/restify": "8.4.2",
"@typescript-eslint/eslint-plugin": "^7.8.0",
"@typescript-eslint/parser": "^7.8.0",
"eslint": "^8.57.0",
"eslint-config-standard": "^14.1.1",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"mocha": "^7.1.2",
"nodemon": "~2.0.4",
"nyc": "^15.0.1",
"ts-node": "^8.10.1",
"tslint": "~6.1.2",
"typescript": "~4.3.2"
"typescript": "~4.9.3"
}
}
}

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

@ -26,16 +26,18 @@ export class CancelAndHelpDialog extends ComponentDialog {
const text = innerDc.context.activity.text.toLowerCase();
switch (text) {
case 'help':
case '?':
const helpMessageText = 'Show help here';
await innerDc.context.sendActivity(helpMessageText, helpMessageText, InputHints.ExpectingInput);
return { status: DialogTurnStatus.waiting };
case 'cancel':
case 'quit':
const cancelMessageText = 'Cancelling...';
await innerDc.context.sendActivity(cancelMessageText, cancelMessageText, InputHints.IgnoringInput);
return await innerDc.cancelAllDialogs();
case 'help':
case '?':{
const helpMessageText = 'Show help here';
await innerDc.context.sendActivity(helpMessageText, helpMessageText, InputHints.ExpectingInput);
return { status: DialogTurnStatus.waiting };
}
case 'cancel':
case 'quit':{
const cancelMessageText = 'Cancelling...';
await innerDc.context.sendActivity(cancelMessageText, cancelMessageText, InputHints.IgnoringInput);
return await innerDc.cancelAllDialogs();
}
}
}
}

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

@ -10,7 +10,6 @@ const DATETIME_PROMPT = 'datetimePrompt';
const WATERFALL_DIALOG = 'waterfallDialog';
export class DateResolverDialog extends CancelAndHelpDialog {
private static async dateTimePromptValidator(promptContext: PromptValidatorContext<DateTimeResolution>): Promise<boolean> {
if (promptContext.recognized.succeeded) {
// This value will be a TIMEX. And we are only interested in a Date so grab the first result and drop the Time part.

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

@ -13,7 +13,7 @@ export class FlightBookingRecognizer {
// Set the recognizer options depending on which endpoint version you want to use e.g LuisRecognizerOptionsV2 or LuisRecognizerOptionsV3.
// More details can be found in https://docs.microsoft.com/en-gb/azure/cognitive-services/luis/luis-migration-api-v3
const recognizerOptions: LuisRecognizerOptionsV3 = {
apiVersion : 'v3'
apiVersion: 'v3'
};
this.recognizer = new LuisRecognizer(config, recognizerOptions);

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

@ -74,7 +74,7 @@ export class MainDialog extends ComponentDialog {
return await stepContext.next();
}
const weekLaterDate = moment().add(7, 'days').format('MMMM D, YYYY');
const messageText = (stepContext.options as any).restartMsg ? (stepContext.options as any).restartMsg : `What can I help you with today?\nSay something like "Book a flight from Paris to Berlin on ${weekLaterDate}"`;
const messageText = (stepContext.options as any).restartMsg ? (stepContext.options as any).restartMsg : `What can I help you with today?\nSay something like "Book a flight from Paris to Berlin on ${ weekLaterDate }"`;
const promptMessage = MessageFactory.text(messageText, messageText, InputHints.ExpectingInput);
return await stepContext.prompt('TextPrompt', { prompt: promptMessage });
}
@ -94,7 +94,7 @@ export class MainDialog extends ComponentDialog {
// Call LUIS and gather any potential booking details. (Note the TurnContext has the response to the prompt)
const luisResult = await this.luisRecognizer.executeLuisQuery(stepContext.context);
switch (LuisRecognizer.topIntent(luisResult)) {
case 'BookFlight':
case 'BookFlight':{
// Extract the values for the composite entities from the LUIS result.
const fromEntities = this.luisRecognizer.getFromEntities(luisResult);
const toEntities = this.luisRecognizer.getToEntities(luisResult);
@ -110,18 +110,19 @@ export class MainDialog extends ComponentDialog {
// Run the BookingDialog passing in whatever details we have from the LUIS call, it will fill out the remainder.
return await stepContext.beginDialog('bookingDialog', bookingDetails);
case 'GetWeather':
}
case 'GetWeather':{
// We haven't implemented the GetWeatherDialog so we just display a TODO message.
const getWeatherMessageText = 'TODO: get weather flow here';
await stepContext.context.sendActivity(getWeatherMessageText, getWeatherMessageText, InputHints.IgnoringInput);
break;
default:
}
default:{
// Catch all for unhandled intents
const didntUnderstandMessageText = `Sorry, I didn't get that. Please try asking in a different way (intent was ${ LuisRecognizer.topIntent(luisResult) })`;
await stepContext.context.sendActivity(didntUnderstandMessageText, didntUnderstandMessageText, InputHints.IgnoringInput);
}
}
return await stepContext.next();
}

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

@ -3,11 +3,6 @@
import * as path from 'path';
import { config } from 'dotenv';
// Note: Ensure you have a .env file and include LuisAppId, LuisAPIKey and LuisAPIHostName.
const ENV_FILE = path.join(__dirname, '..', '.env');
config({ path: ENV_FILE });
import * as restify from 'restify';
import { INodeSocket } from 'botframework-streaming';
@ -31,11 +26,16 @@ import { MainDialog } from './dialogs/mainDialog';
// The bot's booking dialog
import { BookingDialog } from './dialogs/bookingDialog';
const BOOKING_DIALOG = 'bookingDialog';
// The helper-class recognizer that calls LUIS
import { FlightBookingRecognizer } from './dialogs/flightBookingRecognizer';
import { config } from 'dotenv';
// Note: Ensure you have a .env file and include LuisAppId, LuisAPIKey and LuisAPIHostName.
const ENV_FILE = path.join(__dirname, '..', '.env');
config({ path: ENV_FILE });
const BOOKING_DIALOG = 'bookingDialog';
const botFrameworkAuthentication = new ConfigurationBotFrameworkAuthentication(process.env as ConfigurationBotFrameworkAuthenticationOptions);
// Create adapter.
@ -80,11 +80,10 @@ conversationState = new ConversationState(memoryStorage);
userState = new UserState(memoryStorage);
// If configured, pass in the FlightBookingRecognizer. (Defining it externally allows it to be mocked for tests)
let luisRecognizer;
const { LuisAppId, LuisAPIKey, LuisAPIHostName } = process.env;
const luisConfig: LuisApplication = { applicationId: LuisAppId, endpointKey: LuisAPIKey, endpoint: `https://${ LuisAPIHostName }` };
luisRecognizer = new FlightBookingRecognizer(luisConfig);
const luisRecognizer = new FlightBookingRecognizer(luisConfig);
// Create the main dialog.
const bookingDialog = new BookingDialog(BOOKING_DIALOG);

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

@ -86,15 +86,15 @@ describe('MainDialog', () => {
const reply = await client.sendActivity('hi');
const weekLaterDate = moment().add(7, 'days').format('MMMM D, YYYY');
assert.strictEqual(reply.text, `What can I help you with today?\nSay something like "Book a flight from Paris to Berlin on ${weekLaterDate}"`, 'Did not show prompt');
assert.strictEqual(reply.text, `What can I help you with today?\nSay something like "Book a flight from Paris to Berlin on ${ weekLaterDate }"`, 'Did not show prompt');
});
describe('Invokes tasks based on LUIS intent', () => {
// Create array with test case data.
const testCases = [
{ utterance: 'I want to book a flight', intent: 'BookFlight', invokedDialogResponse: 'bookingDialog mock invoked', taskConfirmationMessage: 'I have you booked to Seattle from New York' },
{ utterance: `What's the weather like?`, intent: 'GetWeather', invokedDialogResponse: 'TODO: get weather flow here', taskConfirmationMessage: undefined },
{ utterance: 'bananas', intent: 'None', invokedDialogResponse: `Sorry, I didn't get that. Please try asking in a different way (intent was None)`, taskConfirmationMessage: undefined }
{ utterance: 'What\'s the weather like?', intent: 'GetWeather', invokedDialogResponse: 'TODO: get weather flow here', taskConfirmationMessage: undefined },
{ utterance: 'bananas', intent: 'None', invokedDialogResponse: 'Sorry, I didn\'t get that. Please try asking in a different way (intent was None)', taskConfirmationMessage: undefined }
];
testCases.map((testData) => {
@ -110,7 +110,7 @@ describe('MainDialog', () => {
console.log(`Test Case: ${ testData.intent }`);
let reply = await client.sendActivity('Hi');
const weekLaterDate = moment().add(7, 'days').format('MMMM D, YYYY');
assert.strictEqual(reply.text, `What can I help you with today?\nSay something like "Book a flight from Paris to Berlin on ${weekLaterDate}"`);
assert.strictEqual(reply.text, `What can I help you with today?\nSay something like "Book a flight from Paris to Berlin on ${ weekLaterDate }"`);
reply = await client.sendActivity(testData.utterance);
assert.strictEqual(reply.text, testData.invokedDialogResponse);
@ -150,7 +150,7 @@ describe('MainDialog', () => {
console.log(`Test Case: ${ mockLuisResult.text }`);
let reply = await client.sendActivity('Hi');
const weekLaterDate = moment().add(7, 'days').format('MMMM D, YYYY');
assert.strictEqual(reply.text, `What can I help you with today?\nSay something like "Book a flight from Paris to Berlin on ${weekLaterDate}"`);
assert.strictEqual(reply.text, `What can I help you with today?\nSay something like "Book a flight from Paris to Berlin on ${ weekLaterDate }"`);
reply = await client.sendActivity(mockLuisResult.text);
assert.strictEqual(reply.text, testData.expectedMessage);

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

@ -89,17 +89,17 @@ module.exports = [
expectedResult: {
destination: 'Seattle',
origin: 'Bahamas',
travelDate: bookingDialogToday
travelDate: bookingDialogToday
},
expectedStatus: 'complete',
initialData: {
destination: 'Seattle',
origin: 'Bahamas',
travelDate: bookingDialogToday
travelDate: bookingDialogToday
},
name: 'All booking details given for today',
steps: [
['hi', `Please confirm, I have you traveling to: Seattle from: Bahamas on: ${ bookingDialogToday }. Is this correct? (1) Yes or (2) No`],
['hi', `Please confirm, I have you traveling to: Seattle from: Bahamas on: ${ bookingDialogToday }. Is this correct? (1) Yes or (2) No`],
['yes', null]
]
},

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

@ -1,18 +0,0 @@
{
"defaultSeverity": "error",
"extends": [
"tslint:recommended"
],
"jsRules": {},
"rules": {
"interface-name" : [true, "never-prefix"],
"max-line-length": [false],
"no-console": [false, "log", "error"],
"no-var-requires": false,
"quotemark": [true, "single"],
"one-variable-per-declaration": false,
"curly": [true, "ignore-same-line"],
"trailing-comma": [true, {"multiline": "never", "singleline": "never"}]
},
"rulesDirectory": []
}

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

@ -0,0 +1,15 @@
module.exports = {
"extends": "standard",
"parser": "@typescript-eslint/parser",
"rules": {
"semi": [2, "always"],
"indent": [2, 4],
"no-return-await": 0,
"space-before-function-paren": [2, {
"named": "never",
"anonymous": "never",
"asyncArrow": "always"
}],
"template-curly-spacing": [2, "always"]
}
};

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

@ -7,7 +7,7 @@
"main": "./lib/index.js",
"scripts": {
"build": "tsc --build",
"lint": "tslint -c tslint.json 'src/**/*.ts'",
"lint": "eslint -c .eslintrc.js --ext .ts src",
"postinstall": "npm run build && node ./deploymentScripts/webConfigPrep.js",
"start": "tsc --build && node ./lib/index.js",
"test": "echo \"Error: no test specified\" && exit 1",
@ -26,8 +26,15 @@
"devDependencies": {
"@types/dotenv": "6.1.1",
"@types/restify": "8.4.2",
"@typescript-eslint/eslint-plugin": "^7.8.0",
"@typescript-eslint/parser": "^7.8.0",
"eslint": "^8.57.0",
"eslint-config-standard": "^14.1.1",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"nodemon": "~1.19.4",
"tslint": "~5.20.0",
"typescript": "~4.3.2"
"typescript": "~4.9.3"
}
}
}

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

@ -25,11 +25,11 @@ export class EchoBot extends ActivityHandler {
this.onMembersAdded(async (context, next) => {
const membersAdded = context.activity.membersAdded;
const welcomeText = 'Hello and welcome!';
for (const member of membersAdded) {
if (member.id !== context.activity.recipient.id) {
const welcomeMessage = 'Welcome to the Proactive Bot sample. Navigate to http://localhost:3978/api/notify to proactively message everyone who has previously messaged this bot.';
await context.sendActivity(welcomeMessage); }
await context.sendActivity(welcomeMessage);
}
}
// By calling next() you ensure that the next BotHandler is run.
await next();

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

@ -24,7 +24,7 @@ config({ path: ENV_FILE });
// Create HTTP server.
const server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 3978, () => {
console.log(`\n${server.name} listening to ${server.url}`);
console.log(`\n${ server.name } listening to ${ server.url }`);
console.log('\nGet Bot Framework Emulator: https://aka.ms/botframework-emulator');
console.log('\nTo talk to your bot, open the emulator select "Open Bot"');
});

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

@ -1,18 +0,0 @@
{
"defaultSeverity": "error",
"extends": [
"tslint:recommended"
],
"jsRules": {},
"rules": {
"interface-name" : [true, "never-prefix"],
"max-line-length": [false],
"no-console": [false, "log", "error"],
"no-var-requires": false,
"quotemark": [true, "single"],
"one-variable-per-declaration": false,
"curly": [true, "ignore-same-line"],
"trailing-comma": [true, {"multiline": "never", "singleline": "never"}]
},
"rulesDirectory": []
}