diff --git a/components/clarify/actions/create-company/create-company.mjs b/components/clarify/actions/create-company/create-company.mjs new file mode 100644 index 0000000000000..07712c27ad89b --- /dev/null +++ b/components/clarify/actions/create-company/create-company.mjs @@ -0,0 +1,70 @@ +import app from "../../clarify.app.mjs"; +import constants from "../../common/constants.mjs"; + +export default { + key: "clarify-create-company", + name: "Create Company", + description: "Creates a new company record in the Clarify system. [See the documentation](https://api.getclarify.ai/swagger#/default/createRecord).", + version: "0.0.1", + type: "action", + props: { + app, + workspace: { + propDefinition: [ + app, + "workspace", + ], + }, + name: { + propDefinition: [ + app, + "companyName", + ], + }, + domain: { + propDefinition: [ + app, + "companyDomain", + ], + }, + }, + methods: { + createCompany({ + workspace, ...args + } = {}) { + return this.app.post({ + path: `/workspaces/${workspace}/objects/${constants.OBJECT_ENTITY.COMPANY}/records`, + ...args, + }); + }, + }, + async run({ $ }) { + const { + createCompany, + workspace, + name, + domain, + } = this; + + const response = await createCompany({ + $, + workspace, + data: { + data: { + type: "object", + attributes: { + name, + domains: { + items: [ + domain, + ], + }, + }, + }, + }, + }); + + $.export("$summary", "Successfully created company."); + return response; + }, +}; diff --git a/components/clarify/actions/find-user/find-user.mjs b/components/clarify/actions/find-user/find-user.mjs new file mode 100644 index 0000000000000..45403b6775d53 --- /dev/null +++ b/components/clarify/actions/find-user/find-user.mjs @@ -0,0 +1,79 @@ +import app from "../../clarify.app.mjs"; + +export default { + key: "clarify-find-user", + name: "Find User", + description: "Searches within the Clarify system for a user based on the given 'email' prop. Returns the found user. [See the documentation](https://api.getclarify.ai/swagger#/default/getUsers).", + version: "0.0.1", + type: "action", + props: { + app, + workspace: { + propDefinition: [ + app, + "workspace", + ], + }, + email: { + type: "string", + label: "Email", + description: "The email of the user to search for.", + }, + firstName: { + type: "string", + label: "First Name", + description: "The first name of the user to search for.", + optional: true, + }, + lastName: { + type: "string", + label: "Last Name", + description: "The last name of the user to search for.", + optional: true, + }, + }, + methods: { + getUsers({ + workspace, ...args + } = {}) { + return this.app._makeRequest({ + path: `/workspaces/${workspace}/users`, + ...args, + }); + }, + }, + async run({ $ }) { + const { + getUsers, + workspace, + email, + firstName, + lastName, + } = this; + + const response = await getUsers({ + $, + workspace, + params: { + limit: 1000, + }, + }); + + const userFound = response.data.find(({ attributes }) => + attributes.email === email + || attributes.firstName?.toLowerCase()?.includes(firstName?.toLowerCase()) + || attributes.lastName?.toLowerCase()?.includes(lastName?.toLowerCase()) + || attributes?.name?.first_name?.toLowerCase()?.includes(firstName?.toLowerCase()) + || attributes?.name?.last_name?.toLowerCase()?.includes(lastName?.toLowerCase())); + + if (!userFound) { + $.export("$summary", "No user found with the given attributes."); + return { + success: false, + }; + } + + $.export("$summary", "Successfully found user."); + return userFound; + }, +}; diff --git a/components/clarify/actions/update-person/update-person.mjs b/components/clarify/actions/update-person/update-person.mjs new file mode 100644 index 0000000000000..d34dbb9fd9f4a --- /dev/null +++ b/components/clarify/actions/update-person/update-person.mjs @@ -0,0 +1,72 @@ +import app from "../../clarify.app.mjs"; +import constants from "../../common/constants.mjs"; + +export default { + key: "clarify-update-person", + name: "Update Person", + description: "Updates an existing person record in the Clarify system. [See the documentation](https://api.getclarify.ai/swagger#/default/updateRecord).", + version: "0.0.1", + type: "action", + props: { + app, + workspace: { + propDefinition: [ + app, + "workspace", + ], + }, + personId: { + propDefinition: [ + app, + "personId", + ({ workspace }) => ({ + workspace, + }), + ], + }, + companyId: { + propDefinition: [ + app, + "companyId", + ({ workspace }) => ({ + workspace, + }), + ], + }, + }, + methods: { + updatePerson({ + workspace, personId, ...args + }) { + return this.app.patch({ + path: `/workspaces/${workspace}/objects/${constants.OBJECT_ENTITY.PERSON}/records/${personId}`, + ...args, + }); + }, + }, + async run({ $ }) { + const { + updatePerson, + workspace, + personId, + companyId, + } = this; + + const response = await updatePerson({ + $, + workspace, + personId, + data: { + data: { + type: "object", + attributes: { + companyId, + }, + }, + }, + }); + + $.export("$summary", "Successfully updated person."); + return response; + }, +}; diff --git a/components/clarify/clarify.app.mjs b/components/clarify/clarify.app.mjs index d5f1c88b2aa63..5055344eebfe7 100644 --- a/components/clarify/clarify.app.mjs +++ b/components/clarify/clarify.app.mjs @@ -1,11 +1,177 @@ +import { axios } from "@pipedream/platform"; +import constants from "./common/constants.mjs"; + export default { type: "app", app: "clarify", - propDefinitions: {}, + propDefinitions: { + workspace: { + type: "string", + label: "Workspace", + description: "The workspace name.", + async options() { + const { + workspace: { + name: label, + slug: value, + }, + } = await this.getProfile(); + + return [ + { + label, + value, + }, + ]; + }, + }, + companyName: { + type: "string", + label: "Company Name", + description: "The name of the company.", + }, + companyDomain: { + type: "string", + label: "Company Domain", + description: "The domain of the company.", + }, + companyId: { + type: "string", + label: "Company", + description: "The company to be added to a list.", + async options({ + workspace, prevContext: { offset = 0 }, + }) { + if ( offset === null ) { + return []; + } + const { data = [] } = this.listCompanies({ + workspace, + params: { + offset, + limit: constants.DEFAULT_LIMIT, + }, + }); + + return { + options: data.map(({ + attributes: { + _id: value, name: label, + }, + }) => ({ + label: label || value, + value, + })), + context: { + offset: data.length === constants.DEFAULT_LIMIT + ? offset + constants.DEFAULT_LIMIT + : null, + }, + }; + }, + }, + personId: { + type: "string", + label: "Person ID", + description: "The ID of the person.", + async options({ + workspace, prevContext: { offset = 0 }, + }) { + if ( offset === null ) { + return []; + } + const { data = [] } = this.listPeople({ + workspace, + params: { + offset, + limit: constants.DEFAULT_LIMIT, + }, + }); + + return { + options: data.map(({ + attributes: { + _id: value, email: label, + }, + }) => ({ + label: label || value, + value, + })), + context: { + offset: data.length === constants.DEFAULT_LIMIT + ? offset + constants.DEFAULT_LIMIT + : null, + }, + }; + }, + }, + list: { + type: "string", + label: "List", + description: "The list to add the company to.", + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + getUrl(path) { + return `${constants.BASE_URL}${constants.VERSION_PATH}${path}`; + }, + getHeaders(headers) { + return { + ...headers, + "Authorization": `Bearer ${this.$auth.oauth_access_token}`, + "Content-Type": "application/json", + "Accept": "application/json", + }; + }, + _makeRequest({ + $ = this, path, headers, ...args + } = {}) { + return axios($, { + ...args, + debug: true, + url: this.getUrl(path), + headers: this.getHeaders(headers), + }); + }, + post(args = {}) { + return this._makeRequest({ + method: "POST", + ...args, + }); + }, + patch(args = {}) { + return this._makeRequest({ + method: "PATCH", + ...args, + }); + }, + delete(args = {}) { + return this._makeRequest({ + method: "DELETE", + ...args, + }); + }, + getProfile(args = {}) { + return this._makeRequest({ + path: "/profile", + ...args, + }); + }, + listCompanies({ + workspace, ...args + } = {}) { + return this._makeRequest({ + path: `/workspaces/${workspace}/objects/${constants.OBJECT_ENTITY.COMPANY}/records`, + ...args, + }); + }, + listPeople({ + workspace, ...args + } = {}) { + return this._makeRequest({ + path: `/workspaces/${workspace}/objects/${constants.OBJECT_ENTITY.PERSON}/records`, + ...args, + }); }, }, -}; \ No newline at end of file +}; diff --git a/components/clarify/common/constants.mjs b/components/clarify/common/constants.mjs new file mode 100644 index 0000000000000..fc32101e2f7e0 --- /dev/null +++ b/components/clarify/common/constants.mjs @@ -0,0 +1,20 @@ +const BASE_URL = "https://api.getclarify.ai"; +const VERSION_PATH = "/v1"; +const WEBHOOK_ID = "webhookId"; + +const OBJECT_ENTITY = { + PERSON: "person", + COMPANY: "company", + DEAL: "deal", + MEETING: "meeting", +}; + +const DEFAULT_LIMIT = 100; + +export default { + BASE_URL, + VERSION_PATH, + OBJECT_ENTITY, + WEBHOOK_ID, + DEFAULT_LIMIT, +}; diff --git a/components/clarify/package.json b/components/clarify/package.json index 3ae7680e0a498..591db78b407cf 100644 --- a/components/clarify/package.json +++ b/components/clarify/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/clarify", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Clarify Components", "main": "clarify.app.mjs", "keywords": [ @@ -11,5 +11,8 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "3.0.3" } -} \ No newline at end of file +} diff --git a/components/clarify/sources/common/events.mjs b/components/clarify/sources/common/events.mjs new file mode 100644 index 0000000000000..bc96251adeef3 --- /dev/null +++ b/components/clarify/sources/common/events.mjs @@ -0,0 +1,5 @@ +export default { + CREATE: "clarify:create", + UPDATE: "clarify:update", + DELETE: "clarify:delete", +}; diff --git a/components/clarify/sources/common/webhook.mjs b/components/clarify/sources/common/webhook.mjs new file mode 100644 index 0000000000000..67e420f8ead77 --- /dev/null +++ b/components/clarify/sources/common/webhook.mjs @@ -0,0 +1,95 @@ +import { ConfigurationError } from "@pipedream/platform"; +import app from "../../clarify.app.mjs"; +import constants from "../../common/constants.mjs"; + +export default { + props: { + app, + db: "$.service.db", + http: "$.interface.http", + workspace: { + propDefinition: [ + app, + "workspace", + ], + }, + }, + hooks: { + async activate() { + const { + workspace, + createWebhook, + http: { endpoint: url }, + setWebhookId, + getEntity, + getEventType, + } = this; + + const response = + await createWebhook({ + workspace, + data: { + url, + entity: getEntity(), + event_type: getEventType(), + }, + }); + + setWebhookId(response.id); + }, + async deactivate() { + const { + workspace, + deleteWebhook, + getWebhookId, + } = this; + + const webhookId = getWebhookId(); + if (webhookId) { + await deleteWebhook({ + workspace, + webhookId, + }); + } + }, + }, + methods: { + generateMeta() { + throw new ConfigurationError("generateMeta is not implemented"); + }, + setWebhookId(value) { + this.db.set(constants.WEBHOOK_ID, value); + }, + getWebhookId() { + return this.db.get(constants.WEBHOOK_ID); + }, + getEntity() { + throw new ConfigurationError("getEntity is not implemented"); + }, + getEventType() { + throw new ConfigurationError("getEventType is not implemented"); + }, + processResource(resource) { + this.$emit(resource, this.generateMeta(resource)); + }, + createWebhook({ + workspace, ...args + } = {}) { + return this.app.post({ + path: `/workspaces/${workspace}/webhooks`, + ...args, + }); + }, + deleteWebhook({ + workspace, webhookId, ...args + } = {}) { + return this.app.delete({ + path: `/workspaces/${workspace}/webhooks/${webhookId}`, + ...args, + }); + }, + }, + async run({ body }) { + this.processResource(body); + }, +}; diff --git a/components/clarify/sources/company-added-to-list-instant/company-added-to-list-instant.mjs b/components/clarify/sources/company-added-to-list-instant/company-added-to-list-instant.mjs new file mode 100644 index 0000000000000..b508a1c042bc4 --- /dev/null +++ b/components/clarify/sources/company-added-to-list-instant/company-added-to-list-instant.mjs @@ -0,0 +1,31 @@ +import common from "../common/webhook.mjs"; +import events from "../common/events.mjs"; +import sampleEmit from "./test-event.mjs"; +import constants from "../../common/constants.mjs"; + +export default { + ...common, + key: "clarify-company-added-to-list-instant", + name: "Company Added To List (Instant)", + description: "Emit new event when a company is added to a list. [See the documentation](https://api.getclarify.ai/swagger#/default/createWebhook)", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getEntity() { + return constants.OBJECT_ENTITY.COMPANY; + }, + getEventType() { + return events.UPDATE; + }, + generateMeta(resource) { + return { + id: resource.id, + summary: `New Resource: ${resource.name}`, + ts: Date.parse(resource.created_at), + }; + }, + }, + sampleEmit, +}; diff --git a/components/clarify/sources/company-added-to-list-instant/test-event.mjs b/components/clarify/sources/company-added-to-list-instant/test-event.mjs new file mode 100644 index 0000000000000..4cf8644e1efcd --- /dev/null +++ b/components/clarify/sources/company-added-to-list-instant/test-event.mjs @@ -0,0 +1,31 @@ +export default { + "_id": "65c7d957-e39b-41bb-a108-8056cf087777", + "name": "Test 1", + "description": null, + "categories": null, + "primary_location": null, + "logo_url": null, + "profile_colors": null, + "angel_list": null, + "facebook": null, + "instagram": null, + "linkedin": null, + "twitter": null, + "estimated_arr": null, + "funding_raised": null, + "foundation_date": null, + "employee_range": null, + "first_calendar_interaction": null, + "last_calendar_interaction": null, + "next_calendar_interaction": null, + "first_email_interaction": null, + "last_email_interaction": null, + "first_interaction": null, + "last_interaction": null, + "connection_strength": null, + "strongest_connection": null, + "_created_by": "google-oauth2|108876212509670563181", + "_created_at": "2024-11-27T23:32:59.859Z", + "_enriched_at": null, + "attachments": {} +}; diff --git a/components/clarify/sources/new-company-instant/new-company-instant.mjs b/components/clarify/sources/new-company-instant/new-company-instant.mjs new file mode 100644 index 0000000000000..904c48b06e8e5 --- /dev/null +++ b/components/clarify/sources/new-company-instant/new-company-instant.mjs @@ -0,0 +1,29 @@ +import common from "../common/webhook.mjs"; +import events from "../common/events.mjs"; +import constants from "../../common/constants.mjs"; + +export default { + ...common, + key: "clarify-new-company-instant", + name: "New Company (Instant)", + description: "Emit new event when a new company is created. [See the documentation](https://api.getclarify.ai/swagger#/default/createWebhook).", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getEntity() { + return constants.OBJECT_ENTITY.COMPANY; + }, + getEventType() { + return events.CREATE; + }, + generateMeta(resource) { + return { + id: resource._id, + summary: `New Company ${resource.name}`, + ts: Date.parse(resource._created_at), + }; + }, + }, +}; diff --git a/components/clarify/sources/new-company-instant/test-event.mjs b/components/clarify/sources/new-company-instant/test-event.mjs new file mode 100644 index 0000000000000..3f03aaa650eaa --- /dev/null +++ b/components/clarify/sources/new-company-instant/test-event.mjs @@ -0,0 +1,36 @@ +export default { + "_id": "65c7d957-e39b-41bb-a108-8056cf087777", + "name": "Test 5", + "domains": { + "items": [ + "test5.com" + ] + }, + "description": null, + "categories": null, + "primary_location": null, + "logo_url": null, + "profile_colors": null, + "angel_list": null, + "facebook": null, + "instagram": null, + "linkedin": null, + "twitter": null, + "estimated_arr": null, + "funding_raised": null, + "foundation_date": null, + "employee_range": null, + "first_calendar_interaction": null, + "last_calendar_interaction": null, + "next_calendar_interaction": null, + "first_email_interaction": null, + "last_email_interaction": null, + "first_interaction": null, + "last_interaction": null, + "connection_strength": null, + "strongest_connection": null, + "_created_by": "google-oauth2|108876212509670563181", + "_created_at": "2024-11-27T23:32:59.859Z", + "_enriched_at": null, + "attachments": {} +}; diff --git a/components/clarify/sources/new-person-instant/new-person-instant.mjs b/components/clarify/sources/new-person-instant/new-person-instant.mjs new file mode 100644 index 0000000000000..c25a396684d55 --- /dev/null +++ b/components/clarify/sources/new-person-instant/new-person-instant.mjs @@ -0,0 +1,31 @@ +import common from "../common/webhook.mjs"; +import events from "../common/events.mjs"; +import constants from "../../common/constants.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + ...common, + key: "clarify-new-person-instant", + name: "New Person (Instant)", + description: "Emit new event when a new person is created. [See the documentation](https://api.getclarify.ai/swagger#/default/createWebhook).", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getEntity() { + return constants.OBJECT_ENTITY.PERSON; + }, + getEventType() { + return events.CREATE; + }, + generateMeta(resource) { + return { + id: resource._id, + summary: `New Person ${resource.name.first_name}`, + ts: Date.parse(resource._created_at), + }; + }, + }, + sampleEmit, +}; diff --git a/components/clarify/sources/new-person-instant/test-event.mjs b/components/clarify/sources/new-person-instant/test-event.mjs new file mode 100644 index 0000000000000..83668f39475bb --- /dev/null +++ b/components/clarify/sources/new-person-instant/test-event.mjs @@ -0,0 +1,37 @@ +export default { + "_id": "f97bb865-80c3-4b93-affa-07dada05026a", + "name": { + "full_name": "Test 1 Test 2", + "last_name": "Test 2", + "first_name": "Test 1" + }, + "company_id": "6314a881-7161-462e-8b1d-3758286d1940", + "job_title": null, + "email_addresses": { + "items": [ + "test1@test.com" + ] + }, + "description": null, + "avatar_url": null, + "profile_colors": null, + "phone_numbers": null, + "primary_location": null, + "angel_list": null, + "facebook": null, + "instagram": null, + "linkedin": null, + "twitter": null, + "first_calendar_interaction": null, + "last_calendar_interaction": null, + "next_calendar_interaction": null, + "first_email_interaction": null, + "last_email_interaction": null, + "first_interaction": null, + "last_interaction": null, + "connection_strength": null, + "attachments": {}, + "_created_by": "google-oauth2|108876212509670563181", + "_created_at": "2024-11-27T23:26:47.007Z", + "_enriched_at": null +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3630d84c9e4ca..09d515654f7c1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1769,7 +1769,11 @@ importers: specifier: ^3.0.1 version: 3.0.1(web-streams-polyfill@3.3.3) - components/clarify: {} + components/clarify: + dependencies: + '@pipedream/platform': + specifier: 3.0.3 + version: 3.0.3 components/clearbit: dependencies: