fix: 🐛 Webhook duplication
This commit is contained in:
@ -101,96 +101,119 @@ export const createTypebot = async ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const importTypebot = async (typebot: Typebot, userPlan: Plan) => {
|
export const importTypebot = async (typebot: Typebot, userPlan: Plan) => {
|
||||||
return sendRequest<Typebot>({
|
const { typebot: newTypebot, webhookIdsMapping } = duplicateTypebot(
|
||||||
|
typebot,
|
||||||
|
userPlan
|
||||||
|
)
|
||||||
|
const { data, error } = await sendRequest<Typebot>({
|
||||||
url: `/api/typebots`,
|
url: `/api/typebots`,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: await duplicateTypebot(typebot, userPlan),
|
body: newTypebot,
|
||||||
})
|
})
|
||||||
|
if (!data) return { data, error }
|
||||||
|
const webhookSteps = typebot.blocks
|
||||||
|
.flatMap((b) => b.steps)
|
||||||
|
.filter(isWebhookStep)
|
||||||
|
await Promise.all(
|
||||||
|
webhookSteps.map((s) =>
|
||||||
|
duplicateWebhook(
|
||||||
|
newTypebot.id,
|
||||||
|
s.webhookId,
|
||||||
|
webhookIdsMapping.get(s.webhookId) as string
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return { data, error }
|
||||||
}
|
}
|
||||||
|
|
||||||
const duplicateTypebot = async (
|
const duplicateTypebot = (
|
||||||
typebot: Typebot,
|
typebot: Typebot,
|
||||||
userPlan: Plan
|
userPlan: Plan
|
||||||
): Promise<Typebot> => {
|
): { typebot: Typebot; webhookIdsMapping: Map<string, string> } => {
|
||||||
const blockIdsMapping = generateOldNewIdsMapping(typebot.blocks)
|
const blockIdsMapping = generateOldNewIdsMapping(typebot.blocks)
|
||||||
const edgeIdsMapping = generateOldNewIdsMapping(typebot.edges)
|
const edgeIdsMapping = generateOldNewIdsMapping(typebot.edges)
|
||||||
|
const webhookIdsMapping = generateOldNewIdsMapping(
|
||||||
|
typebot.blocks
|
||||||
|
.flatMap((b) => b.steps)
|
||||||
|
.filter(isWebhookStep)
|
||||||
|
.map((s) => ({ id: s.webhookId }))
|
||||||
|
)
|
||||||
|
const id = cuid()
|
||||||
return {
|
return {
|
||||||
...typebot,
|
typebot: {
|
||||||
id: cuid(),
|
...typebot,
|
||||||
name: `${typebot.name} copy`,
|
id,
|
||||||
publishedTypebotId: null,
|
name: `${typebot.name} copy`,
|
||||||
publicId: null,
|
publishedTypebotId: null,
|
||||||
customDomain: null,
|
publicId: null,
|
||||||
blocks: await Promise.all(
|
customDomain: null,
|
||||||
typebot.blocks.map(async (b) => ({
|
blocks: typebot.blocks.map((b) => ({
|
||||||
...b,
|
...b,
|
||||||
id: blockIdsMapping.get(b.id) as string,
|
id: blockIdsMapping.get(b.id) as string,
|
||||||
steps: await Promise.all(
|
steps: b.steps.map((s) => {
|
||||||
b.steps.map(async (s) => {
|
const newIds = {
|
||||||
const newIds = {
|
blockId: blockIdsMapping.get(s.blockId) as string,
|
||||||
blockId: blockIdsMapping.get(s.blockId) as string,
|
outgoingEdgeId: s.outgoingEdgeId
|
||||||
outgoingEdgeId: s.outgoingEdgeId
|
? edgeIdsMapping.get(s.outgoingEdgeId)
|
||||||
? edgeIdsMapping.get(s.outgoingEdgeId)
|
: undefined,
|
||||||
: undefined,
|
}
|
||||||
}
|
if (
|
||||||
if (
|
s.type === LogicStepType.TYPEBOT_LINK &&
|
||||||
s.type === LogicStepType.TYPEBOT_LINK &&
|
s.options.typebotId === 'current' &&
|
||||||
s.options.typebotId === 'current' &&
|
isDefined(s.options.blockId)
|
||||||
isDefined(s.options.blockId)
|
)
|
||||||
)
|
|
||||||
return {
|
|
||||||
...s,
|
|
||||||
options: {
|
|
||||||
...s.options,
|
|
||||||
blockId: blockIdsMapping.get(s.options.blockId as string),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
if (stepHasItems(s))
|
|
||||||
return {
|
|
||||||
...s,
|
|
||||||
items: s.items.map((item) => ({
|
|
||||||
...item,
|
|
||||||
outgoingEdgeId: item.outgoingEdgeId
|
|
||||||
? (edgeIdsMapping.get(item.outgoingEdgeId) as string)
|
|
||||||
: undefined,
|
|
||||||
})),
|
|
||||||
...newIds,
|
|
||||||
} as ChoiceInputStep | ConditionStep
|
|
||||||
if (isWebhookStep(s)) {
|
|
||||||
const newWebhook = await duplicateWebhook(s.webhookId)
|
|
||||||
return {
|
|
||||||
...s,
|
|
||||||
webhookId: newWebhook ? newWebhook.id : cuid(),
|
|
||||||
...newIds,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
...s,
|
...s,
|
||||||
|
options: {
|
||||||
|
...s.options,
|
||||||
|
blockId: blockIdsMapping.get(s.options.blockId as string),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if (stepHasItems(s))
|
||||||
|
return {
|
||||||
|
...s,
|
||||||
|
items: s.items.map((item) => ({
|
||||||
|
...item,
|
||||||
|
outgoingEdgeId: item.outgoingEdgeId
|
||||||
|
? (edgeIdsMapping.get(item.outgoingEdgeId) as string)
|
||||||
|
: undefined,
|
||||||
|
})),
|
||||||
|
...newIds,
|
||||||
|
} as ChoiceInputStep | ConditionStep
|
||||||
|
if (isWebhookStep(s)) {
|
||||||
|
return {
|
||||||
|
...s,
|
||||||
|
webhookId: webhookIdsMapping.get(s.webhookId) as string,
|
||||||
...newIds,
|
...newIds,
|
||||||
}
|
}
|
||||||
})
|
|
||||||
),
|
|
||||||
}))
|
|
||||||
),
|
|
||||||
edges: typebot.edges.map((e) => ({
|
|
||||||
...e,
|
|
||||||
id: edgeIdsMapping.get(e.id) as string,
|
|
||||||
from: {
|
|
||||||
...e.from,
|
|
||||||
blockId: blockIdsMapping.get(e.from.blockId) as string,
|
|
||||||
},
|
|
||||||
to: { ...e.to, blockId: blockIdsMapping.get(e.to.blockId) as string },
|
|
||||||
})),
|
|
||||||
settings:
|
|
||||||
typebot.settings.general.isBrandingEnabled === false &&
|
|
||||||
userPlan === Plan.FREE
|
|
||||||
? {
|
|
||||||
...typebot.settings,
|
|
||||||
general: { ...typebot.settings.general, isBrandingEnabled: true },
|
|
||||||
}
|
}
|
||||||
: typebot.settings,
|
return {
|
||||||
createdAt: new Date().toISOString(),
|
...s,
|
||||||
updatedAt: new Date().toISOString(),
|
...newIds,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
})),
|
||||||
|
edges: typebot.edges.map((e) => ({
|
||||||
|
...e,
|
||||||
|
id: edgeIdsMapping.get(e.id) as string,
|
||||||
|
from: {
|
||||||
|
...e.from,
|
||||||
|
blockId: blockIdsMapping.get(e.from.blockId) as string,
|
||||||
|
},
|
||||||
|
to: { ...e.to, blockId: blockIdsMapping.get(e.to.blockId) as string },
|
||||||
|
})),
|
||||||
|
settings:
|
||||||
|
typebot.settings.general.isBrandingEnabled === false &&
|
||||||
|
userPlan === Plan.FREE
|
||||||
|
? {
|
||||||
|
...typebot.settings,
|
||||||
|
general: { ...typebot.settings.general, isBrandingEnabled: true },
|
||||||
|
}
|
||||||
|
: typebot.settings,
|
||||||
|
createdAt: new Date().toISOString(),
|
||||||
|
updatedAt: new Date().toISOString(),
|
||||||
|
},
|
||||||
|
webhookIdsMapping,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import cuid from 'cuid'
|
|
||||||
import { Webhook } from 'models'
|
import { Webhook } from 'models'
|
||||||
import { sendRequest } from 'utils'
|
import { sendRequest } from 'utils'
|
||||||
|
|
||||||
@ -10,13 +9,15 @@ export const saveWebhook = (webhookId: string, webhook: Partial<Webhook>) =>
|
|||||||
})
|
})
|
||||||
|
|
||||||
export const duplicateWebhook = async (
|
export const duplicateWebhook = async (
|
||||||
webhookId: string
|
typebotId: string,
|
||||||
|
existingWebhookId: string,
|
||||||
|
newWebhookId: string
|
||||||
): Promise<Webhook | undefined> => {
|
): Promise<Webhook | undefined> => {
|
||||||
const { data } = await sendRequest<{ webhook: Webhook }>(
|
const { data } = await sendRequest<{ webhook: Webhook }>(
|
||||||
`/api/webhooks/${webhookId}`
|
`/api/webhooks/${existingWebhookId}`
|
||||||
)
|
)
|
||||||
if (!data) return
|
if (!data) return
|
||||||
const newWebhook = { ...data.webhook, id: cuid() }
|
const newWebhook = { ...data.webhook, id: newWebhookId, typebotId }
|
||||||
await saveWebhook(newWebhook.id, newWebhook)
|
await saveWebhook(newWebhook.id, newWebhook)
|
||||||
return newWebhook
|
return newWebhook
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user