From 578b216836b50b979fc2f44e60fbca5b6ad32f20 Mon Sep 17 00:00:00 2001 From: michelle0927 Date: Wed, 2 Apr 2025 10:11:03 -0400 Subject: [PATCH 1/3] updates --- .../actions/create-contact/create-contact.mjs | 2 +- .../list-phone-numbers/list-phone-numbers.mjs | 23 ++++++++ .../actions/send-message/send-message.mjs | 44 ++++++---------- .../actions/update-contact/update-contact.mjs | 4 +- components/openphone/openphone.app.mjs | 52 +++++++++++++------ components/openphone/package.json | 5 +- components/openphone/sources/common/base.mjs | 4 +- .../new-call-recording-completed-instant.mjs | 4 +- .../new-incoming-call-completed-instant.mjs | 2 +- .../new-outgoing-call-completed-instant.mjs | 2 +- 10 files changed, 85 insertions(+), 57 deletions(-) create mode 100644 components/openphone/actions/list-phone-numbers/list-phone-numbers.mjs diff --git a/components/openphone/actions/create-contact/create-contact.mjs b/components/openphone/actions/create-contact/create-contact.mjs index be3f6626c2ad4..92e53131c67f7 100644 --- a/components/openphone/actions/create-contact/create-contact.mjs +++ b/components/openphone/actions/create-contact/create-contact.mjs @@ -5,7 +5,7 @@ export default { key: "openphone-create-contact", name: "Create Contact", description: "Create a new contact in OpenPhone. [See the documentation](https://www.openphone.com/docs/api-reference/contacts/create-a-contact)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { openphone, diff --git a/components/openphone/actions/list-phone-numbers/list-phone-numbers.mjs b/components/openphone/actions/list-phone-numbers/list-phone-numbers.mjs new file mode 100644 index 0000000000000..f367b9d487b21 --- /dev/null +++ b/components/openphone/actions/list-phone-numbers/list-phone-numbers.mjs @@ -0,0 +1,23 @@ +import openphone from "../../openphone.app.mjs"; + +export default { + key: "openphone-list-phone-numbers", + name: "List Phone Numbers", + description: "Retrieve the list of phone numbers and users associated with your OpenPhone workspace. [See the documentation](https://www.openphone.com/docs/mdx/api-reference/phone-numbers/list-phone-numbers)", + version: "0.0.1", + type: "action", + props: { + openphone, + }, + async run({ $ }) { + const { data } = await this.openphone.listPhoneNumbers({ + $, + }); + if (data?.length) { + $.export("$summary", `Successfully retrieved ${data.length} phone number${data.length === 1 + ? "" + : "s"}`); + } + return data; + }, +}; diff --git a/components/openphone/actions/send-message/send-message.mjs b/components/openphone/actions/send-message/send-message.mjs index c44ccd8ea68ae..66916fcef0f45 100644 --- a/components/openphone/actions/send-message/send-message.mjs +++ b/components/openphone/actions/send-message/send-message.mjs @@ -1,11 +1,10 @@ -import { ConfigurationError } from "@pipedream/platform"; import openphone from "../../openphone.app.mjs"; export default { key: "openphone-send-message", - name: "Send a Text Message via OpenPhone", + name: "Send a Text Message", description: "Send a text message from your OpenPhone number to a recipient. [See the documentation](https://www.openphone.com/docs/api-reference/messages/send-a-text-message)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { openphone, @@ -27,31 +26,18 @@ export default { }, }, async run({ $ }) { - try { - const response = await this.openphone.sendTextMessage({ - $, - data: { - content: this.content, - from: this.from, - to: [ - this.to, - ], - setInboxStatus: "done", - }, - }); - $.export("$summary", `Successfully sent message to ${this.to}`); - return response; - - } catch ({ response }) { - let errorMessage = ""; - - if (response.data.errors) { - errorMessage = `Prop: ${response.data.errors[0].path} - ${response.data.errors[0].message}`; - } else { - errorMessage = response.data.message; - } - - throw new ConfigurationError(errorMessage); - } + const response = await this.openphone.sendTextMessage({ + $, + data: { + content: this.content, + from: this.from, + to: [ + this.to, + ], + setInboxStatus: "done", + }, + }); + $.export("$summary", `Successfully sent message to ${this.to}`); + return response; }, }; diff --git a/components/openphone/actions/update-contact/update-contact.mjs b/components/openphone/actions/update-contact/update-contact.mjs index d685eb793b0d9..0410016856b23 100644 --- a/components/openphone/actions/update-contact/update-contact.mjs +++ b/components/openphone/actions/update-contact/update-contact.mjs @@ -5,14 +5,14 @@ export default { key: "openphone-update-contact", name: "Update Contact", description: "Update an existing contact on OpenPhone. [See the documentation](https://www.openphone.com/docs/api-reference/contacts/update-a-contact-by-id)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { openphone, contactId: { type: "string", label: "Contact ID", - description: "The unique identifier of the contact.", + description: "The unique identifier of the contact", }, firstName: { propDefinition: [ diff --git a/components/openphone/openphone.app.mjs b/components/openphone/openphone.app.mjs index 7d126dd084736..8f7538b73e0c8 100644 --- a/components/openphone/openphone.app.mjs +++ b/components/openphone/openphone.app.mjs @@ -1,4 +1,12 @@ -import { axios } from "@pipedream/platform"; +import { + axios, ConfigurationError, +} from "@pipedream/platform"; +import Bottleneck from "bottleneck"; +const limiter = new Bottleneck({ + minTime: 100, // 10 requests per seconds (https://www.openphone.com/docs/mdx/api-reference/rate-limits) + maxConcurrent: 1, +}); +const axiosRateLimiter = limiter.wrap(axios); export default { type: "app", @@ -10,51 +18,53 @@ export default { description: "The sender's phone number. Can be either your OpenPhone phone number ID or the full phone number in E.164 format.", async options() { const { data } = await this.listPhoneNumbers(); - return data.map(({ + return data?.map(({ id: value, name, formattedNumber, }) => ({ - label: `${name} - ${formattedNumber}`, + label: name && formattedNumber + ? `${name} - ${formattedNumber}` + : value, value, - })); + })) || []; }, }, firstName: { type: "string", label: "First Name", - description: "The contact's first name.", + description: "The contact's first name", }, lastName: { type: "string", label: "Last Name", - description: "The contact's last name.", + description: "The contact's last name", optional: true, }, company: { type: "string", label: "Company", - description: "The contact's company name.", + description: "The contact's company name", optional: true, }, role: { type: "string", label: "Role", - description: "The contact's role.", + description: "The contact's role", optional: true, }, emails: { type: "string[]", label: "Emails", - description: "Array of objects of contact's emails. **Example:** `{\"name\": \"Company Email\", \"value\": \"abc@example.com\"}`.", + description: "Array of objects of contact's emails. **Example:** `{\"name\": \"Company Email\", \"value\": \"abc@example.com\"}`", }, phoneNumbers: { type: "string[]", label: "Phone Numbers", - description: "Array of objects of contact's phone numbers. **Example:** `{\"name\": \"Company Phone\", \"value\": \"+12345678901\"}`.", + description: "Array of objects of contact's phone numbers. **Example:** `{\"name\": \"Company Phone\", \"value\": \"+12345678901\"}`", }, customFields: { type: "string[]", label: "Custom Fields", - description: "Array of objects of custom fields for the contact. **Example:** `{\"key\": \"inbound-lead\", \"value\": \"[\"option1\", \"option2\"]\"}`.", + description: "Array of objects of custom fields for the contact. **Example:** `{\"key\": \"inbound-lead\", \"value\": [\"option1\", \"option2\"]}`", }, }, methods: { @@ -66,14 +76,22 @@ export default { Authorization: `${this.$auth.api_key}`, }; }, - _makeRequest({ + async _makeRequest({ $ = this, path, ...opts }) { - return axios($, { - url: this._baseUrl() + path, - headers: this._headers(), - ...opts, - }); + try { + return await axiosRateLimiter($, { + url: this._baseUrl() + path, + headers: this._headers(), + ...opts, + }); + } catch ({ response }) { + const errorMessage = response?.data?.errors + ? `Prop: ${response.data.errors[0].path} - ${response.data.errors[0].message}` + : response?.data?.message; + + throw new ConfigurationError(errorMessage); + } }, listPhoneNumbers(opts = {}) { return this._makeRequest({ diff --git a/components/openphone/package.json b/components/openphone/package.json index e7fae1c54b357..5235cef538c7e 100644 --- a/components/openphone/package.json +++ b/components/openphone/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/openphone", - "version": "0.1.0", + "version": "0.2.0", "description": "Pipedream OpenPhone Components", "main": "openphone.app.mjs", "keywords": [ @@ -13,6 +13,7 @@ "access": "public" }, "dependencies": { - "@pipedream/platform": "^3.0.3" + "@pipedream/platform": "^3.0.3", + "bottleneck": "^2.19.5" } } diff --git a/components/openphone/sources/common/base.mjs b/components/openphone/sources/common/base.mjs index 75921c5b6df7d..e2ccb526111f3 100644 --- a/components/openphone/sources/common/base.mjs +++ b/components/openphone/sources/common/base.mjs @@ -12,13 +12,13 @@ export default { ], type: "string[]", label: "Resource IDs", - description: "The unique identifiers of phone numbers associated with the webhook.", + description: "The IDs of the incoming or outgoing phone numbers to retrieve events for. Use the List Phone Numbers action to retrieve information about phone numbers.", optional: true, }, label: { type: "string", label: "Label", - description: "Webhook's label", + description: "A label to identify the webhook", optional: true, }, }, diff --git a/components/openphone/sources/new-call-recording-completed-instant/new-call-recording-completed-instant.mjs b/components/openphone/sources/new-call-recording-completed-instant/new-call-recording-completed-instant.mjs index 9a0098f0fbe39..38039a2e0abec 100644 --- a/components/openphone/sources/new-call-recording-completed-instant/new-call-recording-completed-instant.mjs +++ b/components/openphone/sources/new-call-recording-completed-instant/new-call-recording-completed-instant.mjs @@ -4,9 +4,9 @@ import sampleEmit from "./test-event.mjs"; export default { ...common, key: "openphone-new-call-recording-completed-instant", - name: "New Call Recording Completed", + name: "New Call Recording Completed (Instant)", description: "Emit new event when a call recording has finished.", - version: "0.0.1", + version: "0.0.2", type: "source", dedupe: "unique", methods: { diff --git a/components/openphone/sources/new-incoming-call-completed-instant/new-incoming-call-completed-instant.mjs b/components/openphone/sources/new-incoming-call-completed-instant/new-incoming-call-completed-instant.mjs index dade14952b2a6..b2d89a156a77a 100644 --- a/components/openphone/sources/new-incoming-call-completed-instant/new-incoming-call-completed-instant.mjs +++ b/components/openphone/sources/new-incoming-call-completed-instant/new-incoming-call-completed-instant.mjs @@ -6,7 +6,7 @@ export default { key: "openphone-new-incoming-call-completed-instant", name: "New Incoming Call Completed (Instant)", description: "Emit new event when an incoming call is completed, including calls not picked up or voicemails left.", - version: "0.0.1", + version: "0.0.2", type: "source", dedupe: "unique", methods: { diff --git a/components/openphone/sources/new-outgoing-call-completed-instant/new-outgoing-call-completed-instant.mjs b/components/openphone/sources/new-outgoing-call-completed-instant/new-outgoing-call-completed-instant.mjs index cdd01cfa2a1cd..bf9ca6bfd754c 100644 --- a/components/openphone/sources/new-outgoing-call-completed-instant/new-outgoing-call-completed-instant.mjs +++ b/components/openphone/sources/new-outgoing-call-completed-instant/new-outgoing-call-completed-instant.mjs @@ -6,7 +6,7 @@ export default { key: "openphone-new-outgoing-call-completed-instant", name: "New Outgoing Call Completed (Instant)", description: "Emit new event when an outgoing call has ended.", - version: "0.0.1", + version: "0.0.2", type: "source", dedupe: "unique", methods: { From 03761e3a4918a770b4e1a04369f980d107cf665f Mon Sep 17 00:00:00 2001 From: michelle0927 Date: Thu, 3 Apr 2025 14:39:37 -0400 Subject: [PATCH 2/3] pnpm-lock.yaml --- pnpm-lock.yaml | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 73e876321fefd..2d35a33142d9e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -883,8 +883,7 @@ importers: specifier: ^1.1.1 version: 1.6.6 - components/apiverve: - specifiers: {} + components/apiverve: {} components/apollo_io: dependencies: @@ -7473,8 +7472,7 @@ importers: specifier: ^1.6.0 version: 1.6.6 - components/lucca: - specifiers: {} + components/lucca: {} components/lucid: dependencies: @@ -8072,8 +8070,7 @@ importers: specifier: ^1.4.1 version: 1.6.6 - components/mistral_ai: - specifiers: {} + components/mistral_ai: {} components/mitra: {} @@ -8935,6 +8932,9 @@ importers: '@pipedream/platform': specifier: ^3.0.3 version: 3.0.3 + bottleneck: + specifier: ^2.19.5 + version: 2.19.5 components/openrouter: {} @@ -9299,8 +9299,7 @@ importers: specifier: ^2.0.0 version: 2.0.0 - components/pdf4me: - specifiers: {} + components/pdf4me: {} components/pdf_api_io: {} @@ -10069,8 +10068,7 @@ importers: components/proprofs_quiz_maker: {} - components/provesource: - specifiers: {} + components/provesource: {} components/proworkflow: dependencies: @@ -13688,8 +13686,7 @@ importers: specifier: 3.2.2 version: 3.2.2 - components/verifiedemail: - specifiers: {} + components/verifiedemail: {} components/verifone: {} @@ -14370,8 +14367,7 @@ importers: specifier: ^0.1.4 version: 0.1.6 - components/yepcode: - specifiers: {} + components/yepcode: {} components/yespo: dependencies: @@ -34442,6 +34438,8 @@ snapshots: '@putout/operator-filesystem': 5.0.0(putout@36.13.1(eslint@8.57.1)(typescript@5.6.3)) '@putout/operator-json': 2.2.0 putout: 36.13.1(eslint@8.57.1)(typescript@5.6.3) + transitivePeerDependencies: + - supports-color '@putout/operator-regexp@1.0.0(putout@36.13.1(eslint@8.57.1)(typescript@5.6.3))': dependencies: From 295a7d9dab9b3f64d8ca759b1de9e9494e305ee5 Mon Sep 17 00:00:00 2001 From: michelle0927 Date: Fri, 4 Apr 2025 11:37:36 -0400 Subject: [PATCH 3/3] pnpm-lock.yaml --- pnpm-lock.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 91ca52176ca7c..d4794be11f22b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16465,8 +16465,8 @@ packages: '@dabh/diagnostics@2.0.3': resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==} - '@definitelytyped/header-parser@0.2.18': - resolution: {integrity: sha512-3JWGzhieGOx+zhy+qaPDoiby2TPA1PZGpEJHt0VwR1aK0R9dER5BoBvnT5zSafg9kHQTw4aBRFbt3o41FNkaLw==} + '@definitelytyped/header-parser@0.2.19': + resolution: {integrity: sha512-zu+RxQpUCgorYUQZoyyrRIn9CljL1CeM4qak3NDeMO1r7tjAkodfpAGnVzx/6JR2OUk0tAgwmZxNMSwd9LVgxw==} engines: {node: '>=18.18.0'} '@definitelytyped/typescript-versions@0.1.8': @@ -32208,7 +32208,7 @@ snapshots: enabled: 2.0.0 kuler: 2.0.0 - '@definitelytyped/header-parser@0.2.18': + '@definitelytyped/header-parser@0.2.19': dependencies: '@definitelytyped/typescript-versions': 0.1.8 '@definitelytyped/utils': 0.1.8 @@ -38848,7 +38848,7 @@ snapshots: dts-critic@3.3.11(typescript@5.7.2): dependencies: - '@definitelytyped/header-parser': 0.2.18 + '@definitelytyped/header-parser': 0.2.19 command-exists: 1.2.9 rimraf: 3.0.2 semver: 6.3.1 @@ -38858,7 +38858,7 @@ snapshots: dtslint@4.2.1(typescript@5.7.2): dependencies: - '@definitelytyped/header-parser': 0.2.18 + '@definitelytyped/header-parser': 0.2.19 '@definitelytyped/typescript-versions': 0.1.8 '@definitelytyped/utils': 0.1.8 dts-critic: 3.3.11(typescript@5.7.2)