diff --git a/.env.sample b/.env.sample index f04ddf0..a723023 100644 --- a/.env.sample +++ b/.env.sample @@ -13,4 +13,6 @@ E2E_TESTS_PAGE_ID= E2E_TESTS_PORTAL_ID= E2E_TESTS_TEMPLATE_ID= E2E_TESTS_TEMPLATE_PATH= -E2E_TESTS_WORKFLOW_ID= \ No newline at end of file +E2E_TESTS_WORKFLOW_ID= +E2E_TESTS_HAPI_DEVELOPER_KEY= +E2E_TESTS_APP_ID= \ No newline at end of file diff --git a/src/constants.js b/src/constants.js index d88164d..19d9eeb 100644 --- a/src/constants.js +++ b/src/constants.js @@ -173,6 +173,13 @@ export default { create: `${defaultApiHost}/url-mappings/v3/url-mappings`, update: `${defaultApiHost}/url-mappings/v3/url-mappings/{id}`, delete: `${defaultApiHost}/url-mappings/v3/url-mappings/{id}` + }, + + webhooks: { + getAll: `${defaultApiHost}/webhooks/v1/{appId}/subscriptions`, + create: `${defaultApiHost}/webhooks/v1/{appId}/subscriptions`, + update: `${defaultApiHost}/webhooks/v1/{appId}/subscriptions/{id}`, + delete: `${defaultApiHost}/webhooks/v1/{appId}/subscriptions/{id}` } } }; diff --git a/src/entities/webhooks.js b/src/entities/webhooks.js new file mode 100644 index 0000000..45744b4 --- /dev/null +++ b/src/entities/webhooks.js @@ -0,0 +1,167 @@ +import createRequest, { requiresAuthentication } from '../utilities'; +import constants from '../constants'; + +const defaults = {}; +let _baseOptions; + +const getSubscriptions = async (appId) => { + try { + requiresAuthentication(_baseOptions); + + const mergedProps = { ...defaults, ..._baseOptions }; + + const subscriptions = await createRequest( + constants.api.webhooks.getAll, + { appId }, + mergedProps + ); + return Promise.resolve(subscriptions); + } catch (e) { + return Promise.reject(e.message); + } +}; + +const createSubscription = async (appId, body = {}) => { + try { + requiresAuthentication(_baseOptions); + const method = 'POST'; + const url = constants.api.webhooks.create; + const options = { + appId, + method, + body + }; + + const mergedProps = { ...defaults, ..._baseOptions }; + const create = await createRequest(url, options, mergedProps); + + return Promise.resolve(create); + } catch (e) { + return Promise.reject(e.message); + } +}; + +const updateSubscription = async (appId, subscriptionId, body = {}) => { + try { + requiresAuthentication(_baseOptions); + const method = 'PUT'; + const url = constants.api.webhooks.update; + const options = { + appId, + id: subscriptionId, + method, + body + }; + + const mergedProps = { ...defaults, ..._baseOptions }; + const update = await createRequest(url, options, mergedProps); + + return Promise.resolve(update); + } catch (e) { + return Promise.reject(e.message); + } +}; + +const deleteSubscription = async (appId, subscriptionId) => { + try { + requiresAuthentication(_baseOptions); + const method = 'DELETE'; + const url = constants.api.webhooks.delete; + const options = { + appId, + id: subscriptionId, + method + }; + + const mergedProps = { ...defaults, ..._baseOptions }; + const del = await createRequest(url, options, mergedProps); + + return Promise.resolve(del); + } catch (e) { + return Promise.reject(e.message); + } +}; + +export default function webhooksApi(baseOptions) { + _baseOptions = baseOptions; + + return { + /** + * Retrieve all webhook subscriptions for given appId + * @async + * @memberof hs/getSubscriptions + * @method getSubscriptions + * + * @param {number} appId The app id + * + * @returns {Promise} + * + * @example + * const hs = new HubspotClient(props); + * hs.webhooks.getSubscriptions(123456789).then(response => console.log(response)) + */ + getSubscriptions, + /** + * Create new webhook subscription + * @async + * @memberof hs/createSubscription + * @method getFolders + * + * @param {number} appId The appId + * @param {object} payload Subscription body + * + * @returns {Promise} + * + * @example + * const hs = new HubspotClient(props); + * hs.webhooks.createSubscription(123456789, { + * { + * "subscriptionDetails": { + * "subscriptionType": "company.propertyChange", + * "propertyName": "companyname" + * }, + * "enabled": false + * } + * }).then(response => console.log(response)) + */ + createSubscription, + /** + * Create new webhook subscription + * @async + * @memberof hs/createSubscription + * @method getFolders + * + * @param {number} appId The appId + * @param {number} subscriptionId The subscriptionId + * @param {object} payload Subscription body + * + * @returns {Promise} + * + * @example + * const hs = new HubspotClient(props); + * hs.webhooks.updateSubscription(123456789, 123, { + * { + * "enabled": false + * } + * }).then(response => console.log(response)) + */ + updateSubscription, + /** + * Create new webhook subscription + * @async + * @memberof hs/createSubscription + * @method getFolders + * + * @param {number} appId The appId + * @param {number} subscriptionId The subscription id + * + * @returns {Promise} + * + * @example + * const hs = new HubspotClient(props); + * hs.webhooks.deleteSubscription(123456789, 123) + * .then(response => console.log(response)) + */ + deleteSubscription + }; +} diff --git a/src/index.js b/src/index.js index fed3b88..7c18359 100644 --- a/src/index.js +++ b/src/index.js @@ -20,6 +20,7 @@ import oauthApi from './entities/oauth'; import contactsListsApi from './entities/contacts-lists'; import emailSubscriptionsApi from './entities/email-subscriptions'; import transactionalEmailsApi from './entities/transactional-emails'; +import webhooksApi from './entities/webhooks'; /** * HubSpotClient class @@ -216,6 +217,14 @@ class HubSpotClient { get transactionalEmails() { return transactionalEmailsApi(this.props); } + + /** + * A collection of methods related to the Webhooks Subscription API + * @namespace hs/webhooks + */ + get webhooks() { + return webhooksApi(this.props); + } } export default HubSpotClient; diff --git a/test/schemas/webhooks.js b/test/schemas/webhooks.js new file mode 100644 index 0000000..1db819f --- /dev/null +++ b/test/schemas/webhooks.js @@ -0,0 +1,21 @@ +const joi = require('joi'); + +const schemaSubscription = joi.object().keys({ + id: joi.number(), + createdAt: joi.number(), + createdBy: joi.number().allow(null), + subscriptionDetails: joi.object().keys({ + subscriptionType: joi.string(), + propertyName: joi.string(), + propertyMaybe: joi.string().allow(null) + }), + enabled: joi.boolean(), + createdViaApi: joi.boolean() +}); + +const schemaSubscriptions = joi.array().items(schemaSubscription); +module.exports = { + schemaSubscription, + schemaSubscriptions, + validate: joi.validate +}; diff --git a/test/webhooks.js b/test/webhooks.js new file mode 100644 index 0000000..b159f52 --- /dev/null +++ b/test/webhooks.js @@ -0,0 +1,47 @@ +require('dotenv').config(); +const { expect } = require('chai'); +const debug = require('debug')('hubspot-api:tests'); //eslint-disable-line +const HubSpotClient = require('../dist/bundle.min'); +const { + schemaSubscription, + schemaSubscriptions, + validate +} = require('./schemas/webhooks'); + +const { E2E_TESTS_HAPI_DEVELOPER_KEY: hapikey, E2E_TESTS_APP_ID: appId } = process.env; + +const hs = new HubSpotClient({ hapikey }); + +let id; +describe('Entity:subscriptions', async () => { + it('gets all', async () => { + const response = await hs.webhooks.getSubscriptions(appId); + const valid = validate(response, schemaSubscriptions); + expect(valid.error).to.be.a('null'); + + return Promise.resolve(); + }); + + it('Create subscription', async () => { + const response = await hs.webhooks.createSubscription(appId, { + subscriptionDetails: { + subscriptionType: 'company.propertyChange', + propertyName: 'newpropertynew' + }, + enabled: false + }); + id = response.id; + + const valid = validate(response, schemaSubscription); + expect(valid.error).to.be.a('null'); + return Promise.resolve(); + }); + + it('delete subscription', async () => { + const response = await hs.webhooks.deleteSubscription(appId, id); + + // const valid = validate(response, schemaSubscription); + // expect(valid.error).to.be.a('null'); + return Promise.resolve(); + }); +}); diff --git a/types/main.d.ts b/types/main.d.ts index 438351d..0b5354b 100644 --- a/types/main.d.ts +++ b/types/main.d.ts @@ -21,6 +21,7 @@ declare class HubSpotClient { hubdb: any // hubdbApi; engagements: any // IEngagementsApi; templates: any + webhooks: any // IWebhooksApi } declare namespace HubSpotClient { @@ -147,6 +148,10 @@ interface hubdbApi { } +interface IWebhooksApi { + +} + interface IEngagementsApi { }