Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core: use ActionRequest in all core-bots steps #2873

Draft
wants to merge 1 commit into
base: master-lts
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 45 additions & 66 deletions packages/botonic-core/src/core-bot.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Inspector } from './debug'
import { getString } from './i18n'
import {
ActionRequest,
BotRequest,
BotResponse,
INPUT,
Expand All @@ -9,7 +10,6 @@ import {
ProcessInputResult,
ResolvedPlugins,
Route,
RoutePath,
Routes,
Session,
} from './models'
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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(
Expand All @@ -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<ProcessInputResult> {
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
Expand All @@ -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)
}
}

Expand Down
61 changes: 39 additions & 22 deletions packages/botonic-core/src/models/legacy-types.ts
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -78,23 +79,6 @@ export interface Locales {
[id: string]: string | string[] | Locales
}

interface PluginConstructor<T> {
new (arg: T): Plugin
}

export interface PluginConfig<T> {
id: string
options?: T
resolve: { default: PluginConstructor<T> }
}

export interface ResolvedPlugin extends Plugin {
id: string
name: string
config: any
}
export type ResolvedPlugins = Record<string, ResolvedPlugin>

export type InputType =
| INPUT.AUDIO
| INPUT.BUTTON_MESSAGE
Expand Down Expand Up @@ -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<T> {
new (arg: T): Plugin
}

export interface PluginConfig<T> {
id: string
options?: T
resolve: { default: PluginConstructor<T> }
}

export interface ResolvedPlugin extends Plugin {
id: string
name: string
config: any
}
export type ResolvedPlugins = Record<string, ResolvedPlugin>

export interface Plugin {
post?(request: PluginPostRequest): void | Promise<void>
pre?(request: PluginPreRequest): void | Promise<void>
pre?(request: ActionRequest): void | Promise<void>
post?(request: ActionResponse): void | Promise<void>
}

// export interface PluginPreRequest extends BotRequest {
// plugins: ResolvedPlugins
// }

// export interface PluginPostRequest extends BotResponse {
// plugins: ResolvedPlugins
// }

export interface Params {
[key: string]: any
}
Expand Down
29 changes: 9 additions & 20 deletions packages/botonic-core/src/plugins.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import {
Input,
PluginConfig,
ResolvedPlugins,
RoutePath,
Session,
} from './models'
import { ActionRequest, PluginConfig, ResolvedPlugins } from './models'

type PluginMode = 'pre' | 'post'

Expand All @@ -27,26 +21,21 @@ export function loadPlugins(plugins: PluginConfig<any>[]): ResolvedPlugins {
}

export async function runPlugins(
plugins: ResolvedPlugins,
actionRequest: ActionRequest,
mode: PluginMode,
input: Input,
session: Session,
lastRoutePath: RoutePath,
response: string | null = null
): Promise<void> {
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) {
Expand Down
2 changes: 1 addition & 1 deletion packages/botonic-core/src/routing/router.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { NOT_FOUND_PATH } from '../constants'
import { RouteInspector } from '../debug/inspector'
import {
ActionRequest,
Input,
MatchedValue,
Matcher,
Expand All @@ -19,7 +20,6 @@ import {
getNotFoundAction,
getPathParamsFromPathPayload,
isPathPayload,
pathParamsToParams,
} from './router-utils'

export class Router {
Expand Down
7 changes: 4 additions & 3 deletions packages/botonic-core/tests/routing/router.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
Expand Down Expand Up @@ -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
)
Expand Down Expand Up @@ -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 }) => {
Expand Down
Loading
Loading