@botonic/core 0.56.0-alpha.0 → 0.57.0-rslib-esm.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/esm/constants.js +7 -7
- package/lib/esm/constants.js.map +1 -1
- package/lib/esm/core-bot.d.ts +3 -3
- package/lib/esm/core-bot.js +87 -50
- package/lib/esm/core-bot.js.map +1 -1
- package/lib/esm/debug/index.d.ts +1 -1
- package/lib/esm/debug/index.js +5 -4
- package/lib/esm/debug/index.js.map +1 -1
- package/lib/esm/debug/inspector.d.ts +1 -1
- package/lib/esm/debug/inspector.js +27 -21
- package/lib/esm/debug/inspector.js.map +1 -1
- package/lib/esm/handoff.d.ts +1 -1
- package/lib/esm/handoff.js +82 -53
- package/lib/esm/handoff.js.map +1 -1
- package/lib/esm/hubtype-service.d.ts +3 -3
- package/lib/esm/hubtype-service.js +100 -64
- package/lib/esm/hubtype-service.js.map +1 -1
- package/lib/esm/index.d.ts +9 -9
- package/lib/esm/index.js +21 -12
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/models/ai-agents.d.ts +1 -8
- package/lib/esm/models/ai-agents.js +15 -16
- package/lib/esm/models/ai-agents.js.map +1 -1
- package/lib/esm/models/bot-config.js +6 -6
- package/lib/esm/models/bot-config.js.map +1 -1
- package/lib/esm/models/hubtype-analytics.d.ts +1 -1
- package/lib/esm/models/hubtype-analytics.js +10 -10
- package/lib/esm/models/hubtype-analytics.js.map +1 -1
- package/lib/esm/models/index.d.ts +4 -4
- package/lib/esm/models/index.js +11 -7
- package/lib/esm/models/index.js.map +1 -1
- package/lib/esm/models/legacy-types.js +24 -24
- package/lib/esm/models/legacy-types.js.map +1 -1
- package/lib/esm/package.json +3 -0
- package/lib/esm/plugins.d.ts +1 -1
- package/lib/esm/plugins.js +7 -8
- package/lib/esm/plugins.js.map +1 -1
- package/lib/esm/pusher-utils.js +15 -10
- package/lib/esm/pusher-utils.js.map +1 -1
- package/lib/esm/routing/index.d.ts +2 -2
- package/lib/esm/routing/index.js +7 -5
- package/lib/esm/routing/index.js.map +1 -1
- package/lib/esm/routing/router-utils.d.ts +1 -1
- package/lib/esm/routing/router-utils.js +37 -30
- package/lib/esm/routing/router-utils.js.map +1 -1
- package/lib/esm/routing/router.d.ts +2 -2
- package/lib/esm/routing/router.js +152 -149
- package/lib/esm/routing/router.js.map +1 -1
- package/lib/esm/testing/index.d.ts +1 -1
- package/lib/esm/testing/index.js +60 -94
- package/lib/esm/testing/index.js.map +1 -1
- package/lib/esm/utils/bot-config.d.ts +1 -1
- package/lib/esm/utils/bot-config.js +57 -28
- package/lib/esm/utils/bot-config.js.map +1 -1
- package/lib/esm/utils/check-providers.d.ts +1 -1
- package/lib/esm/utils/check-providers.js +14 -17
- package/lib/esm/utils/check-providers.js.map +1 -1
- package/lib/esm/utils/functional.js +19 -38
- package/lib/esm/utils/functional.js.map +1 -1
- package/lib/esm/utils/index.d.ts +3 -3
- package/lib/esm/utils/index.js +9 -6
- package/lib/esm/utils/index.js.map +1 -1
- package/package.json +12 -11
- package/src/hubtype-service.ts +4 -2
- package/src/models/ai-agents.ts +0 -9
- package/lib/cjs/constants.d.ts +0 -4
- package/lib/cjs/constants.js +0 -8
- package/lib/cjs/constants.js.map +0 -1
- package/lib/cjs/core-bot.d.ts +0 -43
- package/lib/cjs/core-bot.js +0 -205
- package/lib/cjs/core-bot.js.map +0 -1
- package/lib/cjs/debug/index.d.ts +0 -1
- package/lib/cjs/debug/index.js +0 -5
- package/lib/cjs/debug/index.js.map +0 -1
- package/lib/cjs/debug/inspector.d.ts +0 -24
- package/lib/cjs/debug/inspector.js +0 -70
- package/lib/cjs/debug/inspector.js.map +0 -1
- package/lib/cjs/handoff.d.ts +0 -110
- package/lib/cjs/handoff.js +0 -238
- package/lib/cjs/handoff.js.map +0 -1
- package/lib/cjs/hubtype-service.d.ts +0 -58
- package/lib/cjs/hubtype-service.js +0 -205
- package/lib/cjs/hubtype-service.js.map +0 -1
- package/lib/cjs/index.d.ts +0 -9
- package/lib/cjs/index.js +0 -13
- package/lib/cjs/index.js.map +0 -1
- package/lib/cjs/models/ai-agents.d.ts +0 -147
- package/lib/cjs/models/ai-agents.js +0 -31
- package/lib/cjs/models/ai-agents.js.map +0 -1
- package/lib/cjs/models/bot-config.d.ts +0 -24
- package/lib/cjs/models/bot-config.js +0 -10
- package/lib/cjs/models/bot-config.js.map +0 -1
- package/lib/cjs/models/hubtype-analytics.d.ts +0 -210
- package/lib/cjs/models/hubtype-analytics.js +0 -38
- package/lib/cjs/models/hubtype-analytics.js.map +0 -1
- package/lib/cjs/models/index.d.ts +0 -4
- package/lib/cjs/models/index.js +0 -8
- package/lib/cjs/models/index.js.map +0 -1
- package/lib/cjs/models/legacy-types.d.ts +0 -332
- package/lib/cjs/models/legacy-types.js +0 -84
- package/lib/cjs/models/legacy-types.js.map +0 -1
- package/lib/cjs/plugins.d.ts +0 -9
- package/lib/cjs/plugins.js +0 -24
- package/lib/cjs/plugins.js.map +0 -1
- package/lib/cjs/pusher-utils.d.ts +0 -7
- package/lib/cjs/pusher-utils.js +0 -18
- package/lib/cjs/pusher-utils.js.map +0 -1
- package/lib/cjs/routing/index.d.ts +0 -2
- package/lib/cjs/routing/index.js +0 -6
- package/lib/cjs/routing/index.js.map +0 -1
- package/lib/cjs/routing/router-utils.d.ts +0 -11
- package/lib/cjs/routing/router-utils.js +0 -96
- package/lib/cjs/routing/router-utils.js.map +0 -1
- package/lib/cjs/routing/router.d.ts +0 -54
- package/lib/cjs/routing/router.js +0 -330
- package/lib/cjs/routing/router.js.map +0 -1
- package/lib/cjs/testing/index.d.ts +0 -91
- package/lib/cjs/testing/index.js +0 -196
- package/lib/cjs/testing/index.js.map +0 -1
- package/lib/cjs/utils/bot-config.d.ts +0 -4
- package/lib/cjs/utils/bot-config.js +0 -94
- package/lib/cjs/utils/bot-config.js.map +0 -1
- package/lib/cjs/utils/check-providers.d.ts +0 -8
- package/lib/cjs/utils/check-providers.js +0 -34
- package/lib/cjs/utils/check-providers.js.map +0 -1
- package/lib/cjs/utils/functional.d.ts +0 -10
- package/lib/cjs/utils/functional.js +0 -88
- package/lib/cjs/utils/functional.js.map +0 -1
- package/lib/cjs/utils/index.d.ts +0 -3
- package/lib/cjs/utils/index.js +0 -7
- package/lib/cjs/utils/index.js.map +0 -1
|
@@ -1,47 +1,53 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import { EMPTY_ACTION_PATH, NOT_FOUND_PATH, PATH_PAYLOAD_IDENTIFIER, PATH_PAYLOAD_REGEXP } from "../constants.js";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
function _define_property(obj, key, value) {
|
|
5
|
+
if (key in obj) {
|
|
6
|
+
Object.defineProperty(obj, key, {
|
|
7
|
+
value: value,
|
|
8
|
+
enumerable: true,
|
|
9
|
+
configurable: true,
|
|
10
|
+
writable: true
|
|
11
|
+
});
|
|
12
|
+
} else obj[key] = value;
|
|
13
|
+
return obj;
|
|
14
|
+
}
|
|
15
|
+
|
|
11
16
|
class NoMatchingRouteError extends Error {
|
|
12
|
-
constructor(input)
|
|
13
|
-
super(`No route found for input '${JSON.stringify(input)}' and no ${
|
|
17
|
+
constructor(input){
|
|
18
|
+
super(`No route found for input '${JSON.stringify(input)}' and no ${NOT_FOUND_PATH} route defined`), _define_property(this, "input", void 0);
|
|
14
19
|
this.input = input;
|
|
15
20
|
}
|
|
16
21
|
}
|
|
17
|
-
|
|
18
|
-
function isPathPayload(payload) {
|
|
22
|
+
function router_utils_isPathPayload(payload) {
|
|
19
23
|
if (!payload) {
|
|
20
24
|
return false;
|
|
21
25
|
}
|
|
22
|
-
const isPathPayload =
|
|
26
|
+
const isPathPayload = PATH_PAYLOAD_REGEXP.exec(payload);
|
|
23
27
|
return Boolean(isPathPayload);
|
|
24
28
|
}
|
|
25
29
|
function getPathParamsFromPathPayload(payload) {
|
|
26
30
|
const defaultPathParams = {
|
|
27
31
|
path: null,
|
|
28
|
-
params: {}
|
|
32
|
+
params: {}
|
|
29
33
|
};
|
|
30
34
|
if (!payload) {
|
|
31
35
|
return defaultPathParams;
|
|
32
36
|
}
|
|
33
|
-
if (!
|
|
37
|
+
if (!router_utils_isPathPayload(payload)) {
|
|
34
38
|
return defaultPathParams;
|
|
35
39
|
}
|
|
36
40
|
try {
|
|
37
|
-
const pathWithParams = payload.split(
|
|
41
|
+
const pathWithParams = payload.split(PATH_PAYLOAD_IDENTIFIER)[1];
|
|
38
42
|
if (!pathWithParams) {
|
|
39
|
-
throw `${
|
|
43
|
+
throw `${PATH_PAYLOAD_IDENTIFIER} is empty`;
|
|
40
44
|
}
|
|
41
45
|
const [path, params] = pathWithParams.split('?');
|
|
42
|
-
return {
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
return {
|
|
47
|
+
path: path ?? null,
|
|
48
|
+
params: pathParamsToParams(params)
|
|
49
|
+
};
|
|
50
|
+
} catch (e) {
|
|
45
51
|
console.error('Error getting path and params from input.payload:', e);
|
|
46
52
|
return defaultPathParams;
|
|
47
53
|
}
|
|
@@ -53,12 +59,11 @@ function pathParamsToParams(pathParams) {
|
|
|
53
59
|
try {
|
|
54
60
|
const params = {};
|
|
55
61
|
const searchParams = new URLSearchParams(pathParams);
|
|
56
|
-
for (const [key, value] of searchParams)
|
|
62
|
+
for (const [key, value] of searchParams){
|
|
57
63
|
params[key] = value;
|
|
58
64
|
}
|
|
59
65
|
return params;
|
|
60
|
-
}
|
|
61
|
-
catch (_e) {
|
|
66
|
+
} catch (_e) {
|
|
62
67
|
return {};
|
|
63
68
|
}
|
|
64
69
|
}
|
|
@@ -66,14 +71,14 @@ function getEmptyAction(childRoutes) {
|
|
|
66
71
|
if (!childRoutes) {
|
|
67
72
|
return null;
|
|
68
73
|
}
|
|
69
|
-
const emptyActionRoute = childRoutes.find(r
|
|
74
|
+
const emptyActionRoute = childRoutes.find((r)=>r.path === EMPTY_ACTION_PATH);
|
|
70
75
|
if (!emptyActionRoute) {
|
|
71
76
|
return null;
|
|
72
77
|
}
|
|
73
78
|
return emptyActionRoute.action;
|
|
74
79
|
}
|
|
75
80
|
function getNotFoundAction(input, routes) {
|
|
76
|
-
const notFoundActionRoute = routes.find(r
|
|
81
|
+
const notFoundActionRoute = routes.find((r)=>r.path === NOT_FOUND_PATH);
|
|
77
82
|
if (!notFoundActionRoute) {
|
|
78
83
|
throw new NoMatchingRouteError(input);
|
|
79
84
|
}
|
|
@@ -83,14 +88,16 @@ async function getComputedRoutes(routes, botContext) {
|
|
|
83
88
|
if (routes instanceof Function) {
|
|
84
89
|
return await getComputedRoutes(await routes(botContext), botContext);
|
|
85
90
|
}
|
|
86
|
-
for (const [key, route] of Object.entries(routes))
|
|
91
|
+
for (const [key, route] of Object.entries(routes)){
|
|
87
92
|
if (route.childRoutes && route.childRoutes instanceof Function) {
|
|
88
93
|
routes[key].childRoutes = await getComputedRoutes(await route.childRoutes(botContext), botContext);
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
94
|
+
} else {
|
|
91
95
|
routes[key] = route;
|
|
92
96
|
}
|
|
93
97
|
}
|
|
94
98
|
return routes;
|
|
95
99
|
}
|
|
100
|
+
|
|
101
|
+
export { NoMatchingRouteError, getComputedRoutes, getEmptyAction, getNotFoundAction, getPathParamsFromPathPayload, pathParamsToParams, router_utils_isPathPayload as isPathPayload };
|
|
102
|
+
|
|
96
103
|
//# sourceMappingURL=router-utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router-utils.js","
|
|
1
|
+
{"version":3,"file":"routing/router-utils.js","sources":["../../../src/routing/router-utils.ts"],"sourcesContent":["import {\n EMPTY_ACTION_PATH,\n NOT_FOUND_PATH,\n PATH_PAYLOAD_IDENTIFIER,\n PATH_PAYLOAD_REGEXP,\n} from '../constants'\nimport type {\n Action,\n BotContext,\n Input,\n Params,\n PathParams,\n Route,\n Routes,\n} from '../models'\n\nexport class NoMatchingRouteError extends Error {\n input: Input\n constructor(input: Input) {\n super(\n `No route found for input '${JSON.stringify(\n input\n )}' and no ${NOT_FOUND_PATH} route defined`\n )\n this.input = input\n }\n}\n\nexport function isPathPayload(payload?: string): boolean {\n if (!payload) {\n return false\n }\n const isPathPayload = PATH_PAYLOAD_REGEXP.exec(payload)\n return Boolean(isPathPayload)\n}\n\nexport function getPathParamsFromPathPayload(payload?: string): PathParams {\n const defaultPathParams = {\n path: null,\n params: {},\n }\n if (!payload) {\n return defaultPathParams\n }\n if (!isPathPayload(payload)) {\n return defaultPathParams\n }\n try {\n const pathWithParams = payload.split(PATH_PAYLOAD_IDENTIFIER)[1]\n if (!pathWithParams) {\n throw `${PATH_PAYLOAD_IDENTIFIER} is empty`\n }\n const [path, params] = pathWithParams.split('?')\n return { path: path ?? null, params: pathParamsToParams(params) }\n } catch (e) {\n console.error('Error getting path and params from input.payload:', e)\n return defaultPathParams\n }\n}\n\nexport function pathParamsToParams(pathParams?: string): Params {\n if (!pathParams) {\n return {}\n }\n try {\n const params = {}\n const searchParams = new URLSearchParams(pathParams)\n for (const [key, value] of searchParams) {\n params[key] = value\n }\n return params\n } catch (_e) {\n return {}\n }\n}\n\nexport function getEmptyAction(childRoutes?: Route[]): Action {\n if (!childRoutes) {\n return null\n }\n const emptyActionRoute = childRoutes.find(r => r.path === EMPTY_ACTION_PATH)\n if (!emptyActionRoute) {\n return null\n }\n return emptyActionRoute.action\n}\n\nexport function getNotFoundAction(input: Input, routes: Route[]): Action {\n const notFoundActionRoute = routes.find(r => r.path === NOT_FOUND_PATH)\n if (!notFoundActionRoute) {\n throw new NoMatchingRouteError(input)\n }\n return notFoundActionRoute.action\n}\n\nexport async function getComputedRoutes(\n routes: Routes,\n botContext: BotContext\n): Promise<Route[]> {\n if (routes instanceof Function) {\n return await getComputedRoutes(await routes(botContext), botContext)\n }\n for (const [key, route] of Object.entries(routes) as any) {\n if (route.childRoutes && route.childRoutes instanceof Function) {\n routes[key].childRoutes = await getComputedRoutes(\n await route.childRoutes(botContext),\n botContext\n )\n } else {\n routes[key] = route\n }\n }\n return routes\n}\n"],"names":["EMPTY_ACTION_PATH","NOT_FOUND_PATH","PATH_PAYLOAD_IDENTIFIER","PATH_PAYLOAD_REGEXP","NoMatchingRouteError","Error","input","JSON","isPathPayload","payload","Boolean","getPathParamsFromPathPayload","defaultPathParams","pathWithParams","path","params","pathParamsToParams","e","console","pathParams","searchParams","URLSearchParams","key","value","_e","getEmptyAction","childRoutes","emptyActionRoute","r","getNotFoundAction","routes","notFoundActionRoute","getComputedRoutes","botContext","Function","route","Object"],"mappings":";;;;;;;;;;;;;;AAKqB;AAWd,MAAMI,oBAAoBA,SAASC;IAExC,YAAYC,KAAY,CAAE;QACxB,KAAK,CACH,CAAC,0BAA0B,EAAEC,KAAK,SAAS,CACzCD,OACA,SAAS,EAAEL,cAAcA,CAAC,cAAc,CAAC,GAL/C;QAOE,IAAI,CAAC,KAAK,GAAGK;IACf;AACF;AAEO,SAASE,0BAAaA,CAACC,OAAgB;IAC5C,IAAI,CAACA,SAAS;QACZ,OAAO;IACT;IACA,MAAMD,gBAAgBL,wBAAwB,CAACM;IAC/C,OAAOC,QAAQF;AACjB;AAEO,SAASG,4BAA4BA,CAACF,OAAgB;IAC3D,MAAMG,oBAAoB;QACxB,MAAM;QACN,QAAQ,CAAC;IACX;IACA,IAAI,CAACH,SAAS;QACZ,OAAOG;IACT;IACA,IAAI,CAACJ,0BAAaA,CAACC,UAAU;QAC3B,OAAOG;IACT;IACA,IAAI;QACF,MAAMC,iBAAiBJ,QAAQ,KAAK,CAACP,uBAAuBA,CAAC,CAAC,EAAE;QAChE,IAAI,CAACW,gBAAgB;YACnB,MAAM,GAAGX,uBAAuBA,CAAC,SAAS,CAAC;QAC7C;QACA,MAAM,CAACY,MAAMC,OAAO,GAAGF,eAAe,KAAK,CAAC;QAC5C,OAAO;YAAE,MAAMC,QAAQ;YAAM,QAAQE,kBAAkBA,CAACD;QAAQ;IAClE,EAAE,OAAOE,GAAG;QACVC,QAAQ,KAAK,CAAC,qDAAqDD;QACnE,OAAOL;IACT;AACF;AAEO,SAASI,kBAAkBA,CAACG,UAAmB;IACpD,IAAI,CAACA,YAAY;QACf,OAAO,CAAC;IACV;IACA,IAAI;QACF,MAAMJ,SAAS,CAAC;QAChB,MAAMK,eAAe,IAAIC,gBAAgBF;QACzC,KAAK,MAAM,CAACG,KAAKC,MAAM,IAAIH,aAAc;YACvCL,MAAM,CAACO,IAAI,GAAGC;QAChB;QACA,OAAOR;IACT,EAAE,OAAOS,IAAI;QACX,OAAO,CAAC;IACV;AACF;AAEO,SAASC,cAAcA,CAACC,WAAqB;IAClD,IAAI,CAACA,aAAa;QAChB,OAAO;IACT;IACA,MAAMC,mBAAmBD,YAAY,IAAI,CAACE,CAAAA,IAAKA,EAAE,IAAI,KAAK5B,iBAAiBA;IAC3E,IAAI,CAAC2B,kBAAkB;QACrB,OAAO;IACT;IACA,OAAOA,iBAAiB,MAAM;AAChC;AAEO,SAASE,iBAAiBA,CAACvB,KAAY,EAAEwB,MAAe;IAC7D,MAAMC,sBAAsBD,OAAO,IAAI,CAACF,CAAAA,IAAKA,EAAE,IAAI,KAAK3B,cAAcA;IACtE,IAAI,CAAC8B,qBAAqB;QACxB,MAAM,IAAI3B,oBAAoBA,CAACE;IACjC;IACA,OAAOyB,oBAAoB,MAAM;AACnC;AAEO,eAAeC,iBAAiBA,CACrCF,MAAc,EACdG,UAAsB;IAEtB,IAAIH,kBAAkBI,UAAU;QAC9B,OAAO,MAAMF,iBAAiBA,CAAC,MAAMF,OAAOG,aAAaA;IAC3D;IACA,KAAK,MAAM,CAACX,KAAKa,MAAM,IAAIC,OAAO,OAAO,CAACN,QAAgB;QACxD,IAAIK,MAAM,WAAW,IAAIA,MAAM,WAAW,YAAYD,UAAU;YAC9DJ,MAAM,CAACR,IAAI,CAAC,WAAW,GAAG,MAAMU,iBAAiBA,CAC/C,MAAMG,MAAM,WAAW,CAACF,aACxBA;QAEJ,OAAO;YACLH,MAAM,CAACR,IAAI,GAAGa;QAChB;IACF;IACA,OAAOL;AACT"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { RouteInspector } from '../debug/inspector';
|
|
2
|
-
import type { Input, MatchedValue, Matcher, MatchingProp, Nullable, ProcessInputResult, Route, RouteParams, RoutePath, RoutingState, Session } from '../models';
|
|
1
|
+
import { RouteInspector } from '../debug/inspector.js';
|
|
2
|
+
import type { Input, MatchedValue, Matcher, MatchingProp, Nullable, ProcessInputResult, Route, RouteParams, RoutePath, RoutingState, Session } from '../models/index.js';
|
|
3
3
|
export declare class Router {
|
|
4
4
|
routes: Route[];
|
|
5
5
|
routeInspector: RouteInspector;
|
|
@@ -1,26 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import { NOT_FOUND_PATH } from "../constants.js";
|
|
2
|
+
import { RouteInspector } from "../debug/inspector.js";
|
|
3
|
+
import { cloneObject } from "../utils/index.js";
|
|
4
|
+
import { getEmptyAction, getNotFoundAction, getPathParamsFromPathPayload, isPathPayload } from "./router-utils.js";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
function _define_property(obj, key, value) {
|
|
11
|
+
if (key in obj) {
|
|
12
|
+
Object.defineProperty(obj, key, {
|
|
13
|
+
value: value,
|
|
14
|
+
enumerable: true,
|
|
15
|
+
configurable: true,
|
|
16
|
+
writable: true
|
|
17
|
+
});
|
|
18
|
+
} else obj[key] = value;
|
|
19
|
+
return obj;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
8
25
|
class Router {
|
|
9
|
-
constructor(routes, routeInspector = undefined) {
|
|
10
|
-
this.routes = routes;
|
|
11
|
-
this.routeInspector = routeInspector || new inspector_1.RouteInspector();
|
|
12
|
-
}
|
|
13
26
|
/**
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
// eslint-disable-next-line complexity
|
|
27
|
+
* Processes an input and return a representation of the new bot state.
|
|
28
|
+
* The algorithm is splitted in two main parts:
|
|
29
|
+
* 1. Getting the current routing state.
|
|
30
|
+
* 2. Given a routing state, resolve the different possible scenarios and return the new bot state.
|
|
31
|
+
* The new bot state can return three type of actions:
|
|
32
|
+
* - action: an action directly resolved from a matching route
|
|
33
|
+
* - emptyAction: optional action that can exists or not only within childRoutes
|
|
34
|
+
* - fallbackAction: any other action that acts as a fallback (404, )
|
|
35
|
+
*/ // eslint-disable-next-line complexity
|
|
24
36
|
processInput(input, session, lastRoutePath = null) {
|
|
25
37
|
session.__retries = session?.__retries ?? 0;
|
|
26
38
|
// 1. Getting the current routing state.
|
|
@@ -29,136 +41,127 @@ class Router {
|
|
|
29
41
|
const matchedRoutePath = matchedRoute?.path ?? null;
|
|
30
42
|
// 2. Given a routing state, resolve the different possible scenarios and return the new bot state.
|
|
31
43
|
/**
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (matchedRoute?.redirect) {
|
|
44
|
+
* Redirect Scenario:
|
|
45
|
+
* We have matched a redirect route with a given redirection path, so we try to obtain the redirectionRoute with getRouteByPath.
|
|
46
|
+
* Independently of whether the redirectionRoute is found or not, the intent is to trigger a redirection which by definition breaks the flow, so retries are set to 0.
|
|
47
|
+
* It has preference over ignoring retries.
|
|
48
|
+
*/ if (matchedRoute?.redirect) {
|
|
38
49
|
session.__retries = 0;
|
|
39
50
|
const redirectionRoute = this.getRouteByPath(matchedRoute.redirect);
|
|
40
51
|
if (redirectionRoute) {
|
|
41
52
|
return {
|
|
42
53
|
action: redirectionRoute.action,
|
|
43
|
-
emptyAction:
|
|
54
|
+
emptyAction: getEmptyAction(redirectionRoute.childRoutes),
|
|
44
55
|
fallbackAction: null,
|
|
45
56
|
lastRoutePath: matchedRoute.redirect,
|
|
46
|
-
params
|
|
57
|
+
params
|
|
47
58
|
};
|
|
48
59
|
}
|
|
49
60
|
return {
|
|
50
61
|
action: null,
|
|
51
62
|
emptyAction: null,
|
|
52
|
-
fallbackAction:
|
|
63
|
+
fallbackAction: getNotFoundAction(input, this.routes),
|
|
53
64
|
lastRoutePath: null,
|
|
54
|
-
params
|
|
65
|
+
params
|
|
55
66
|
};
|
|
56
67
|
}
|
|
57
68
|
/**
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (matchedRoute?.ignoreRetry) {
|
|
69
|
+
* Ignore Retry Scenario:
|
|
70
|
+
* We have matched a route with an ignore retry, so we return directly the new bot state. The intent is to break the flow, so retries are set to 0.
|
|
71
|
+
*/ if (matchedRoute?.ignoreRetry) {
|
|
62
72
|
session.__retries = 0;
|
|
63
73
|
return {
|
|
64
74
|
action: matchedRoute.action,
|
|
65
|
-
emptyAction:
|
|
75
|
+
emptyAction: getEmptyAction(matchedRoute.childRoutes),
|
|
66
76
|
fallbackAction: null,
|
|
67
77
|
lastRoutePath: matchedRoutePath,
|
|
68
|
-
params
|
|
78
|
+
params
|
|
69
79
|
};
|
|
70
80
|
}
|
|
71
81
|
/**
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (isFlowBroken &&
|
|
77
|
-
currentRoute &&
|
|
78
|
-
currentRoute.retry &&
|
|
79
|
-
session.__retries < currentRoute.retry) {
|
|
82
|
+
* Retry Scenario:
|
|
83
|
+
* We were in a route which had retries enabled, so we check if the number of retries is exceeded.
|
|
84
|
+
* If we have not surpassed the limit of retries and we haven't matched an ignoreRetry route, update them, and then return the new bot state.
|
|
85
|
+
*/ if (isFlowBroken && currentRoute && currentRoute.retry && session.__retries < currentRoute.retry) {
|
|
80
86
|
session.__retries = session.__retries !== 0 ? session.__retries + 1 : 1;
|
|
81
|
-
if (matchedRoute && matchedRoutePath !==
|
|
87
|
+
if (matchedRoute && matchedRoutePath !== NOT_FOUND_PATH) {
|
|
82
88
|
return {
|
|
83
89
|
action: currentRoute.action,
|
|
84
|
-
emptyAction:
|
|
90
|
+
emptyAction: getEmptyAction(matchedRoute.childRoutes),
|
|
85
91
|
fallbackAction: matchedRoute.action,
|
|
86
92
|
lastRoutePath: currentRoutePath,
|
|
87
|
-
params
|
|
93
|
+
params
|
|
88
94
|
};
|
|
89
95
|
}
|
|
90
96
|
return {
|
|
91
97
|
action: currentRoute.action ?? null,
|
|
92
|
-
emptyAction:
|
|
93
|
-
fallbackAction:
|
|
98
|
+
emptyAction: getEmptyAction(currentRoute.childRoutes),
|
|
99
|
+
fallbackAction: getNotFoundAction(input, this.routes),
|
|
94
100
|
lastRoutePath: currentRoutePath,
|
|
95
|
-
params
|
|
101
|
+
params
|
|
96
102
|
};
|
|
97
103
|
}
|
|
98
104
|
/**
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
session.__retries = 0;
|
|
105
|
+
* Default Scenario:
|
|
106
|
+
* We have matched a route or not, but we don't need to execute retries logic, so retries stay to 0.
|
|
107
|
+
*/ session.__retries = 0;
|
|
103
108
|
/**
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if (matchedRoute && matchedRoutePath !== constants_1.NOT_FOUND_PATH) {
|
|
109
|
+
* Matching Route Scenario:
|
|
110
|
+
* We have matched a route, so we return the new bot state.
|
|
111
|
+
*/ if (matchedRoute && matchedRoutePath !== NOT_FOUND_PATH) {
|
|
108
112
|
return {
|
|
109
113
|
action: matchedRoute.action ?? null,
|
|
110
|
-
emptyAction:
|
|
114
|
+
emptyAction: getEmptyAction(matchedRoute.childRoutes),
|
|
111
115
|
fallbackAction: null,
|
|
112
116
|
lastRoutePath: matchedRoutePath,
|
|
113
|
-
params
|
|
117
|
+
params
|
|
114
118
|
};
|
|
115
119
|
}
|
|
116
120
|
/**
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
return {
|
|
121
|
+
* 404 Scenario (No Route Found):
|
|
122
|
+
* We have not matched any route, so we return the new bot state.
|
|
123
|
+
*/ return {
|
|
121
124
|
action: null,
|
|
122
125
|
emptyAction: null,
|
|
123
|
-
fallbackAction:
|
|
126
|
+
fallbackAction: getNotFoundAction(input, this.routes),
|
|
124
127
|
params,
|
|
125
|
-
lastRoutePath: currentRoutePath
|
|
128
|
+
lastRoutePath: currentRoutePath
|
|
126
129
|
};
|
|
127
130
|
}
|
|
128
131
|
/**
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
getRoute(input, routes, session, lastRoutePath) {
|
|
132
|
+
* Find the route that matches the given input, if it match with some of the entries, return the whole Route of the entry with optional params captured if matcher was a regex.
|
|
133
|
+
* IMPORTANT: It returns a cloned route instead of the route itself to avoid modifying original routes and introduce side effects
|
|
134
|
+
* */ getRoute(input, routes, session, lastRoutePath) {
|
|
133
135
|
let params = {};
|
|
134
|
-
const route = routes.find(r
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}));
|
|
136
|
+
const route = routes.find((r)=>Object.entries(r).filter(([key, _])=>key !== 'action' && key !== 'childRoutes' && key !== 'path').some(([key, value])=>{
|
|
137
|
+
const match = this.matchRoute(r, key, value, input, session, lastRoutePath);
|
|
138
|
+
try {
|
|
139
|
+
if (match !== null && typeof match !== 'boolean' && match.groups) {
|
|
140
|
+
// Strip '[Object: null prototype]' from groups result: https://stackoverflow.com/a/62945609/6237608
|
|
141
|
+
params = {
|
|
142
|
+
...match.groups
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
} catch (_e) {}
|
|
146
|
+
return Boolean(match);
|
|
147
|
+
}));
|
|
147
148
|
if (route) {
|
|
148
|
-
return {
|
|
149
|
+
return {
|
|
150
|
+
route: cloneObject(route),
|
|
151
|
+
params
|
|
152
|
+
};
|
|
149
153
|
}
|
|
150
154
|
return null;
|
|
151
155
|
}
|
|
152
156
|
/**
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
getRouteByPath(path, routeList = this.routes) {
|
|
157
|
+
* Find the route that matches the given path. Path can include concatenations, e.g: 'Flow1/Subflow1.1'.
|
|
158
|
+
* IMPORTANT: It returns a cloned route instead of the route itself to avoid modifying original routes and introduce side effects
|
|
159
|
+
* */ getRouteByPath(path, routeList = this.routes) {
|
|
157
160
|
if (!path) {
|
|
158
161
|
return null;
|
|
159
162
|
}
|
|
160
163
|
const [currentPath, ...childPath] = path.split('/');
|
|
161
|
-
for (const route of routeList)
|
|
164
|
+
for (const route of routeList){
|
|
162
165
|
// iterate over all routeList
|
|
163
166
|
if (route.path === currentPath) {
|
|
164
167
|
if (route.childRoutes?.length && childPath.length > 0) {
|
|
@@ -166,53 +169,50 @@ class Router {
|
|
|
166
169
|
const computedRoute = this.getRouteByPath(childPath.join('/'), route.childRoutes);
|
|
167
170
|
// IMPORTANT: Returning a new object to avoid modifying dev routes and introduce side effects
|
|
168
171
|
if (computedRoute) {
|
|
169
|
-
return
|
|
172
|
+
return cloneObject(computedRoute);
|
|
170
173
|
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
+
} else if (childPath.length === 0) {
|
|
175
|
+
return cloneObject(route) // last action and found route
|
|
176
|
+
;
|
|
174
177
|
}
|
|
175
178
|
}
|
|
176
179
|
}
|
|
177
180
|
return null;
|
|
178
181
|
}
|
|
179
182
|
/**
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
matchRoute(route, prop, matcher, input, session, lastRoutePath) {
|
|
183
|
+
* Returns the matched value for a specific route.
|
|
184
|
+
* Matching Props: ('text' | 'payload' | 'intent' | 'type' | 'input' | 'session' | 'request' ...)
|
|
185
|
+
* Matchers: (string: exact match | regex: regular expression match | function: return true)
|
|
186
|
+
* input: user input object, e.g.: {type: 'text', data: 'Hi'}
|
|
187
|
+
* */ matchRoute(route, prop, matcher, input, session, lastRoutePath) {
|
|
186
188
|
let value = null;
|
|
187
189
|
if (Object.keys(input).indexOf(prop) > -1) {
|
|
188
190
|
value = input[prop];
|
|
189
|
-
}
|
|
190
|
-
else if (prop === 'text') {
|
|
191
|
+
} else if (prop === 'text') {
|
|
191
192
|
value = input.data;
|
|
192
|
-
}
|
|
193
|
-
else if (prop === 'input') {
|
|
193
|
+
} else if (prop === 'input') {
|
|
194
194
|
value = input;
|
|
195
|
-
}
|
|
196
|
-
else if (prop === 'session') {
|
|
195
|
+
} else if (prop === 'session') {
|
|
197
196
|
value = session;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
|
|
197
|
+
} else if (prop === 'request') {
|
|
198
|
+
value = {
|
|
199
|
+
input,
|
|
200
|
+
session,
|
|
201
|
+
lastRoutePath
|
|
202
|
+
};
|
|
201
203
|
}
|
|
202
204
|
const matched = this.matchValue(matcher, value);
|
|
203
205
|
if (matched) {
|
|
204
206
|
this.routeInspector.routeMatched(route, prop, matcher, value);
|
|
205
|
-
}
|
|
206
|
-
else {
|
|
207
|
+
} else {
|
|
207
208
|
this.routeInspector.routeNotMatched(route, prop, matcher, value);
|
|
208
209
|
}
|
|
209
210
|
return matched;
|
|
210
211
|
}
|
|
211
212
|
/**
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
matchValue(matcher, value) {
|
|
213
|
+
* Runs the matcher against the given value.
|
|
214
|
+
* If there is a match, it will return a truthy value (true, RegExp result), o.w., it will return a falsy value.
|
|
215
|
+
* */ matchValue(matcher, value) {
|
|
216
216
|
if (typeof matcher === 'string') {
|
|
217
217
|
return value === matcher;
|
|
218
218
|
}
|
|
@@ -228,24 +228,22 @@ class Router {
|
|
|
228
228
|
return false;
|
|
229
229
|
}
|
|
230
230
|
/**
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
getRoutingState(input, session, lastRoutePath) {
|
|
231
|
+
* It resolves the current state of navigation. Two scenarios:
|
|
232
|
+
* 1. Given a path payload input (__PATH_PAYLOAD__somePath?someParam=someValue), we can resolve the routing state directly from it (using getRouteByPath).
|
|
233
|
+
* 2. Given any other type of input, we resolve the routing state with normal resolution (using getRoute).
|
|
234
|
+
* */ getRoutingState(input, session, lastRoutePath) {
|
|
236
235
|
const currentRoute = this.getRouteByPath(lastRoutePath);
|
|
237
236
|
if (currentRoute && lastRoutePath) {
|
|
238
237
|
currentRoute.path = lastRoutePath;
|
|
239
238
|
}
|
|
240
|
-
if (typeof input.payload === 'string' &&
|
|
239
|
+
if (typeof input.payload === 'string' && isPathPayload(input.payload)) {
|
|
241
240
|
return this.getRoutingStateFromPathPayload(currentRoute, input.payload);
|
|
242
241
|
}
|
|
243
242
|
return this.getRoutingStateFromInput(currentRoute, input, session);
|
|
244
243
|
}
|
|
245
244
|
/**
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
getRoutingStateFromInput(currentRoute, input, session) {
|
|
245
|
+
* Given a non path payload input, try to run it against the routes, update matching routes information in consequence and dictamine if the flow has been broken.
|
|
246
|
+
* */ getRoutingStateFromInput(currentRoute, input, session) {
|
|
249
247
|
// get route depending of current ChildRoutes
|
|
250
248
|
if (currentRoute?.childRoutes) {
|
|
251
249
|
const routeParams = this.getRoute(input, currentRoute.childRoutes, session, currentRoute.path);
|
|
@@ -254,68 +252,65 @@ class Router {
|
|
|
254
252
|
currentRoute,
|
|
255
253
|
matchedRoute: {
|
|
256
254
|
...routeParams.route,
|
|
257
|
-
path: routeParams.route && currentRoute.path
|
|
258
|
-
? `${currentRoute.path}/${routeParams.route.path}`
|
|
259
|
-
: currentRoute.path,
|
|
255
|
+
path: routeParams.route && currentRoute.path ? `${currentRoute.path}/${routeParams.route.path}` : currentRoute.path
|
|
260
256
|
},
|
|
261
257
|
params: routeParams.params,
|
|
262
|
-
isFlowBroken: false
|
|
258
|
+
isFlowBroken: false
|
|
263
259
|
};
|
|
264
260
|
}
|
|
265
261
|
}
|
|
266
262
|
/**
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
const routeParams = this.getRoute(input, this.routes, session, currentRoute?.path ?? null);
|
|
263
|
+
* we couldn't find a route in the state of the currentRoute childRoutes,
|
|
264
|
+
* so let's find in the general routes
|
|
265
|
+
*/ const routeParams = this.getRoute(input, this.routes, session, currentRoute?.path ?? null);
|
|
271
266
|
const isFlowBroken = Boolean(currentRoute?.path);
|
|
272
267
|
if (routeParams?.route) {
|
|
273
268
|
return {
|
|
274
269
|
currentRoute,
|
|
275
270
|
matchedRoute: {
|
|
276
271
|
...routeParams.route,
|
|
277
|
-
path: routeParams.route?.path ?? null
|
|
272
|
+
path: routeParams.route?.path ?? null
|
|
278
273
|
},
|
|
279
274
|
params: routeParams.params,
|
|
280
|
-
isFlowBroken
|
|
275
|
+
isFlowBroken
|
|
281
276
|
};
|
|
282
277
|
}
|
|
283
278
|
return {
|
|
284
279
|
currentRoute,
|
|
285
280
|
matchedRoute: null,
|
|
286
281
|
params: {},
|
|
287
|
-
isFlowBroken
|
|
282
|
+
isFlowBroken
|
|
288
283
|
};
|
|
289
284
|
}
|
|
290
285
|
/**
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
const { path, params } = (0, router_utils_1.getPathParamsFromPathPayload)(pathPayload);
|
|
286
|
+
* Given a path payload input, try to run the path against the routes, update matching routes information in consequence and dictamine if the flow has been broken.
|
|
287
|
+
* */ getRoutingStateFromPathPayload(currentRoute, pathPayload) {
|
|
288
|
+
const { path, params } = getPathParamsFromPathPayload(pathPayload);
|
|
295
289
|
/**
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
const getRoutingStateFromPath = (seekPath) => {
|
|
290
|
+
* shorthand function to update the matching information given a path
|
|
291
|
+
*/ const getRoutingStateFromPath = (seekPath)=>{
|
|
299
292
|
const matchedRoute = this.getRouteByPath(seekPath);
|
|
300
293
|
if (!matchedRoute) {
|
|
301
294
|
return {
|
|
302
295
|
currentRoute,
|
|
303
296
|
matchedRoute: null,
|
|
304
297
|
params: {},
|
|
305
|
-
isFlowBroken: true
|
|
298
|
+
isFlowBroken: true
|
|
306
299
|
};
|
|
307
300
|
}
|
|
308
301
|
return {
|
|
309
302
|
currentRoute,
|
|
310
|
-
matchedRoute: {
|
|
303
|
+
matchedRoute: {
|
|
304
|
+
...matchedRoute,
|
|
305
|
+
path: seekPath
|
|
306
|
+
},
|
|
311
307
|
params,
|
|
312
|
-
isFlowBroken: false
|
|
308
|
+
isFlowBroken: false
|
|
313
309
|
};
|
|
314
310
|
};
|
|
315
311
|
/**
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
// 1. Received __PATH_PAYLOAD__Subflow2, so we need to first try to concatenate it with Flow1 (lastRoutePath)
|
|
312
|
+
* Given a valid path: 'Flow1/Subflow1' we are in one of the two scenarios below.
|
|
313
|
+
*/ // 1. Received __PATH_PAYLOAD__Subflow2, so we need to first try to concatenate it with Flow1 (lastRoutePath)
|
|
319
314
|
if (currentRoute?.path) {
|
|
320
315
|
const routingState = getRoutingStateFromPath(`${currentRoute.path}/${path}`);
|
|
321
316
|
if (routingState.matchedRoute) {
|
|
@@ -325,6 +320,14 @@ class Router {
|
|
|
325
320
|
// 2. Received __PATH_PAYLOAD__Flow1/Subflow1, so we can resolve it directly
|
|
326
321
|
return getRoutingStateFromPath(path);
|
|
327
322
|
}
|
|
323
|
+
constructor(routes, routeInspector = undefined){
|
|
324
|
+
_define_property(this, "routes", void 0);
|
|
325
|
+
_define_property(this, "routeInspector", void 0);
|
|
326
|
+
this.routes = routes;
|
|
327
|
+
this.routeInspector = routeInspector || new RouteInspector();
|
|
328
|
+
}
|
|
328
329
|
}
|
|
329
|
-
|
|
330
|
+
|
|
331
|
+
export { Router };
|
|
332
|
+
|
|
330
333
|
//# sourceMappingURL=router.js.map
|