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
7 changes: 6 additions & 1 deletion .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,18 @@ runs:
steps:
- uses: pnpm/action-setup@v4
with:
version: 8.6.2
version: 10.12.4

- uses: actions/setup-node@v3
with:
node-version: '22.17.0'
check-latest: true

- name: Install Node Gyp Build
shell: ${{ runner.os == 'Windows' && 'pwsh' || 'bash' }}
run: |
npm install -g node-gyp-build

- name: Install dependencies
shell: ${{ runner.os == 'Windows' && 'pwsh' || 'bash' }}
run: pnpm i --frozen-lockfile
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/deploy-integrations-production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
uses: ./.github/actions/deploy-integrations
with:
environment: 'production'
extra_filter: "-F '!intercom' -F '!calendly' -F '!hubspot'"
extra_filter: "-F '!intercom' -F '!calendly'"
force: ${{ github.event.inputs.force == 'true' }}
sentry_auth_token: ${{ secrets.SENTRY_AUTH_TOKEN }}
token_cloud_ops_account: ${{ secrets.PRODUCTION_TOKEN_CLOUD_OPS_ACCOUNT }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/deploy-integrations-staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ jobs:
uses: ./.github/actions/deploy-integrations
with:
environment: 'staging'
extra_filter: "-F '!calendly'"
force: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.force == 'true' }}
dry_run: ${{ github.event_name == 'pull_request' }}
sentry_auth_token: ${{ secrets.SENTRY_AUTH_TOKEN }}
Expand Down
2 changes: 2 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
link-workspace-packages=true

2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
pnpm 8.6.2
pnpm 10.12.4
nodejs 22.17.0
tilt 0.35.0
226 changes: 226 additions & 0 deletions integrations/hubspot/definitions/actions/contact.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
import { z, ActionDefinition } from '@botpress/sdk'

// TODO: Extract common schema for contact

const searchContact: ActionDefinition = {
title: 'Search Contact',
description: 'Search for a contact in Hubspot',
input: {
schema: z.object({
email: z.string().optional().title('Email').describe('The email of the contact to search for'),
phone: z.string().optional().title('Phone').describe('The phone number of the contact to search for'),
properties: z
.array(z.string())
.optional()
.title('Property Names')
.describe('The properties to include in the response'),
}),
},
output: {
schema: z.object({
contact: z
.object({
id: z.string().title('Contact ID').describe('The ID of the contact'),
properties: z.record(z.any()).title('Properties').describe('The properties of the contact'),
})
.optional()
.title('Contact')
.describe('The contact found'),
}),
},
}

const createContact: ActionDefinition = {
title: 'Create Contact',
description: 'Create a contact in Hubspot',
input: {
schema: z.object({
email: z.string().optional().title('Email').describe('The email of the contact'),
phone: z.string().optional().title('Phone').describe('The phone number of the contact'),
owner: z.string().optional().title('Owner').describe('The ID or email of the owner of the contact'),
companies: z
.array(
z.object({
idOrNameOrDomain: z
.string()
.title('Company ID, name or domain')
.describe('The ID, name or domain of the company'),
primary: z
.boolean()
.optional()
.title('Primary Contact')
.describe('Whether the contact is the primary contact for the company'),
})
)
.optional()
.title('Companies')
.describe('The companies to which the contact is associated'),
tickets: z
.array(z.string().title('Ticket ID').describe('The ID of the ticket'))
.optional()
.title('Tickets')
.describe('The tickets to which the contact is associated'),
// TODO: Associate leads?
properties: z
.array(
z.object({
name: z.string().title('Property Name').describe('The name of the property'),
value: z.string().title('Property Value').describe('The value of the property'),
})
)
.title('Additional Properties')
.optional()
.describe('Additional properties of the contact'),
}),
},
output: {
schema: z.object({
contact: z
.object({
id: z.string().title('Contact ID').describe('The ID of the contact'),
properties: z.record(z.any()).title('Properties').describe('The properties of the contact'),
})
.title('Contact')
.describe('The created contact'),
}),
},
}

const getContact: ActionDefinition = {
title: 'Get Contact',
description: 'Get a contact from Hubspot',
input: {
schema: z.object({
contactIdOrEmail: z
.string()
.min(1)
.title('Contact ID or Email')
.describe('The ID or email of the contact to get'),
properties: z
.array(z.string())
.optional()
.title('Properties')
.describe('The properties to include in the response'),
}),
},
output: {
schema: z.object({
contact: z
.object({
id: z.string().title('Contact ID').describe('The ID of the contact'),
properties: z.record(z.any()).title('Properties').describe('The properties of the contact'),
})
.title('Contact')
.describe('The fetched contact'),
}),
},
}

const updateContact: ActionDefinition = {
title: 'Update Contact',
description: 'Update a contact in Hubspot',
input: {
schema: z.object({
contactIdOrEmail: z
.string()
.min(1)
.title('Contact ID or Email')
.describe('The ID or email of the contact to update'),
email: z.string().optional().title('Email').describe('The new email of the contact'),
phone: z.string().optional().title('Phone').describe('The new phone number of the contact'),
properties: z
.array(
z.object({
name: z.string().title('Property Name').describe('The name of the property'),
value: z.string().title('Property Value').describe('The new value of the property'),
})
)
.title('Additional Properties')
.optional()
.describe('Additional properties of the contact'),
}),
},
output: {
schema: z.object({
contact: z
.object({
id: z.string().title('Contact ID').describe('The ID of the contact'),
properties: z.record(z.any()).title('Properties').describe('The properties of the contact'),
})
.title('Contact')
.describe('The updated contact'),
}),
},
}

const deleteContact: ActionDefinition = {
title: 'Delete Contact',
description: 'Delete a contact in Hubspot',
input: {
schema: z.object({
contactId: z.string().min(1).title('Contact ID').describe('The ID of the contact to delete'),
}),
},
output: {
schema: z.object({}).title('Empty').describe('Empty output'),
},
}

const listContacts: ActionDefinition = {
title: 'List Contacts',
description: 'List contacts in Hubspot',
input: {
schema: z.object({
properties: z
.array(z.string())
.optional()
.title('Properties')
.describe('The properties to include in the response'),
meta: z
.object({
nextToken: z
.string()
.optional()
.title('Pagination token')
.describe('The token to get the next page of contacts'),
})
.title('Metadata')
.describe('Metadata containing pagination information'),
}),
},
output: {
schema: z.object({
contacts: z
.array(
z
.object({
id: z.string().title('Contact ID').describe('The ID of the contact'),
properties: z.record(z.any()).title('Properties').describe('The properties of the contact'),
})
.title('Contact')
.describe('A contact')
)
.title('Contacts')
.describe('The contacts found'),
meta: z
.object({
nextToken: z
.string()
.optional()
.title('Pagination token')
.describe('The token to get the next page of contacts'),
})
.title('Metadata')
.describe('Metadata containing pagination information'),
}),
},
}

export const actions = {
searchContact,
createContact,
getContact,
updateContact,
deleteContact,
listContacts,
} as const
112 changes: 112 additions & 0 deletions integrations/hubspot/definitions/actions/deal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { z, ActionDefinition } from '@botpress/sdk'

const dealSchema = z
.object({
id: z.string().title('Deal ID').describe('The ID of the deal'),
name: z.string().title('Name').describe('The name of the deal'),
createdAt: z.string().title('Created At').describe('Creation date of the deal'),
updatedAt: z.string().title('Updated At').describe('Last time the deal was updated'),
properties: z.record(z.any()).title('Properties').describe('The properties of the deal'),
})
.title('Deal')
.describe('The deal object')

const searchDeal: ActionDefinition = {
title: 'Search Deal',
description: 'Search for a deal in Hubspot',
input: {
schema: z.object({
name: z.string().optional().title('Name').describe('The name of the deal to search for'),
}),
},
output: {
schema: z.object({
deal: dealSchema,
}),
},
}

const createDeal: ActionDefinition = {
title: 'Create Deal',
description: 'Create a deal in Hubspot',
input: {
schema: z.object({
properties: z
.array(
z.object({
name: z.string().title('Property Name').describe('The name of the property'),
value: z.string().title('Property Value').describe('The value of the property'),
})
)
.optional()
.title('Properties')
.describe('The properties of the deal'),
}),
},
output: {
schema: z.object({
deal: dealSchema,
}),
},
}

const getDeal: ActionDefinition = {
title: 'Get Deal',
description: 'Get a deal from Hubspot',
input: {
schema: z.object({
dealId: z.string().title('Deal ID').describe('The ID of the deal to get'),
}),
},
output: {
schema: z.object({
deal: dealSchema,
}),
},
}

const updateDeal: ActionDefinition = {
title: 'Update Deal',
description: 'Update a deal in Hubspot',
input: {
schema: z.object({
dealId: z.string().title('Deal ID').describe('The ID of the deal to update'),
properties: z
.array(
z.object({
name: z.string().title('Property Name').describe('The name of the property'),
value: z.string().title('Property Value').describe('The value of the property'),
})
)
.optional()
.title('Properties')
.describe('The properties of the deal'),
}),
},
output: {
schema: z.object({
deal: dealSchema,
}),
},
}

const deleteDeal: ActionDefinition = {
title: 'Delete Deal',
description: 'Delete a deal in Hubspot',
input: {
schema: z.object({
dealId: z.string().title('Deal ID').describe('The ID of the deal to delete'),
}),
},
output: {
schema: z.object({}).title('Empty').describe('Empty output'),
},
}

export const actions = {
searchDeal,
createDeal,
getDeal,
updateDeal,
deleteDeal,
} as const
11 changes: 11 additions & 0 deletions integrations/hubspot/definitions/actions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { actions as contactActions } from './contact'
import { actions as dealActions } from './deal'
import { actions as leadActions } from './lead'
import { actions as ticketActions } from './ticket'

export const actions = {
...contactActions,
...ticketActions,
...dealActions,
...leadActions,
} as const
Loading
Loading