Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"recommendations": ["esbenp.prettier-vscode", "oxc.oxc-vscode"]
"recommendations": ["esbenp.prettier-vscode", "oxc.oxc-vscode", "vitest.explorer"]
}
4 changes: 2 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
},
"editor.tabSize": 2,
"git.branchProtection": ["master"],
"typescript.tsdk": "node_modules/typescript/lib",
"vitest.disableWorkspaceWarning": true
"vitest.disableWorkspaceWarning": true,
"js/ts.tsdk.path": "node_modules/typescript/lib"
}
2 changes: 1 addition & 1 deletion integrations/hubspot/integration.definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default new IntegrationDefinition({
name: 'hubspot',
title: 'HubSpot',
description: 'Manage contacts, tickets and more from your chatbot.',
version: '6.0.0',
version: '6.0.1',
readme: 'hub.md',
icon: 'icon.svg',
configuration: {
Expand Down
7 changes: 6 additions & 1 deletion integrations/hubspot/linkTemplate.vrl
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
webhookId = to_string!(.webhookId)
webhookUrl = to_string!(.webhookUrl)
source = to_string!(.source) ?? ""

"{{ webhookUrl }}/oauth/wizard/start?state={{ webhookId }}"
if source == "desk" {
"{{ webhookUrl }}/oauth/wizard/start?state={{ webhookId }}&wizchoice=without-hitl"
} else {
"{{ webhookUrl }}/oauth/wizard/start?state={{ webhookId }}"
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
},
"devDependencies": {
"@aws-sdk/client-dynamodb": "^3.564.0",
"@botpress/api": "1.99.0",
"@botpress/api": "1.102.0",
"@botpress/cli": "workspace:*",
"@botpress/client": "workspace:*",
"@botpress/sdk": "workspace:*",
Expand Down
12 changes: 8 additions & 4 deletions packages/common/src/entity-helpers/create-or-update-user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import * as sdk from '@botpress/sdk'
// this type is not exported by the sdk: it's a placeholder for the integration type
type BaseIntegration = sdk.DefaultIntegration<any>

type Cast<T, U> = T extends U ? T : U

/**
* Creates or updates a user based on the provided input.
* If a user is found with the same discriminating tags, it will be updated.
Expand All @@ -15,26 +17,28 @@ type BaseIntegration = sdk.DefaultIntegration<any>
export const createOrUpdateUser = async <
Client extends sdk.IntegrationSpecificClient<TIntegration>,
TIntegration extends BaseIntegration = Client extends sdk.IntegrationSpecificClient<infer TI> ? TI : never,
CreateProps extends Parameters<Client['getOrCreateUser']>[0] = Parameters<Client['getOrCreateUser']>[0],
CreateProps extends Parameters<Client['createUser']>[0] = Parameters<Client['createUser']>[0],
DiscriminatingTags extends Extract<keyof CreateProps['tags'], string> = Extract<keyof CreateProps['tags'], string>,
>(
props: CreateProps & { client: Client; discriminateByTags?: DiscriminatingTags[] }
): Promise<Awaited<ReturnType<Client['getOrCreateUser']>>> => {
): Promise<Awaited<ReturnType<Client['createUser']>>> => {
const { users: matchingUsers } = await props.client.listUsers({ tags: _getFilteredTags(props) })

if (matchingUsers.length > 1) {
throw new sdk.RuntimeError('Multiple users found with the same discriminating tags')
}

type UserTags = keyof TIntegration['user']['tags']
const updateTags: Partial<Record<UserTags, string | null>> = { ...matchingUsers[0]!.tags, ...props.tags }
return (
matchingUsers.length === 1
? await props.client.updateUser({
...matchingUsers[0]!,
...props,
tags: { ...matchingUsers[0]!.tags, ...props.tags },
tags: updateTags as Cast<typeof updateTags, Record<string, string | null>>,
})
: await props.client.createUser(props)
) as Awaited<ReturnType<Client['getOrCreateUser']>>
) as Awaited<ReturnType<Client['createUser']>>
}

const _getFilteredTags = <TAGS extends client.User['tags']>({
Expand Down
5 changes: 5 additions & 0 deletions packages/sdk/src/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ export type ToTags<TTags extends string | number | symbol> = typeUtils.Cast<
Record<string, string>
>

export type ToNullableTags<TTags extends string | number | symbol> = typeUtils.Cast<
Partial<Record<TTags, string | null>>,
Record<string, string | null>
>

export type SchemaTransformOptions = {
useLegacyZuiTransformer?: boolean
toJSONSchemaOptions?: Partial<z.transforms.JSONSchemaGenerationOptions>
Expand Down
5 changes: 1 addition & 4 deletions packages/sdk/src/integration/client/sub-types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { commonTypes } from '../../common'
import * as utils from '../../utils/type-utils'
import * as common from '../common'

Expand Down Expand Up @@ -45,9 +44,7 @@ export type MessageTags<TIntegration extends common.BaseIntegration> = keyof uti
}>
>

export type UserTags<TIntegration extends common.BaseIntegration> = commonTypes.ToTags<
keyof TIntegration['user']['tags']
>
export type UserTags<TIntegration extends common.BaseIntegration> = keyof TIntegration['user']['tags']

export type TagsOfMessage<
TIntegration extends common.BaseIntegration,
Expand Down
27 changes: 16 additions & 11 deletions packages/sdk/src/integration/client/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export type GetOrCreateConversation<TIntegration extends common.BaseIntegration>
Arg<client.Client['getOrCreateConversation']>,
{
channel: utils.Cast<ChannelName, string>
tags: commonTypes.ToTags<TTags>
tags: commonTypes.ToNullableTags<TTags>
discriminateByTags?: NoInfer<utils.Cast<TTags[], string[]>>
}
>
Expand All @@ -89,7 +89,7 @@ export type UpdateConversation<TIntegration extends common.BaseIntegration> = (
x: utils.Merge<
Arg<client.Client['updateConversation']>,
{
tags?: commonTypes.ToTags<ConversationTags<TIntegration>>
tags?: commonTypes.ToNullableTags<ConversationTags<TIntegration>>
}
>
) => Promise<ConversationResponse<TIntegration>>
Expand Down Expand Up @@ -181,7 +181,7 @@ export type GetOrCreateMessage<TIntegration extends common.BaseIntegration> = <
{
type: utils.Cast<TMessage, string>
payload?: GetMessageByName<TIntegration, TMessage>['payload']
tags: commonTypes.ToTags<TTags>
tags: commonTypes.ToNullableTags<TTags>
// TODO: find a way to restrict discriminateByTags to tags present in x.tags
discriminateByTags?: NoInfer<utils.Cast<TTags[], string[]>>
}
Expand All @@ -196,7 +196,7 @@ export type UpdateMessage<TIntegration extends common.BaseIntegration> = (
x: utils.Merge<
Arg<client.Client['updateMessage']>,
{
tags: commonTypes.ToTags<MessageTags<TIntegration>>
tags?: commonTypes.ToNullableTags<MessageTags<TIntegration>>
}
>
) => Promise<MessageResponse<TIntegration>>
Expand All @@ -216,7 +216,7 @@ type UserResponse<TIntegration extends common.BaseIntegration> = {
user: utils.Merge<
Awaited<Res<client.Client['getUser']>>['user'],
{
tags: UserTags<TIntegration>
tags: commonTypes.ToTags<UserTags<TIntegration>>
}
>
}
Expand All @@ -225,7 +225,7 @@ export type CreateUser<TIntegration extends common.BaseIntegration> = (
x: utils.Merge<
Arg<client.Client['createUser']>,
{
tags: UserTags<TIntegration>
tags: commonTypes.ToTags<UserTags<TIntegration>>
}
>
) => Promise<UserResponse<TIntegration>>
Expand All @@ -238,15 +238,20 @@ export type ListUsers<TIntegration extends common.BaseIntegration> = (
x: utils.Merge<
Arg<client.Client['listUsers']>,
{
tags?: UserTags<TIntegration>
tags?: commonTypes.ToTags<UserTags<TIntegration>>
}
>
) => Res<client.Client['listUsers']>

type GetOrCreateUserResponse<TIntegration extends common.BaseIntegration> = utils.Merge<
Awaited<Res<client.Client['getOrCreateUser']>>,
{
user: utils.Merge<Awaited<Res<client.Client['getOrCreateUser']>>['user'], { tags: UserTags<TIntegration> }>
user: utils.Merge<
Awaited<Res<client.Client['getOrCreateUser']>>['user'],
{
tags: commonTypes.ToTags<UserTags<TIntegration>>
}
>
}
>

Expand All @@ -256,7 +261,7 @@ export type GetOrCreateUser<TIntegration extends common.BaseIntegration> = <
x: utils.Merge<
Arg<client.Client['getOrCreateUser']>,
{
tags: commonTypes.ToTags<TTags>
tags: commonTypes.ToNullableTags<TTags>
discriminateByTags?: NoInfer<utils.Cast<TTags[], string[]>>
}
>
Expand All @@ -266,7 +271,7 @@ export type UpdateUser<TIntegration extends common.BaseIntegration> = (
x: utils.Merge<
Arg<client.Client['updateUser']>,
{
tags?: UserTags<TIntegration>
tags?: commonTypes.ToNullableTags<UserTags<TIntegration>>
}
>
) => Promise<UserResponse<TIntegration>>
Expand All @@ -279,7 +284,7 @@ export type InitializeIncomingMessage<TIntegration extends common.BaseIntegratio
{
user?: utils.Merge<
NonNullable<Arg<client.Client['initializeIncomingMessage']>['user']>,
{ tags: UserTags<TIntegration> }
{ tags: commonTypes.ToTags<UserTags<TIntegration>> }
>
conversation?: utils.Merge<
NonNullable<Arg<client.Client['initializeIncomingMessage']>['conversation']>,
Expand Down
10 changes: 5 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading