diff --git a/packages/backend/src/apps/hubspot/actions/create-contact/index.ts b/packages/backend/src/apps/hubspot/actions/create-contact/index.ts new file mode 100644 index 00000000..8c6c6317 --- /dev/null +++ b/packages/backend/src/apps/hubspot/actions/create-contact/index.ts @@ -0,0 +1,92 @@ +import defineAction from '../../../../helpers/define-action'; + +export default defineAction({ + name: 'Create contact', + key: 'createContact', + description: `Create contact on user's account.`, + arguments: [ + { + label: 'Company', + key: 'company', + type: 'string' as const, + required: false, + description: 'company name', + variables: true, + }, + { + label: 'E-mail', + key: 'email', + type: 'string' as const, + required: false, + description: 'Contact email', + variables: true, + }, + { + label: 'First name', + key: 'firstname', + type: 'string' as const, + required: false, + description: 'Contact First name', + variables: true, + }, + { + label: 'Last name', + key: 'lastname', + type: 'string' as const, + required: false, + description: 'Contact Last name', + variables: true, + }, + { + label: 'Phone', + key: 'phone', + type: 'string' as const, + required: false, + description: 'Contact phone number', + variables: true, + }, + { + label: 'Webiste URL', + key: 'website', + type: 'string' as const, + required: false, + description: 'Contact Webiste URL', + variables: true, + }, + { + label: 'Owner ID', + key: 'hubspot_owner_id', + type: 'string' as const, + required: false, + description: 'Contact Owner ID', + variables: true, + }, + ], + + async run($) { + const company = $.step.parameters.company as string || undefined; + const email = $.step.parameters.email as string || undefined; + const firstname = $.step.parameters.firstname as string || undefined; + const lastname = $.step.parameters.lastname as string || undefined; + const phone = $.step.parameters.phone as string || undefined; + const website = $.step.parameters.website as string || undefined; + const hubspot_owner_id = $.step.parameters.hubspot_owner_id as number || undefined; + + const response = await $.http.post( + `crm/v3/objects/contacts`, + { + properties: { + company, + email, + firstname, + lastname, + phone, + website, + hubspot_owner_id, + } + } + ); + + $.setActionItem({ raw: response.data }); + }, +}); diff --git a/packages/backend/src/apps/hubspot/actions/index.ts b/packages/backend/src/apps/hubspot/actions/index.ts new file mode 100644 index 00000000..fe753ed8 --- /dev/null +++ b/packages/backend/src/apps/hubspot/actions/index.ts @@ -0,0 +1,3 @@ +import createContact from './create-contact'; + +export default [ createContact ]; diff --git a/packages/backend/src/apps/hubspot/assets/favicon.svg b/packages/backend/src/apps/hubspot/assets/favicon.svg new file mode 100644 index 00000000..c21891fb --- /dev/null +++ b/packages/backend/src/apps/hubspot/assets/favicon.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/packages/backend/src/apps/hubspot/auth/index.ts b/packages/backend/src/apps/hubspot/auth/index.ts new file mode 100644 index 00000000..02064ff5 --- /dev/null +++ b/packages/backend/src/apps/hubspot/auth/index.ts @@ -0,0 +1,20 @@ +import verifyCredentials from "./verify-credentials"; +import isStillVerified from "./is-still-verified"; + +export default { + fields: [ + { + key: 'accessToken', + label: 'Access Token', + type: 'string' as const, + required: true, + readOnly: false, + value: null, + placeholder: null, + description: null, + clickToCopy: false, + }, + ], + verifyCredentials, + isStillVerified +}; diff --git a/packages/backend/src/apps/hubspot/auth/is-still-verified.ts b/packages/backend/src/apps/hubspot/auth/is-still-verified.ts new file mode 100644 index 00000000..4470a643 --- /dev/null +++ b/packages/backend/src/apps/hubspot/auth/is-still-verified.ts @@ -0,0 +1,9 @@ +import { IGlobalVariable } from '@automatisch/types'; +import verifyCredentials from "./verify-credentials"; + +const isStillVerified = async ($: IGlobalVariable) => { + await verifyCredentials($); + return true; +}; + +export default isStillVerified; diff --git a/packages/backend/src/apps/hubspot/auth/verify-credentials.ts b/packages/backend/src/apps/hubspot/auth/verify-credentials.ts new file mode 100644 index 00000000..cff860ba --- /dev/null +++ b/packages/backend/src/apps/hubspot/auth/verify-credentials.ts @@ -0,0 +1,12 @@ +import { IGlobalVariable } from '@automatisch/types'; + +const verifyCredentials = async ($: IGlobalVariable) => { + await $.http.get( + `/crm/v3/objects/contacts?limit=1`, + ); + await $.auth.set({ + screenName: $.auth.data?.displayName, + }); +}; + +export default verifyCredentials; diff --git a/packages/backend/src/apps/hubspot/common/add-auth-header.ts b/packages/backend/src/apps/hubspot/common/add-auth-header.ts new file mode 100644 index 00000000..d16f394f --- /dev/null +++ b/packages/backend/src/apps/hubspot/common/add-auth-header.ts @@ -0,0 +1,14 @@ +import { TBeforeRequest } from '@automatisch/types'; + +const addAuthHeader: TBeforeRequest = ($, requestConfig) => { + if (requestConfig.additionalProperties?.skipAddingAuthHeader) return requestConfig; + + if ($.auth.data?.accessToken) { + const authorizationHeader = `Bearer ${$.auth.data.accessToken}`; + requestConfig.headers.Authorization = authorizationHeader; + } + + return requestConfig; +}; + +export default addAuthHeader; diff --git a/packages/backend/src/apps/hubspot/index.d.ts b/packages/backend/src/apps/hubspot/index.d.ts new file mode 100644 index 00000000..e69de29b diff --git a/packages/backend/src/apps/hubspot/index.ts b/packages/backend/src/apps/hubspot/index.ts new file mode 100644 index 00000000..3855131c --- /dev/null +++ b/packages/backend/src/apps/hubspot/index.ts @@ -0,0 +1,18 @@ +import defineApp from '../../helpers/define-app'; +import addAuthHeader from './common/add-auth-header'; +import actions from './actions'; +import auth from './auth'; + +export default defineApp({ + name: 'Hubspot', + key: 'hubspot', + iconUrl: '{BASE_URL}/apps/hubspot/assets/favicon.svg', + authDocUrl: 'https://developers.hubspot.com/docs/api/crm/contacts', + supportsConnections: true, + baseUrl: 'https://www.hubspot.com', + apiBaseUrl: 'https://api.hubapi.com', + primaryColor: '000000', + beforeRequest: [addAuthHeader], + auth, + actions, +}); diff --git a/packages/docs/pages/.vitepress/config.js b/packages/docs/pages/.vitepress/config.js index d87539a5..76dc9d9e 100644 --- a/packages/docs/pages/.vitepress/config.js +++ b/packages/docs/pages/.vitepress/config.js @@ -271,6 +271,15 @@ export default defineConfig({ { text: 'Connection', link: '/apps/spotify/connection' }, ], }, + { + text: 'Hubspot', + collapsible: true, + collapsed: true, + items: [ + { text: 'Actions', link: '/apps/hubspot/actions' }, + { text: 'Connection', link: '/apps/hubspot/connection' }, + ], + }, { text: 'Strava', collapsible: true, diff --git a/packages/docs/pages/apps/hubspot/actions.md b/packages/docs/pages/apps/hubspot/actions.md new file mode 100644 index 00000000..f2ae7746 --- /dev/null +++ b/packages/docs/pages/apps/hubspot/actions.md @@ -0,0 +1,12 @@ +--- +favicon: /favicons/hubspot.svg +items: + - name: Create a contact + desc: Create a contact on user's account. +--- + + + + diff --git a/packages/docs/pages/apps/hubspot/connection.md b/packages/docs/pages/apps/hubspot/connection.md new file mode 100644 index 00000000..df4467b9 --- /dev/null +++ b/packages/docs/pages/apps/hubspot/connection.md @@ -0,0 +1,11 @@ +# Spotify + +:::info +This page explains the steps you need to follow to set up the Hubspot connection in Automatisch. If any of the steps are outdated, please let us know! +::: + +1. Create new app +1. Create new app token +1. Paste **API TOKEN** value into Automatisch as **Access Token**, respectively. +1. Click **Submit** button on Automatisch. +1. Now, you can start using the Spotify connection with Automatisch. diff --git a/packages/docs/pages/guide/available-apps.md b/packages/docs/pages/guide/available-apps.md index 63578431..e76f7f3c 100644 --- a/packages/docs/pages/guide/available-apps.md +++ b/packages/docs/pages/guide/available-apps.md @@ -28,6 +28,7 @@ The following integrations are currently supported by Automatisch. - [Slack](/apps/slack/actions) - [SMTP](/apps/smtp/actions) - [Spotify](/apps/spotify/actions) +- [Hubspot](/apps/hubspot/actions) - [Strava](/apps/strava/actions) - [Stripe](/apps/stripe/triggers) - [Telegram](/apps/telegram-bot/actions) diff --git a/packages/docs/pages/public/favicons/hubspot.svg b/packages/docs/pages/public/favicons/hubspot.svg new file mode 100644 index 00000000..c21891fb --- /dev/null +++ b/packages/docs/pages/public/favicons/hubspot.svg @@ -0,0 +1,8 @@ + + + + + + + +