From bb5bb4c8f9a65f46672b2fb9785127479382aef4 Mon Sep 17 00:00:00 2001 From: Marcelo Schmidt Date: Thu, 18 Nov 2021 08:50:35 -0300 Subject: [PATCH 01/19] Add environment settings --- config/Settings.ts | 9 +++++++++ i18n/en.json | 1 + lib/Dialogflow.ts | 3 ++- package.json | 4 ++-- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/config/Settings.ts b/config/Settings.ts index 69949f3..10c174e 100644 --- a/config/Settings.ts +++ b/config/Settings.ts @@ -3,6 +3,7 @@ import { ISetting, SettingType } from '@rocket.chat/apps-engine/definition/setti export enum AppSetting { DialogflowBotUsername = 'dialogflow_bot_username', DialogflowProjectId = 'dialogflow_project_id', + DialogflowEnvironment = 'dialogflow_environment', DialogflowClientEmail = 'dialogflow_client_email', DialogFlowPrivateKey = 'dialogflow_private_key', DialogflowFallbackResponsesLimit = 'dialogflow_fallback_responses_limit', @@ -42,6 +43,14 @@ export const settings: Array = [ i18nLabel: 'dialogflow_project_id', required: true, }, + { + id: AppSetting.DialogflowEnvironment, + public: true, + type: SettingType.STRING, + packageValue: '', + i18nLabel: 'dialogflow_environment', + required: true, + }, { id: AppSetting.DialogflowClientEmail, public: true, diff --git a/i18n/en.json b/i18n/en.json index f4a6491..4a1abe1 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -1,6 +1,7 @@ { "bot_username": "Bot Username", "dialogflow_project_id": "Project Id", + "dialogflow_environment": "Environment", "dialogflow_client_email": "Client Email", "dialogflow_private_key": "Private Key", "dialogflow_fallback_responses_limit": "Fallback Responses Limit", diff --git a/lib/Dialogflow.ts b/lib/Dialogflow.ts index c26bf97..637904a 100644 --- a/lib/Dialogflow.ts +++ b/lib/Dialogflow.ts @@ -129,11 +129,12 @@ class DialogflowClass { private async getServerURL(read: IRead, modify: IModify, http: IHttp, sessionId: string) { const projectId = await getAppSettingValue(read, AppSetting.DialogflowProjectId); + const environment = await getAppSettingValue(read, AppSetting.DialogflowEnvironment); const accessToken = await this.getAccessToken(read, modify, http, sessionId); if (!accessToken) { throw Error(Logs.ACCESS_TOKEN_ERROR); } - return `https://dialogflow.googleapis.com/v2/projects/${projectId}/agent/environments/draft/users/-/sessions/${sessionId}:detectIntent?access_token=${accessToken}`; + return `https://dialogflow.googleapis.com/v2/projects/${projectId}/agent/environments/${environment}/users/-/sessions/${sessionId}:detectIntent?access_token=${accessToken}`; } private async getAccessToken(read: IRead, modify: IModify, http: IHttp, sessionId: string) { diff --git a/package.json b/package.json index 959b925..e2421a7 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,6 @@ "typescript": "^2.9.1" }, "scripts": { - "tslint": "tslint --project ." - } + "tslint": "tslint --project ." + } } From 64f770945891e3cbf683f3c38f955b3c9f7ae7d1 Mon Sep 17 00:00:00 2001 From: Marcelo Schmidt Date: Thu, 18 Nov 2021 08:54:28 -0300 Subject: [PATCH 02/19] Set default value for environment = draft --- config/Settings.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/Settings.ts b/config/Settings.ts index 10c174e..f643102 100644 --- a/config/Settings.ts +++ b/config/Settings.ts @@ -39,7 +39,7 @@ export const settings: Array = [ id: AppSetting.DialogflowProjectId, public: true, type: SettingType.STRING, - packageValue: '', + packageValue: 'draft', i18nLabel: 'dialogflow_project_id', required: true, }, From c093b8d2394fa18f6254698582db6c12729260ef Mon Sep 17 00:00:00 2001 From: Marcelo Schmidt Date: Thu, 18 Nov 2021 08:57:26 -0300 Subject: [PATCH 03/19] Bump version --- app.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.json b/app.json index cdedeec..83c4e16 100644 --- a/app.json +++ b/app.json @@ -1,6 +1,6 @@ { "id": "21b7d3ba-031b-41d9-8ff2-fbbfa081ae90", - "version": "1.2.3", + "version": "1.2.4", "requiredApiVersion": "^1.17.0", "iconFile": "icon.png", "author": { From 6cfe8710d90d90767223e5b7748c41449f8b4355 Mon Sep 17 00:00:00 2001 From: Marcelo Schmidt Date: Thu, 18 Nov 2021 09:03:31 -0300 Subject: [PATCH 04/19] Update config/Settings.ts Co-authored-by: Shailesh Baldaniya --- config/Settings.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/Settings.ts b/config/Settings.ts index f643102..10c174e 100644 --- a/config/Settings.ts +++ b/config/Settings.ts @@ -39,7 +39,7 @@ export const settings: Array = [ id: AppSetting.DialogflowProjectId, public: true, type: SettingType.STRING, - packageValue: 'draft', + packageValue: '', i18nLabel: 'dialogflow_project_id', required: true, }, From 04301ee9fd6acef771ea5451234c5a35056f5b42 Mon Sep 17 00:00:00 2001 From: Marcelo Schmidt Date: Thu, 18 Nov 2021 09:03:36 -0300 Subject: [PATCH 05/19] Update config/Settings.ts Co-authored-by: Shailesh Baldaniya --- config/Settings.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/Settings.ts b/config/Settings.ts index 10c174e..109c8a6 100644 --- a/config/Settings.ts +++ b/config/Settings.ts @@ -47,7 +47,7 @@ export const settings: Array = [ id: AppSetting.DialogflowEnvironment, public: true, type: SettingType.STRING, - packageValue: '', + packageValue: 'draft', i18nLabel: 'dialogflow_environment', required: true, }, From 26ed342c45f5836457f97a32ab9029b37ff0fd75 Mon Sep 17 00:00:00 2001 From: Murtaza Patrawala <34130764+murtaza98@users.noreply.github.com> Date: Tue, 30 Nov 2021 14:45:45 +0530 Subject: [PATCH 06/19] [IMPROVE] Increase log verbosity (#70) --- lib/Dialogflow.ts | 13 ++++++++++--- lib/Helper.ts | 2 ++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/Dialogflow.ts b/lib/Dialogflow.ts index 637904a..8ef2d56 100644 --- a/lib/Dialogflow.ts +++ b/lib/Dialogflow.ts @@ -5,7 +5,7 @@ import { AppSetting } from '../config/Settings'; import { DialogflowJWT, DialogflowRequestType, DialogflowUrl, IDialogflowAccessToken, IDialogflowEvent, IDialogflowMessage, IDialogflowQuickReplies, LanguageCode } from '../enum/Dialogflow'; import { Headers } from '../enum/Http'; import { Logs } from '../enum/Logs'; -import { base64urlEncode } from './Helper'; +import { base64urlEncode, stringifyError } from './Helper'; import { createHttpRequest } from './Http'; import { updateRoomCustomFields } from './Room'; import { getAppSettingValue } from './Settings'; @@ -32,9 +32,16 @@ class DialogflowClass { try { const response = await http.post(serverURL, httpRequestContent); + if (!response) { + throw new Error('Failed to get any response from the Dialogflow api. Please check if you server is able to connect to public n/w'); + } + if (!response.statusCode.toString().startsWith('2') || !response.data) { + throw new Error(`Invalid response received from Dialogflow api. Response: ${ response.content }`); + } + return this.parseRequest(response.data); } catch (error) { - throw new Error(`${ Logs.HTTP_REQUEST_ERROR }`); + throw new Error(`${ Logs.HTTP_REQUEST_ERROR }. Details: ${ error.message }. Raw Error: ${ stringifyError(error) }`); } } @@ -167,7 +174,7 @@ class DialogflowClass { return accessToken.token; } catch (error) { - throw Error(Logs.ACCESS_TOKEN_ERROR + error); + throw Error(`${ Logs.ACCESS_TOKEN_ERROR }. Raw Error: ${ stringifyError(error) }`); } } diff --git a/lib/Helper.ts b/lib/Helper.ts index b1e9cfd..0c613eb 100644 --- a/lib/Helper.ts +++ b/lib/Helper.ts @@ -44,3 +44,5 @@ export const uuid = (): string => { export const escapeRegExp = (str: string): string => { return str.replace(/[.*+?^${}()|[\]\\\/]/g, '\\$&'); // $& means the whole matched string }; + +export const stringifyError = (error: Error): string => (JSON.stringify(error, Object.getOwnPropertyNames(error))); From d0d4deecef8cefb7ad77a32b320101187ca676ec Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Wed, 1 Dec 2021 03:39:31 -0600 Subject: [PATCH 07/19] Chore: Replace tslint with eslint and improve typing of app (#72) Co-authored-by: murtaza98 --- .eslintignore | 5 + .eslintrc.js | 15 + .github/workflows/main.yml | 7 +- .husky/pre-commit | 4 + .prettierignore | 3 + .prettierrc | 8 + DialogflowApp.ts | 127 +- config/Settings.ts | 249 +-- endpoints/FulfillmentsEndpoint.ts | 86 +- endpoints/IncomingEndpoint.ts | 213 ++- enum/ActionIds.ts | 4 +- enum/Dialogflow.ts | 80 +- enum/Endpoints.ts | 22 +- enum/Http.ts | 10 +- enum/Logs.ts | 44 +- handler/ExecuteLivechatBlockActionHandler.ts | 148 +- handler/OnSettingUpdatedHandler.ts | 46 +- handler/PostMessageSentHandler.ts | 176 +- lib/Dialogflow.ts | 543 +++--- lib/Helper.ts | 82 +- lib/Http.ts | 40 +- lib/Message.ts | 384 +++-- lib/Room.ts | 224 ++- lib/Settings.ts | 9 +- lib/SynchronousHandover.ts | 76 +- package-lock.json | 1625 +++++++++++++++++- package.json | 27 +- tsconfig.json | 38 +- tslint.json | 33 +- types/misc.ts | 8 + 30 files changed, 3235 insertions(+), 1101 deletions(-) create mode 100644 .eslintignore create mode 100644 .eslintrc.js create mode 100755 .husky/pre-commit create mode 100644 .prettierignore create mode 100644 .prettierrc create mode 100644 types/misc.ts diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..1f80d12 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,5 @@ +node_modules +dist +.github +i18n +.* \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..650dc32 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,15 @@ +module.exports = { + root: true, + parser: '@typescript-eslint/parser', + plugins: [ + '@typescript-eslint', + ], + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + ], + rules: { + "no-case-declarations": "off", + "@typescript-eslint/no-unused-vars": ["error", { "vars": "all", "args": "after-used", "ignoreRestSiblings": false }] + }, +}; diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 586f092..9776b4f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,8 +18,11 @@ jobs: - name: Install Rocket.Chat Apps cli run: npm i -g @rocket.chat/apps-cli - - name: Tslint check - run: npm run tslint + - name: ESLint check + run: npm run lint + + - name: Typescript check + run: npm run typecheck - name: Bundle App run: rc-apps package diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..20d0d06 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npm run lint diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..801eb0a --- /dev/null +++ b/.prettierignore @@ -0,0 +1,3 @@ +node_modules +dist +.* \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..3f5f64a --- /dev/null +++ b/.prettierrc @@ -0,0 +1,8 @@ +{ + "semi": true, + "trailingComma": "all", + "singleQuote": true, + "printWidth": 80, + "useTabs": true, + "tabWidth": 4 +} diff --git a/DialogflowApp.ts b/DialogflowApp.ts index a17b4c3..fec7064 100644 --- a/DialogflowApp.ts +++ b/DialogflowApp.ts @@ -1,20 +1,27 @@ import { - IAppAccessors, - IConfigurationExtend, - IConfigurationModify, - IHttp, - ILogger, - IModify, - IPersistence, - IRead, + IAppAccessors, + IConfigurationExtend, + IConfigurationModify, + IHttp, + ILogger, + IModify, + IPersistence, + IRead, } from '@rocket.chat/apps-engine/definition/accessors'; -import { ApiSecurity, ApiVisibility } from '@rocket.chat/apps-engine/definition/api'; +import { + ApiSecurity, + ApiVisibility, +} from '@rocket.chat/apps-engine/definition/api'; import { App } from '@rocket.chat/apps-engine/definition/App'; import { ILivechatMessage } from '@rocket.chat/apps-engine/definition/livechat'; import { IPostMessageSent } from '@rocket.chat/apps-engine/definition/messages'; import { IAppInfo } from '@rocket.chat/apps-engine/definition/metadata'; import { ISetting } from '@rocket.chat/apps-engine/definition/settings'; -import { IUIKitLivechatInteractionHandler, IUIKitResponse, UIKitLivechatBlockInteractionContext } from '@rocket.chat/apps-engine/definition/uikit'; +import { + IUIKitLivechatInteractionHandler, + IUIKitResponse, + UIKitLivechatBlockInteractionContext, +} from '@rocket.chat/apps-engine/definition/uikit'; import { settings } from './config/Settings'; import { FulfillmentsEndpoint } from './endpoints/FulfillmentsEndpoint'; import { IncomingEndpoint } from './endpoints/IncomingEndpoint'; @@ -22,43 +29,73 @@ import { ExecuteLivechatBlockActionHandler } from './handler/ExecuteLivechatBloc import { OnSettingUpdatedHandler } from './handler/OnSettingUpdatedHandler'; import { PostMessageSentHandler } from './handler/PostMessageSentHandler'; -export class DialogflowApp extends App implements IPostMessageSent, IUIKitLivechatInteractionHandler { - constructor(info: IAppInfo, logger: ILogger, accessors: IAppAccessors) { - super(info, logger, accessors); - } +export class DialogflowApp + extends App + implements IPostMessageSent, IUIKitLivechatInteractionHandler +{ + constructor(info: IAppInfo, logger: ILogger, accessors: IAppAccessors) { + super(info, logger, accessors); + } - public async executeLivechatBlockActionHandler(context: UIKitLivechatBlockInteractionContext, - read: IRead, - http: IHttp, - persistence: IPersistence, - modify: IModify): Promise { - const handler = new ExecuteLivechatBlockActionHandler(this, context, read, http, persistence, modify); - return await handler.run(); - } + public async executeLivechatBlockActionHandler( + context: UIKitLivechatBlockInteractionContext, + read: IRead, + _http: IHttp, + _persistence: IPersistence, + modify: IModify, + ): Promise { + const handler = new ExecuteLivechatBlockActionHandler( + this, + context, + read, + modify, + ); + return await handler.run(); + } - public async executePostMessageSent(message: ILivechatMessage, - read: IRead, - http: IHttp, - persis: IPersistence, - modify: IModify): Promise { - const handler = new PostMessageSentHandler(this, message, read, http, persis, modify); - await handler.run(); - } + public async executePostMessageSent( + message: ILivechatMessage, + read: IRead, + http: IHttp, + _persis: IPersistence, + modify: IModify, + ): Promise { + const handler = new PostMessageSentHandler( + this, + message, + read, + http, + modify, + ); + await handler.run(); + } - public async onSettingUpdated(setting: ISetting, configurationModify: IConfigurationModify, read: IRead, http: IHttp): Promise { - const onSettingUpdatedHandler: OnSettingUpdatedHandler = new OnSettingUpdatedHandler(this, read, http); - await onSettingUpdatedHandler.run(); - } + public async onSettingUpdated( + _setting: ISetting, + _configurationModify: IConfigurationModify, + read: IRead, + http: IHttp, + ): Promise { + const onSettingUpdatedHandler: OnSettingUpdatedHandler = + new OnSettingUpdatedHandler(this, read, http); + await onSettingUpdatedHandler.run(); + } - protected async extendConfiguration(configuration: IConfigurationExtend): Promise { - configuration.api.provideApi({ - visibility: ApiVisibility.PUBLIC, - security: ApiSecurity.UNSECURE, - endpoints: [ - new IncomingEndpoint(this), - new FulfillmentsEndpoint(this), - ], - }); - await Promise.all(settings.map((setting) => configuration.settings.provideSetting(setting))); - } + protected async extendConfiguration( + configuration: IConfigurationExtend, + ): Promise { + configuration.api.provideApi({ + visibility: ApiVisibility.PUBLIC, + security: ApiSecurity.UNSECURE, + endpoints: [ + new IncomingEndpoint(this), + new FulfillmentsEndpoint(this), + ], + }); + await Promise.all( + settings.map((setting) => + configuration.settings.provideSetting(setting), + ), + ); + } } diff --git a/config/Settings.ts b/config/Settings.ts index 109c8a6..c195994 100644 --- a/config/Settings.ts +++ b/config/Settings.ts @@ -1,135 +1,138 @@ -import { ISetting, SettingType } from '@rocket.chat/apps-engine/definition/settings'; +import { + ISetting, + SettingType, +} from '@rocket.chat/apps-engine/definition/settings'; export enum AppSetting { - DialogflowBotUsername = 'dialogflow_bot_username', - DialogflowProjectId = 'dialogflow_project_id', - DialogflowEnvironment = 'dialogflow_environment', - DialogflowClientEmail = 'dialogflow_client_email', - DialogFlowPrivateKey = 'dialogflow_private_key', - DialogflowFallbackResponsesLimit = 'dialogflow_fallback_responses_limit', - FallbackTargetDepartment = 'fallback_target_department', - DialogflowHandoverMessage = 'dialogflow_handover_message', - DialogflowServiceUnavailableMessage = 'dialogflow_service_unavailable_message', - DialogflowHandoverFailedMessage = 'dialogflow_no_agents_online_for_handover', - DialogflowCloseChatMessage = 'dialogflow_close_chat_message', - DialogflowHideQuickReplies = 'dialogflow_hide_quick_replies', + DialogflowBotUsername = 'dialogflow_bot_username', + DialogflowProjectId = 'dialogflow_project_id', + DialogflowEnvironment = 'dialogflow_environment', + DialogflowClientEmail = 'dialogflow_client_email', + DialogFlowPrivateKey = 'dialogflow_private_key', + DialogflowFallbackResponsesLimit = 'dialogflow_fallback_responses_limit', + FallbackTargetDepartment = 'fallback_target_department', + DialogflowHandoverMessage = 'dialogflow_handover_message', + DialogflowServiceUnavailableMessage = 'dialogflow_service_unavailable_message', + DialogflowHandoverFailedMessage = 'dialogflow_no_agents_online_for_handover', + DialogflowCloseChatMessage = 'dialogflow_close_chat_message', + DialogflowHideQuickReplies = 'dialogflow_hide_quick_replies', } export enum ServerSetting { - SITE_URL = 'Site_Url', + SITE_URL = 'Site_Url', } export enum DefaultMessage { - DEFAULT_DialogflowServiceUnavailableMessage = 'Sorry, I\'m having trouble answering your question.', - DEFAULT_DialogflowRequestFailedMessage = 'Sorry, something went wrong.', - DEFAULT_DialogflowHandoverMessage = 'Transferring to an online agent', - DEFAULT_DialogflowCloseChatMessage = 'Closing the chat, Goodbye', + DEFAULT_DialogflowServiceUnavailableMessage = "Sorry, I'm having trouble answering your question.", + DEFAULT_DialogflowRequestFailedMessage = 'Sorry, something went wrong.', + DEFAULT_DialogflowHandoverMessage = 'Transferring to an online agent', + DEFAULT_DialogflowCloseChatMessage = 'Closing the chat, Goodbye', } export const settings: Array = [ - { - id: AppSetting.DialogflowBotUsername, - public: true, - type: SettingType.STRING, - packageValue: '', - i18nLabel: 'bot_username', - required: true, - }, - { - id: AppSetting.DialogflowProjectId, - public: true, - type: SettingType.STRING, - packageValue: '', - i18nLabel: 'dialogflow_project_id', - required: true, - }, - { - id: AppSetting.DialogflowEnvironment, - public: true, - type: SettingType.STRING, - packageValue: 'draft', - i18nLabel: 'dialogflow_environment', - required: true, - }, - { - id: AppSetting.DialogflowClientEmail, - public: true, - type: SettingType.STRING, - packageValue: '', - i18nLabel: 'dialogflow_client_email', - required: true, - }, - { - id: AppSetting.DialogFlowPrivateKey, - public: true, - type: SettingType.STRING, - packageValue: '', - i18nLabel: 'dialogflow_private_key', - required: true, - }, - { - id: AppSetting.DialogflowFallbackResponsesLimit, - public: true, - type: SettingType.NUMBER, - packageValue: 0, - value: 0, - i18nLabel: 'dialogflow_fallback_responses_limit', - i18nDescription: 'dialogflow_fallback_responses_limit_description', - required: false, - }, - { - id: AppSetting.FallbackTargetDepartment, - public: true, - type: SettingType.STRING, - packageValue: '', - i18nLabel: 'target_department_for_handover', - i18nDescription: 'target_department_for_handover_description', - required: false, - }, - { - id: AppSetting.DialogflowHandoverMessage, - public: true, - type: SettingType.STRING, - packageValue: '', - i18nLabel: 'dialogflow_handover_message', - i18nDescription: 'dialogflow_handover_message_description', - required: false, - }, - { - id: AppSetting.DialogflowHandoverFailedMessage, - public: true, - type: SettingType.STRING, - packageValue: '', - i18nLabel: 'dialogflow_handover_failed_message', - i18nDescription: 'dialogflow_handover_failed_message_description', - required: false, - }, - { - id: AppSetting.DialogflowServiceUnavailableMessage, - public: true, - type: SettingType.STRING, - packageValue: '', - i18nLabel: 'dialogflow_service_unavailable_message', - i18nDescription: 'dialogflow_service_unavailable_message_description', - required: false, - }, - { - id: AppSetting.DialogflowCloseChatMessage, - public: true, - type: SettingType.STRING, - packageValue: '', - i18nLabel: 'dialogflow_close_chat_message', - i18nDescription: 'dialogflow_close_chat_message_description', - required: false, - }, - { - id: AppSetting.DialogflowHideQuickReplies, - public: true, - type: SettingType.BOOLEAN, - packageValue: true, - value: true, - i18nLabel: 'dialogflow_hide_quick_replies', - i18nDescription: 'dialogflow_hide_quick_replies_description', - required: true, - }, + { + id: AppSetting.DialogflowBotUsername, + public: true, + type: SettingType.STRING, + packageValue: '', + i18nLabel: 'bot_username', + required: true, + }, + { + id: AppSetting.DialogflowProjectId, + public: true, + type: SettingType.STRING, + packageValue: '', + i18nLabel: 'dialogflow_project_id', + required: true, + }, + { + id: AppSetting.DialogflowEnvironment, + public: true, + type: SettingType.STRING, + packageValue: 'draft', + i18nLabel: 'dialogflow_environment', + required: true, + }, + { + id: AppSetting.DialogflowClientEmail, + public: true, + type: SettingType.STRING, + packageValue: '', + i18nLabel: 'dialogflow_client_email', + required: true, + }, + { + id: AppSetting.DialogFlowPrivateKey, + public: true, + type: SettingType.STRING, + packageValue: '', + i18nLabel: 'dialogflow_private_key', + required: true, + }, + { + id: AppSetting.DialogflowFallbackResponsesLimit, + public: true, + type: SettingType.NUMBER, + packageValue: 0, + value: 0, + i18nLabel: 'dialogflow_fallback_responses_limit', + i18nDescription: 'dialogflow_fallback_responses_limit_description', + required: false, + }, + { + id: AppSetting.FallbackTargetDepartment, + public: true, + type: SettingType.STRING, + packageValue: '', + i18nLabel: 'target_department_for_handover', + i18nDescription: 'target_department_for_handover_description', + required: false, + }, + { + id: AppSetting.DialogflowHandoverMessage, + public: true, + type: SettingType.STRING, + packageValue: '', + i18nLabel: 'dialogflow_handover_message', + i18nDescription: 'dialogflow_handover_message_description', + required: false, + }, + { + id: AppSetting.DialogflowHandoverFailedMessage, + public: true, + type: SettingType.STRING, + packageValue: '', + i18nLabel: 'dialogflow_handover_failed_message', + i18nDescription: 'dialogflow_handover_failed_message_description', + required: false, + }, + { + id: AppSetting.DialogflowServiceUnavailableMessage, + public: true, + type: SettingType.STRING, + packageValue: '', + i18nLabel: 'dialogflow_service_unavailable_message', + i18nDescription: 'dialogflow_service_unavailable_message_description', + required: false, + }, + { + id: AppSetting.DialogflowCloseChatMessage, + public: true, + type: SettingType.STRING, + packageValue: '', + i18nLabel: 'dialogflow_close_chat_message', + i18nDescription: 'dialogflow_close_chat_message_description', + required: false, + }, + { + id: AppSetting.DialogflowHideQuickReplies, + public: true, + type: SettingType.BOOLEAN, + packageValue: true, + value: true, + i18nLabel: 'dialogflow_hide_quick_replies', + i18nDescription: 'dialogflow_hide_quick_replies_description', + required: true, + }, ]; diff --git a/endpoints/FulfillmentsEndpoint.ts b/endpoints/FulfillmentsEndpoint.ts index e365233..6855289 100644 --- a/endpoints/FulfillmentsEndpoint.ts +++ b/endpoints/FulfillmentsEndpoint.ts @@ -1,5 +1,14 @@ -import { HttpStatusCode, IHttp, IModify, IPersistence, IRead } from '@rocket.chat/apps-engine/definition/accessors'; -import { ApiEndpoint, IApiEndpointInfo, IApiRequest, IApiResponse } from '@rocket.chat/apps-engine/definition/api'; +import { + HttpStatusCode, + IModify, + IRead, +} from '@rocket.chat/apps-engine/definition/accessors'; +import { + ApiEndpoint, + IApiEndpointInfo, + IApiRequest, + IApiResponse, +} from '@rocket.chat/apps-engine/definition/api'; import { IDialogflowMessage } from '../enum/Dialogflow'; import { Headers } from '../enum/Http'; import { Logs } from '../enum/Logs'; @@ -8,33 +17,56 @@ import { createHttpResponse } from '../lib/Http'; import { createDialogflowMessage } from '../lib/Message'; export class FulfillmentsEndpoint extends ApiEndpoint { - public path = 'fulfillment'; + public path = 'fulfillment'; - public async post(request: IApiRequest, - endpoint: IApiEndpointInfo, - read: IRead, - modify: IModify, - http: IHttp, - persis: IPersistence): Promise { - this.app.getLogger().info(Logs.ENDPOINT_RECEIVED_REQUEST); + public async post( + request: IApiRequest, + _endpoint: IApiEndpointInfo, + read: IRead, + modify: IModify, + ): Promise { + this.app.getLogger().info(Logs.ENDPOINT_RECEIVED_REQUEST); - try { - await this.processRequest(read, modify, persis, request); - return createHttpResponse( - HttpStatusCode.OK, - { 'Content-Type': Headers.CONTENT_TYPE_JSON }, - { fulfillmentMessages: [] }); - } catch (error) { - this.app.getLogger().error(Logs.ENDPOINT_REQUEST_PROCESSING_ERROR, error); - return createHttpResponse(HttpStatusCode.INTERNAL_SERVER_ERROR, { 'Content-Type': Headers.CONTENT_TYPE_JSON }, { error: error.message }); - } - } + try { + await this.processRequest(read, modify, request); + return createHttpResponse( + HttpStatusCode.OK, + { 'Content-Type': Headers.CONTENT_TYPE_JSON }, + { fulfillmentMessages: [] }, + ); + } catch (error: unknown) { + this.app + .getLogger() + .error(Logs.ENDPOINT_REQUEST_PROCESSING_ERROR, error); + return createHttpResponse( + HttpStatusCode.INTERNAL_SERVER_ERROR, + { 'Content-Type': Headers.CONTENT_TYPE_JSON }, + { error: (error as Error).message }, + ); + } + } - private async processRequest(read: IRead, modify: IModify, persis: IPersistence, request: IApiRequest) { - const message: IDialogflowMessage = Dialogflow.parseRequest(request.content); - if (!message) { throw new Error(Logs.INVALID_REQUEST_CONTENT); } - if (!message.sessionId) { throw new Error(Logs.INVALID_SESSION_ID); } + private async processRequest( + read: IRead, + modify: IModify, + request: IApiRequest, + ) { + const message: IDialogflowMessage = Dialogflow.parseRequest( + request.content, + ); + if (!message) { + throw new Error(Logs.INVALID_REQUEST_CONTENT); + } + if (!message.sessionId) { + throw new Error(Logs.INVALID_SESSION_ID); + } - await createDialogflowMessage(this.app, message.sessionId, read, modify, message); - } + await createDialogflowMessage( + this.app, + message.sessionId, + read, + modify, + message, + ); + } } diff --git a/endpoints/IncomingEndpoint.ts b/endpoints/IncomingEndpoint.ts index 63e96e5..05bba15 100644 --- a/endpoints/IncomingEndpoint.ts +++ b/endpoints/IncomingEndpoint.ts @@ -1,8 +1,21 @@ -import { HttpStatusCode, IHttp, IModify, IPersistence, IRead } from '@rocket.chat/apps-engine/definition/accessors'; -import { ApiEndpoint, IApiEndpointInfo, IApiRequest, IApiResponse } from '@rocket.chat/apps-engine/definition/api'; +import { + HttpStatusCode, + IHttp, + IModify, + IRead, +} from '@rocket.chat/apps-engine/definition/accessors'; +import { + ApiEndpoint, + IApiEndpointInfo, + IApiRequest, + IApiResponse, +} from '@rocket.chat/apps-engine/definition/api'; import { ILivechatRoom } from '@rocket.chat/apps-engine/definition/livechat'; import { DialogflowRequestType, IDialogflowMessage } from '../enum/Dialogflow'; -import { EndpointActionNames, IActionsEndpointContent } from '../enum/Endpoints'; +import { + EndpointActionNames, + IActionsEndpointContent, +} from '../enum/Endpoints'; import { Headers, Response } from '../enum/Http'; import { Logs } from '../enum/Logs'; import { Dialogflow } from '../lib/Dialogflow'; @@ -11,67 +24,145 @@ import { createDialogflowMessage } from '../lib/Message'; import { closeChat, performHandover } from '../lib/Room'; export class IncomingEndpoint extends ApiEndpoint { - public path = 'incoming'; + public path = 'incoming'; - public async post(request: IApiRequest, - endpoint: IApiEndpointInfo, - read: IRead, - modify: IModify, - http: IHttp, - persis: IPersistence): Promise { - this.app.getLogger().info(Logs.ENDPOINT_RECEIVED_REQUEST); + public async post( + request: IApiRequest, + _endpoint: IApiEndpointInfo, + read: IRead, + modify: IModify, + http: IHttp, + ): Promise { + this.app.getLogger().info(Logs.ENDPOINT_RECEIVED_REQUEST); - try { - const { statusCode = HttpStatusCode.OK, data = null } = await this.processRequest(read, modify, http, request.content); - return createHttpResponse(statusCode, { 'Content-Type': Headers.CONTENT_TYPE_JSON }, { ...data ? { ...data } : { result: Response.SUCCESS } }); - } catch (error) { - this.app.getLogger().error(Logs.ENDPOINT_REQUEST_PROCESSING_ERROR, error); - return createHttpResponse(HttpStatusCode.INTERNAL_SERVER_ERROR, { 'Content-Type': Headers.CONTENT_TYPE_JSON }, { error: error.message }); - } - } + try { + const { statusCode = HttpStatusCode.OK, data = null } = + await this.processRequest(read, modify, http, request.content); + return createHttpResponse( + statusCode, + { 'Content-Type': Headers.CONTENT_TYPE_JSON }, + { ...(data ? { ...data } : { result: Response.SUCCESS }) }, + ); + } catch (error) { + this.app + .getLogger() + .error(Logs.ENDPOINT_REQUEST_PROCESSING_ERROR, error); + return createHttpResponse( + HttpStatusCode.INTERNAL_SERVER_ERROR, + { 'Content-Type': Headers.CONTENT_TYPE_JSON }, + { error: (error as Error).message }, + ); + } + } - private async processRequest(read: IRead, - modify: IModify, - http: IHttp, - endpointContent: IActionsEndpointContent, - ): Promise<{ statusCode: HttpStatusCode, data?: { result?: string; error?: string } }> { - const { action, sessionId } = endpointContent; - if (!sessionId) { throw new Error(Logs.INVALID_SESSION_ID); } - switch (action) { - case EndpointActionNames.CLOSE_CHAT: - await closeChat(modify, read, sessionId); - break; - case EndpointActionNames.HANDOVER: - const { actionData: { targetDepartment = '' } = {} } = endpointContent; - const room = await read.getRoomReader().getById(sessionId) as ILivechatRoom; - if (!room || !room.isOpen) { throw new Error('Error! Invalid session Id. No active room found with the given session id'); } - const { visitor: { token: visitorToken } } = room; - const result = await performHandover(this.app, modify, read, sessionId, visitorToken, targetDepartment); - if (!result) { - return { statusCode: HttpStatusCode.CONFLICT, data: { error: Response.NO_AGENTS_ONLINE }}; - } - break; - case EndpointActionNames.TRIGGER_EVENT: - const { actionData: { event = null } = {} } = endpointContent; - if (!event) { throw new Error(Logs.INVALID_EVENT_DATA); } + private async processRequest( + read: IRead, + modify: IModify, + http: IHttp, + endpointContent: IActionsEndpointContent, + ): Promise<{ + statusCode: HttpStatusCode; + data?: { result?: string; error?: string }; + }> { + const { action, sessionId } = endpointContent; + if (!sessionId) { + throw new Error(Logs.INVALID_SESSION_ID); + } + switch (action) { + case EndpointActionNames.CLOSE_CHAT: + await closeChat(modify, read, sessionId); + break; + case EndpointActionNames.HANDOVER: + const { actionData: { targetDepartment = '' } = {} } = + endpointContent; + const room = (await read + .getRoomReader() + .getById(sessionId)) as ILivechatRoom; + if (!room || !room.isOpen) { + throw new Error( + 'Error! Invalid session Id. No active room found with the given session id', + ); + } + const { + visitor: { token: visitorToken }, + } = room; + const result = await performHandover( + this.app, + modify, + read, + sessionId, + visitorToken, + targetDepartment, + ); + if (!result) { + return { + statusCode: HttpStatusCode.CONFLICT, + data: { error: Response.NO_AGENTS_ONLINE }, + }; + } + break; + case EndpointActionNames.TRIGGER_EVENT: + const { actionData: { event = null } = {} } = endpointContent; + if (!event) { + throw new Error(Logs.INVALID_EVENT_DATA); + } - try { - const response: IDialogflowMessage = await Dialogflow.sendRequest(http, read, modify, sessionId, event, DialogflowRequestType.EVENT); - await createDialogflowMessage(this.app, sessionId, read, modify, response); - } catch (error) { - this.app.getLogger().error(`${Logs.DIALOGFLOW_REST_API_ERROR} ${error.message}`); - throw new Error(`${Logs.DIALOGFLOW_REST_API_ERROR} ${error.message}`); - } - break; - case EndpointActionNames.SEND_MESSAGE: - const { actionData: { messages = null } = {} } = endpointContent; - if (!messages) { throw new Error(Logs.INVALID_MESSAGES); } - await createDialogflowMessage(this.app, sessionId, read, modify, { messages, isFallback: false }); - break; - default: - throw new Error(Logs.INVALID_ENDPOINT_ACTION); - } + try { + const response: IDialogflowMessage = + await Dialogflow.sendRequest( + http, + read, + modify, + sessionId, + event, + DialogflowRequestType.EVENT, + ); + await createDialogflowMessage( + this.app, + sessionId, + read, + modify, + response, + ); + } catch (error) { + this.app + .getLogger() + .error( + `${Logs.DIALOGFLOW_REST_API_ERROR} ${ + (error as Error).message + }`, + ); + throw new Error( + `${Logs.DIALOGFLOW_REST_API_ERROR} ${ + (error as Error).message + }`, + ); + } + break; + case EndpointActionNames.SEND_MESSAGE: + const { actionData: { messages = null } = {} } = + endpointContent; + if (!messages) { + throw new Error(Logs.INVALID_MESSAGES); + } + await createDialogflowMessage( + this.app, + sessionId, + read, + modify, + { + messages, + isFallback: false, + }, + ); + break; + default: + throw new Error(Logs.INVALID_ENDPOINT_ACTION); + } - return { statusCode: HttpStatusCode.OK, data: { result: Response.SUCCESS }}; - } + return { + statusCode: HttpStatusCode.OK, + data: { result: Response.SUCCESS }, + }; + } } diff --git a/enum/ActionIds.ts b/enum/ActionIds.ts index 022f9b3..28970fa 100644 --- a/enum/ActionIds.ts +++ b/enum/ActionIds.ts @@ -1,4 +1,4 @@ export enum ActionIds { - PERFORM_HANDOVER = 'df_perform_handover', - CLOSE_CHAT = 'df_close_chat', + PERFORM_HANDOVER = 'df_perform_handover', + CLOSE_CHAT = 'df_close_chat', } diff --git a/enum/Dialogflow.ts b/enum/Dialogflow.ts index 77b2505..b1073fc 100644 --- a/enum/Dialogflow.ts +++ b/enum/Dialogflow.ts @@ -1,62 +1,86 @@ import { ButtonStyle } from '@rocket.chat/apps-engine/definition/uikit'; export interface IDialogflowMessage { - messages?: Array; - isFallback: boolean; - sessionId?: string; + messages?: Array; + isFallback: boolean; + sessionId?: string; +} + +export interface IDialogflowFulfillmentMessage { + text: { + text: string; + }; + payload: { + quickReplies: IDialogflowQuickReplies; + }; +} + +type SessionString = `projects/${string}/agent/sessions/${string}`; + +export interface IDialogflowResponse { + session: SessionString; + queryResult: { + fulfillmentMessages: IDialogflowFulfillmentMessage[]; + intent: { + isFallback: boolean; + }; + }; + error?: { + message: string; + }; } export interface IDialogflowQuickReplies { - text: string; - options: Array; + text: string; + options: Array; } export interface IDialogflowQuickReplyOptions { - text: string; - actionId?: string; - buttonStyle?: ButtonStyle; - data?: { - [prop: string]: any; - }; + text: string; + actionId?: string; + buttonStyle?: ButtonStyle; + data?: { + [prop: string]: string; + }; } export interface IDialogflowAccessToken { - token: string; - expiration: Date; + token: string; + expiration: Date; } export interface IDialogflowEvent { - name: string; - parameters?: any; - languageCode: string; + name: string; + parameters?: unknown; + languageCode: string; } export enum QuickReplyContentType { - TEXT = 'text', + TEXT = 'text', } export enum DialogflowUrl { - AUTHENTICATION_SERVER_URL = 'https://oauth2.googleapis.com/token', + AUTHENTICATION_SERVER_URL = 'https://oauth2.googleapis.com/token', } export enum DialogflowJWT { - JWT_HEADER = '{"alg":"RS256","typ":"JWT"}', - SCOPE_URL = 'https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/dialogflow', - AUD_URL = 'https://oauth2.googleapis.com/token', - SHA_256 = 'SHA256', - BASE_64 = 'base64', + JWT_HEADER = '{"alg":"RS256","typ":"JWT"}', + SCOPE_URL = 'https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/dialogflow', + AUD_URL = 'https://oauth2.googleapis.com/token', + SHA_256 = 'SHA256', + BASE_64 = 'base64', } export enum Base64 { - BASE64_DICTIONARY = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_', - BASE64_PAD = '=', + BASE64_DICTIONARY = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_', + BASE64_PAD = '=', } export enum LanguageCode { - EN = 'en', + EN = 'en', } export enum DialogflowRequestType { - MESSAGE = 'message', - EVENT = 'event', + MESSAGE = 'message', + EVENT = 'event', } diff --git a/enum/Endpoints.ts b/enum/Endpoints.ts index 484c1a2..843d103 100644 --- a/enum/Endpoints.ts +++ b/enum/Endpoints.ts @@ -1,18 +1,18 @@ import { IDialogflowEvent, IDialogflowQuickReplies } from './Dialogflow'; export interface IActionsEndpointContent { - action: EndpointActionNames; - sessionId: string; - actionData?: { - targetDepartment?: string; - event?: IDialogflowEvent; - messages: Array; - }; + action: EndpointActionNames; + sessionId: string; + actionData?: { + targetDepartment?: string; + event?: IDialogflowEvent; + messages: Array; + }; } export enum EndpointActionNames { - CLOSE_CHAT = 'close-chat', - HANDOVER = 'handover', - TRIGGER_EVENT = 'trigger-event', - SEND_MESSAGE = 'send-message', + CLOSE_CHAT = 'close-chat', + HANDOVER = 'handover', + TRIGGER_EVENT = 'trigger-event', + SEND_MESSAGE = 'send-message', } diff --git a/enum/Http.ts b/enum/Http.ts index dbd3b14..4f643de 100644 --- a/enum/Http.ts +++ b/enum/Http.ts @@ -1,10 +1,10 @@ export enum Headers { - CONTENT_TYPE_JSON = 'application/json', - CONTENT_TYPE_X_FORM_URL_ENCODED = 'application/x-www-form-urlencoded', - ACCEPT_JSON = 'application/json', + CONTENT_TYPE_JSON = 'application/json', + CONTENT_TYPE_X_FORM_URL_ENCODED = 'application/x-www-form-urlencoded', + ACCEPT_JSON = 'application/json', } export enum Response { - SUCCESS = 'Your request was processed successfully', - NO_AGENTS_ONLINE = 'Handover failed! No agents online', + SUCCESS = 'Your request was processed successfully', + NO_AGENTS_ONLINE = 'Handover failed! No agents online', } diff --git a/enum/Logs.ts b/enum/Logs.ts index 5dd401d..371dd47 100644 --- a/enum/Logs.ts +++ b/enum/Logs.ts @@ -1,24 +1,24 @@ export enum Logs { - ENDPOINT_RECEIVED_REQUEST = 'Endpoint received a request', - INVALID_SESSION_ID = 'Error! Session Id not valid', - INVALID_ROOM_ID = 'Error! Room Id not valid', - INVALID_REQUEST_CONTENT = 'Error! Request content not valid', - INVALID_BOT_USERNAME_SETTING = 'The Bot User does not exist.', - INVALID_VISITOR_TOKEN = 'Error: Visitor Token not valid', - INVALID_DEPARTMENT_NAME = 'Error: Department Name is not valid', - INVALID_EVENT_DATA = 'Error! Event Data not valid', - INVALID_MESSAGES = 'Error! Messages data not present or in wrong format. Kindly refer the api documentation.', - ENDPOINT_REQUEST_PROCESSING_ERROR = 'Error occurred while processing the request. Details:- ', - INVALID_ENDPOINT_ACTION = 'Error!! Invalid Action type', - EMPTY_CLIENT_EMAIL_OR_PRIVATE_KEY_SETTING = 'Client Email or Private Key Field cannot be empty', - EMPTY_BOT_USERNAME_SETTING = 'The Bot Username setting is not defined.', - GOOGLE_AUTH_SUCCESS = '------------------ Google Credentials validation Success ----------------', - DIALOGFLOW_REST_API_ERROR = 'Error occurred while using Dialogflow Rest API. Details:-', - INVALID_RESPONSE_FROM_DIALOGFLOW = 'Error!! Invalid Response From Dialogflow', - INVALID_RESPONSE_FROM_DIALOGFLOW_CONTENT_UNDEFINED = 'Error Parsing Dialogflow\'s Response. Content is undefined', - ACCESS_TOKEN_ERROR = 'Error retrieving access token', - HTTP_REQUEST_ERROR = 'Error occurred while sending a HTTP Request', - CLOSE_CHAT_REQUEST_FAILED_ERROR = 'Error: Internal Server Error. Could not close the chat', - HANDOVER_REQUEST_FAILED_ERROR = 'Error occurred while processing handover. Details', - NO_AGENTS_ONLINE = 'Handover failed! No agents online', + ENDPOINT_RECEIVED_REQUEST = 'Endpoint received a request', + INVALID_SESSION_ID = 'Error! Session Id not valid', + INVALID_ROOM_ID = 'Error! Room Id not valid', + INVALID_REQUEST_CONTENT = 'Error! Request content not valid', + INVALID_BOT_USERNAME_SETTING = 'The Bot User does not exist.', + INVALID_VISITOR_TOKEN = 'Error: Visitor Token not valid', + INVALID_DEPARTMENT_NAME = 'Error: Department Name is not valid', + INVALID_EVENT_DATA = 'Error! Event Data not valid', + INVALID_MESSAGES = 'Error! Messages data not present or in wrong format. Kindly refer the api documentation.', + ENDPOINT_REQUEST_PROCESSING_ERROR = 'Error occurred while processing the request. Details:- ', + INVALID_ENDPOINT_ACTION = 'Error!! Invalid Action type', + EMPTY_CLIENT_EMAIL_OR_PRIVATE_KEY_SETTING = 'Client Email or Private Key Field cannot be empty', + EMPTY_BOT_USERNAME_SETTING = 'The Bot Username setting is not defined.', + GOOGLE_AUTH_SUCCESS = '------------------ Google Credentials validation Success ----------------', + DIALOGFLOW_REST_API_ERROR = 'Error occurred while using Dialogflow Rest API. Details:-', + INVALID_RESPONSE_FROM_DIALOGFLOW = 'Error!! Invalid Response From Dialogflow', + INVALID_RESPONSE_FROM_DIALOGFLOW_CONTENT_UNDEFINED = "Error Parsing Dialogflow's Response. Content is undefined", + ACCESS_TOKEN_ERROR = 'Error retrieving access token', + HTTP_REQUEST_ERROR = 'Error occurred while sending a HTTP Request', + CLOSE_CHAT_REQUEST_FAILED_ERROR = 'Error: Internal Server Error. Could not close the chat', + HANDOVER_REQUEST_FAILED_ERROR = 'Error occurred while processing handover. Details', + NO_AGENTS_ONLINE = 'Handover failed! No agents online', } diff --git a/handler/ExecuteLivechatBlockActionHandler.ts b/handler/ExecuteLivechatBlockActionHandler.ts index c02e98b..7d414ce 100644 --- a/handler/ExecuteLivechatBlockActionHandler.ts +++ b/handler/ExecuteLivechatBlockActionHandler.ts @@ -1,69 +1,121 @@ -import { IHttp, IModify, IPersistence, IRead } from '@rocket.chat/apps-engine/definition/accessors'; +import { + IModify, + IRead, +} from '@rocket.chat/apps-engine/definition/accessors'; import { IApp } from '@rocket.chat/apps-engine/definition/IApp'; import { ILivechatRoom } from '@rocket.chat/apps-engine/definition/livechat'; -import { IUIKitResponse, UIKitLivechatBlockInteractionContext } from '@rocket.chat/apps-engine/definition/uikit'; +import { + IUIKitResponse, + UIKitLivechatBlockInteractionContext, +} from '@rocket.chat/apps-engine/definition/uikit'; import { UIKitIncomingInteractionContainerType } from '@rocket.chat/apps-engine/definition/uikit/UIKitIncomingInteractionContainer'; import { IUser } from '@rocket.chat/apps-engine/definition/users'; import { AppSetting, DefaultMessage } from '../config/Settings'; import { ActionIds } from '../enum/ActionIds'; -import { createLivechatMessage, createMessage, deleteAllActionBlocks } from '../lib/Message'; +import { + createLivechatMessage, + createMessage, + deleteAllActionBlocks, +} from '../lib/Message'; import { closeChat, performHandover } from '../lib/Room'; import { getAppSettingValue } from '../lib/Settings'; export class ExecuteLivechatBlockActionHandler { - constructor(private readonly app: IApp, - private context: UIKitLivechatBlockInteractionContext, - private read: IRead, - private http: IHttp, - private persistence: IPersistence, - private modify: IModify) {} + constructor( + private readonly app: IApp, + private context: UIKitLivechatBlockInteractionContext, + private read: IRead, + private modify: IModify, + ) {} - public async run(): Promise { - try { - const interactionData = this.context.getInteractionData(); - const { visitor, room, container: { id, type }, value, actionId } = interactionData; + public async run(): Promise { + try { + const interactionData = this.context.getInteractionData(); + const { + visitor, + room, + container: { id, type }, + value, + actionId, + } = interactionData; - if (type !== UIKitIncomingInteractionContainerType.MESSAGE) { - return this.context.getInteractionResponder().successResponse(); - } + if (type !== UIKitIncomingInteractionContainerType.MESSAGE) { + return this.context.getInteractionResponder().successResponse(); + } - const DialogflowBotUsername: string = await getAppSettingValue(this.read, AppSetting.DialogflowBotUsername); - const { servedBy: { username = null } = {}, id: rid } = room as ILivechatRoom; + const DialogflowBotUsername: string = await getAppSettingValue( + this.read, + AppSetting.DialogflowBotUsername, + ); + const { servedBy: { username = null } = {}, id: rid } = + room as ILivechatRoom; - if (!username || DialogflowBotUsername !== username) { - return this.context.getInteractionResponder().successResponse(); - } + if (!username || DialogflowBotUsername !== username) { + return this.context.getInteractionResponder().successResponse(); + } - const appUser = await this.read.getUserReader().getAppUser(this.app.getID()) as IUser; + const appUser = (await this.read + .getUserReader() + .getAppUser(this.app.getID())) as IUser; - switch (actionId) { - case ActionIds.PERFORM_HANDOVER: - const targetDepartment: string = value || await getAppSettingValue(this.read, AppSetting.FallbackTargetDepartment); - if (!targetDepartment) { - await createMessage(this.app, rid, this.read, this.modify, { text: DefaultMessage.DEFAULT_DialogflowRequestFailedMessage }); - break; - } - await performHandover(this.app, this.modify, this.read, rid, visitor.token, targetDepartment); - break; + switch (actionId) { + case ActionIds.PERFORM_HANDOVER: + const targetDepartment: string = + value || + (await getAppSettingValue( + this.read, + AppSetting.FallbackTargetDepartment, + )); + if (!targetDepartment) { + await createMessage( + this.app, + rid, + this.read, + this.modify, + { + text: DefaultMessage.DEFAULT_DialogflowRequestFailedMessage, + }, + ); + break; + } + await performHandover( + this.app, + this.modify, + this.read, + rid, + visitor.token, + targetDepartment, + ); + break; - case ActionIds.CLOSE_CHAT: - await closeChat(this.modify, this.read, rid); - break; + case ActionIds.CLOSE_CHAT: + await closeChat(this.modify, this.read, rid); + break; - default: - await createLivechatMessage(this.app, rid, this.read, this.modify, { text: value }, visitor); - break; - } + default: + await createLivechatMessage( + this.app, + rid, + this.read, + this.modify, + { text: value }, + visitor, + ); + break; + } - const { value: hideQuickRepliesSetting } = await this.read.getEnvironmentReader().getSettings().getById(AppSetting.DialogflowHideQuickReplies); - if (hideQuickRepliesSetting) { - await deleteAllActionBlocks(this.modify, appUser, id); - } + const { value: hideQuickRepliesSetting } = await this.read + .getEnvironmentReader() + .getSettings() + .getById(AppSetting.DialogflowHideQuickReplies); + if (hideQuickRepliesSetting) { + await deleteAllActionBlocks(this.modify, appUser, id); + } - return this.context.getInteractionResponder().successResponse(); - } catch (error) { - this.app.getLogger().error(error); - return this.context.getInteractionResponder().errorResponse(); - } - } + return this.context.getInteractionResponder().successResponse(); + } catch (error) { + this.app.getLogger().error(error); + return this.context.getInteractionResponder().errorResponse(); + } + } } diff --git a/handler/OnSettingUpdatedHandler.ts b/handler/OnSettingUpdatedHandler.ts index 32917c4..aec7a3c 100644 --- a/handler/OnSettingUpdatedHandler.ts +++ b/handler/OnSettingUpdatedHandler.ts @@ -6,22 +6,38 @@ import { Dialogflow } from '../lib/Dialogflow'; import { getAppSettingValue } from '../lib/Settings'; export class OnSettingUpdatedHandler { - constructor(private readonly app: IApp, private readonly read: IRead, private readonly http: IHttp) {} + constructor( + private readonly app: IApp, + private readonly read: IRead, + private readonly http: IHttp, + ) {} - public async run() { - const clientEmail: string = await getAppSettingValue(this.read, AppSetting.DialogflowClientEmail); - const privateKey: string = await getAppSettingValue(this.read, AppSetting.DialogFlowPrivateKey); + public async run() { + const clientEmail: string = await getAppSettingValue( + this.read, + AppSetting.DialogflowClientEmail, + ); + const privateKey: string = await getAppSettingValue( + this.read, + AppSetting.DialogFlowPrivateKey, + ); - if (clientEmail.length === 0 || privateKey.length === 0) { - this.app.getLogger().error(Logs.EMPTY_CLIENT_EMAIL_OR_PRIVATE_KEY_SETTING); - return; - } + if (clientEmail.length === 0 || privateKey.length === 0) { + this.app + .getLogger() + .error(Logs.EMPTY_CLIENT_EMAIL_OR_PRIVATE_KEY_SETTING); + return; + } - try { - await Dialogflow.generateNewAccessToken(this.http, clientEmail, privateKey); - this.app.getLogger().info(Logs.GOOGLE_AUTH_SUCCESS); - } catch (error) { - this.app.getLogger().error(error.message); - } - } + try { + await Dialogflow.generateNewAccessToken( + this.http, + clientEmail, + privateKey, + ); + this.app.getLogger().info(Logs.GOOGLE_AUTH_SUCCESS); + } catch (error) { + this.app.getLogger().error(error); + } + } } diff --git a/handler/PostMessageSentHandler.ts b/handler/PostMessageSentHandler.ts index e6c6f78..d9817b2 100644 --- a/handler/PostMessageSentHandler.ts +++ b/handler/PostMessageSentHandler.ts @@ -1,78 +1,118 @@ -import { IHttp, IModify, IPersistence, IRead } from '@rocket.chat/apps-engine/definition/accessors'; +import { + IHttp, + IModify, + IRead, +} from '@rocket.chat/apps-engine/definition/accessors'; import { IApp } from '@rocket.chat/apps-engine/definition/IApp'; -import { ILivechatMessage, ILivechatRoom } from '@rocket.chat/apps-engine/definition/livechat'; +import { + ILivechatMessage, + ILivechatRoom, +} from '@rocket.chat/apps-engine/definition/livechat'; import { RoomType } from '@rocket.chat/apps-engine/definition/rooms'; import { AppSetting, DefaultMessage } from '../config/Settings'; import { DialogflowRequestType, IDialogflowMessage } from '../enum/Dialogflow'; import { Logs } from '../enum/Logs'; import { Dialogflow } from '../lib/Dialogflow'; -import { createDialogflowMessage, createMessage, removeQuotedMessage } from '../lib/Message'; +import { + createDialogflowMessage, + createMessage, + removeQuotedMessage, +} from '../lib/Message'; import { getAppSettingValue } from '../lib/Settings'; -import { incFallbackIntent, resetFallbackIntent } from '../lib/SynchronousHandover'; +import { + incFallbackIntent, + resetFallbackIntent, +} from '../lib/SynchronousHandover'; export class PostMessageSentHandler { - constructor(private readonly app: IApp, - private readonly message: ILivechatMessage, - private readonly read: IRead, - private readonly http: IHttp, - private readonly persis: IPersistence, - private readonly modify: IModify) {} - - public async run() { - const { text, editedAt, room, token, sender } = this.message; - const livechatRoom = room as ILivechatRoom; - - const { id: rid, type, servedBy, isOpen } = livechatRoom; - - const DialogflowBotUsername: string = await getAppSettingValue(this.read, AppSetting.DialogflowBotUsername); - - if (!type || type !== RoomType.LIVE_CHAT) { - return; - } - - if (!isOpen || !token || editedAt || !text) { - return; - } - - if (!servedBy || servedBy.username !== DialogflowBotUsername) { - return; - } - - if (sender.username === DialogflowBotUsername) { - return; - } - - if (!text || (text && text.trim().length === 0)) { - return; - } - - let messageText = text; - messageText = await removeQuotedMessage(this.read, room, messageText); - - let response: IDialogflowMessage; - try { - response = (await Dialogflow.sendRequest(this.http, this.read, this.modify, rid, messageText, DialogflowRequestType.MESSAGE)); - } catch (error) { - this.app.getLogger().error(`${Logs.DIALOGFLOW_REST_API_ERROR} ${error.message}`); - - const serviceUnavailable: string = await getAppSettingValue(this.read, AppSetting.DialogflowServiceUnavailableMessage); - - await createMessage(this.app, - rid, - this.read, - this.modify, - { text: serviceUnavailable ? serviceUnavailable : DefaultMessage.DEFAULT_DialogflowServiceUnavailableMessage }); - - return; - } - - await createDialogflowMessage(this.app, rid, this.read, this.modify, response); - - // synchronous handover check - const { isFallback } = response; - if (isFallback) { - return incFallbackIntent(this.app, this.read, this.modify, rid); - } - return resetFallbackIntent(this.read, this.modify, rid); - } + constructor( + private readonly app: IApp, + private readonly message: ILivechatMessage, + private readonly read: IRead, + private readonly http: IHttp, + private readonly modify: IModify, + ) {} + + public async run() { + const { text, editedAt, room, token, sender } = this.message; + const livechatRoom = room as ILivechatRoom; + + const { id: rid, type, servedBy, isOpen } = livechatRoom; + + const DialogflowBotUsername: string = await getAppSettingValue( + this.read, + AppSetting.DialogflowBotUsername, + ); + + if (!type || type !== RoomType.LIVE_CHAT) { + return; + } + + if (!isOpen || !token || editedAt || !text) { + return; + } + + if (!servedBy || servedBy.username !== DialogflowBotUsername) { + return; + } + + if (sender.username === DialogflowBotUsername) { + return; + } + + if (!text || (text && text.trim().length === 0)) { + return; + } + + let messageText = text; + messageText = await removeQuotedMessage(this.read, room, messageText); + + let response: IDialogflowMessage; + try { + response = await Dialogflow.sendRequest( + this.http, + this.read, + this.modify, + rid, + messageText, + DialogflowRequestType.MESSAGE, + ); + } catch (error) { + this.app + .getLogger() + .error( + `${Logs.DIALOGFLOW_REST_API_ERROR} ${ + (error as Error).message + }`, + ); + + const serviceUnavailable: string = await getAppSettingValue( + this.read, + AppSetting.DialogflowServiceUnavailableMessage, + ); + + await createMessage(this.app, rid, this.read, this.modify, { + text: serviceUnavailable + ? serviceUnavailable + : DefaultMessage.DEFAULT_DialogflowServiceUnavailableMessage, + }); + + return; + } + + await createDialogflowMessage( + this.app, + rid, + this.read, + this.modify, + response, + ); + + // synchronous handover check + const { isFallback } = response; + if (isFallback) { + return incFallbackIntent(this.app, this.read, this.modify, rid); + } + return resetFallbackIntent(this.read, this.modify, rid); + } } diff --git a/lib/Dialogflow.ts b/lib/Dialogflow.ts index 8ef2d56..4dabbd2 100644 --- a/lib/Dialogflow.ts +++ b/lib/Dialogflow.ts @@ -1,8 +1,23 @@ -import { IHttp, IHttpRequest, IModify, IPersistence, IRead } from '@rocket.chat/apps-engine/definition/accessors'; +import { + IHttp, + IHttpRequest, + IModify, + IRead, +} from '@rocket.chat/apps-engine/definition/accessors'; import { IRoom } from '@rocket.chat/apps-engine/definition/rooms'; import { createSign } from 'crypto'; import { AppSetting } from '../config/Settings'; -import { DialogflowJWT, DialogflowRequestType, DialogflowUrl, IDialogflowAccessToken, IDialogflowEvent, IDialogflowMessage, IDialogflowQuickReplies, LanguageCode } from '../enum/Dialogflow'; +import { + DialogflowJWT, + DialogflowRequestType, + DialogflowUrl, + IDialogflowAccessToken, + IDialogflowEvent, + IDialogflowMessage, + IDialogflowQuickReplies, + IDialogflowResponse, + LanguageCode, +} from '../enum/Dialogflow'; import { Headers } from '../enum/Http'; import { Logs } from '../enum/Logs'; import { base64urlEncode, stringifyError } from './Helper'; @@ -11,227 +26,321 @@ import { updateRoomCustomFields } from './Room'; import { getAppSettingValue } from './Settings'; class DialogflowClass { - private jwtExpiration: Date; - public async sendRequest(http: IHttp, - read: IRead, - modify: IModify, - sessionId: string, - request: IDialogflowEvent | string, - requestType: DialogflowRequestType): Promise { - const serverURL = await this.getServerURL(read, modify, http, sessionId); - - const queryInput = { - ...requestType === DialogflowRequestType.EVENT && { event: request }, - ...requestType === DialogflowRequestType.MESSAGE && { text: { languageCode: LanguageCode.EN, text: request } }, - }; - - const httpRequestContent: IHttpRequest = createHttpRequest( - { 'Content-Type': Headers.CONTENT_TYPE_JSON, 'Accept': Headers.ACCEPT_JSON }, - { queryInput }, - ); - - try { - const response = await http.post(serverURL, httpRequestContent); - if (!response) { - throw new Error('Failed to get any response from the Dialogflow api. Please check if you server is able to connect to public n/w'); - } - if (!response.statusCode.toString().startsWith('2') || !response.data) { - throw new Error(`Invalid response received from Dialogflow api. Response: ${ response.content }`); - } - - return this.parseRequest(response.data); - } catch (error) { - throw new Error(`${ Logs.HTTP_REQUEST_ERROR }. Details: ${ error.message }. Raw Error: ${ stringifyError(error) }`); - } - } - - public async generateNewAccessToken(http: IHttp, clientEmail: string, privateKey: string): Promise { - const authUrl = DialogflowUrl.AUTHENTICATION_SERVER_URL; - const jwt = this.getJWT(clientEmail, privateKey); - - const httpRequestContent: IHttpRequest = { - headers: { - 'Content-Type': Headers.CONTENT_TYPE_X_FORM_URL_ENCODED, - }, - content: `grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=${jwt}`, - }; - - try { - const response = await http.post(authUrl, httpRequestContent); - - if (!response.content) { throw new Error(Logs.INVALID_RESPONSE_FROM_DIALOGFLOW); } - const responseJSON = JSON.parse(response.content); - - const { access_token } = responseJSON; - if (access_token) { - const accessToken: IDialogflowAccessToken = { - token: access_token, - expiration: this.jwtExpiration, - }; - return accessToken; - } else { - const { error, error_description } = responseJSON; - if (error) { - throw Error(`\ + private jwtExpiration: Date; + public async sendRequest( + http: IHttp, + read: IRead, + modify: IModify, + sessionId: string, + request: IDialogflowEvent | string, + requestType: DialogflowRequestType, + ): Promise { + const serverURL = await this.getServerURL( + read, + modify, + http, + sessionId, + ); + + const queryInput = { + ...requestType === DialogflowRequestType.EVENT && { + event: request, + }, + ...requestType === DialogflowRequestType.MESSAGE && { + text: { languageCode: LanguageCode.EN, text: request }, + }, + }; + + const httpRequestContent: IHttpRequest = createHttpRequest( + { + 'Content-Type': Headers.CONTENT_TYPE_JSON, + Accept: Headers.ACCEPT_JSON, + }, + { queryInput }, + ); + + try { + const response = await http.post(serverURL, httpRequestContent); + if (!response) { + throw new Error( + 'Failed to get any response from the Dialogflow api. Please check if you server is able to connect to public n/w', + ); + } + if ( + !response.statusCode.toString().startsWith('2') || + !response.data + ) { + throw new Error( + `Invalid response received from Dialogflow api. Response: ${response.content}`, + ); + } + + return this.parseRequest(response.data); + } catch (error) { + throw new Error( + `${Logs.HTTP_REQUEST_ERROR}. Details: ${ + (error as Error).message + }. Raw Error: ${stringifyError(error as Error)}`, + ); + } + } + + public async generateNewAccessToken( + http: IHttp, + clientEmail: string, + privateKey: string, + ): Promise { + const authUrl = DialogflowUrl.AUTHENTICATION_SERVER_URL; + const jwt = this.getJWT(clientEmail, privateKey); + + const httpRequestContent: IHttpRequest = { + headers: { + 'Content-Type': Headers.CONTENT_TYPE_X_FORM_URL_ENCODED, + }, + content: `grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=${jwt}`, + }; + + try { + const response = await http.post(authUrl, httpRequestContent); + + if (!response.content) { + throw new Error(Logs.INVALID_RESPONSE_FROM_DIALOGFLOW); + } + const responseJSON = JSON.parse(response.content); + + const { access_token } = responseJSON; + if (access_token) { + const accessToken: IDialogflowAccessToken = { + token: access_token, + expiration: this.jwtExpiration, + }; + return accessToken; + } else { + const { error, error_description } = responseJSON; + if (error) { + throw Error(`\ ---------------------Error with Google Credentials-------------------\ Details:- \ Error Message:- ${error} \ Error Description:- ${error_description}`); - } - throw Error(Logs.ACCESS_TOKEN_ERROR); - } - } catch (error) { - throw new Error(Logs.HTTP_REQUEST_ERROR); - } - } - - public parseRequest(response: any): IDialogflowMessage { - if (!response) { throw new Error(Logs.INVALID_RESPONSE_FROM_DIALOGFLOW_CONTENT_UNDEFINED); } - - const { session, queryResult } = response; - if (queryResult) { - const { fulfillmentMessages, intent: { isFallback } } = queryResult; - const parsedMessage: IDialogflowMessage = { - isFallback: isFallback ? isFallback : false, - }; - - const messages: Array = []; - - fulfillmentMessages.forEach((message) => { - const { text, payload: { quickReplies = null } = {} } = message; - if (text) { - const { text: textMessageArray } = text; - messages.push(textMessageArray[0]); - } - if (quickReplies) { - const { text: optionsText, options } = quickReplies; - if (optionsText && options) { - messages.push(quickReplies); - } - } - }); - if (messages.length > 0) { - parsedMessage.messages = messages; - } - - if (session) { - // "session" format -> projects/project-id/agent/sessions/session-id - const splittedText: Array = session.split('/'); - const sessionId: string = splittedText[splittedText.length - 1]; - if (sessionId) { - parsedMessage.sessionId = sessionId; - } - } - - return parsedMessage; - } else { - // some error occurred. Dialogflow's response has a error field containing more info abt error - throw Error(`An Error occurred while connecting to Dialogflow's REST API\ + } + throw Error(Logs.ACCESS_TOKEN_ERROR); + } + } catch (error) { + throw new Error(Logs.HTTP_REQUEST_ERROR); + } + } + + public parseRequest(response: IDialogflowResponse): IDialogflowMessage { + if (!response) { + throw new Error( + Logs.INVALID_RESPONSE_FROM_DIALOGFLOW_CONTENT_UNDEFINED, + ); + } + + const { session, queryResult } = response; + if (queryResult) { + const { + fulfillmentMessages, + intent: { isFallback }, + } = queryResult; + const parsedMessage: IDialogflowMessage = { + isFallback: isFallback ? isFallback : false, + }; + + const messages: Array = []; + + fulfillmentMessages.forEach((message) => { + const { text, payload: { quickReplies = null } = {} } = message; + if (text) { + const { text: textMessageArray } = text; + messages.push(textMessageArray[0]); + } + if (quickReplies) { + const { text: optionsText, options } = quickReplies; + if (optionsText && options) { + messages.push(quickReplies); + } + } + }); + if (messages.length > 0) { + parsedMessage.messages = messages; + } + + if (session) { + // "session" format -> projects/project-id/agent/sessions/session-id + const splittedText: Array = session.split('/'); + const sessionId: string = splittedText[splittedText.length - 1]; + if (sessionId) { + parsedMessage.sessionId = sessionId; + } + } + + return parsedMessage; + } else { + // some error occurred. Dialogflow's response has a error field containing more info abt error + throw Error(`An Error occurred while connecting to Dialogflow's REST API\ Error Details:- - message:- ${response.error.message}\ - status:- ${response.error.message}\ + message:- ${response.error?.message}\ + status:- ${response.error?.message}\ Try checking the google credentials in App Setting and your internet connection`); - } - } - - private async getServerURL(read: IRead, modify: IModify, http: IHttp, sessionId: string) { - const projectId = await getAppSettingValue(read, AppSetting.DialogflowProjectId); - const environment = await getAppSettingValue(read, AppSetting.DialogflowEnvironment); - - const accessToken = await this.getAccessToken(read, modify, http, sessionId); - if (!accessToken) { throw Error(Logs.ACCESS_TOKEN_ERROR); } - - return `https://dialogflow.googleapis.com/v2/projects/${projectId}/agent/environments/${environment}/users/-/sessions/${sessionId}:detectIntent?access_token=${accessToken}`; - } - - private async getAccessToken(read: IRead, modify: IModify, http: IHttp, sessionId: string) { - - const clientEmail = await getAppSettingValue(read, AppSetting.DialogflowClientEmail); - const privateKey = await getAppSettingValue(read, AppSetting.DialogFlowPrivateKey); - if (!privateKey || !clientEmail) { throw new Error(Logs.EMPTY_CLIENT_EMAIL_OR_PRIVATE_KEY_SETTING); } - - const room: IRoom = await read.getRoomReader().getById(sessionId) as IRoom; - if (!room) { throw new Error(Logs.INVALID_ROOM_ID); } - - // check is there is a valid access token already present - const { customFields } = room; - if (customFields) { - const { accessToken: oldAccessToken } = customFields as any; - if (oldAccessToken) { - // check expiration - if (!this.hasExpired(oldAccessToken.expiration)) { - return oldAccessToken.token; - } - } - } - - try { - // get a new access token - const accessToken: IDialogflowAccessToken = await this.generateNewAccessToken(http, clientEmail, privateKey); - - // save this access Token for future use - await updateRoomCustomFields(sessionId, { accessToken }, read, modify); - - return accessToken.token; - } catch (error) { - throw Error(`${ Logs.ACCESS_TOKEN_ERROR }. Raw Error: ${ stringifyError(error) }`); - } - } - - private hasExpired(expiration: Date): boolean { - if (!expiration) { return true; } - return Date.now() >= expiration.getTime(); - } - - private getJWT(clientEmail, privateKey) { - // request format - // {Base64url encoded header}.{Base64url encoded claim set}.{Base64url encoded signature} - - const header = this.getJWTHeader(); - const claimSet = this.getClaimSet(clientEmail); - const signature = this.getSignature(header, claimSet, privateKey); - // combining all together to form jwt - return `${ header }.${ claimSet }.${ signature }`; - } - - // Forming the JWT header - private getJWTHeader() { - return base64urlEncode(DialogflowJWT.JWT_HEADER); - } - - // Forming the jwt claim set - private getClaimSet(clientEmail) { - - let currentUnixTime = Date.now(); - const hourInc = 1000 * 60 * 30; // an hour - let oneHourInFuture = currentUnixTime + hourInc; - // record the expiration date-time - this.jwtExpiration = new Date(oneHourInFuture); - - // convert milliseconds to seconds - currentUnixTime = Math.round(currentUnixTime / 1000); - oneHourInFuture = Math.round(oneHourInFuture / 1000); - - const jwtClaimSet = { - iss: clientEmail, - scope: DialogflowJWT.SCOPE_URL, - aud: DialogflowJWT.AUD_URL, - exp: oneHourInFuture, - iat: currentUnixTime, - }; - - return base64urlEncode(JSON.stringify(jwtClaimSet)); - } - - private getSignature(b64uHeader: string, b64uClaimSetClaimSet: string, privateKey) { - const signatureInput = `${b64uHeader}.${b64uClaimSetClaimSet}`; - const sign = createSign(DialogflowJWT.SHA_256); - sign.update(signatureInput); - // replace \\n by \n in private key - privateKey = privateKey.trim().replace(/\\n/gm, '\n'); - // sign the signature then in the result replace + with - | / with _ - return sign.sign(privateKey, DialogflowJWT.BASE_64).replace(/\+/g, '-').replace(/\//g, '_'); - } + } + } + + private async getServerURL( + read: IRead, + modify: IModify, + http: IHttp, + sessionId: string, + ) { + const projectId = await getAppSettingValue( + read, + AppSetting.DialogflowProjectId, + ); + const environment = await getAppSettingValue( + read, + AppSetting.DialogflowEnvironment, + ); + + const accessToken = await this.getAccessToken( + read, + modify, + http, + sessionId, + ); + if (!accessToken) { + throw Error(Logs.ACCESS_TOKEN_ERROR); + } + + return `https://dialogflow.googleapis.com/v2/projects/${projectId}/agent/environments/${environment}/users/-/sessions/${sessionId}:detectIntent?access_token=${accessToken}`; + } + + private async getAccessToken( + read: IRead, + modify: IModify, + http: IHttp, + sessionId: string, + ) { + const clientEmail = await getAppSettingValue( + read, + AppSetting.DialogflowClientEmail, + ); + const privateKey = await getAppSettingValue( + read, + AppSetting.DialogFlowPrivateKey, + ); + if (!privateKey || !clientEmail) { + throw new Error(Logs.EMPTY_CLIENT_EMAIL_OR_PRIVATE_KEY_SETTING); + } + + const room: IRoom = (await read + .getRoomReader() + .getById(sessionId)) as IRoom; + if (!room) { + throw new Error(Logs.INVALID_ROOM_ID); + } + + // check is there is a valid access token already present + const { customFields } = room; + if (customFields) { + const { accessToken: oldAccessToken } = customFields; + if (oldAccessToken) { + // check expiration + if (!this.hasExpired(oldAccessToken.expiration)) { + return oldAccessToken.token; + } + } + } + + try { + // get a new access token + const accessToken: IDialogflowAccessToken = + await this.generateNewAccessToken( + http, + clientEmail, + privateKey, + ); + + // save this access Token for future use + await updateRoomCustomFields( + sessionId, + { accessToken }, + read, + modify, + ); + + return accessToken.token; + } catch (error) { + throw Error( + `${Logs.ACCESS_TOKEN_ERROR}. Raw Error: ${stringifyError( + error as Error, + )}`, + ); + } + } + + private hasExpired(expiration: Date): boolean { + if (!expiration) { + return true; + } + return Date.now() >= expiration.getTime(); + } + + private getJWT(clientEmail, privateKey) { + // request format + // {Base64url encoded header}.{Base64url encoded claim set}.{Base64url encoded signature} + + const header = this.getJWTHeader(); + const claimSet = this.getClaimSet(clientEmail); + const signature = this.getSignature(header, claimSet, privateKey); + // combining all together to form jwt + return `${header}.${claimSet}.${signature}`; + } + + // Forming the JWT header + private getJWTHeader() { + return base64urlEncode(DialogflowJWT.JWT_HEADER); + } + + // Forming the jwt claim set + private getClaimSet(clientEmail) { + let currentUnixTime = Date.now(); + const hourInc = 1000 * 60 * 30; // an hour + let oneHourInFuture = currentUnixTime + hourInc; + // record the expiration date-time + this.jwtExpiration = new Date(oneHourInFuture); + + // convert milliseconds to seconds + currentUnixTime = Math.round(currentUnixTime / 1000); + oneHourInFuture = Math.round(oneHourInFuture / 1000); + + const jwtClaimSet = { + iss: clientEmail, + scope: DialogflowJWT.SCOPE_URL, + aud: DialogflowJWT.AUD_URL, + exp: oneHourInFuture, + iat: currentUnixTime, + }; + + return base64urlEncode(JSON.stringify(jwtClaimSet)); + } + + private getSignature( + b64uHeader: string, + b64uClaimSetClaimSet: string, + privateKey, + ) { + const signatureInput = `${b64uHeader}.${b64uClaimSetClaimSet}`; + const sign = createSign(DialogflowJWT.SHA_256); + sign.update(signatureInput); + // replace \\n by \n in private key + privateKey = privateKey.trim().replace(/\\n/gm, '\n'); + // sign the signature then in the result replace + with - | / with _ + return sign + .sign(privateKey, DialogflowJWT.BASE_64) + .replace(/\+/g, '-') + .replace(/\//g, '_'); + } } export const Dialogflow = new DialogflowClass(); diff --git a/lib/Helper.ts b/lib/Helper.ts index 0c613eb..908eecd 100644 --- a/lib/Helper.ts +++ b/lib/Helper.ts @@ -1,48 +1,64 @@ import { Base64 } from '../enum/Dialogflow'; -export const base64urlEncode = (str: any) => { - const utf8str = unescape(encodeURIComponent(str)); - return base64EncodeData(utf8str, utf8str.length, Base64.BASE64_DICTIONARY, Base64.BASE64_PAD); +export const base64urlEncode = (str: string) => { + const utf8str = unescape(encodeURIComponent(str)); + return base64EncodeData( + utf8str, + utf8str.length, + Base64.BASE64_DICTIONARY, + Base64.BASE64_PAD, + ); }; -export const base64EncodeData = (data: string, len: number, b64x: string, b64pad: string) => { - let dst = ''; - let i: number; +export const base64EncodeData = ( + data: string, + len: number, + b64x: string, + b64pad: string, +) => { + let dst = ''; + let i: number; - for (i = 0; i <= len - 3; i += 3) { + for (i = 0; i <= len - 3; i += 3) { + dst += b64x.charAt(data.charCodeAt(i) >>> 2); + dst += b64x.charAt( + ((data.charCodeAt(i) & 3) << 4) | (data.charCodeAt(i + 1) >>> 4), + ); + dst += b64x.charAt( + ((data.charCodeAt(i + 1) & 15) << 2) | + (data.charCodeAt(i + 2) >>> 6), + ); + dst += b64x.charAt(data.charCodeAt(i + 2) & 63); + } - dst += b64x.charAt(data.charCodeAt(i) >>> 2); - dst += b64x.charAt(((data.charCodeAt(i) & 3) << 4) | (data.charCodeAt(i + 1) >>> 4)); - dst += b64x.charAt(((data.charCodeAt(i + 1) & 15) << 2) | (data.charCodeAt(i + 2) >>> 6)); - dst += b64x.charAt(data.charCodeAt(i + 2) & 63); + if (len % 3 === 2) { + dst += b64x.charAt(data.charCodeAt(i) >>> 2); + dst += b64x.charAt( + ((data.charCodeAt(i) & 3) << 4) | (data.charCodeAt(i + 1) >>> 4), + ); + dst += b64x.charAt((data.charCodeAt(i + 1) & 15) << 2); + dst += b64pad; + } else if (len % 3 === 1) { + dst += b64x.charAt(data.charCodeAt(i) >>> 2); + dst += b64x.charAt((data.charCodeAt(i) & 3) << 4); + dst += b64pad; + dst += b64pad; + } - } - - if (len % 3 === 2) { - dst += b64x.charAt(data.charCodeAt(i) >>> 2); - dst += b64x.charAt(((data.charCodeAt(i) & 3) << 4) | (data.charCodeAt(i + 1) >>> 4)); - dst += b64x.charAt(((data.charCodeAt(i + 1) & 15) << 2)); - dst += b64pad; - } else if (len % 3 === 1) { - dst += b64x.charAt(data.charCodeAt(i) >>> 2); - dst += b64x.charAt(((data.charCodeAt(i) & 3) << 4)); - dst += b64pad; - dst += b64pad; - } - - return dst; + return dst; }; export const uuid = (): string => { - return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { - const r = Math.random() * 16 | 0; - const v = c === 'x' ? r : (r & 0x3 | 0x8); - return v.toString(16); - }); + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { + const r = (Math.random() * 16) | 0; + const v = c === 'x' ? r : (r & 0x3) | 0x8; + return v.toString(16); + }); }; export const escapeRegExp = (str: string): string => { - return str.replace(/[.*+?^${}()|[\]\\\/]/g, '\\$&'); // $& means the whole matched string + return str.replace(/[.*+?^${}()|[\]\\/]/g, '\\$&'); // $& means the whole matched string }; -export const stringifyError = (error: Error): string => (JSON.stringify(error, Object.getOwnPropertyNames(error))); +export const stringifyError = (error: Error): string => + JSON.stringify(error, Object.getOwnPropertyNames(error)); diff --git a/lib/Http.ts b/lib/Http.ts index 8925051..42801ef 100644 --- a/lib/Http.ts +++ b/lib/Http.ts @@ -2,24 +2,28 @@ import { HttpStatusCode } from '@rocket.chat/apps-engine/definition/accessors'; import { IApiResponse } from '@rocket.chat/apps-engine/definition/api'; export const createHttpRequest = (headers, data) => { - return { - headers: { - ...headers, - }, - data: { - ...data, - }, - }; + return { + headers: { + ...headers, + }, + data: { + ...data, + }, + }; }; -export const createHttpResponse = (status: HttpStatusCode, headers: object, payload: object): IApiResponse => { - return { - status, - headers: { - ...headers, - }, - content: { - ...payload, - }, - }; +export const createHttpResponse = ( + status: HttpStatusCode, + headers: object, + payload: object, +): IApiResponse => { + return { + status, + headers: { + ...headers, + }, + content: { + ...payload, + }, + }; }; diff --git a/lib/Message.ts b/lib/Message.ts index 64f36f5..aeae399 100644 --- a/lib/Message.ts +++ b/lib/Message.ts @@ -2,175 +2,247 @@ import { IModify, IRead } from '@rocket.chat/apps-engine/definition/accessors'; import { IApp } from '@rocket.chat/apps-engine/definition/IApp'; import { IVisitor } from '@rocket.chat/apps-engine/definition/livechat'; import { IRoom } from '@rocket.chat/apps-engine/definition/rooms'; -import { BlockElementType, BlockType, IActionsBlock, IBlock, IButtonElement, TextObjectType } from '@rocket.chat/apps-engine/definition/uikit'; +import { + BlockElementType, + BlockType, + IActionsBlock, + IBlock, + IButtonElement, + TextObjectType, +} from '@rocket.chat/apps-engine/definition/uikit'; import { IUser } from '@rocket.chat/apps-engine/definition/users'; import { AppSetting, ServerSetting } from '../config/Settings'; import { ActionIds } from '../enum/ActionIds'; -import { IDialogflowMessage, IDialogflowQuickReplies, IDialogflowQuickReplyOptions } from '../enum/Dialogflow'; +import { + IDialogflowMessage, + IDialogflowQuickReplies, + IDialogflowQuickReplyOptions, +} from '../enum/Dialogflow'; import { Logs } from '../enum/Logs'; +import { IMessageParam } from '../types/misc'; import { escapeRegExp, uuid } from './Helper'; import { getAppSettingValue, getServerSettingValue } from './Settings'; -export const createDialogflowMessage = async (app: IApp, rid: string, read: IRead, modify: IModify, dialogflowMessage: IDialogflowMessage): Promise => { - const { messages = [] } = dialogflowMessage; - - for (const message of messages) { - const { text, options } = message as IDialogflowQuickReplies; - if (text && options) { - const elements: Array = options.map((payload: IDialogflowQuickReplyOptions) => { - const buttonElement: IButtonElement = { - type: BlockElementType.BUTTON, - actionId: payload.actionId || uuid(), - text: { - text: payload.text, - type: TextObjectType.PLAINTEXT, - }, - value: payload.text, - ...payload.buttonStyle && { style: payload.buttonStyle }, - }; - - if (payload.actionId && payload.actionId === ActionIds.PERFORM_HANDOVER) { - buttonElement.value = payload.data && payload.data.departmentName ? payload.data.departmentName : undefined; - } - - return buttonElement; - }); - - const blocks = modify.getCreator().getBlockBuilder(); - - blocks.addSectionBlock({ - text: blocks.newMarkdownTextObject(text), - }); - - blocks.addActionsBlock({ - elements, - }); - - await createMessage(app, rid, read, modify, { blocks }); - } else { - // message is instanceof string - if ((message as string).trim().length > 0) { - await createMessage(app, rid, read, modify, { text: message }); - } - } - } +export const createDialogflowMessage = async ( + app: IApp, + rid: string, + read: IRead, + modify: IModify, + dialogflowMessage: IDialogflowMessage, +): Promise => { + const { messages = [] } = dialogflowMessage; + + for (const message of messages) { + const { text, options } = message as IDialogflowQuickReplies; + if (text && options) { + const elements: Array = options.map( + (payload: IDialogflowQuickReplyOptions) => { + const buttonElement: IButtonElement = { + type: BlockElementType.BUTTON, + actionId: payload.actionId || uuid(), + text: { + text: payload.text, + type: TextObjectType.PLAINTEXT, + }, + value: payload.text, + ...(payload.buttonStyle && { + style: payload.buttonStyle, + }), + }; + + if ( + payload.actionId && + payload.actionId === ActionIds.PERFORM_HANDOVER + ) { + buttonElement.value = + payload.data && payload.data.departmentName + ? payload.data.departmentName + : undefined; + } + + return buttonElement; + }, + ); + + const blocks = modify.getCreator().getBlockBuilder(); + + blocks.addSectionBlock({ + text: blocks.newMarkdownTextObject(text), + }); + + blocks.addActionsBlock({ + elements, + }); + + const blockArray = blocks.getBlocks(); + + await createMessage(app, rid, read, modify, { blocks: blockArray }); + } else { + // message is instanceof string + if ((message as string).trim().length > 0) { + await createMessage(app, rid, read, modify, { + text: message as string, + }); + } + } + } }; -export const createMessage = async (app: IApp, rid: string, read: IRead, modify: IModify, message: any ): Promise => { - if (!message) { - return; - } - - const botUserName = await getAppSettingValue(read, AppSetting.DialogflowBotUsername); - if (!botUserName) { - app.getLogger().error(Logs.EMPTY_BOT_USERNAME_SETTING); - return; - } - - const sender = await read.getUserReader().getByUsername(botUserName); - if (!sender) { - app.getLogger().error(Logs.INVALID_BOT_USERNAME_SETTING); - return; - } - - const room = await read.getRoomReader().getById(rid); - if (!room) { - app.getLogger().error(`${Logs.INVALID_ROOM_ID} ${rid}`); - return; - } - - const msg = modify.getCreator().startMessage().setRoom(room).setSender(sender); - - const { text, blocks, attachment } = message; - - if (text) { - msg.setText(text); - } - - if (attachment) { - msg.addAttachment(attachment); - } - - if (blocks) { - msg.addBlocks(blocks); - } - - return new Promise(async (resolve) => { - modify.getCreator().finish(msg) - .then((result) => resolve(result)) - .catch((error) => console.error(error)); - }); +export const createMessage = async ( + app: IApp, + rid: string, + read: IRead, + modify: IModify, + message: IMessageParam, +): Promise => { + if (!message) { + return; + } + + const botUserName = await getAppSettingValue( + read, + AppSetting.DialogflowBotUsername, + ); + if (!botUserName) { + app.getLogger().error(Logs.EMPTY_BOT_USERNAME_SETTING); + return; + } + + const sender = await read.getUserReader().getByUsername(botUserName); + if (!sender) { + app.getLogger().error(Logs.INVALID_BOT_USERNAME_SETTING); + return; + } + + const room = await read.getRoomReader().getById(rid); + if (!room) { + app.getLogger().error(`${Logs.INVALID_ROOM_ID} ${rid}`); + return; + } + + const msg = modify + .getCreator() + .startMessage() + .setRoom(room) + .setSender(sender); + + const { text, blocks, attachment } = message; + + if (text) { + msg.setText(text); + } + + if (attachment) { + msg.addAttachment(attachment); + } + + if (blocks) { + msg.addBlocks(blocks); + } + + return modify.getCreator().finish(msg); }; -export const createLivechatMessage = async (app: IApp, rid: string, read: IRead, modify: IModify, message: any, visitor: IVisitor ): Promise => { - if (!message) { - return; - } - - const botUserName = await getAppSettingValue(read, AppSetting.DialogflowBotUsername); - if (!botUserName) { - app.getLogger().error(Logs.EMPTY_BOT_USERNAME_SETTING); - return; - } - - const room = await read.getRoomReader().getById(rid); - if (!room) { - app.getLogger().error(`${ Logs.INVALID_ROOM_ID } ${ rid }`); - return; - } - - const msg = modify.getCreator().startLivechatMessage().setRoom(room).setVisitor(visitor); - - const { text, attachment } = message; - - if (text) { - msg.setText(text); - } - - if (attachment) { - msg.addAttachment(attachment); - } - - return new Promise(async (resolve) => { - modify.getCreator().finish(msg) - .then((result) => resolve(result)) - .catch((error) => console.error(error)); - }); +export const createLivechatMessage = async ( + app: IApp, + rid: string, + read: IRead, + modify: IModify, + message: IMessageParam, + visitor: IVisitor, +): Promise => { + if (!message) { + return; + } + + const botUserName = await getAppSettingValue( + read, + AppSetting.DialogflowBotUsername, + ); + if (!botUserName) { + app.getLogger().error(Logs.EMPTY_BOT_USERNAME_SETTING); + return; + } + + const room = await read.getRoomReader().getById(rid); + if (!room) { + app.getLogger().error(`${Logs.INVALID_ROOM_ID} ${rid}`); + return; + } + + const msg = modify + .getCreator() + .startLivechatMessage() + .setRoom(room) + .setVisitor(visitor); + + const { text, attachment } = message; + + if (text) { + msg.setText(text); + } + + if (attachment) { + msg.addAttachment(attachment); + } + + return modify.getCreator().finish(msg); }; -export const deleteAllActionBlocks = async (modify: IModify, appUser: IUser, msgId: string): Promise => { - const msgBuilder = await modify.getUpdater().message(msgId, appUser); - - const withoutActionBlocks: Array = msgBuilder.getBlocks().filter( - (block) => (!( - block.type === BlockType.ACTIONS && - (block as IActionsBlock).elements.some((element) => (element.type === BlockElementType.BUTTON)) - ) - )); - - msgBuilder.setEditor(appUser).setBlocks(withoutActionBlocks); - return modify.getUpdater().finish(msgBuilder); +export const deleteAllActionBlocks = async ( + modify: IModify, + appUser: IUser, + msgId: string, +): Promise => { + const msgBuilder = await modify.getUpdater().message(msgId, appUser); + + const withoutActionBlocks: Array = msgBuilder + .getBlocks() + .filter( + (block) => + !( + block.type === BlockType.ACTIONS && + (block as IActionsBlock).elements.some( + (element) => element.type === BlockElementType.BUTTON, + ) + ), + ); + + msgBuilder.setEditor(appUser).setBlocks(withoutActionBlocks); + return modify.getUpdater().finish(msgBuilder); }; -export const removeQuotedMessage = async (read: IRead, room: IRoom, message: string): Promise => { - if (!message) { - throw new Error('Error! message text undefined'); - } - - let serverUrl: string | undefined = await getServerSettingValue(read, ServerSetting.SITE_URL); - serverUrl = serverUrl && serverUrl.trim(); - if (!serverUrl) { - throw new Error('Error! Getting server url'); - } - - serverUrl = serverUrl.endsWith('/') ? - serverUrl.substr(0, serverUrl.length - 1) : - serverUrl; - - const pattern = new RegExp(`\\[\\s*\\]\\(${ escapeRegExp(serverUrl) }\\/live\\/${ escapeRegExp(room.id) }\\?msg=.*\\)`, 'gi'); - - if (message.match(pattern)) { - return message.replace(pattern, ''); - } - return message; +export const removeQuotedMessage = async ( + read: IRead, + room: IRoom, + message: string, +): Promise => { + if (!message) { + throw new Error('Error! message text undefined'); + } + + let serverUrl: string | undefined = await getServerSettingValue( + read, + ServerSetting.SITE_URL, + ); + serverUrl = serverUrl && serverUrl.trim(); + if (!serverUrl) { + throw new Error('Error! Getting server url'); + } + + serverUrl = serverUrl.endsWith('/') + ? serverUrl.substr(0, serverUrl.length - 1) + : serverUrl; + + const pattern = new RegExp( + `\\[\\s*\\]\\(${escapeRegExp(serverUrl)}\\/live\\/${escapeRegExp( + room.id, + )}\\?msg=.*\\)`, + 'gi', + ); + + if (message.match(pattern)) { + return message.replace(pattern, ''); + } + return message; }; diff --git a/lib/Room.ts b/lib/Room.ts index 9a33cdd..744ad02 100644 --- a/lib/Room.ts +++ b/lib/Room.ts @@ -1,90 +1,162 @@ import { IModify, IRead } from '@rocket.chat/apps-engine/definition/accessors'; import { IApp } from '@rocket.chat/apps-engine/definition/IApp'; -import { IDepartment, ILivechatRoom, ILivechatTransferData, IVisitor } from '@rocket.chat/apps-engine/definition/livechat'; +import { + IDepartment, + ILivechatRoom, + ILivechatTransferData, + IVisitor, +} from '@rocket.chat/apps-engine/definition/livechat'; import { IRoom } from '@rocket.chat/apps-engine/definition/rooms'; import { AppSetting, DefaultMessage } from '../config/Settings'; import { Logs } from '../enum/Logs'; import { getAppSettingValue } from '../lib/Settings'; import { createMessage } from './Message'; -export const updateRoomCustomFields = async (rid: string, data: any, read: IRead, modify: IModify): Promise => { - if (!rid) { - return; - } - const room = await read.getRoomReader().getById(rid); - if (!room) { throw new Error(`${Logs.INVALID_ROOM_ID} ${rid}`); } - - const botUserName = await getAppSettingValue(read, AppSetting.DialogflowBotUsername); - if (!botUserName) { throw new Error(Logs.EMPTY_BOT_USERNAME_SETTING); } - - const user = await read.getUserReader().getByUsername(botUserName); - if (!user) { throw new Error(Logs.INVALID_BOT_USERNAME_SETTING); } - - let { customFields = {} } = room; - customFields = Object.assign(customFields, data); - const roomBuilder = await modify.getUpdater().room(rid, user); - roomBuilder.setCustomFields(customFields); - - try { - modify.getUpdater().finish(roomBuilder); - } catch (error) { - console.error(error); - } +export const updateRoomCustomFields = async ( + rid: string, + data: { [k: string]: unknown }, + read: IRead, + modify: IModify, +): Promise => { + if (!rid) { + return; + } + const room = await read.getRoomReader().getById(rid); + if (!room) { + throw new Error(`${Logs.INVALID_ROOM_ID} ${rid}`); + } + + const botUserName = await getAppSettingValue( + read, + AppSetting.DialogflowBotUsername, + ); + if (!botUserName) { + throw new Error(Logs.EMPTY_BOT_USERNAME_SETTING); + } + + const user = await read.getUserReader().getByUsername(botUserName); + if (!user) { + throw new Error(Logs.INVALID_BOT_USERNAME_SETTING); + } + + let { customFields = {} } = room; + customFields = Object.assign(customFields, data); + const roomBuilder = await modify.getUpdater().room(rid, user); + roomBuilder.setCustomFields(customFields); + + return modify.getUpdater().finish(roomBuilder); }; export const closeChat = async (modify: IModify, read: IRead, rid: string) => { - const room: IRoom = (await read.getRoomReader().getById(rid)) as IRoom; - if (!room) { throw new Error(Logs.INVALID_ROOM_ID); } - - const closeChatMessage = await getAppSettingValue(read, AppSetting.DialogflowCloseChatMessage); - - const result = await modify.getUpdater().getLivechatUpdater() - .closeRoom(room, closeChatMessage ? closeChatMessage : DefaultMessage.DEFAULT_DialogflowCloseChatMessage); - if (!result) { throw new Error(Logs.CLOSE_CHAT_REQUEST_FAILED_ERROR); } + const room: IRoom = (await read.getRoomReader().getById(rid)) as IRoom; + if (!room) { + throw new Error(Logs.INVALID_ROOM_ID); + } + + const closeChatMessage = await getAppSettingValue( + read, + AppSetting.DialogflowCloseChatMessage, + ); + + const result = await modify + .getUpdater() + .getLivechatUpdater() + .closeRoom( + room, + closeChatMessage + ? closeChatMessage + : DefaultMessage.DEFAULT_DialogflowCloseChatMessage, + ); + if (!result) { + throw new Error(Logs.CLOSE_CHAT_REQUEST_FAILED_ERROR); + } }; -export const performHandover = async (app: IApp, modify: IModify, read: IRead, rid: string, visitorToken: string, targetDepartmentName?: string): Promise => { - const room: ILivechatRoom = (await read.getRoomReader().getById(rid)) as ILivechatRoom; - if (!room) { throw new Error(Logs.INVALID_ROOM_ID); } - - const visitor: IVisitor = (await read.getLivechatReader().getLivechatVisitorByToken(visitorToken)) as IVisitor; - if (!visitor) { throw new Error(Logs.INVALID_VISITOR_TOKEN); } - - const livechatTransferData: ILivechatTransferData = { - currentRoom: room, - }; - - // Fill livechatTransferData.targetDepartment param if required - if (targetDepartmentName) { - const targetDepartment: IDepartment = (await read.getLivechatReader().getLivechatDepartmentByIdOrName(targetDepartmentName)) as IDepartment; - if (!targetDepartment) { throw new Error(Logs.INVALID_DEPARTMENT_NAME); } - livechatTransferData.targetDepartment = targetDepartment.id; - } - - // check if any agent is online in the department where we're transferring this chat - const serviceOnline = await read.getLivechatReader().isOnlineAsync(livechatTransferData.targetDepartment); - if (!serviceOnline) { - const offlineMessage: string = await getAppSettingValue(read, AppSetting.DialogflowHandoverFailedMessage); - if (offlineMessage && offlineMessage.trim()) { - await createMessage(app, rid, read, modify, { text: offlineMessage }); - } - return false; - } - - const handoverMessage: string = await getAppSettingValue(read, AppSetting.DialogflowHandoverMessage); - await createMessage(app, rid, read, modify, { text: handoverMessage ? handoverMessage : DefaultMessage.DEFAULT_DialogflowHandoverMessage }); - - const result = await modify.getUpdater().getLivechatUpdater().transferVisitor(visitor, livechatTransferData) - .catch((error) => { - throw new Error(`${Logs.HANDOVER_REQUEST_FAILED_ERROR} ${error}`); - }); - if (!result) { - const offlineMessage: string = await getAppSettingValue(read, AppSetting.DialogflowHandoverFailedMessage); - if (offlineMessage && offlineMessage.trim()) { - await createMessage(app, rid, read, modify, { text: offlineMessage }); - } - - return false; - } - return true; +export const performHandover = async ( + app: IApp, + modify: IModify, + read: IRead, + rid: string, + visitorToken: string, + targetDepartmentName?: string, +): Promise => { + const room: ILivechatRoom = (await read + .getRoomReader() + .getById(rid)) as ILivechatRoom; + if (!room) { + throw new Error(Logs.INVALID_ROOM_ID); + } + + const visitor: IVisitor = (await read + .getLivechatReader() + .getLivechatVisitorByToken(visitorToken)) as IVisitor; + if (!visitor) { + throw new Error(Logs.INVALID_VISITOR_TOKEN); + } + + const livechatTransferData: ILivechatTransferData = { + currentRoom: room, + }; + + // Fill livechatTransferData.targetDepartment param if required + if (targetDepartmentName) { + const targetDepartment: IDepartment = (await read + .getLivechatReader() + .getLivechatDepartmentByIdOrName( + targetDepartmentName, + )) as IDepartment; + if (!targetDepartment) { + throw new Error(Logs.INVALID_DEPARTMENT_NAME); + } + livechatTransferData.targetDepartment = targetDepartment.id; + } + + // check if any agent is online in the department where we're transferring this chat + const serviceOnline = await read + .getLivechatReader() + .isOnlineAsync(livechatTransferData.targetDepartment); + if (!serviceOnline) { + const offlineMessage: string = await getAppSettingValue( + read, + AppSetting.DialogflowHandoverFailedMessage, + ); + if (offlineMessage && offlineMessage.trim()) { + await createMessage(app, rid, read, modify, { + text: offlineMessage, + }); + } + return false; + } + + const handoverMessage: string = await getAppSettingValue( + read, + AppSetting.DialogflowHandoverMessage, + ); + await createMessage(app, rid, read, modify, { + text: handoverMessage + ? handoverMessage + : DefaultMessage.DEFAULT_DialogflowHandoverMessage, + }); + + const result = await modify + .getUpdater() + .getLivechatUpdater() + .transferVisitor(visitor, livechatTransferData) + .catch((error) => { + throw new Error(`${Logs.HANDOVER_REQUEST_FAILED_ERROR} ${error}`); + }); + if (!result) { + const offlineMessage: string = await getAppSettingValue( + read, + AppSetting.DialogflowHandoverFailedMessage, + ); + if (offlineMessage && offlineMessage.trim()) { + await createMessage(app, rid, read, modify, { + text: offlineMessage, + }); + } + + return false; + } + return true; }; diff --git a/lib/Settings.ts b/lib/Settings.ts index 1c5637d..29c8a75 100644 --- a/lib/Settings.ts +++ b/lib/Settings.ts @@ -1,9 +1,14 @@ import { IRead } from '@rocket.chat/apps-engine/definition/accessors'; export const getAppSettingValue = async (read: IRead, id: string) => { - return id && await read.getEnvironmentReader().getSettings().getValueById(id); + return ( + id && (await read.getEnvironmentReader().getSettings().getValueById(id)) + ); }; export const getServerSettingValue = async (read: IRead, id: string) => { - return id && (await read.getEnvironmentReader().getServerSettings().getValueById(id)); + return ( + id && + (await read.getEnvironmentReader().getServerSettings().getValueById(id)) + ); }; diff --git a/lib/SynchronousHandover.ts b/lib/SynchronousHandover.ts index 6c7d44c..ae5b53e 100644 --- a/lib/SynchronousHandover.ts +++ b/lib/SynchronousHandover.ts @@ -1,4 +1,4 @@ -import { IModify, IPersistence, IRead } from '@rocket.chat/apps-engine/definition/accessors'; +import { IModify, IRead } from '@rocket.chat/apps-engine/definition/accessors'; import { IApp } from '@rocket.chat/apps-engine/definition/IApp'; import { ILivechatRoom } from '@rocket.chat/apps-engine/definition/livechat'; import { AppSetting } from '../config/Settings'; @@ -6,31 +6,69 @@ import { Logs } from '../enum/Logs'; import { performHandover, updateRoomCustomFields } from './Room'; import { getAppSettingValue } from './Settings'; -export const incFallbackIntent = async (app: IApp, read: IRead, modify: IModify, sessionId: string) => { - const fallbackThreshold = (await getAppSettingValue(read, AppSetting.DialogflowFallbackResponsesLimit)) as number; +export const incFallbackIntent = async ( + app: IApp, + read: IRead, + modify: IModify, + sessionId: string, +) => { + const fallbackThreshold = (await getAppSettingValue( + read, + AppSetting.DialogflowFallbackResponsesLimit, + )) as number; - if (!fallbackThreshold || (fallbackThreshold && fallbackThreshold === 0)) { return; } + if (!fallbackThreshold || (fallbackThreshold && fallbackThreshold === 0)) { + return; + } - const room: ILivechatRoom = await read.getRoomReader().getById(sessionId) as ILivechatRoom; - if (!room) { throw new Error(Logs.INVALID_ROOM_ID); } + const room: ILivechatRoom = (await read + .getRoomReader() + .getById(sessionId)) as ILivechatRoom; + if (!room) { + throw new Error(Logs.INVALID_ROOM_ID); + } - const { fallbackCount: oldFallbackCount } = room.customFields as any; - const newFallbackCount: number = oldFallbackCount ? oldFallbackCount + 1 : 1; + let newFallbackCount = 0; + if (room?.customFields) { + const { fallbackCount: oldFallbackCount } = room.customFields; + newFallbackCount = oldFallbackCount ? oldFallbackCount + 1 : 1; - await updateRoomCustomFields(sessionId, { fallbackCount: newFallbackCount }, read, modify); + await updateRoomCustomFields( + sessionId, + { fallbackCount: newFallbackCount }, + read, + modify, + ); + } - if (newFallbackCount === fallbackThreshold) { - // perform handover - const { visitor: { token: visitorToken } } = room; - if (!visitorToken) { throw new Error(Logs.INVALID_VISITOR_TOKEN); } + if (newFallbackCount === fallbackThreshold) { + // perform handover + const { + visitor: { token: visitorToken }, + } = room; + if (!visitorToken) { + throw new Error(Logs.INVALID_VISITOR_TOKEN); + } - const targetDepartmentName: string | undefined = await getAppSettingValue(read, AppSetting.FallbackTargetDepartment); + const targetDepartmentName: string | undefined = + await getAppSettingValue(read, AppSetting.FallbackTargetDepartment); - // Session Id from Dialogflow will be the same as Room id - await performHandover(app, modify, read, sessionId, visitorToken, targetDepartmentName); - } + // Session Id from Dialogflow will be the same as Room id + await performHandover( + app, + modify, + read, + sessionId, + visitorToken, + targetDepartmentName, + ); + } }; -export const resetFallbackIntent = async (read: IRead, modify: IModify, sessionId: string) => { - await updateRoomCustomFields(sessionId, { fallbackCount: 0 }, read, modify); +export const resetFallbackIntent = async ( + read: IRead, + modify: IModify, + sessionId: string, +) => { + await updateRoomCustomFields(sessionId, { fallbackCount: 0 }, read, modify); }; diff --git a/package-lock.json b/package-lock.json index 9d2e645..06e5f08 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2,15 +2,6 @@ "requires": true, "lockfileVersion": 1, "dependencies": { - "@babel/code-frame": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", - "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", - "dev": true, - "requires": { - "@babel/highlight": "^7.12.13" - } - }, "@babel/helper-validator-identifier": { "version": "7.14.0", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", @@ -28,6 +19,89 @@ "js-tokens": "^4.0.0" } }, + "@eslint/eslintrc": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.4.tgz", + "integrity": "sha512-h8Vx6MdxwWI2WM8/zREHMoqdgLNXEL4QX3MWSVMdyNJGvXVOs+6lp+m2hc3FnuMHDc4poxFNI20vCk0OmI4G0Q==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.0.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + } + } + }, + "@humanwhocodes/config-array": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz", + "integrity": "sha512-JQlEKbcgEUjBFhLIF4iqM7u/9lwgHRBcpHrmUNCALK0Q3amXN6lxdoXLnF0sm11E9VqTmBALR87IlUg1bZ8A9A==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + } + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, "@rocket.chat/apps-engine": { "version": "1.25.0", "resolved": "https://registry.npmjs.org/@rocket.chat/apps-engine/-/apps-engine-1.25.0.tgz", @@ -42,18 +116,180 @@ "uuid": "^3.2.1" } }, + "@types/eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "dev": true + }, "@types/node": { "version": "10.17.5", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.5.tgz", "integrity": "sha512-RElZIr/7JreF1eY6oD5RF3kpmdcreuQPjg5ri4oQ5g9sq7YWU8HkfB3eH8GwAwxf5OaCh0VPi7r4N/yoTGelrA==", "dev": true }, + "@typescript-eslint/eslint-plugin": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.4.0.tgz", + "integrity": "sha512-9/yPSBlwzsetCsGEn9j24D8vGQgJkOTr4oMLas/w886ZtzKIs1iyoqFrwsX2fqYEeUwsdBpC21gcjRGo57u0eg==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "5.4.0", + "@typescript-eslint/scope-manager": "5.4.0", + "debug": "^4.3.2", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.1.8", + "regexpp": "^3.2.0", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "dependencies": { + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/experimental-utils": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.4.0.tgz", + "integrity": "sha512-Nz2JDIQUdmIGd6p33A+naQmwfkU5KVTLb/5lTk+tLVTDacZKoGQisj8UCxk7onJcrgjIvr8xWqkYI+DbI3TfXg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.4.0", + "@typescript-eslint/types": "5.4.0", + "@typescript-eslint/typescript-estree": "5.4.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + } + }, + "@typescript-eslint/parser": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.4.0.tgz", + "integrity": "sha512-JoB41EmxiYpaEsRwpZEYAJ9XQURPFer8hpkIW9GiaspVLX8oqbqNM8P4EP8HOZg96yaALiLEVWllA2E8vwsIKw==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.4.0", + "@typescript-eslint/types": "5.4.0", + "@typescript-eslint/typescript-estree": "5.4.0", + "debug": "^4.3.2" + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.4.0.tgz", + "integrity": "sha512-pRxFjYwoi8R+n+sibjgF9iUiAELU9ihPBtHzocyW8v8D8G8KeQvXTsW7+CBYIyTYsmhtNk50QPGLE3vrvhM5KA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.4.0", + "@typescript-eslint/visitor-keys": "5.4.0" + } + }, + "@typescript-eslint/types": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.4.0.tgz", + "integrity": "sha512-GjXNpmn+n1LvnttarX+sPD6+S7giO+9LxDIGlRl4wK3a7qMWALOHYuVSZpPTfEIklYjaWuMtfKdeByx0AcaThA==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.4.0.tgz", + "integrity": "sha512-nhlNoBdhKuwiLMx6GrybPT3SFILm5Gij2YBdPEPFlYNFAXUJWX6QRgvi/lwVoadaQEFsizohs6aFRMqsXI2ewA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.4.0", + "@typescript-eslint/visitor-keys": "5.4.0", + "debug": "^4.3.2", + "globby": "^11.0.4", + "is-glob": "^4.0.3", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "dependencies": { + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.4.0.tgz", + "integrity": "sha512-PVbax7MeE7tdLfW5SA0fs8NGVVr+buMPrcj+CWYWPXsZCH8qZ1THufDzbXm1xrZ2b2PA1iENJ0sRq5fuUtvsJg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.4.0", + "eslint-visitor-keys": "^3.0.0" + } + }, + "acorn": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.6.0.tgz", + "integrity": "sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true + }, "adm-zip": { "version": "0.4.16", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", "dev": true }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -72,6 +308,18 @@ "sprintf-js": "~1.0.2" } }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -97,10 +345,19 @@ "concat-map": "0.0.1" } }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, "chalk": { @@ -129,10 +386,10 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", "dev": true }, "concat-map": { @@ -141,6 +398,17 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, "cryptiles": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-4.1.3.tgz", @@ -150,34 +418,404 @@ "boom": "7.x.x" } }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, + "eslint": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.3.0.tgz", + "integrity": "sha512-aIay56Ph6RxOTC7xyr59Kt3ewX185SaGnAr8eWukoPLeriCrvGjvAubxuvaXOfsxhtwV5g0uBOsyhAom4qJdww==", + "dev": true, + "requires": { + "@eslint/eslintrc": "^1.0.4", + "@humanwhocodes/config-array": "^0.6.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.0", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.1.0", + "espree": "^9.1.0", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^6.0.1", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.2.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint-scope": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz", + "integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz", + "integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==", + "dev": true + }, + "espree": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.1.0.tgz", + "integrity": "sha512-ZgYLvCS1wxOczBYGcQT9DDWgicXwJ4dbocr9uYN+/eresBAUuBu+O4WzB21ufQ/JqQT8gyp7hJ3z8SHii32mTQ==", + "dev": true, + "requires": { + "acorn": "^8.6.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^3.1.0" + } + }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-glob": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", + "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz", + "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==", + "dev": true + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, "glob": { @@ -194,13 +832,53 @@ "path-is-absolute": "^1.0.0" } }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", + "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "globby": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "function-bind": "^1.1.1" + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } } }, "has-flag": { @@ -215,6 +893,40 @@ "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==", "dev": true }, + "husky": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.4.tgz", + "integrity": "sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==", + "dev": true + }, + "ignore": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.9.tgz", + "integrity": "sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -231,15 +943,39 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "is-core-module": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", - "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "requires": { - "has": "^1.0.3" + "is-extglob": "^2.1.1" } }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -256,12 +992,135 @@ "esprima": "^4.0.0" } }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, "lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", "dev": true }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, + "loglevel": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz", + "integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==", + "dev": true + }, + "loglevel-colored-level-prefix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/loglevel-colored-level-prefix/-/loglevel-colored-level-prefix-1.0.0.tgz", + "integrity": "sha1-akAhj9x64V/HbD0PPmdsRlOIYD4=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "loglevel": "^1.4.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -271,20 +1130,17 @@ "brace-expansion": "^1.1.7" } }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true }, "once": { "version": "1.4.0", @@ -295,16 +1151,57 @@ "wrappy": "1" } }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, "prettier": { @@ -313,14 +1210,377 @@ "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", "dev": true }, - "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "prettier-eslint": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/prettier-eslint/-/prettier-eslint-13.0.0.tgz", + "integrity": "sha512-P5K31qWgUOQCtJL/3tpvEe28KfP49qbr6MTVEXC7I2k7ci55bP3YDr+glhyCdhIzxGCVp2f8eobfQ5so52RIIA==", "dev": true, "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" + "@typescript-eslint/parser": "^3.0.0", + "common-tags": "^1.4.0", + "dlv": "^1.1.0", + "eslint": "^7.9.0", + "indent-string": "^4.0.0", + "lodash.merge": "^4.6.0", + "loglevel-colored-level-prefix": "^1.0.0", + "prettier": "^2.0.0", + "pretty-format": "^23.0.1", + "require-relative": "^0.8.7", + "typescript": "^3.9.3", + "vue-eslint-parser": "~7.1.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@eslint/eslintrc": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", + "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + } + }, + "@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + } + }, + "@typescript-eslint/experimental-utils": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz", + "integrity": "sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/types": "3.10.1", + "@typescript-eslint/typescript-estree": "3.10.1", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + } + }, + "@typescript-eslint/parser": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.10.1.tgz", + "integrity": "sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw==", + "dev": true, + "requires": { + "@types/eslint-visitor-keys": "^1.0.0", + "@typescript-eslint/experimental-utils": "3.10.1", + "@typescript-eslint/types": "3.10.1", + "@typescript-eslint/typescript-estree": "3.10.1", + "eslint-visitor-keys": "^1.1.0" + } + }, + "@typescript-eslint/types": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.10.1.tgz", + "integrity": "sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz", + "integrity": "sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w==", + "dev": true, + "requires": { + "@typescript-eslint/types": "3.10.1", + "@typescript-eslint/visitor-keys": "3.10.1", + "debug": "^4.1.1", + "glob": "^7.1.6", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz", + "integrity": "sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint": { + "version": "7.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", + "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", + "dev": true, + "requires": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.3", + "@humanwhocodes/config-array": "^0.5.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.9", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + } + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "typescript": { + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", + "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", + "dev": true + } + } + }, + "pretty-format": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz", + "integrity": "sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0", + "ansi-styles": "^3.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + } + } + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "require-relative": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz", + "integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" } }, "semver": { @@ -329,6 +1589,64 @@ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } + } + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -341,6 +1659,32 @@ "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", "dev": true }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -350,59 +1694,176 @@ "has-flag": "^3.0.0" } }, + "table": { + "version": "6.7.3", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.3.tgz", + "integrity": "sha512-5DkIxeA7XERBqMwJq0aHZOdMadBx4e6eDoFRuyT5VR82J0Ycg2DwM6GfA/EQAhJ+toRTaS1lIdSQCqgrmhPnlw==", + "dev": true, + "requires": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "ajv": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.8.2.tgz", + "integrity": "sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, - "tslint": { - "version": "5.20.1", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", - "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.8.0", - "tsutils": "^2.29.0" + "tslib": "^1.8.1" } }, - "tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "requires": { - "tslib": "^1.8.1" + "prelude-ls": "^1.2.1" } }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, "typescript": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", - "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.2.tgz", + "integrity": "sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==", "dev": true }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, "uuid": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "dev": true }, + "v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "vue-eslint-parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.1.1.tgz", + "integrity": "sha512-8FdXi0gieEwh1IprIBafpiJWcApwrU+l2FEj8c1HtHFdNXMd0+2jUSjBVmcQYohf/E72irwAXEXLga6TQcB3FA==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "eslint-scope": "^5.0.0", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.2.1", + "esquery": "^1.0.1", + "lodash": "^4.17.15" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "espree": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", + "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", + "dev": true, + "requires": { + "acorn": "^7.1.1", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.1.0" + } + } + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } } } diff --git a/package.json b/package.json index e2421a7..cd87c73 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,19 @@ { - "devDependencies": { - "@rocket.chat/apps-engine": "^1.17.0", - "@types/node": "10.17.5", - "prettier": "^2.0.5", - "tslint": "^5.20.1", - "typescript": "^2.9.1" - }, - "scripts": { - "tslint": "tslint --project ." - } + "devDependencies": { + "@rocket.chat/apps-engine": "^1.17.0", + "@types/node": "10.17.5", + "@typescript-eslint/eslint-plugin": "^5.4.0", + "@typescript-eslint/parser": "^5.4.0", + "eslint": "^8.3.0", + "husky": "^7.0.4", + "prettier": "^2.0.5", + "prettier-eslint": "^13.0.0", + "typescript": "^4.3.4" + }, + "scripts": { + "prepare": "husky install", + "typecheck": "tsc --noEmit --skipLibCheck", + "lint": "eslint -c .eslintrc.js --ext .ts .", + "prettier-format": "prettier --config .prettierrc '**.ts' --write" + } } diff --git a/tsconfig.json b/tsconfig.json index 1fe4878..88f4c83 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,17 +1,23 @@ { - "compilerOptions": { - "target": "es2017", - "module": "commonjs", - "moduleResolution": "node", - "declaration": false, - "noImplicitAny": false, - "removeComments": true, - "strictNullChecks": true, - "noImplicitReturns": true, - "emitDecoratorMetadata": true, - "experimentalDecorators": true, - }, - "include": [ - "**/*.ts" - ] - } + "compilerOptions":{ + "target":"es2018", + "module":"commonjs", + "moduleResolution":"node", + "declaration":false, + "noImplicitAny":false, + "removeComments":true, + "strictNullChecks":true, + "noImplicitReturns":true, + "emitDecoratorMetadata":true, + "experimentalDecorators":true, + "strict":true, + "strictPropertyInitialization":false, + "allowJs":false, + "noUnusedLocals":true, + "noUnusedParameters":true, + "noFallthroughCasesInSwitch":false + }, + "include":[ + "**/*.ts" + ] +} diff --git a/tslint.json b/tslint.json index 0d443fd..eeb9230 100644 --- a/tslint.json +++ b/tslint.json @@ -1,16 +1,19 @@ { - "extends": "tslint:recommended", - "rules": { - "array-type": [true, "generic"], - "member-access": true, - "no-console": [false], - "no-duplicate-variable": true, - "object-literal-sort-keys": false, - "quotemark": [true, "single"], - "max-line-length": [true, { - "limit": 160, - "ignore-pattern": "^import | *export .*? {" - }], - "no-bitwise": false - } - } + "extends": "tslint:recommended", + "rules": { + "array-type": [true, "generic"], + "member-access": true, + "no-console": [false], + "no-duplicate-variable": true, + "object-literal-sort-keys": false, + "quotemark": [true, "single"], + "max-line-length": [ + true, + { + "limit": 160, + "ignore-pattern": "^import | *export .*? {" + } + ], + "no-bitwise": false + } +} diff --git a/types/misc.ts b/types/misc.ts new file mode 100644 index 0000000..ef7a52c --- /dev/null +++ b/types/misc.ts @@ -0,0 +1,8 @@ +import { IMessageAttachment } from '@rocket.chat/apps-engine/definition/messages'; +import { IBlock } from '@rocket.chat/apps-engine/definition/uikit'; + +export interface IMessageParam { + text?: string; + blocks?: IBlock[]; + attachment?: IMessageAttachment; +} From 9eaa8e34afdf0a5d862075b56a74f7e364d497ce Mon Sep 17 00:00:00 2001 From: Murtaza Patrawala <34130764+murtaza98@users.noreply.github.com> Date: Thu, 9 Dec 2021 16:54:41 +0530 Subject: [PATCH 08/19] [IMPROVE] Add doc link to app description & Improve app settings (#74) --- .gitignore | 3 +++ app.json | 2 +- config/Settings.ts | 5 +++-- i18n/en.json | 1 + 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 6db8a93..6abc5f0 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,6 @@ Temporary Items .editorconfig .vscode + +# related to rc-apps cli +.rcappsconfig \ No newline at end of file diff --git a/app.json b/app.json index 83c4e16..8ee54d5 100644 --- a/app.json +++ b/app.json @@ -11,7 +11,7 @@ "name": "Dialogflow", "nameSlug": "dialogflow", "classFile": "DialogflowApp.ts", - "description": "Integration between Rocket.Chat and the Dialogflow Chatbot platform", + "description": "Integration between Rocket.Chat and the Dialogflow Chatbot platform. Relevant documentation of this app can be found [here](https://docs.rocket.chat/guides/app-guides/omnichannel-apps/dialogflow-app)", "implements": [ "IPostMessageSent", "IUIKitLivechatInteractionHandler" diff --git a/config/Settings.ts b/config/Settings.ts index c195994..ad361b5 100644 --- a/config/Settings.ts +++ b/config/Settings.ts @@ -23,7 +23,7 @@ export enum ServerSetting { } export enum DefaultMessage { - DEFAULT_DialogflowServiceUnavailableMessage = "Sorry, I'm having trouble answering your question.", + DEFAULT_DialogflowServiceUnavailableMessage = `Sorry, I'm having trouble answering your question.`, DEFAULT_DialogflowRequestFailedMessage = 'Sorry, something went wrong.', DEFAULT_DialogflowHandoverMessage = 'Transferring to an online agent', DEFAULT_DialogflowCloseChatMessage = 'Closing the chat, Goodbye', @@ -52,6 +52,7 @@ export const settings: Array = [ type: SettingType.STRING, packageValue: 'draft', i18nLabel: 'dialogflow_environment', + i18nDescription: 'dialogflow_environment_description', required: true, }, { @@ -133,6 +134,6 @@ export const settings: Array = [ value: true, i18nLabel: 'dialogflow_hide_quick_replies', i18nDescription: 'dialogflow_hide_quick_replies_description', - required: true, + required: false, }, ]; diff --git a/i18n/en.json b/i18n/en.json index 4a1abe1..beddb9f 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -2,6 +2,7 @@ "bot_username": "Bot Username", "dialogflow_project_id": "Project Id", "dialogflow_environment": "Environment", + "dialogflow_environment_description": "Define the environment which you want your bot to use. More info about the Dialogflow Environments can be found [here](https://cloud.google.com/dialogflow/es/docs/agents-versions)", "dialogflow_client_email": "Client Email", "dialogflow_private_key": "Private Key", "dialogflow_fallback_responses_limit": "Fallback Responses Limit", From 567abd5b44d2db927e2d209151714b2cdfb8eb1b Mon Sep 17 00:00:00 2001 From: Murtaza Patrawala <34130764+murtaza98@users.noreply.github.com> Date: Tue, 21 Dec 2021 15:41:04 +0530 Subject: [PATCH 09/19] [NEW] Add multiple language support - text messages (#49) Co-authored-by: Renato Becker --- config/Settings.ts | 43 +++++++++++++++++++++++++++++++++++++++++++ i18n/en.json | 31 ++++++++++++++++++++++++++++++- lib/Dialogflow.ts | 4 +++- 3 files changed, 76 insertions(+), 2 deletions(-) diff --git a/config/Settings.ts b/config/Settings.ts index ad361b5..9e8fda8 100644 --- a/config/Settings.ts +++ b/config/Settings.ts @@ -1,5 +1,6 @@ import { ISetting, + ISettingSelectValue, SettingType, } from '@rocket.chat/apps-engine/definition/settings'; @@ -16,6 +17,7 @@ export enum AppSetting { DialogflowHandoverFailedMessage = 'dialogflow_no_agents_online_for_handover', DialogflowCloseChatMessage = 'dialogflow_close_chat_message', DialogflowHideQuickReplies = 'dialogflow_hide_quick_replies', + DialogflowDefaultLanguage = 'dialogflow_default_language', } export enum ServerSetting { @@ -29,6 +31,36 @@ export enum DefaultMessage { DEFAULT_DialogflowCloseChatMessage = 'Closing the chat, Goodbye', } +export const LanguageCode: Array = [ + { key: 'zh-CN', i18nLabel: 'Chinese - Simplified' }, + { key: 'da', i18nLabel: 'Danish' }, + { key: 'nl', i18nLabel: 'Dutch' }, + { key: 'en', i18nLabel: 'English' }, + { key: 'en-AU', i18nLabel: 'English - Australia' }, + { key: 'en-CA', i18nLabel: 'English - Canada' }, + { key: 'en-GB', i18nLabel: 'English - Great Britain' }, + { key: 'en-IN', i18nLabel: 'English - India' }, + { key: 'en-US', i18nLabel: 'English - US' }, + { key: 'fr-CA', i18nLabel: 'French - Canada' }, + { key: 'fr-FR', i18nLabel: 'French - France' }, + { key: 'de', i18nLabel: 'German' }, + { key: 'hi', i18nLabel: 'Hindi' }, + { key: 'id', i18nLabel: 'Indonesian' }, + { key: 'it', i18nLabel: 'Italian' }, + { key: 'ja', i18nLabel: 'Japanese' }, + { key: 'ko', i18nLabel: 'Korean' }, + { key: 'no', i18nLabel: 'Norwegian' }, + { key: 'pl', i18nLabel: 'Polish' }, + { key: 'pt-BR', i18nLabel: 'Portuguese - Brazil' }, + { key: 'pt', i18nLabel: 'Portuguese - Portugal' }, + { key: 'ru', i18nLabel: 'Russian' }, + { key: 'es', i18nLabel: 'Spanish' }, + { key: 'es-ES', i18nLabel: 'Spanish - Spain' }, + { key: 'sv', i18nLabel: 'Swedish' }, + { key: 'tr', i18nLabel: 'Turkish' }, + { key: 'uk', i18nLabel: 'Ukrainian' }, +]; + export const settings: Array = [ { id: AppSetting.DialogflowBotUsername, @@ -71,6 +103,17 @@ export const settings: Array = [ i18nLabel: 'dialogflow_private_key', required: true, }, + { + id: AppSetting.DialogflowDefaultLanguage, + public: true, + type: SettingType.SELECT, + values: LanguageCode, + packageValue: 'en', + value: 'en', + i18nLabel: 'dialogflow_default_language', + i18nDescription: 'dialogflow_default_language_description', + required: false, + }, { id: AppSetting.DialogflowFallbackResponsesLimit, public: true, diff --git a/i18n/en.json b/i18n/en.json index beddb9f..2265646 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -18,5 +18,34 @@ "dialogflow_hide_quick_replies": "Hide Quick Replies", "dialogflow_hide_quick_replies_description": "If enabled, then all quick-replies will hide when a visitor clicks on any one of them", "dialogflow_handover_failed_message": "Handover Failed Message", - "dialogflow_handover_failed_message_description": "The Bot will send this message to Visitor if the handover failed because no agents were online" + "dialogflow_handover_failed_message_description": "The Bot will send this message to Visitor if the handover failed because no agents were online", + "dialogflow_default_language": "Language", + "dialogflow_default_language_description": "Define the language in which you'd be interacting with the Bot", + "dialogflow_chinese_simplified": "Chinese - Simplified", + "dialogflow_danish": "Danish", + "dialogflow_dutch": "Dutch", + "dialogflow_english": "English", + "dialogflow_english_australia": "English - Australia", + "dialogflow_english_canada": "English - Canada", + "dialogflow_english_great_britain": "English - Great Britain", + "dialogflow_english_india": "English - India", + "dialogflow_english_us": "English - US", + "dialogflow_french_canada": "French - Canada", + "dialogflow_french_france": "French - France", + "dialogflow_german": "German", + "dialogflow_hindi": "Hindi", + "dialogflow_indonesian": "Indonesian", + "dialogflow_italian": "Italian", + "dialogflow_japanese": "Japanese", + "dialogflow_korean": "Korean", + "dialogflow_norwegian": "Norwegian", + "dialogflow_polish": "Polish", + "dialogflow_portuguese-brazil": "Portuguese - Brazil", + "dialogflow_portuguese-portugal": "Portuguese - Portugal", + "dialogflow_russian": "Russian", + "dialogflow_spanish": "Spanish", + "dialogflow_spanish-spain": "Spanish - Spain", + "dialogflow_swedish": "Swedish", + "dialogflow_turkish": "Turkish", + "dialogflow_ukrainian": "Ukrainian" } diff --git a/lib/Dialogflow.ts b/lib/Dialogflow.ts index 4dabbd2..5ed89ba 100644 --- a/lib/Dialogflow.ts +++ b/lib/Dialogflow.ts @@ -42,12 +42,14 @@ class DialogflowClass { sessionId, ); + const languageCode = await getAppSettingValue(read, AppSetting.DialogflowDefaultLanguage) || LanguageCode.EN; + const queryInput = { ...requestType === DialogflowRequestType.EVENT && { event: request, }, ...requestType === DialogflowRequestType.MESSAGE && { - text: { languageCode: LanguageCode.EN, text: request }, + text: { languageCode, text: request }, }, }; From bcaa489eabbe734d6554a318b72ed2a2557afe97 Mon Sep 17 00:00:00 2001 From: murtaza98 Date: Tue, 15 Mar 2022 18:22:28 +0530 Subject: [PATCH 10/19] [NEW] Introduce redirect URL buttons to Chatbot apps --- docs/QuickReplies.md | 1 + enum/Dialogflow.ts | 1 + handler/ExecuteLivechatBlockActionHandler.ts | 5 +++++ handler/PostMessageSentHandler.ts | 2 ++ lib/Message.ts | 6 +++++- 5 files changed, 14 insertions(+), 1 deletion(-) diff --git a/docs/QuickReplies.md b/docs/QuickReplies.md index 3a38238..c352243 100644 --- a/docs/QuickReplies.md +++ b/docs/QuickReplies.md @@ -24,6 +24,7 @@ | **Param Name** | **Param Type** | **Description** | **Dependency** | **Acceptable Values** | **Example** | |:--------------:|:--------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------:|:---------------------:|:---------------------------------------:| | `text` | String | Title of the quick replies action. | Required | Any | ``` "text": "Start Chat" ``` | +| `url` | String | Redirect Url in-case you wish to redirect user somewhere if they click on the button | Optional | Any | ``` "text": "Start Chat" ``` | | `actionId` | String | Id of the quick replies action. | Optional | Any | ``` "actionId": "sflaia-start-chat" ``` | | `buttonStyle` | String | Button style of your quick replies action. Use `danger` to render a red colour action and `primary` for an action that matches your Livechat Bar colour. | Optional | `danger` or `primary` | ``` "buttonStyle": "primary" ``` | diff --git a/enum/Dialogflow.ts b/enum/Dialogflow.ts index b1073fc..a58ee37 100644 --- a/enum/Dialogflow.ts +++ b/enum/Dialogflow.ts @@ -37,6 +37,7 @@ export interface IDialogflowQuickReplies { export interface IDialogflowQuickReplyOptions { text: string; + url?: string; actionId?: string; buttonStyle?: ButtonStyle; data?: { diff --git a/handler/ExecuteLivechatBlockActionHandler.ts b/handler/ExecuteLivechatBlockActionHandler.ts index 7d414ce..8f92e77 100644 --- a/handler/ExecuteLivechatBlockActionHandler.ts +++ b/handler/ExecuteLivechatBlockActionHandler.ts @@ -39,6 +39,11 @@ export class ExecuteLivechatBlockActionHandler { actionId, } = interactionData; + if (!value) { + // most likely, this button has a url to open. So we don't need to do anything here. + return this.context.getInteractionResponder().successResponse(); + } + if (type !== UIKitIncomingInteractionContainerType.MESSAGE) { return this.context.getInteractionResponder().successResponse(); } diff --git a/handler/PostMessageSentHandler.ts b/handler/PostMessageSentHandler.ts index d9817b2..db9ce82 100644 --- a/handler/PostMessageSentHandler.ts +++ b/handler/PostMessageSentHandler.ts @@ -67,6 +67,8 @@ export class PostMessageSentHandler { let messageText = text; messageText = await removeQuotedMessage(this.read, room, messageText); + this.app.getLogger().debug('Attempting to send following message to Dialogflow:', messageText); + let response: IDialogflowMessage; try { response = await Dialogflow.sendRequest( diff --git a/lib/Message.ts b/lib/Message.ts index aeae399..f56bf56 100644 --- a/lib/Message.ts +++ b/lib/Message.ts @@ -44,10 +44,14 @@ export const createDialogflowMessage = async ( text: payload.text, type: TextObjectType.PLAINTEXT, }, - value: payload.text, + // if the button is a link, then we don't need to pass any value as clicking the button will open the link + value: payload.url ? '' : payload.text, ...(payload.buttonStyle && { style: payload.buttonStyle, }), + ...(payload.url && { + url: payload.url, + }), }; if ( From 46457d1d5f73168b6e02ee334758dc990cebbe31 Mon Sep 17 00:00:00 2001 From: Murtaza Patrawala <34130764+murtaza98@users.noreply.github.com> Date: Tue, 15 Mar 2022 18:33:36 +0530 Subject: [PATCH 11/19] Update QuickReplies.md --- docs/QuickReplies.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/QuickReplies.md b/docs/QuickReplies.md index c352243..148f354 100644 --- a/docs/QuickReplies.md +++ b/docs/QuickReplies.md @@ -24,7 +24,7 @@ | **Param Name** | **Param Type** | **Description** | **Dependency** | **Acceptable Values** | **Example** | |:--------------:|:--------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------:|:---------------------:|:---------------------------------------:| | `text` | String | Title of the quick replies action. | Required | Any | ``` "text": "Start Chat" ``` | -| `url` | String | Redirect Url in-case you wish to redirect user somewhere if they click on the button | Optional | Any | ``` "text": "Start Chat" ``` | +| `url` | String | Redirect Url in-case you wish to redirect user somewhere if they click on the button.
⚠️ Recommended to only use with Livechat conversations | Optional | Any | ``` "text": "Start Chat" ``` | | `actionId` | String | Id of the quick replies action. | Optional | Any | ``` "actionId": "sflaia-start-chat" ``` | | `buttonStyle` | String | Button style of your quick replies action. Use `danger` to render a red colour action and `primary` for an action that matches your Livechat Bar colour. | Optional | `danger` or `primary` | ``` "buttonStyle": "primary" ``` | From 515df006a854f098f530518554f8a7e4e7788c55 Mon Sep 17 00:00:00 2001 From: murtaza98 Date: Wed, 16 Mar 2022 20:24:53 +0530 Subject: [PATCH 12/19] Apply suggestions from code review --- handler/PostMessageSentHandler.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/handler/PostMessageSentHandler.ts b/handler/PostMessageSentHandler.ts index db9ce82..202d4fd 100644 --- a/handler/PostMessageSentHandler.ts +++ b/handler/PostMessageSentHandler.ts @@ -34,7 +34,7 @@ export class PostMessageSentHandler { ) {} public async run() { - const { text, editedAt, room, token, sender } = this.message; + const { text, editedAt, room, token, sender, id } = this.message; const livechatRoom = room as ILivechatRoom; const { id: rid, type, servedBy, isOpen } = livechatRoom; @@ -67,7 +67,7 @@ export class PostMessageSentHandler { let messageText = text; messageText = await removeQuotedMessage(this.read, room, messageText); - this.app.getLogger().debug('Attempting to send following message to Dialogflow:', messageText); + this.app.getLogger().debug(`Attempting to send message with id ${ id } to Dialogflow`); let response: IDialogflowMessage; try { From dd314118d04cb632151718a047008cd793c2dae6 Mon Sep 17 00:00:00 2001 From: Murtaza Patrawala <34130764+murtaza98@users.noreply.github.com> Date: Mon, 28 Mar 2022 18:17:01 +0530 Subject: [PATCH 13/19] Chore: Bump app version to 1.2.5 (#81) --- app.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.json b/app.json index 8ee54d5..4ec696c 100644 --- a/app.json +++ b/app.json @@ -1,6 +1,6 @@ { "id": "21b7d3ba-031b-41d9-8ff2-fbbfa081ae90", - "version": "1.2.4", + "version": "1.2.5", "requiredApiVersion": "^1.17.0", "iconFile": "icon.png", "author": { From 4217396b4410a11d93540c83814702659c9e3dad Mon Sep 17 00:00:00 2001 From: AlexanderKanakis Date: Thu, 9 Jun 2022 17:18:24 +0300 Subject: [PATCH 14/19] Fixed conflict for package/package.log --- package-lock.json | 6 ------ package.json | 20 -------------------- 2 files changed, 26 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4c06a23..a6504c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1772,15 +1772,9 @@ "dev": true }, "typescript": { -<<<<<<< HEAD - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.2.tgz", - "integrity": "sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==", -======= "version": "4.5.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", ->>>>>>> master "dev": true }, "uri-js": { diff --git a/package.json b/package.json index 9ad0eed..e3eb982 100644 --- a/package.json +++ b/package.json @@ -1,23 +1,4 @@ { -<<<<<<< HEAD - "devDependencies": { - "@rocket.chat/apps-engine": "^1.17.0", - "@types/node": "10.17.5", - "@typescript-eslint/eslint-plugin": "^5.4.0", - "@typescript-eslint/parser": "^5.4.0", - "eslint": "^8.3.0", - "husky": "^7.0.4", - "prettier": "^2.0.5", - "prettier-eslint": "^13.0.0", - "typescript": "^4.3.4" - }, - "scripts": { - "prepare": "husky install", - "typecheck": "tsc --noEmit --skipLibCheck", - "lint": "eslint -c .eslintrc.js --ext .ts .", - "prettier-format": "prettier --config .prettierrc '**.ts' --write" - } -======= "devDependencies": { "@rocket.chat/apps-engine": "WideChat/Rocket.Chat.Apps-engine.git#v1.29.2", "@types/node": "10.17.5", @@ -28,5 +9,4 @@ "scripts": { "tslint": "tslint --project ." } ->>>>>>> master } From 5421423770a6f0409fd8acc51c299f9de97d535e Mon Sep 17 00:00:00 2001 From: AlexanderKanakis Date: Tue, 14 Jun 2022 17:10:53 +0300 Subject: [PATCH 15/19] Fixed merge issues --- app.json | 2 +- enum/Dialogflow.ts | 2 +- enum/Endpoints.ts | 22 +- enum/Http.ts | 10 +- handler/ExecuteLivechatBlockActionHandler.ts | 156 +- handler/OnSettingUpdatedHandler.ts | 45 +- handler/PostMessageSentHandler.ts | 118 +- package-lock.json | 1760 ++---------------- 8 files changed, 234 insertions(+), 1881 deletions(-) diff --git a/app.json b/app.json index 367a7e9..c65f992 100644 --- a/app.json +++ b/app.json @@ -19,5 +19,5 @@ "IPostLivechatRoomClosed", "IUIKitLivechatInteractionHandler" ], - "commitHash": "ce5d31508c6e678172c5bf73a1525dd0fda6b29f" + "commitHash": "4217396b4410a11d93540c83814702659c9e3dad" } \ No newline at end of file diff --git a/enum/Dialogflow.ts b/enum/Dialogflow.ts index f096e2b..cca3e2e 100644 --- a/enum/Dialogflow.ts +++ b/enum/Dialogflow.ts @@ -54,7 +54,7 @@ export interface IDialogflowAccessToken { export interface IDialogflowEvent { name: string; - parameters?: unknown; + parameters?: any; languageCode: string; } diff --git a/enum/Endpoints.ts b/enum/Endpoints.ts index 843d103..484c1a2 100644 --- a/enum/Endpoints.ts +++ b/enum/Endpoints.ts @@ -1,18 +1,18 @@ import { IDialogflowEvent, IDialogflowQuickReplies } from './Dialogflow'; export interface IActionsEndpointContent { - action: EndpointActionNames; - sessionId: string; - actionData?: { - targetDepartment?: string; - event?: IDialogflowEvent; - messages: Array; - }; + action: EndpointActionNames; + sessionId: string; + actionData?: { + targetDepartment?: string; + event?: IDialogflowEvent; + messages: Array; + }; } export enum EndpointActionNames { - CLOSE_CHAT = 'close-chat', - HANDOVER = 'handover', - TRIGGER_EVENT = 'trigger-event', - SEND_MESSAGE = 'send-message', + CLOSE_CHAT = 'close-chat', + HANDOVER = 'handover', + TRIGGER_EVENT = 'trigger-event', + SEND_MESSAGE = 'send-message', } diff --git a/enum/Http.ts b/enum/Http.ts index 4f643de..dbd3b14 100644 --- a/enum/Http.ts +++ b/enum/Http.ts @@ -1,10 +1,10 @@ export enum Headers { - CONTENT_TYPE_JSON = 'application/json', - CONTENT_TYPE_X_FORM_URL_ENCODED = 'application/x-www-form-urlencoded', - ACCEPT_JSON = 'application/json', + CONTENT_TYPE_JSON = 'application/json', + CONTENT_TYPE_X_FORM_URL_ENCODED = 'application/x-www-form-urlencoded', + ACCEPT_JSON = 'application/json', } export enum Response { - SUCCESS = 'Your request was processed successfully', - NO_AGENTS_ONLINE = 'Handover failed! No agents online', + SUCCESS = 'Your request was processed successfully', + NO_AGENTS_ONLINE = 'Handover failed! No agents online', } diff --git a/handler/ExecuteLivechatBlockActionHandler.ts b/handler/ExecuteLivechatBlockActionHandler.ts index 0310f6d..b557277 100644 --- a/handler/ExecuteLivechatBlockActionHandler.ts +++ b/handler/ExecuteLivechatBlockActionHandler.ts @@ -1,61 +1,57 @@ import { - IModify, - IRead, + IHttp, + IModify, + IPersistence, + IRead, } from '@rocket.chat/apps-engine/definition/accessors'; import { IApp } from '@rocket.chat/apps-engine/definition/IApp'; import { ILivechatRoom } from '@rocket.chat/apps-engine/definition/livechat'; import { - IUIKitResponse, - UIKitLivechatBlockInteractionContext, + IUIKitResponse, + UIKitLivechatBlockInteractionContext, } from '@rocket.chat/apps-engine/definition/uikit'; import { UIKitIncomingInteractionContainerType } from '@rocket.chat/apps-engine/definition/uikit/UIKitIncomingInteractionContainer'; import { IUser } from '@rocket.chat/apps-engine/definition/users'; import { AppSetting, DefaultMessage } from '../config/Settings'; import { ActionIds } from '../enum/ActionIds'; import { - createLivechatMessage, - createMessage, - deleteAllActionBlocks, + createLivechatMessage, + createMessage, + deleteAllActionBlocks, } from '../lib/Message'; import { closeChat, performHandover } from '../lib/Room'; import { getLivechatAgentConfig } from '../lib/Settings'; export class ExecuteLivechatBlockActionHandler { - constructor( - private readonly app: IApp, - private context: UIKitLivechatBlockInteractionContext, - private read: IRead, - private modify: IModify, - ) {} + constructor( + private readonly app: IApp, + private context: UIKitLivechatBlockInteractionContext, + private read: IRead, + private http: IHttp, + private persistence: IPersistence, + private modify: IModify, + ) {} - public async run(): Promise { - try { - const interactionData = this.context.getInteractionData(); - const { - visitor, - room, - container: { id, type }, - value, - actionId, - } = interactionData; + public async run(): Promise { + try { + const interactionData = this.context.getInteractionData(); + const { + visitor, + room, + container: { id, type }, + value, + actionId, + } = interactionData; - if (!value) { - // most likely, this button has a url to open. So we don't need to do anything here. - return this.context.getInteractionResponder().successResponse(); - } + if (!value) { + // most likely, this button has a url to open. So we don't need to do anything here. + return this.context.getInteractionResponder().successResponse(); + } -<<<<<<< HEAD - if (type !== UIKitIncomingInteractionContainerType.MESSAGE) { - return this.context.getInteractionResponder().successResponse(); - } + if (type !== UIKitIncomingInteractionContainerType.MESSAGE) { + return this.context.getInteractionResponder().successResponse(); + } - const DialogflowBotUsername: string = await getAppSettingValue( - this.read, - AppSetting.DialogflowBotUsername, - ); - const { servedBy: { username = null } = {}, id: rid } = - room as ILivechatRoom; -======= const { servedBy: { username = null } = {}, id: rid, isOpen, closedAt } = room as ILivechatRoom; if (!isOpen || closedAt) { @@ -65,47 +61,9 @@ export class ExecuteLivechatBlockActionHandler { if (!username ) { return this.context.getInteractionResponder().successResponse(); } ->>>>>>> master - - if (!username || DialogflowBotUsername !== username) { - return this.context.getInteractionResponder().successResponse(); - } -<<<<<<< HEAD - const appUser = (await this.read - .getUserReader() - .getAppUser(this.app.getID())) as IUser; + const appUser = await this.read.getUserReader().getAppUser(this.app.getID()) as IUser; - switch (actionId) { - case ActionIds.PERFORM_HANDOVER: - const targetDepartment: string = - value || - (await getAppSettingValue( - this.read, - AppSetting.FallbackTargetDepartment, - )); - if (!targetDepartment) { - await createMessage( - this.app, - rid, - this.read, - this.modify, - { - text: DefaultMessage.DEFAULT_DialogflowRequestFailedMessage, - }, - ); - break; - } - await performHandover( - this.app, - this.modify, - this.read, - rid, - visitor.token, - targetDepartment, - ); - break; -======= switch (actionId) { case ActionIds.PERFORM_HANDOVER: const targetDepartment: string = value || await getLivechatAgentConfig(this.read, rid, AppSetting.FallbackTargetDepartment); @@ -119,43 +77,25 @@ export class ExecuteLivechatBlockActionHandler { case ActionIds.CLOSE_CHAT: await closeChat(this.modify, this.read, rid, this.persistence); break; ->>>>>>> master - case ActionIds.CLOSE_CHAT: - await closeChat(this.modify, this.read, rid); - break; + default: + await createLivechatMessage(this.app, rid, this.read, this.modify, { text: value }, visitor); + break; + } -<<<<<<< HEAD - default: - await createLivechatMessage( - this.app, - rid, - this.read, - this.modify, - { text: value }, - visitor, - ); - break; - } -======= const hideQuickRepliesSetting = await getLivechatAgentConfig(this.read, rid, AppSetting.DialogflowHideQuickReplies); if (hideQuickRepliesSetting) { await deleteAllActionBlocks(this.modify, appUser, id); } ->>>>>>> master - const { value: hideQuickRepliesSetting } = await this.read - .getEnvironmentReader() - .getSettings() - .getById(AppSetting.DialogflowHideQuickReplies); - if (hideQuickRepliesSetting) { - await deleteAllActionBlocks(this.modify, appUser, id); - } + if (hideQuickRepliesSetting) { + await deleteAllActionBlocks(this.modify, appUser, id); + } - return this.context.getInteractionResponder().successResponse(); - } catch (error) { - this.app.getLogger().error(error); - return this.context.getInteractionResponder().errorResponse(); - } - } + return this.context.getInteractionResponder().successResponse(); + } catch (error) { + this.app.getLogger().error(error); + return this.context.getInteractionResponder().errorResponse(); + } + } } diff --git a/handler/OnSettingUpdatedHandler.ts b/handler/OnSettingUpdatedHandler.ts index e95f5c2..2ab60e4 100644 --- a/handler/OnSettingUpdatedHandler.ts +++ b/handler/OnSettingUpdatedHandler.ts @@ -7,42 +7,12 @@ import { getError } from '../lib/Helper'; import { getAppSettingValue } from '../lib/Settings'; export class OnSettingUpdatedHandler { - constructor( - private readonly app: IApp, - private readonly read: IRead, - private readonly http: IHttp, - ) {} + constructor( + private readonly app: IApp, + private readonly read: IRead, + private readonly http: IHttp, + ) {} -<<<<<<< HEAD - public async run() { - const clientEmail: string = await getAppSettingValue( - this.read, - AppSetting.DialogflowClientEmail, - ); - const privateKey: string = await getAppSettingValue( - this.read, - AppSetting.DialogFlowPrivateKey, - ); - - if (clientEmail.length === 0 || privateKey.length === 0) { - this.app - .getLogger() - .error(Logs.EMPTY_CLIENT_EMAIL_OR_PRIVATE_KEY_SETTING); - return; - } - - try { - await Dialogflow.generateNewAccessToken( - this.http, - clientEmail, - privateKey, - ); - this.app.getLogger().info(Logs.GOOGLE_AUTH_SUCCESS); - } catch (error) { - this.app.getLogger().error(error); - } - } -======= public async run() { try { const dialogflowBotList = JSON.parse(await getAppSettingValue(this.read, AppSetting.DialogflowBotList)); @@ -63,7 +33,7 @@ export class OnSettingUpdatedHandler { try { await Dialogflow.generateNewAccessToken(this.http, clientEmail, privateKey); this.app.getLogger().info(Logs.GOOGLE_AUTH_SUCCESS); - } catch (error) { + } catch (error: any) { console.error(Logs.HTTP_REQUEST_ERROR, getError(error)); this.app.getLogger().error(error.message); } @@ -71,11 +41,10 @@ export class OnSettingUpdatedHandler { } } - } catch (e) { + } catch (e: any) { this.app.getLogger().error(Logs.AGENT_CONFIG_FORMAT_ERROR); console.error(Logs.AGENT_CONFIG_FORMAT_ERROR, e); throw new Error(e); } } ->>>>>>> master } diff --git a/handler/PostMessageSentHandler.ts b/handler/PostMessageSentHandler.ts index 54fcf4e..51a4d56 100644 --- a/handler/PostMessageSentHandler.ts +++ b/handler/PostMessageSentHandler.ts @@ -1,12 +1,13 @@ import { - IHttp, - IModify, - IRead, + IHttp, + IModify, + IPersistence, + IRead, } from '@rocket.chat/apps-engine/definition/accessors'; import { IApp } from '@rocket.chat/apps-engine/definition/IApp'; import { - ILivechatMessage, - ILivechatRoom, + ILivechatMessage, + ILivechatRoom, } from '@rocket.chat/apps-engine/definition/livechat'; import { RoomType } from '@rocket.chat/apps-engine/definition/rooms'; import { AppSetting } from '../config/Settings'; @@ -15,112 +16,6 @@ import { DialogflowRequestType, IDialogflowMessage, IDialogflowQuickReplies, Lan import { Logs } from '../enum/Logs'; import { botTypingListener, removeBotTypingListener } from '../lib//BotTyping'; import { Dialogflow } from '../lib/Dialogflow'; -<<<<<<< HEAD -import { - createDialogflowMessage, - createMessage, - removeQuotedMessage, -} from '../lib/Message'; -import { getAppSettingValue } from '../lib/Settings'; -import { - incFallbackIntent, - resetFallbackIntent, -} from '../lib/SynchronousHandover'; - -export class PostMessageSentHandler { - constructor( - private readonly app: IApp, - private readonly message: ILivechatMessage, - private readonly read: IRead, - private readonly http: IHttp, - private readonly modify: IModify, - ) {} - - public async run() { - const { text, editedAt, room, token, sender, id } = this.message; - const livechatRoom = room as ILivechatRoom; - - const { id: rid, type, servedBy, isOpen } = livechatRoom; - - const DialogflowBotUsername: string = await getAppSettingValue( - this.read, - AppSetting.DialogflowBotUsername, - ); - - if (!type || type !== RoomType.LIVE_CHAT) { - return; - } - - if (!isOpen || !token || editedAt || !text) { - return; - } - - if (!servedBy || servedBy.username !== DialogflowBotUsername) { - return; - } - - if (sender.username === DialogflowBotUsername) { - return; - } - - if (!text || (text && text.trim().length === 0)) { - return; - } - - let messageText = text; - messageText = await removeQuotedMessage(this.read, room, messageText); - - this.app.getLogger().debug(`Attempting to send message with id ${ id } to Dialogflow`); - - let response: IDialogflowMessage; - try { - response = await Dialogflow.sendRequest( - this.http, - this.read, - this.modify, - rid, - messageText, - DialogflowRequestType.MESSAGE, - ); - } catch (error) { - this.app - .getLogger() - .error( - `${Logs.DIALOGFLOW_REST_API_ERROR} ${ - (error as Error).message - }`, - ); - - const serviceUnavailable: string = await getAppSettingValue( - this.read, - AppSetting.DialogflowServiceUnavailableMessage, - ); - - await createMessage(this.app, rid, this.read, this.modify, { - text: serviceUnavailable - ? serviceUnavailable - : DefaultMessage.DEFAULT_DialogflowServiceUnavailableMessage, - }); - - return; - } - - await createDialogflowMessage( - this.app, - rid, - this.read, - this.modify, - response, - ); - - // synchronous handover check - const { isFallback } = response; - if (isFallback) { - return incFallbackIntent(this.app, this.read, this.modify, rid); - } - return resetFallbackIntent(this.read, this.modify, rid); - } -======= import { getErrorMessage } from '../lib/Helper'; import { createDialogflowMessage, createMessage, removeQuotedMessage } from '../lib/Message'; import { handleResponse } from '../lib/payloadAction'; @@ -326,5 +221,4 @@ export class PostMessageSentHandler { const DialogflowBotUsername = room.servedBy.username; await removeBotTypingListener(this.modify, rid, DialogflowBotUsername); } ->>>>>>> master } diff --git a/package-lock.json b/package-lock.json index a6504c3..9ed02bf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2,106 +2,34 @@ "requires": true, "lockfileVersion": 1, "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", - "dev": true - }, - "@babel/highlight": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", - "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@eslint/eslintrc": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.4.tgz", - "integrity": "sha512-h8Vx6MdxwWI2WM8/zREHMoqdgLNXEL4QX3MWSVMdyNJGvXVOs+6lp+m2hc3FnuMHDc4poxFNI20vCk0OmI4G0Q==", + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", "dev": true, "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.0.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" + "@babel/highlight": "^7.16.7" }, "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", "dev": true }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "@babel/highlight": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.12.tgz", + "integrity": "sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg==", "dev": true, "requires": { - "argparse": "^2.0.1" + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" } } } }, - "@humanwhocodes/config-array": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz", - "integrity": "sha512-JQlEKbcgEUjBFhLIF4iqM7u/9lwgHRBcpHrmUNCALK0Q3amXN6lxdoXLnF0sm11E9VqTmBALR87IlUg1bZ8A9A==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.0", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, "@rocket.chat/apps-engine": { "version": "github:WideChat/Rocket.Chat.Apps-engine#3e5da1c2c996a27197f9de7ca2292e1d1545e9d5", "from": "github:WideChat/Rocket.Chat.Apps-engine#v1.29.2", @@ -115,180 +43,18 @@ "uuid": "^3.2.1" } }, - "@types/eslint-visitor-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", - "dev": true - }, - "@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", - "dev": true - }, "@types/node": { "version": "10.17.5", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.5.tgz", "integrity": "sha512-RElZIr/7JreF1eY6oD5RF3kpmdcreuQPjg5ri4oQ5g9sq7YWU8HkfB3eH8GwAwxf5OaCh0VPi7r4N/yoTGelrA==", "dev": true }, - "@typescript-eslint/eslint-plugin": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.4.0.tgz", - "integrity": "sha512-9/yPSBlwzsetCsGEn9j24D8vGQgJkOTr4oMLas/w886ZtzKIs1iyoqFrwsX2fqYEeUwsdBpC21gcjRGo57u0eg==", - "dev": true, - "requires": { - "@typescript-eslint/experimental-utils": "5.4.0", - "@typescript-eslint/scope-manager": "5.4.0", - "debug": "^4.3.2", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.1.8", - "regexpp": "^3.2.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "dependencies": { - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "@typescript-eslint/experimental-utils": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.4.0.tgz", - "integrity": "sha512-Nz2JDIQUdmIGd6p33A+naQmwfkU5KVTLb/5lTk+tLVTDacZKoGQisj8UCxk7onJcrgjIvr8xWqkYI+DbI3TfXg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.4.0", - "@typescript-eslint/types": "5.4.0", - "@typescript-eslint/typescript-estree": "5.4.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - } - }, - "@typescript-eslint/parser": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.4.0.tgz", - "integrity": "sha512-JoB41EmxiYpaEsRwpZEYAJ9XQURPFer8hpkIW9GiaspVLX8oqbqNM8P4EP8HOZg96yaALiLEVWllA2E8vwsIKw==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.4.0", - "@typescript-eslint/types": "5.4.0", - "@typescript-eslint/typescript-estree": "5.4.0", - "debug": "^4.3.2" - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.4.0.tgz", - "integrity": "sha512-pRxFjYwoi8R+n+sibjgF9iUiAELU9ihPBtHzocyW8v8D8G8KeQvXTsW7+CBYIyTYsmhtNk50QPGLE3vrvhM5KA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.4.0", - "@typescript-eslint/visitor-keys": "5.4.0" - } - }, - "@typescript-eslint/types": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.4.0.tgz", - "integrity": "sha512-GjXNpmn+n1LvnttarX+sPD6+S7giO+9LxDIGlRl4wK3a7qMWALOHYuVSZpPTfEIklYjaWuMtfKdeByx0AcaThA==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.4.0.tgz", - "integrity": "sha512-nhlNoBdhKuwiLMx6GrybPT3SFILm5Gij2YBdPEPFlYNFAXUJWX6QRgvi/lwVoadaQEFsizohs6aFRMqsXI2ewA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.4.0", - "@typescript-eslint/visitor-keys": "5.4.0", - "debug": "^4.3.2", - "globby": "^11.0.4", - "is-glob": "^4.0.3", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "dependencies": { - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - } - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.4.0.tgz", - "integrity": "sha512-PVbax7MeE7tdLfW5SA0fs8NGVVr+buMPrcj+CWYWPXsZCH8qZ1THufDzbXm1xrZ2b2PA1iENJ0sRq5fuUtvsJg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.4.0", - "eslint-visitor-keys": "^3.0.0" - } - }, - "acorn": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.6.0.tgz", - "integrity": "sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true - }, "adm-zip": { "version": "0.4.16", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", "dev": true }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -307,18 +73,6 @@ "sprintf-js": "~1.0.2" } }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -344,19 +98,10 @@ "concat-map": "0.0.1" } }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==", "dev": true }, "chalk": { @@ -385,10 +130,10 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "common-tags": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", - "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, "concat-map": { @@ -397,17 +142,6 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, "cryptiles": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-4.1.3.tgz", @@ -417,730 +151,142 @@ "boom": "7.x.x" } }, - "debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1" - } + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, - "eslint": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.3.0.tgz", - "integrity": "sha512-aIay56Ph6RxOTC7xyr59Kt3ewX185SaGnAr8eWukoPLeriCrvGjvAubxuvaXOfsxhtwV5g0uBOsyhAom4qJdww==", + "glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", "dev": true, "requires": { - "@eslint/eslintrc": "^1.0.4", - "@humanwhocodes/config-array": "^0.6.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.0", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.1.0", - "espree": "^9.1.0", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.2.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint-scope": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz", - "integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "function-bind": "^1.1.1" } }, - "eslint-utils": { + "has-flag": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true }, - "eslint-visitor-keys": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz", - "integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==", + "hoek": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz", + "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==", "dev": true }, - "espree": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.1.0.tgz", - "integrity": "sha512-ZgYLvCS1wxOczBYGcQT9DDWgicXwJ4dbocr9uYN+/eresBAUuBu+O4WzB21ufQ/JqQT8gyp7hJ3z8SHii32mTQ==", + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "acorn": "^8.6.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.1.0" + "once": "^1.3.0", + "wrappy": "1" } }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", "dev": true, "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } + "has": "^1.0.3" } }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } + "argparse": "^1.0.7", + "esprima": "^4.0.0" } }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", "dev": true }, - "fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "brace-expansion": "^1.1.7" } }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, - "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, "requires": { - "reusify": "^1.0.4" + "minimist": "^1.2.6" } }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz", - "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "globals": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", - "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "globby": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", - "slash": "^3.0.0" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - } - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "hoek": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz", - "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==", - "dev": true - }, - "husky": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.4.tgz", - "integrity": "sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==", - "dev": true - }, - "ignore": { - "version": "5.1.9", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.9.tgz", - "integrity": "sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", - "dev": true - }, - "loglevel": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz", - "integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==", - "dev": true - }, - "loglevel-colored-level-prefix": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/loglevel-colored-level-prefix/-/loglevel-colored-level-prefix-1.0.0.tgz", - "integrity": "sha1-akAhj9x64V/HbD0PPmdsRlOIYD4=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "loglevel": "^1.4.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1150,57 +296,16 @@ "wrappy": "1" } }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", - "dev": true - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "prettier": { @@ -1209,377 +314,15 @@ "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", "dev": true }, - "prettier-eslint": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/prettier-eslint/-/prettier-eslint-13.0.0.tgz", - "integrity": "sha512-P5K31qWgUOQCtJL/3tpvEe28KfP49qbr6MTVEXC7I2k7ci55bP3YDr+glhyCdhIzxGCVp2f8eobfQ5so52RIIA==", - "dev": true, - "requires": { - "@typescript-eslint/parser": "^3.0.0", - "common-tags": "^1.4.0", - "dlv": "^1.1.0", - "eslint": "^7.9.0", - "indent-string": "^4.0.0", - "lodash.merge": "^4.6.0", - "loglevel-colored-level-prefix": "^1.0.0", - "prettier": "^2.0.0", - "pretty-format": "^23.0.1", - "require-relative": "^0.8.7", - "typescript": "^3.9.3", - "vue-eslint-parser": "~7.1.0" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@eslint/eslintrc": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", - "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - } - }, - "@humanwhocodes/config-array": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", - "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.0", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "@typescript-eslint/experimental-utils": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz", - "integrity": "sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.3", - "@typescript-eslint/types": "3.10.1", - "@typescript-eslint/typescript-estree": "3.10.1", - "eslint-scope": "^5.0.0", - "eslint-utils": "^2.0.0" - } - }, - "@typescript-eslint/parser": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.10.1.tgz", - "integrity": "sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw==", - "dev": true, - "requires": { - "@types/eslint-visitor-keys": "^1.0.0", - "@typescript-eslint/experimental-utils": "3.10.1", - "@typescript-eslint/types": "3.10.1", - "@typescript-eslint/typescript-estree": "3.10.1", - "eslint-visitor-keys": "^1.1.0" - } - }, - "@typescript-eslint/types": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.10.1.tgz", - "integrity": "sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz", - "integrity": "sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w==", - "dev": true, - "requires": { - "@typescript-eslint/types": "3.10.1", - "@typescript-eslint/visitor-keys": "3.10.1", - "debug": "^4.1.1", - "glob": "^7.1.6", - "is-glob": "^4.0.1", - "lodash": "^4.17.15", - "semver": "^7.3.2", - "tsutils": "^3.17.1" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz", - "integrity": "sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - } - }, - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint": { - "version": "7.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", - "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", - "dev": true, - "requires": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.3", - "@humanwhocodes/config-array": "^0.5.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.1.2", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.9", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - } - }, - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - }, - "espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "requires": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, - "typescript": { - "version": "3.9.10", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", - "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", - "dev": true - } - } - }, - "pretty-format": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz", - "integrity": "sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0", - "ansi-styles": "^3.2.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - } - } - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "require-relative": { - "version": "0.8.7", - "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz", - "integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=", - "dev": true - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", "dev": true, "requires": { - "queue-microtask": "^1.2.2" + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" } }, "semver": { @@ -1588,64 +331,6 @@ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - } - } - }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -1658,32 +343,6 @@ "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", "dev": true }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -1693,176 +352,67 @@ "has-flag": "^3.0.0" } }, - "table": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/table/-/table-6.7.3.tgz", - "integrity": "sha512-5DkIxeA7XERBqMwJq0aHZOdMadBx4e6eDoFRuyT5VR82J0Ycg2DwM6GfA/EQAhJ+toRTaS1lIdSQCqgrmhPnlw==", - "dev": true, - "requires": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "dependencies": { - "ajv": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.8.2.tgz", - "integrity": "sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - } - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "tslint": { + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", + "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", "dev": true, "requires": { - "tslib": "^1.8.1" - } - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.29.0" + }, + "dependencies": { + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + } } }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - }, "typescript": { "version": "4.5.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", "dev": true }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, "uuid": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "dev": true }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "vue-eslint-parser": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.1.1.tgz", - "integrity": "sha512-8FdXi0gieEwh1IprIBafpiJWcApwrU+l2FEj8c1HtHFdNXMd0+2jUSjBVmcQYohf/E72irwAXEXLga6TQcB3FA==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "eslint-scope": "^5.0.0", - "eslint-visitor-keys": "^1.1.0", - "espree": "^6.2.1", - "esquery": "^1.0.1", - "lodash": "^4.17.15" - }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - }, - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - }, - "espree": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", - "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", - "dev": true, - "requires": { - "acorn": "^7.1.1", - "acorn-jsx": "^5.2.0", - "eslint-visitor-keys": "^1.1.0" - } - } - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true } } } From 83901323da2f405b3e601582d04b62f30c5163cd Mon Sep 17 00:00:00 2001 From: AlexanderKanakis Date: Tue, 14 Jun 2022 17:45:07 +0300 Subject: [PATCH 16/19] fixed workflow scripts --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b37220b..1f40821 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,8 +18,8 @@ jobs: - name: Install Rocket.Chat Apps cli run: npm i -g WideChat/Rocket.Chat.Apps-cli - - name: ESLint check - run: npm run lint + - name: Tslint check + run: npm run tslint - name: Typescript check run: npm run typecheck From a24f71530c9d3ca9bcab2fd88e39a81fca9847f9 Mon Sep 17 00:00:00 2001 From: AlexanderKanakis Date: Tue, 14 Jun 2022 18:05:13 +0300 Subject: [PATCH 17/19] fixed merger issue --- i18n/en.json | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/i18n/en.json b/i18n/en.json index 6153119..883614c 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -3,13 +3,8 @@ "dialogflow_bot_id": "Bot Id", "dialogflow_bot_id_description": "Select the bot to use from the list of bots. Use comma to seperate values in respective fields", "dialogflow_project_id": "Project Id", -<<<<<<< HEAD - "dialogflow_environment": "Environment", - "dialogflow_environment_description": "Define the environment which you want your bot to use. More info about the Dialogflow Environments can be found [here](https://cloud.google.com/dialogflow/es/docs/agents-versions)", -======= "dialogflow_bot_list_config": "Dialogflow Agent Configuration List", "dialogflow_bot_list_config_description": "An object containing the Omnichannel bots and the configurations necessary to reach the corresponsind DF agent endpont", ->>>>>>> master "dialogflow_client_email": "Client Email", "dialogflow_cx_agent_id": "[CX ONLY] Dialogflow Agent ID", "dialogflow_cx_agent_id_desc": "1. Go to the Dialogflow CX console. \n 2. Select the project. \n 3. From the agent list find the right agent and click `⋮` . \n 4. Select copy name. \n 5. The agent name has the following format: \n 6. `projects/PROJECT_ID/locations/REGION_ID/agents/AGENT_ID`. \n 7. Copy `AGENT_ID` and paste it here.", @@ -37,8 +32,6 @@ "dialogflow_hide_quick_replies_description": "If enabled, then all quick-replies will hide when a visitor clicks on any one of them", "dialogflow_handover_failed_message": "Handover Failed Message", "dialogflow_handover_failed_message_description": "The Bot will send this message to Visitor if the handover failed because no agents were online", -<<<<<<< HEAD - "dialogflow_default_language": "Language", "dialogflow_default_language_description": "Define the language in which you'd be interacting with the Bot", "dialogflow_chinese_simplified": "Chinese - Simplified", "dialogflow_danish": "Danish", @@ -66,8 +59,7 @@ "dialogflow_spanish-spain": "Spanish - Spain", "dialogflow_swedish": "Swedish", "dialogflow_turkish": "Turkish", - "dialogflow_ukrainian": "Ukrainian" -======= + "dialogflow_ukrainian": "Ukrainian", "dialogflow_enable_chat_closed_by_visitor_event": "Enable Dialogflow Event When Visitor Ends Chat", "dialogflow_enable_chat_closed_by_visitor_event_description": "If enabled, then a dialogflow event will be triggered when visitor ends chat", "dialogflow_chat_closed_by_visitor_event_name": "Dialogflow Event Name When Visitor Ends Chat", @@ -96,5 +88,4 @@ "dialogflow_log_level_description":"Redeploying app or restarting server is required to apply changes", "dialogflow_disable_composer_on_trigger_event":"Disable composer for trigger event", "dialogflow_disable_composer_on_trigger_event_description": "Composer disable while the widget waits for welcome event. True for ES and False for CX." ->>>>>>> master } From d58e7397a85c41b454c45bd34138d1c152d5aecc Mon Sep 17 00:00:00 2001 From: AlexanderKanakis Date: Tue, 14 Jun 2022 18:20:42 +0300 Subject: [PATCH 18/19] fixed lint issues --- lib/Settings.ts | 16 ++++++++-------- types/misc.ts | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/Settings.ts b/lib/Settings.ts index e160896..33a3e8e 100644 --- a/lib/Settings.ts +++ b/lib/Settings.ts @@ -4,16 +4,16 @@ import { Logs } from '../enum/Logs'; import { getPersistentAgentConfigToRoom } from './Persistence'; export const getAppSettingValue = async (read: IRead, id: string) => { - return ( - id && (await read.getEnvironmentReader().getSettings().getValueById(id)) - ); + return ( + id && (await read.getEnvironmentReader().getSettings().getValueById(id)) + ); }; export const getServerSettingValue = async (read: IRead, id: string) => { - return ( - id && - (await read.getEnvironmentReader().getServerSettings().getValueById(id)) - ); + return ( + id && + (await read.getEnvironmentReader().getServerSettings().getValueById(id)) + ); }; export const getLivechatAgentConfig = async (read: IRead, sessionId: string, type?: string) => { @@ -42,7 +42,7 @@ export const getLivechatAgentConfig = async (read: IRead, sessionId: string, typ console.error(Logs.NO_AGENT_IN_CONFIG_WITH_CURRENT_AGENT_NAME, agentName); throw Error(`Agent ${ agentName } not found in Dialogflow Agent Endpoints`); - } catch (e) { + } catch (e: any) { console.error(Logs.AGENT_CONFIG_FORMAT_ERROR); throw new Error(e); } diff --git a/types/misc.ts b/types/misc.ts index ef7a52c..929c114 100644 --- a/types/misc.ts +++ b/types/misc.ts @@ -2,7 +2,7 @@ import { IMessageAttachment } from '@rocket.chat/apps-engine/definition/messages import { IBlock } from '@rocket.chat/apps-engine/definition/uikit'; export interface IMessageParam { - text?: string; - blocks?: IBlock[]; - attachment?: IMessageAttachment; + text?: string; + blocks?: Array; + attachment?: IMessageAttachment; } From 62205851ed73d5aae0f86624e430fb63da49185d Mon Sep 17 00:00:00 2001 From: AlexanderKanakis Date: Tue, 14 Jun 2022 19:03:00 +0300 Subject: [PATCH 19/19] fixed workflow scripts --- .github/workflows/main.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1f40821..6ca4223 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,8 +21,5 @@ jobs: - name: Tslint check run: npm run tslint - - name: Typescript check - run: npm run typecheck - - name: Bundle App run: rc-apps package