diff --git a/components/suitedash/.gitignore b/components/suitedash/.gitignore deleted file mode 100644 index ec761ccab7595..0000000000000 --- a/components/suitedash/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.js -*.mjs -dist \ No newline at end of file diff --git a/components/suitedash/actions/create-company/create-company.mjs b/components/suitedash/actions/create-company/create-company.mjs new file mode 100644 index 0000000000000..c497119ddf5a0 --- /dev/null +++ b/components/suitedash/actions/create-company/create-company.mjs @@ -0,0 +1,79 @@ +import suitedash from "../../suitedash.app.mjs"; + +export default { + key: "suitedash-create-company", + name: "Create Company", + description: "Creates a new company in SuiteDash. [See the documentation](https://app.suitedash.com/secure-api/swagger)", + version: "0.0.1", + type: "action", + props: { + suitedash, + companyName: { + propDefinition: [ + suitedash, + "companyName", + ], + }, + companyRole: { + propDefinition: [ + suitedash, + "role", + ], + }, + firstName: { + type: "string", + label: "First Name", + description: "First name of the company's primary contact", + }, + lastName: { + type: "string", + label: "Last Name", + description: "Last name of the company's primary contact", + }, + email: { + type: "string", + label: "Email", + description: "Email address of the company's primary contact", + }, + sendWelcomeEmail: { + type: "boolean", + label: "Send Welcome Email", + description: "Send welcome email to the primary contact. Default: `false`", + optional: true, + default: false, + }, + createPrimaryContactIfNotExists: { + type: "boolean", + label: "Create Primary Contact If Not Exists", + description: "Create a Primary Contact with all provided data if the email does not exist. Default: `true`", + optional: true, + default: true, + }, + preventIndividualMode: { + type: "boolean", + label: "Prevent Individual Mode", + description: "Prevent this Primary Contact from switching into `Individual Mode`. Default: `false`", + optional: true, + default: false, + }, + }, + async run({ $ }) { + const response = await this.suitedash.createCompany({ + $, + data: { + name: this.companyName, + role: this.companyRole, + primaryContact: { + first_name: this.firstName, + last_name: this.lastName, + email: this.email, + send_welcome_email: this.sendWelcomeEmail, + create_primary_contact_if_not_exists: this.createPrimaryContactIfNotExists, + prevent_individual_mode: this.preventIndividualMode, + }, + }, + }); + $.export("$summary", `Successfully created company ${this.companyName}`); + return response; + }, +}; diff --git a/components/suitedash/actions/create-contact/create-contact.mjs b/components/suitedash/actions/create-contact/create-contact.mjs new file mode 100644 index 0000000000000..e81198c85fae6 --- /dev/null +++ b/components/suitedash/actions/create-contact/create-contact.mjs @@ -0,0 +1,55 @@ +import suitedash from "../../suitedash.app.mjs"; + +export default { + key: "suitedash-create-contact", + name: "Create Contact", + description: "Creates a new contact in SuiteDash. [See the documentation](https://app.suitedash.com/secure-api/swagger)", + version: "0.0.1", + type: "action", + props: { + suitedash, + firstName: { + type: "string", + label: "Contact First Name", + description: "The first name of the new contact", + }, + lastName: { + type: "string", + label: "Contact Last Name", + description: "The last name of the new contact", + }, + email: { + type: "string", + label: "Contact Email", + description: "The email of the new contact", + }, + role: { + propDefinition: [ + suitedash, + "role", + ], + label: "Contact Role", + description: "The role of the new contact", + }, + sendWelcomeEmail: { + type: "boolean", + label: "Send Welcome Email", + description: "Whether to send a welcome email to the new contact", + optional: true, + }, + }, + async run({ $ }) { + const response = await this.suitedash.createContact({ + $, + data: { + first_name: this.firstName, + last_name: this.lastName, + email: this.email, + role: this.role, + send_welcome_email: this.sendWelcomeEmail, + }, + }); + $.export("$summary", `Successfully created contact ${this.firstName} ${this.lastName}`); + return response; + }, +}; diff --git a/components/suitedash/actions/update-company/update-company.mjs b/components/suitedash/actions/update-company/update-company.mjs new file mode 100644 index 0000000000000..ee0f0959e2182 --- /dev/null +++ b/components/suitedash/actions/update-company/update-company.mjs @@ -0,0 +1,82 @@ +import suitedash from "../../suitedash.app.mjs"; +import { ConfigurationError } from "@pipedream/platform"; + +export default { + key: "suitedash-update-company", + name: "Update Company", + description: "Updates an existing company's details in SuiteDash. [See the documentation](https://app.suitedash.com/secure-api/swagger)", + version: "0.0.1", + type: "action", + props: { + suitedash, + companyId: { + propDefinition: [ + suitedash, + "companyId", + ], + }, + companyName: { + propDefinition: [ + suitedash, + "companyName", + ], + optional: true, + }, + website: { + type: "string", + label: "Website", + description: "The website of the company.", + optional: true, + }, + phone: { + type: "string", + label: "Phone", + description: "The phone number of the company", + optional: true, + }, + companyAddress: { + type: "string", + label: "Company Address", + description: "The full address of the company. Example: dba Staybridge Suites Mount Laurel 324 Church Road Mount Laurel, NJ 09478", + optional: true, + }, + tags: { + type: "string[]", + label: "Tags", + description: "An array of tags associated with the company", + optional: true, + }, + backgroundInfo: { + type: "string", + label: "Background Info", + description: "Background information about the company", + optional: true, + }, + }, + async run({ $ }) { + if (!this.companyName + && !this.website + && !this.phone + && !this.companyAddress + && !this.tags + && !this.backgroundInfo + ) { + throw new ConfigurationError("Please enter at least one field to update"); + } + + const response = await this.suitedash.updateCompany({ + $, + companyId: this.companyId, + data: { + name: this.companyName, + website: this.website, + phone: this.phone, + full_address: this.companyAddress, + tags: this.tags, + background_info: this.backgroundInfo, + }, + }); + $.export("$summary", `Successfully updated company ${this.companyId}`); + return response; + }, +}; diff --git a/components/suitedash/app/suitedash.app.ts b/components/suitedash/app/suitedash.app.ts deleted file mode 100644 index c8b2488f4b65c..0000000000000 --- a/components/suitedash/app/suitedash.app.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { defineApp } from "@pipedream/types"; - -export default defineApp({ - type: "app", - app: "suitedash", - propDefinitions: {}, - methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); - }, - }, -}); \ No newline at end of file diff --git a/components/suitedash/package.json b/components/suitedash/package.json index 8eb4b2fddf4be..ea621228da30d 100644 --- a/components/suitedash/package.json +++ b/components/suitedash/package.json @@ -1,16 +1,18 @@ { "name": "@pipedream/suitedash", - "version": "0.0.2", + "version": "0.1.0", "description": "Pipedream SuiteDash Components", "main": "dist/app/suitedash.app.mjs", "keywords": [ "pipedream", "suitedash" ], - "files": ["dist"], "homepage": "https://pipedream.com/apps/suitedash", "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^3.0.3" } } diff --git a/components/suitedash/sources/common/base.mjs b/components/suitedash/sources/common/base.mjs new file mode 100644 index 0000000000000..13274bd46d638 --- /dev/null +++ b/components/suitedash/sources/common/base.mjs @@ -0,0 +1,79 @@ +import suitedash from "../../suitedash.app.mjs"; +import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform"; + +export default { + props: { + suitedash, + db: "$.service.db", + timer: { + type: "$.interface.timer", + default: { + intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, + }, + }, + }, + hooks: { + async deploy() { + await this.processEvent(25); + }, + }, + methods: { + _getLastTs() { + return this.db.get("lastTs") || 0; + }, + _setLastTs(lastTs) { + this.db.set("lastTs", lastTs); + }, + getParams() { + return {}; + }, + getTsField() { + return "created"; + }, + generateMeta(item) { + return { + id: item.uid, + summary: this.getSummary(item), + ts: Date.parse(item[this.getTsField()]), + }; + }, + getFn() { + throw new Error("getFn is not implemented"); + }, + getSummary() { + throw new Error("getSummary is not implemented"); + }, + async processEvent(max) { + const lastTs = this._getLastTs(); + let maxTs = lastTs; + let results = []; + + const items = this.suitedash.paginate({ + fn: this.getFn(), + params: this.getParams(), + }); + + for await (const item of items) { + const ts = Date.parse(item[this.getTsField()]); + if (ts >= lastTs) { + results.push(item); + maxTs = Math.max(ts, maxTs); + } + } + + this._setLastTs(maxTs); + + if (max) { + results = results.slice(-1 * max); + } + + results.forEach((item) => { + const meta = this.generateMeta(item); + this.$emit(item, meta); + }); + }, + }, + async run() { + await this.processEvent(); + }, +}; diff --git a/components/suitedash/sources/new-company/new-company.mjs b/components/suitedash/sources/new-company/new-company.mjs new file mode 100644 index 0000000000000..1606ba0fc2e2d --- /dev/null +++ b/components/suitedash/sources/new-company/new-company.mjs @@ -0,0 +1,24 @@ +import common from "../common/base.mjs"; + +export default { + ...common, + key: "suitedash-new-company", + name: "New Company Created", + description: "Emit new event when a new company is created in SuiteDash", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getFn() { + return this.suitedash.listCompanies; + }, + getSummary(company) { + if (!company || typeof company !== "object") { + return "New Company: Unknown"; + } + const name = company.name || "Unnamed"; + return `New Company: ${name}`; + }, + }, +}; diff --git a/components/suitedash/sources/new-contact/new-contact.mjs b/components/suitedash/sources/new-contact/new-contact.mjs new file mode 100644 index 0000000000000..d8d13259f9144 --- /dev/null +++ b/components/suitedash/sources/new-contact/new-contact.mjs @@ -0,0 +1,26 @@ +import common from "../common/base.mjs"; + +export default { + ...common, + key: "suitedash-new-contact", + name: "New Contact Created", + description: "Emit new event when a new contact is created.", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getFn() { + return this.suitedash.listContacts; + }, + getSummary(contact) { + const firstName = contact.first_name || ""; + const lastName = contact.last_name || ""; + const fullName = [ + firstName, + lastName, + ].filter(Boolean).join(" ") || "Unknown"; + return `New Contact: ${fullName}`; + }, + }, +}; diff --git a/components/suitedash/suitedash.app.mjs b/components/suitedash/suitedash.app.mjs new file mode 100644 index 0000000000000..a0dc627f72308 --- /dev/null +++ b/components/suitedash/suitedash.app.mjs @@ -0,0 +1,119 @@ +import { axios } from "@pipedream/platform"; + +export default { + type: "app", + app: "suitedash", + propDefinitions: { + companyId: { + type: "string", + label: "Company ID", + description: "The ID of the company", + async options({ page }) { + const { data } = await this.listCompanies({ + params: { + page: page + 1, + }, + }); + return data?.map(({ + uid: value, name: label, + }) => ({ + value, + label, + })) || []; + }, + }, + companyName: { + type: "string", + label: "Company Name", + description: "The name of the new company.", + }, + role: { + type: "string", + label: "Company Role", + description: "The role of the new company.", + options: [ + "Lead", + "Client", + "Prospect", + ], + }, + }, + methods: { + _baseUrl() { + return "https://app.suitedash.com/secure-api"; + }, + _makeRequest(opts = {}) { + const { + $ = this, + path, + ...otherOpts + } = opts; + return axios($, { + ...otherOpts, + url: `${this._baseUrl()}${path}`, + headers: { + "Accept": "application/json", + "X-Public-ID": this.$auth.public_id, + "X-Secret-Key": this.$auth.secret_key, + }, + }); + }, + listCompanies(opts = {}) { + return this._makeRequest({ + path: "/companies", + ...opts, + }); + }, + listContacts(opts = {}) { + return this._makeRequest({ + path: "/contacts", + ...opts, + }); + }, + createCompany(opts = {}) { + return this._makeRequest({ + method: "POST", + path: "/company", + ...opts, + }); + }, + createContact(opts = {}) { + return this._makeRequest({ + method: "POST", + path: "/contact", + ...opts, + }); + }, + updateCompany({ + companyId, ...opts + }) { + return this._makeRequest({ + method: "PUT", + path: `/company/${companyId}`, + ...opts, + }); + }, + async *paginate({ + fn, + params, + }) { + params = { + ...params, + page: 1, + }; + let hasMore; + do { + const { + data, meta: { pagination }, + } = await fn({ + params, + }); + for (const item of data) { + yield item; + } + hasMore = params.page < pagination.totalPages; + params.page++; + } while (hasMore); + }, + }, +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cdf597432a0a3..c1e8b572b3216 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9667,7 +9667,10 @@ importers: specifiers: {} components/suitedash: - specifiers: {} + specifiers: + '@pipedream/platform': ^3.0.3 + dependencies: + '@pipedream/platform': 3.0.3 components/summit: specifiers: