From c39ebbf9fd2abbce72bc457fbfb0a7a088020dde Mon Sep 17 00:00:00 2001 From: Oriol Raventos Date: Mon, 15 Jul 2024 09:12:35 +0200 Subject: [PATCH] WIP --- packages/botonic-core/src/core-bot.ts | 111 +++++++----------- .../botonic-core/src/models/legacy-types.ts | 61 ++++++---- packages/botonic-core/src/plugins.ts | 29 ++--- packages/botonic-core/src/routing/router.ts | 2 +- .../botonic-core/tests/routing/router.test.ts | 7 +- packages/botonic-react/src/index-types.ts | 22 ++-- 6 files changed, 110 insertions(+), 122 deletions(-) diff --git a/packages/botonic-core/src/core-bot.ts b/packages/botonic-core/src/core-bot.ts index ea26766f7f..9481cb04e3 100644 --- a/packages/botonic-core/src/core-bot.ts +++ b/packages/botonic-core/src/core-bot.ts @@ -1,6 +1,7 @@ import { Inspector } from './debug' import { getString } from './i18n' import { + ActionRequest, BotRequest, BotResponse, INPUT, @@ -9,7 +10,6 @@ import { ProcessInputResult, ResolvedPlugins, Route, - RoutePath, Routes, Session, } from './models' @@ -30,12 +30,12 @@ export interface CoreBotConfig { } export class CoreBot { appId?: string - defaultDelay?: number + defaultDelay: number defaultRoutes: Route[] - defaultTyping?: number + defaultTyping: number inspector: Inspector locales: Locales - plugins?: ResolvedPlugins + plugins: ResolvedPlugins renderer: any rootElement: any router: Router | null @@ -57,9 +57,8 @@ export class CoreBot { this.renderer = renderer this.plugins = loadPlugins(plugins) this.theme = theme || {} - this.defaultTyping = - typeof defaultTyping !== 'undefined' ? defaultTyping : 0.6 - this.defaultDelay = typeof defaultDelay !== 'undefined' ? defaultDelay : 0.4 + this.defaultTyping = defaultTyping ?? 0.6 + this.defaultDelay = defaultDelay ?? 0.4 this.locales = locales this.appId = appId || undefined this.rootElement = null @@ -118,9 +117,19 @@ export class CoreBot { } } - await this.runPrePlugins(input, session, lastRoutePath) + const actionRequest: ActionRequest = { + defaultDelay: this.defaultDelay, + defaultTyping: this.defaultTyping, + input, + lastRoutePath, + params: {}, + plugins: this.plugins, + session, + } + + await this.runPrePlugins(actionRequest) - const output = await this.getOutput(input, session, lastRoutePath) + const output = await this.getOutput(actionRequest) const response = await this.renderer({ request: this.createRequestFromOutput( @@ -130,65 +139,44 @@ export class CoreBot { actions: [output.fallbackAction, output.action, output.emptyAction], }) - lastRoutePath = output.lastRoutePath + actionRequest.lastRoutePath = output.lastRoutePath - await this.runPostPlugins(input, session, lastRoutePath, response) + await this.runPostPlugins(actionRequest, response) session.is_first_interaction = false return { - input, + input: actionRequest.input, + session: actionRequest.session, + lastRoutePath: actionRequest.lastRoutePath, response, - session, - lastRoutePath, } } - private async runPrePlugins( - input: Input, - session: Session, - lastRoutePath: RoutePath - ) { + private async runPrePlugins(actionRequest: ActionRequest) { if (this.plugins) { - await runPlugins( - this.plugins, - 'pre', - input, - session, - lastRoutePath, - undefined - ) + await runPlugins(actionRequest, 'pre', undefined) } } private async getOutput( - input: Input, - session: Session, - lastRoutePath: RoutePath + actionRequest: ActionRequest ): Promise { - await this.setRouter(input, session, lastRoutePath) + await this.setRouter(actionRequest) const output = (this.router as Router).processInput( - input, - session, - lastRoutePath + actionRequest.input, + actionRequest.session, + actionRequest.lastRoutePath ) return output } - private async setRouter( - input: Input, - session: Session, - lastRoutePath: RoutePath - ) { + private async setRouter(actionRequest: ActionRequest) { if (this.routes instanceof Function) { this.router = new Router( [ - ...(await getComputedRoutes(this.routes, { - input, - session, - lastRoutePath, - })), + ...(await getComputedRoutes(this.routes, actionRequest)), ...this.defaultRoutes, ], this.inspector.routeInspector @@ -199,35 +187,26 @@ export class CoreBot { private createRequestFromOutput( { input, session, lastRoutePath }: BotRequest, output: ProcessInputResult - ) { + ): ActionRequest & { + getString: (stringId: string) => string + setLocale: (locale: string) => void + } { return { - getString: stringId => this.getString(stringId, session), - setLocale: locale => this.setLocale(locale, session), - session: session || {}, - params: output.params || {}, - input, - plugins: this.plugins, - defaultTyping: this.defaultTyping, + getString: (stringId: string) => this.getString(stringId, session), + setLocale: (locale: string) => this.setLocale(locale, session), defaultDelay: this.defaultDelay, + defaultTyping: this.defaultTyping, + input, lastRoutePath, + params: output.params || {}, + plugins: this.plugins || {}, + session: session || {}, } } - private async runPostPlugins( - input: Input, - session: Session, - lastRoutePath: RoutePath, - response: any - ) { + private async runPostPlugins(actionRequest: ActionRequest, response: any) { if (this.plugins) { - await runPlugins( - this.plugins, - 'post', - input, - session, - lastRoutePath, - response - ) + await runPlugins(actionRequest, 'post', response) } } diff --git a/packages/botonic-core/src/models/legacy-types.ts b/packages/botonic-core/src/models/legacy-types.ts index e108ce1e9c..0c8052ec46 100644 --- a/packages/botonic-core/src/models/legacy-types.ts +++ b/packages/botonic-core/src/models/legacy-types.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/naming-convention */ // TODO: This file contains all the legacy types we had in index.ts. After some refactors, we should be able to get rid of many of them. export enum CASE_STATUS { @@ -78,23 +79,6 @@ export interface Locales { [id: string]: string | string[] | Locales } -interface PluginConstructor { - new (arg: T): Plugin -} - -export interface PluginConfig { - id: string - options?: T - resolve: { default: PluginConstructor } -} - -export interface ResolvedPlugin extends Plugin { - id: string - name: string - config: any -} -export type ResolvedPlugins = Record - export type InputType = | INPUT.AUDIO | INPUT.BUTTON_MESSAGE @@ -258,18 +242,51 @@ export interface BotResponse extends BotRequest { response: any } -export interface PluginPreRequest extends BotRequest { +export interface ActionRequest { + defaultDelay: number + defaultTyping: number + input: Input + lastRoutePath: string | null + params: { [key: string]: string } plugins: ResolvedPlugins + session: Session } -export interface PluginPostRequest extends BotResponse { - plugins: ResolvedPlugins + +// Aquest tipus s'hauria de fer servir en el post dels plugins ja que a de tenir la response i els plugins +export interface ActionResponse extends ActionRequest { + response: any +} + +interface PluginConstructor { + new (arg: T): Plugin +} + +export interface PluginConfig { + id: string + options?: T + resolve: { default: PluginConstructor } +} + +export interface ResolvedPlugin extends Plugin { + id: string + name: string + config: any } +export type ResolvedPlugins = Record export interface Plugin { - post?(request: PluginPostRequest): void | Promise - pre?(request: PluginPreRequest): void | Promise + pre?(request: ActionRequest): void | Promise + post?(request: ActionResponse): void | Promise } +// export interface PluginPreRequest extends BotRequest { +// plugins: ResolvedPlugins +// } + +// export interface PluginPostRequest extends BotResponse { +// plugins: ResolvedPlugins +// } + export interface Params { [key: string]: any } diff --git a/packages/botonic-core/src/plugins.ts b/packages/botonic-core/src/plugins.ts index 341ffe837b..9d623aeac6 100644 --- a/packages/botonic-core/src/plugins.ts +++ b/packages/botonic-core/src/plugins.ts @@ -1,10 +1,4 @@ -import { - Input, - PluginConfig, - ResolvedPlugins, - RoutePath, - Session, -} from './models' +import { ActionRequest, PluginConfig, ResolvedPlugins } from './models' type PluginMode = 'pre' | 'post' @@ -27,26 +21,21 @@ export function loadPlugins(plugins: PluginConfig[]): ResolvedPlugins { } export async function runPlugins( - plugins: ResolvedPlugins, + actionRequest: ActionRequest, mode: PluginMode, - input: Input, - session: Session, - lastRoutePath: RoutePath, response: string | null = null ): Promise { + const { plugins } = actionRequest for (const key in plugins) { - const p = await plugins[key] + const plugin = plugins[key] try { - if (mode === 'pre' && p.pre) { - await p.pre({ input, session, lastRoutePath, plugins }) + if (mode === 'pre' && plugin.pre) { + await plugin.pre(actionRequest) } - if (mode === 'post' && p.post) { - await p.post({ - input, - session, - lastRoutePath, + if (mode === 'post' && plugin.post) { + await plugin.post({ + ...actionRequest, response, - plugins, }) } } catch (e) { diff --git a/packages/botonic-core/src/routing/router.ts b/packages/botonic-core/src/routing/router.ts index 14f9633a50..0e47fbaebc 100644 --- a/packages/botonic-core/src/routing/router.ts +++ b/packages/botonic-core/src/routing/router.ts @@ -1,6 +1,7 @@ import { NOT_FOUND_PATH } from '../constants' import { RouteInspector } from '../debug/inspector' import { + ActionRequest, Input, MatchedValue, Matcher, @@ -19,7 +20,6 @@ import { getNotFoundAction, getPathParamsFromPathPayload, isPathPayload, - pathParamsToParams, } from './router-utils' export class Router { diff --git a/packages/botonic-core/tests/routing/router.test.ts b/packages/botonic-core/tests/routing/router.test.ts index 5551b11981..59aee36544 100644 --- a/packages/botonic-core/tests/routing/router.test.ts +++ b/packages/botonic-core/tests/routing/router.test.ts @@ -87,11 +87,12 @@ const routes = [...defaultRoutes, ...fallbackRoutes, notFoundRoute] describe('TEST: Root Level Accesses (lastRoutePath is null)', () => { const router = new Router(routes) + // que es normal input? hi ha diferents inputs amb intent, payload, text describe('normal input', () => { it('1. should retrieve routes at root level (initial path)', () => { expect( router.processInput( - { type: 'text', text: 'hi', intent: 'greeting' }, + { type: 'text', text: 'hi', intent: 'greeting' }, // Com funciona el match del intent? si trec el intent falla, si poso ggreting funciona testSession(), null ) @@ -176,7 +177,7 @@ describe('TEST: Root Level Accesses (lastRoutePath is null)', () => { it('3. should retrieve routes at root level (404 path payload)', () => { expect( router.processInput( - { type: 'postback', payload: createPathPayload('404') }, + { type: 'postback', payload: createPathPayload('404') }, // qualsevol payload que no existeixi fa que el test passi en verd testSession(), null ) @@ -1257,7 +1258,7 @@ describe('TEST: Converting Functional Routes to Routes', () => { expect(computedRoutes).toEqual(routes) }) }) -// eslint-disable-next-line jest/valid-describe + describe('TEST: Functional Router process input', () => { it('Resolves correctly the dynamic routes and incoming input', async () => { const routes = async ({ input, session }) => { diff --git a/packages/botonic-react/src/index-types.ts b/packages/botonic-react/src/index-types.ts index 139ffa3a30..5f77c9890b 100644 --- a/packages/botonic-react/src/index-types.ts +++ b/packages/botonic-react/src/index-types.ts @@ -1,4 +1,5 @@ import { + ActionRequest, BotRequest as CoreBotRequest, Input as CoreInput, InputType as CoreInputType, @@ -36,19 +37,20 @@ export interface Route extends CoreRoute { export type Routes = CoreRoutes // Parameters of the actions' botonicInit method -export interface ActionRequest { - defaultDelay: number - defaultTyping: number - input: CoreInput - lastRoutePath: string - params: { [key: string]: string } - plugins: { [id: string]: CorePlugin } - session: CoreSession -} +// export interface ActionRequest { +// defaultDelay: number +// defaultTyping: number +// input: CoreInput +// lastRoutePath: string +// params: { [key: string]: string } +// plugins: { [id: string]: CorePlugin } +// session: CoreSession +// } +export { ActionRequest } from '@botonic/core' export interface RequestContextInterface extends ActionRequest { getString: (stringId: string) => string - setLocale: (locale: string) => string + setLocale: (locale: string) => void } export interface CustomMessageType {