@botonic/plugin-flow-builder 0.57.1-alpha.0 → 0.58.0-alpha.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/cjs/action/contents-result.d.ts +5 -0
- package/lib/cjs/action/contents-result.js +3 -0
- package/lib/cjs/action/contents-result.js.map +1 -0
- package/lib/cjs/action/first-interaction.js +1 -1
- package/lib/cjs/action/first-interaction.js.map +1 -1
- package/lib/cjs/action/get-contents.d.ts +3 -2
- package/lib/cjs/action/get-contents.js +13 -6
- package/lib/cjs/action/get-contents.js.map +1 -1
- package/lib/cjs/action/index.d.ts +2 -0
- package/lib/cjs/action/index.js +16 -6
- package/lib/cjs/action/index.js.map +1 -1
- package/lib/cjs/action/payload.d.ts +2 -2
- package/lib/cjs/action/payload.js +12 -28
- package/lib/cjs/action/payload.js.map +1 -1
- package/lib/cjs/action/push-flow-resolver.d.ts +22 -0
- package/lib/cjs/action/push-flow-resolver.js +66 -0
- package/lib/cjs/action/push-flow-resolver.js.map +1 -0
- package/lib/cjs/api.d.ts +1 -1
- package/lib/cjs/api.js +7 -2
- package/lib/cjs/api.js.map +1 -1
- package/lib/cjs/content-fields/flow-do-nothing.js +1 -1
- package/lib/cjs/content-fields/flow-do-nothing.js.map +1 -1
- package/lib/esm/action/contents-result.d.ts +5 -0
- package/lib/esm/action/contents-result.js +3 -0
- package/lib/esm/action/contents-result.js.map +1 -0
- package/lib/esm/action/first-interaction.js +1 -1
- package/lib/esm/action/first-interaction.js.map +1 -1
- package/lib/esm/action/get-contents.d.ts +3 -2
- package/lib/esm/action/get-contents.js +13 -6
- package/lib/esm/action/get-contents.js.map +1 -1
- package/lib/esm/action/index.d.ts +2 -0
- package/lib/esm/action/index.js +16 -6
- package/lib/esm/action/index.js.map +1 -1
- package/lib/esm/action/payload.d.ts +2 -2
- package/lib/esm/action/payload.js +12 -28
- package/lib/esm/action/payload.js.map +1 -1
- package/lib/esm/action/push-flow-resolver.d.ts +22 -0
- package/lib/esm/action/push-flow-resolver.js +66 -0
- package/lib/esm/action/push-flow-resolver.js.map +1 -0
- package/lib/esm/api.d.ts +1 -1
- package/lib/esm/api.js +7 -2
- package/lib/esm/api.js.map +1 -1
- package/lib/esm/content-fields/flow-do-nothing.js +1 -1
- package/lib/esm/content-fields/flow-do-nothing.js.map +1 -1
- package/package.json +2 -2
- package/src/action/contents-result.ts +6 -0
- package/src/action/first-interaction.ts +7 -6
- package/src/action/get-contents.ts +17 -8
- package/src/action/index.tsx +40 -6
- package/src/action/payload.ts +16 -46
- package/src/action/push-flow-resolver.ts +101 -0
- package/src/api.ts +13 -3
- package/src/content-fields/flow-do-nothing.tsx +1 -1
package/src/action/payload.ts
CHANGED
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
import { EventAction, type EventFeedback, storeCaseRating } from '@botonic/core'
|
|
2
2
|
import { v7 as uuid } from 'uuid'
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
AGENT_RATING_PAYLOAD,
|
|
6
|
-
PUSH_FLOW_PAYLOAD,
|
|
7
|
-
SEPARATOR,
|
|
8
|
-
} from '../constants'
|
|
9
|
-
import type { FlowContent } from '../content-fields'
|
|
3
|
+
import { AGENT_RATING_PAYLOAD, PUSH_FLOW_PAYLOAD } from '../constants'
|
|
10
4
|
import type { HtNodeWithContent } from '../content-fields/hubtype-fields'
|
|
11
5
|
import { trackEvent } from '../tracking'
|
|
6
|
+
import type { FlowBuilderContentsResult } from './contents-result'
|
|
12
7
|
import type { FlowBuilderContext } from './context'
|
|
8
|
+
import { PushFlowResolver } from './push-flow-resolver'
|
|
13
9
|
|
|
14
10
|
export async function getContentsByPayload(
|
|
15
11
|
context: FlowBuilderContext
|
|
16
|
-
): Promise<
|
|
12
|
+
): Promise<FlowBuilderContentsResult> {
|
|
17
13
|
const { cmsApi, flowBuilderPlugin, request, contentID } = context
|
|
18
14
|
if (request.input.payload?.startsWith(AGENT_RATING_PAYLOAD)) {
|
|
19
15
|
return await resolveRatingPayload(context)
|
|
20
16
|
}
|
|
21
17
|
if (request.input.payload?.startsWith(PUSH_FLOW_PAYLOAD)) {
|
|
22
|
-
|
|
18
|
+
const pushFlow = new PushFlowResolver(context)
|
|
19
|
+
return await pushFlow.getContents()
|
|
23
20
|
}
|
|
24
21
|
|
|
25
22
|
const id = contentID
|
|
@@ -28,19 +25,21 @@ export async function getContentsByPayload(
|
|
|
28
25
|
const targetNode = id ? cmsApi.getNodeById<HtNodeWithContent>(id) : undefined
|
|
29
26
|
|
|
30
27
|
if (targetNode) {
|
|
31
|
-
return
|
|
28
|
+
return {
|
|
29
|
+
contents: await flowBuilderPlugin.getContentsByNode(targetNode),
|
|
30
|
+
}
|
|
32
31
|
}
|
|
33
32
|
|
|
34
|
-
return []
|
|
33
|
+
return { contents: [] }
|
|
35
34
|
}
|
|
36
35
|
|
|
37
36
|
async function resolveRatingPayload(
|
|
38
37
|
context: FlowBuilderContext
|
|
39
|
-
): Promise<
|
|
38
|
+
): Promise<FlowBuilderContentsResult> {
|
|
40
39
|
const { cmsApi, flowBuilderPlugin, request } = context
|
|
41
40
|
|
|
42
41
|
if (!request.input.payload) {
|
|
43
|
-
return []
|
|
42
|
+
return { contents: [] }
|
|
44
43
|
}
|
|
45
44
|
|
|
46
45
|
const { target, text, value, possibleOptions, possibleValues } =
|
|
@@ -66,39 +65,10 @@ async function resolveRatingPayload(
|
|
|
66
65
|
: undefined
|
|
67
66
|
|
|
68
67
|
if (targetNode) {
|
|
69
|
-
return
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
return []
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
async function resolvePushFlowPayload(
|
|
76
|
-
context: FlowBuilderContext
|
|
77
|
-
): Promise<FlowContent[]> {
|
|
78
|
-
const { cmsApi, flowBuilderPlugin, request } = context
|
|
79
|
-
|
|
80
|
-
if (!request.input.payload) {
|
|
81
|
-
return []
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const parts = request.input.payload.split(SEPARATOR)
|
|
85
|
-
const pushFlowId = parts.length > 1 ? parts[1] : ''
|
|
86
|
-
|
|
87
|
-
if (!pushFlowId) {
|
|
88
|
-
return []
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
try {
|
|
92
|
-
const pushFlowNode =
|
|
93
|
-
cmsApi.getNodeByCampaignId<HtNodeWithContent>(pushFlowId)
|
|
94
|
-
|
|
95
|
-
if (!pushFlowNode) {
|
|
96
|
-
return []
|
|
68
|
+
return {
|
|
69
|
+
contents: await flowBuilderPlugin.getContentsByNode(targetNode),
|
|
97
70
|
}
|
|
98
|
-
|
|
99
|
-
return await flowBuilderPlugin.getContentsByNode(pushFlowNode)
|
|
100
|
-
} catch {
|
|
101
|
-
// Campaign not found - return empty to trigger fallback
|
|
102
|
-
return []
|
|
103
71
|
}
|
|
72
|
+
|
|
73
|
+
return { contents: [] }
|
|
104
74
|
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type { BotContext } from '@botonic/core'
|
|
2
|
+
import type { FlowBuilderApi } from '../api'
|
|
3
|
+
import { SEPARATOR } from '../constants'
|
|
4
|
+
import type { HtNodeWithContent } from '../content-fields/hubtype-fields'
|
|
5
|
+
import type BotonicPluginFlowBuilder from '../index'
|
|
6
|
+
import type { FlowBuilderContentsResult } from './contents-result'
|
|
7
|
+
import type { FlowBuilderContext } from './context'
|
|
8
|
+
|
|
9
|
+
export enum PushFlowErrorCode {
|
|
10
|
+
NoInputPayload = 'NoInputPayload',
|
|
11
|
+
NoPushFlowId = 'NoPushFlowId',
|
|
12
|
+
NoCampaignStartNode = 'NoCampaignStartNode',
|
|
13
|
+
NoCampaignId = 'NoCampaignId',
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class PushFlowError extends Error {
|
|
17
|
+
readonly code: PushFlowErrorCode
|
|
18
|
+
|
|
19
|
+
constructor(code: PushFlowErrorCode, reason: string) {
|
|
20
|
+
super(`push-flow failed: ${reason}`)
|
|
21
|
+
this.code = code
|
|
22
|
+
this.name = 'PushFlowError'
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export class PushFlowResolver {
|
|
27
|
+
private botContext: BotContext
|
|
28
|
+
private cmsApi: FlowBuilderApi
|
|
29
|
+
private flowBuilderPlugin: BotonicPluginFlowBuilder
|
|
30
|
+
|
|
31
|
+
constructor(context: FlowBuilderContext) {
|
|
32
|
+
this.botContext = context.request
|
|
33
|
+
this.cmsApi = context.cmsApi
|
|
34
|
+
this.flowBuilderPlugin = context.flowBuilderPlugin
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async getContents(): Promise<FlowBuilderContentsResult> {
|
|
38
|
+
const pushFlowId = this.getPushFlowId()
|
|
39
|
+
const pushFlowNode = this.getPushFlowNode(pushFlowId)
|
|
40
|
+
const campaignId = this.getCampaignId()
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
contents: await this.flowBuilderPlugin.getContentsByNode(pushFlowNode),
|
|
44
|
+
campaignFirstMessageId: campaignId,
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private getPushFlowId(): string {
|
|
49
|
+
const payload = this.botContext.input.payload
|
|
50
|
+
|
|
51
|
+
if (!payload) {
|
|
52
|
+
throw new PushFlowError(
|
|
53
|
+
PushFlowErrorCode.NoInputPayload,
|
|
54
|
+
'No payload found in input'
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const parts = payload.split(SEPARATOR)
|
|
59
|
+
const pushFlowId = parts.length > 1 ? parts[1] : ''
|
|
60
|
+
|
|
61
|
+
if (!pushFlowId) {
|
|
62
|
+
throw new PushFlowError(
|
|
63
|
+
PushFlowErrorCode.NoPushFlowId,
|
|
64
|
+
'No push flow id found in input payload'
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return pushFlowId
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private getPushFlowNode(pushFlowId: string): HtNodeWithContent {
|
|
72
|
+
const pushFlowNode =
|
|
73
|
+
this.cmsApi.getNodeByCampaignId<HtNodeWithContent>(pushFlowId)
|
|
74
|
+
|
|
75
|
+
if (!pushFlowNode) {
|
|
76
|
+
throw new PushFlowError(
|
|
77
|
+
PushFlowErrorCode.NoCampaignStartNode,
|
|
78
|
+
'No campaign start node found'
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return pushFlowNode
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private getCampaignId(): string {
|
|
86
|
+
const campaignId =
|
|
87
|
+
this.botContext.input.context &&
|
|
88
|
+
'campaign_id' in this.botContext.input.context
|
|
89
|
+
? this.botContext.input.context.campaign_id
|
|
90
|
+
: undefined
|
|
91
|
+
|
|
92
|
+
if (!campaignId) {
|
|
93
|
+
throw new PushFlowError(
|
|
94
|
+
PushFlowErrorCode.NoCampaignId,
|
|
95
|
+
'No campaign id found in input context'
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return campaignId
|
|
100
|
+
}
|
|
101
|
+
}
|
package/src/api.ts
CHANGED
|
@@ -82,12 +82,22 @@ export class FlowBuilderApi {
|
|
|
82
82
|
return this.getNodeById<HtNodeWithContent>(subFlow.start_node_id)
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
getNodeByCampaignId<T extends HtNodeComponent>(id: string): T {
|
|
85
|
+
getNodeByCampaignId<T extends HtNodeComponent>(id: string): T | undefined {
|
|
86
86
|
const campaign = this.flow.campaigns.find(campaign => campaign.id === id)
|
|
87
87
|
if (!campaign) {
|
|
88
|
-
|
|
88
|
+
return undefined
|
|
89
89
|
}
|
|
90
|
-
|
|
90
|
+
|
|
91
|
+
const node = this.flow.nodes.find(
|
|
92
|
+
flowNode => flowNode.id === campaign.start_node_id
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
if (!node) {
|
|
96
|
+
console.error(`Node with id: '${campaign.start_node_id}' not found`)
|
|
97
|
+
return undefined
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return node as T
|
|
91
101
|
}
|
|
92
102
|
|
|
93
103
|
getNodeById<T extends HtNodeComponent>(id: string): T {
|
|
@@ -8,7 +8,7 @@ export class FlowDoNothing extends ContentFieldsBase {
|
|
|
8
8
|
static fromHubtypeCMS(cmsDoNothing: HtDoNothingNode): FlowDoNothing {
|
|
9
9
|
const newDoNothing = new FlowDoNothing(cmsDoNothing.id)
|
|
10
10
|
newDoNothing.code = cmsDoNothing.code
|
|
11
|
-
newDoNothing.followUp =
|
|
11
|
+
newDoNothing.followUp = undefined
|
|
12
12
|
|
|
13
13
|
return newDoNothing
|
|
14
14
|
}
|