From f835c5558de733ed970ddb09b9fd07135dfb6829 Mon Sep 17 00:00:00 2001 From: Jorge Cortes Date: Tue, 17 Oct 2023 07:45:34 -0500 Subject: [PATCH 001/186] [ACTIONS/SOURCES] Booqable new actions sources (#8435) * First version generated by AI tool with issueId. With minor fixes * Tested components * pnpm-lock.yaml * Revert "Exclude files with name test-event.mjs in scripts/findDuplicateKeys.js" This reverts commit e20bdc39ed7169e38151b4b6fdb9179d1336ac32. * pnpm-lock.yaml --- .../create-customer/create-customer.mjs | 50 ++++++ .../update-customer/update-customer.mjs | 62 ++++++++ components/booqable/booqable.app.mjs | 148 +++++++++++++++++- components/booqable/common/constants.mjs | 15 ++ components/booqable/common/utils.mjs | 11 ++ components/booqable/package.json | 18 +++ components/booqable/sources/common/base.mjs | 14 ++ .../booqable/sources/common/polling.mjs | 62 ++++++++ .../sources/new-customer/new-customer.mjs | 35 +++++ .../sources/order-reserved/order-reserved.mjs | 39 +++++ pnpm-lock.yaml | 6 + 11 files changed, 456 insertions(+), 4 deletions(-) create mode 100644 components/booqable/actions/create-customer/create-customer.mjs create mode 100644 components/booqable/actions/update-customer/update-customer.mjs create mode 100644 components/booqable/common/constants.mjs create mode 100644 components/booqable/common/utils.mjs create mode 100644 components/booqable/package.json create mode 100644 components/booqable/sources/common/base.mjs create mode 100644 components/booqable/sources/common/polling.mjs create mode 100644 components/booqable/sources/new-customer/new-customer.mjs create mode 100644 components/booqable/sources/order-reserved/order-reserved.mjs diff --git a/components/booqable/actions/create-customer/create-customer.mjs b/components/booqable/actions/create-customer/create-customer.mjs new file mode 100644 index 0000000000000..6725eab899f96 --- /dev/null +++ b/components/booqable/actions/create-customer/create-customer.mjs @@ -0,0 +1,50 @@ +import app from "../../booqable.app.mjs"; + +export default { + key: "booqable-create-customer", + name: "Create Customer", + description: "Create a new customer in Booqable. [See the documentation](https://developers.booqable.com/#create-a-new-customer)", + version: "0.0.1", + type: "action", + props: { + app, + name: { + propDefinition: [ + app, + "name", + ], + }, + email: { + propDefinition: [ + app, + "email", + ], + }, + }, + methods: { + createCustomer(args = {}) { + return this.app.post({ + path: "/customers", + ...args, + }); + }, + }, + run({ $: step }) { + const { + createCustomer, + name, + email, + } = this; + + return createCustomer({ + step, + data: { + customer: { + name, + email, + }, + }, + summary: (response) => `Successfully created customer with ID: \`${response.customer.id}\``, + }); + }, +}; diff --git a/components/booqable/actions/update-customer/update-customer.mjs b/components/booqable/actions/update-customer/update-customer.mjs new file mode 100644 index 0000000000000..6d931e29745d5 --- /dev/null +++ b/components/booqable/actions/update-customer/update-customer.mjs @@ -0,0 +1,62 @@ +import app from "../../booqable.app.mjs"; + +export default { + key: "booqable-update-customer", + name: "Update Customer", + description: "Updates the details of an existing customer in Booqable. [See the documentation](https://developers.booqable.com/#update-customer)", + version: "0.0.1", + type: "action", + props: { + app, + customerId: { + propDefinition: [ + app, + "customerId", + ], + }, + name: { + optional: true, + propDefinition: [ + app, + "name", + ], + }, + email: { + optional: true, + propDefinition: [ + app, + "email", + ], + }, + }, + methods: { + updateCustomer({ + customerId, ...args + } = {}) { + return this.app.put({ + path: `/customers/${customerId}`, + ...args, + }); + }, + }, + async run({ $: step }) { + const { + updateCustomer, + customerId, + name, + email, + } = this; + + return updateCustomer({ + step, + customerId, + data: { + customer: { + name, + email, + }, + }, + summary: (response) => `Successfully updated customer with ID: \`${response.customer.id}\``, + }); + }, +}; diff --git a/components/booqable/booqable.app.mjs b/components/booqable/booqable.app.mjs index 2e0b47172de77..9987b6025b5fd 100644 --- a/components/booqable/booqable.app.mjs +++ b/components/booqable/booqable.app.mjs @@ -1,11 +1,151 @@ +import { + axios, ConfigurationError, +} from "@pipedream/platform"; +import constants from "./common/constants.mjs"; +import utils from "./common/utils.mjs"; + export default { type: "app", app: "booqable", - propDefinitions: {}, + propDefinitions: { + name: { + type: "string", + label: "Name", + description: "The name of the customer", + }, + email: { + type: "string", + label: "Email", + description: "The email of the customer", + }, + customerId: { + type: "string", + label: "Customer ID", + description: "Select the customer to update", + async options({ page }) { + const { customers } = await this.listCustomers({ + params: { + page, + }, + }); + return customers.map(({ + name: label, id: value, + }) => ({ + label, + value, + })); + }, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + exportSummary(step) { + if (!step?.export) { + throw new ConfigurationError("The summary method should be bind to the step object aka `$`"); + } + return (msg = "") => step.export(constants.SUMMARY_LABEL, msg); + }, + getBaseUrl() { + const baseUrl = + constants.BASE_URL + .replace(constants.SUBDOMAIN_PLACEHOLDER, this.$auth.company_slug); + return `${baseUrl}${constants.VERSION_PATH}`; + }, + getParams(params) { + return { + api_key: this.$auth.api_key, + ...params, + }; + }, + async makeRequest({ + step = this, path, summary, params, ...args + } = {}) { + const config = { + ...args, + url: this.getBaseUrl() + path, + params: this.getParams(params), + }; + + const response = await axios(step, config); + + if (typeof(summary) === "function") { + this.exportSummary(step)(summary(response)); + } + + return response; + }, + post(args = {}) { + return this.makeRequest({ + method: "post", + ...args, + }); + }, + put(args = {}) { + return this.makeRequest({ + method: "put", + ...args, + }); + }, + listCustomers(args = {}) { + return this.makeRequest({ + path: "/customers", + ...args, + }); + }, + getCustomer({ + customerId, ...args + } = {}) { + return this.makeRequest({ + path: `/customers/${customerId}`, + ...args, + }); + }, + listOrders(args = {}) { + return this.makeRequest({ + path: "/orders", + ...args, + }); + }, + async *getIterations({ + resourceFn, + resourceFnArgs, + resourceName, + max = constants.DEFAULT_MAX, + }) { + let page = 1; + let resourcesCount = 0; + + while (true) { + const response = + await resourceFn({ + ...resourceFnArgs, + params: { + ...resourceFnArgs?.params, + page, + }, + }); + + console.log("response!!!", JSON.stringify(response, null, 2)); + const nextResources = resourceName && response[resourceName] || response; + + if (!nextResources?.length) { + console.log("No more resources found"); + return; + } + + for (const resource of nextResources) { + yield resource; + resourcesCount += 1; + + if (resourcesCount >= max) { + return; + } + } + + page += 1; + } + }, + paginate(args = {}) { + return utils.iterate(this.getIterations(args)); }, }, }; diff --git a/components/booqable/common/constants.mjs b/components/booqable/common/constants.mjs new file mode 100644 index 0000000000000..7f991ae4f88e8 --- /dev/null +++ b/components/booqable/common/constants.mjs @@ -0,0 +1,15 @@ +const SUMMARY_LABEL = "$summary"; +const SUBDOMAIN_PLACEHOLDER = "{subdomain}"; +const BASE_URL = `https://${SUBDOMAIN_PLACEHOLDER}.booqable.com`; +const VERSION_PATH = "/api/1"; +const DEFAULT_MAX = 600; +const DEFAULT_LIMIT = 60; + +export default { + SUMMARY_LABEL, + SUBDOMAIN_PLACEHOLDER, + BASE_URL, + VERSION_PATH, + DEFAULT_MAX, + DEFAULT_LIMIT, +}; diff --git a/components/booqable/common/utils.mjs b/components/booqable/common/utils.mjs new file mode 100644 index 0000000000000..903b2593ed3c2 --- /dev/null +++ b/components/booqable/common/utils.mjs @@ -0,0 +1,11 @@ +async function iterate(iterations) { + const items = []; + for await (const item of iterations) { + items.push(item); + } + return items; +} + +export default { + iterate, +}; diff --git a/components/booqable/package.json b/components/booqable/package.json new file mode 100644 index 0000000000000..5a8333dc6d17d --- /dev/null +++ b/components/booqable/package.json @@ -0,0 +1,18 @@ +{ + "name": "@pipedream/booqable", + "version": "0.1.0", + "description": "Pipedream Booqable Components", + "main": "booqable.app.mjs", + "keywords": [ + "pipedream", + "booqable" + ], + "homepage": "https://pipedream.com/apps/booqable", + "author": "Pipedream (https://pipedream.com/)", + "dependencies": { + "@pipedream/platform": "^1.5.1" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/components/booqable/sources/common/base.mjs b/components/booqable/sources/common/base.mjs new file mode 100644 index 0000000000000..e53cd36143f57 --- /dev/null +++ b/components/booqable/sources/common/base.mjs @@ -0,0 +1,14 @@ +import { ConfigurationError } from "@pipedream/platform"; +import app from "../../booqable.app.mjs"; + +export default { + props: { + app, + db: "$.service.db", + }, + methods: { + generateMeta() { + throw new ConfigurationError("generateMeta is not implemented"); + }, + }, +}; diff --git a/components/booqable/sources/common/polling.mjs b/components/booqable/sources/common/polling.mjs new file mode 100644 index 0000000000000..488f0e7f137ed --- /dev/null +++ b/components/booqable/sources/common/polling.mjs @@ -0,0 +1,62 @@ +import { + ConfigurationError, + DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, +} from "@pipedream/platform"; +import common from "./base.mjs"; + +export default { + ...common, + props: { + ...common.props, + timer: { + type: "$.interface.timer", + label: "Polling schedule", + description: "How often to poll the API", + default: { + intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, + }, + }, + }, + methods: { + ...common.methods, + isResourceRelevant() { + return true; + }, + getResourceName() { + throw new ConfigurationError("getResourceName is not implemented"); + }, + getResourceFn() { + throw new ConfigurationError("getResourceFn is not implemented"); + }, + getResourceFnArgs() { + throw new ConfigurationError("getResourceFnArgs is not implemented"); + }, + processEvent(resource) { + const meta = this.generateMeta(resource); + this.$emit(resource, meta); + }, + async processResources(resources) { + Array.from(resources) + .reverse() + .filter(this.isResourceRelevant) + .forEach(this.processEvent); + }, + }, + async run() { + const { + app, + getResourceFn, + getResourceFnArgs, + getResourceName, + processResources, + } = this; + + const resources = await app.paginate({ + resourceFn: getResourceFn(), + resourceFnArgs: getResourceFnArgs(), + resourceName: getResourceName(), + }); + + processResources(resources); + }, +}; diff --git a/components/booqable/sources/new-customer/new-customer.mjs b/components/booqable/sources/new-customer/new-customer.mjs new file mode 100644 index 0000000000000..9120276eb758a --- /dev/null +++ b/components/booqable/sources/new-customer/new-customer.mjs @@ -0,0 +1,35 @@ +import common from "../common/polling.mjs"; +import constants from "../../common/constants.mjs"; + +export default { + ...common, + key: "booqable-new-customer", + name: "New Customer", + description: "Emits a new event anytime there is a new customer. [See the documentation](https://developers.booqable.com/#list-all-customers)", + type: "source", + version: "0.0.1", + dedupe: "unique", + methods: { + ...common.methods, + getResourceName() { + return "customers"; + }, + getResourceFn() { + return this.app.listCustomers; + }, + getResourceFnArgs() { + return { + params: { + per: constants.DEFAULT_LIMIT, + }, + }; + }, + generateMeta(resource) { + return { + id: resource.id, + summary: `New Customer: ${resource.name}`, + ts: Date.parse(resource.created_at), + }; + }, + }, +}; diff --git a/components/booqable/sources/order-reserved/order-reserved.mjs b/components/booqable/sources/order-reserved/order-reserved.mjs new file mode 100644 index 0000000000000..6038f451e272e --- /dev/null +++ b/components/booqable/sources/order-reserved/order-reserved.mjs @@ -0,0 +1,39 @@ +import common from "../common/polling.mjs"; +import constants from "../../common/constants.mjs"; + +export default { + ...common, + key: "booqable-order-reserved", + name: "Order Reserved", + description: "Emits an event when an order changes status to reserved in Booqable. [See the documentation](https://developers.booqable.com/#list-all-orders)", + type: "source", + version: "0.0.1", + dedupe: "unique", + methods: { + ...common.methods, + isResourceRelevant(resource) { + return resource?.status === "reserved"; + }, + getResourceName() { + return "orders"; + }, + getResourceFn() { + return this.app.listOrders; + }, + getResourceFnArgs() { + return { + params: { + per: constants.DEFAULT_LIMIT, + }, + }; + }, + generateMeta(resource) { + const ts = Date.parse(resource.updated_at); + return { + id: `${resource.id}-${ts}`, + summary: `Order ${resource.number} was reserved`, + ts, + }; + }, + }, +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b79d96ff25ef4..071ef4ea36202 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -594,6 +594,12 @@ importers: components/blue: specifiers: {} + components/booqable: + specifiers: + '@pipedream/platform': ^1.5.1 + dependencies: + '@pipedream/platform': 1.5.1 + components/botbaba: specifiers: {} From ec10d7ee9a7c19b4eadbfa3b07af01cb6df16c4b Mon Sep 17 00:00:00 2001 From: Lucas Caresia Date: Tue, 17 Oct 2023 10:34:13 -0300 Subject: [PATCH 002/186] [Components] Piggy #8188 (#8413) * Added actions * Bump package.json * Fixed requested bugs * Removed action Update Contact --- components/piggy/.gitignore | 3 - components/piggy/actions/common/constants.mjs | 88 +++++++++++++++++++ .../create-contact-attribute.mjs | 51 +++++++++++ .../find-or-create-contact.mjs | 31 +++++++ components/piggy/app/piggy.app.ts | 13 --- components/piggy/package.json | 10 ++- components/piggy/piggy.app.mjs | 72 +++++++++++++++ .../new-contact-created.mjs | 76 ++++++++++++++++ pnpm-lock.yaml | 5 +- 9 files changed, 328 insertions(+), 21 deletions(-) delete mode 100644 components/piggy/.gitignore create mode 100644 components/piggy/actions/common/constants.mjs create mode 100644 components/piggy/actions/create-contact-attribute/create-contact-attribute.mjs create mode 100644 components/piggy/actions/find-or-create-contact/find-or-create-contact.mjs delete mode 100644 components/piggy/app/piggy.app.ts create mode 100644 components/piggy/piggy.app.mjs create mode 100644 components/piggy/sources/new-contact-created/new-contact-created.mjs diff --git a/components/piggy/.gitignore b/components/piggy/.gitignore deleted file mode 100644 index ec761ccab7595..0000000000000 --- a/components/piggy/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.js -*.mjs -dist \ No newline at end of file diff --git a/components/piggy/actions/common/constants.mjs b/components/piggy/actions/common/constants.mjs new file mode 100644 index 0000000000000..bf0f1c0069c93 --- /dev/null +++ b/components/piggy/actions/common/constants.mjs @@ -0,0 +1,88 @@ +export default { + DATA_TYPES: [ + { + label: "URL", + value: "url", + }, + { + label: "Text", + value: "text", + }, + { + label: "Date", + value: "date", + }, + { + label: "Phone", + value: "phone", + }, + { + label: "Float", + value: "float", + }, + { + label: "Color", + value: "color", + }, + { + label: "Email", + value: "email", + }, + { + label: "Number", + value: "number", + }, + { + label: "Select", + value: "select", + }, + { + label: "Boolean", + value: "boolean", + }, + { + label: "Rich Text", + value: "rich_text", + }, + { + label: "Date & Time", + value: "date_time", + }, + { + label: "Long Text", + value: "long_text", + }, + { + label: "Date Range", + value: "date_range", + }, + { + label: "Time Range", + value: "time_range", + }, + { + label: "Identifier", + value: "identifier", + }, + { + label: "Birth Date", + value: "birth_date", + }, + { + label: "File Upload", + value: "file_upload", + }, + { + label: "Media Upload", + value: "media_upload", + }, + { + label: "Multi-Select", + value: "multi_select", + }, + { + label: "License Plate", + value: "license_plate", + }, + ], +}; diff --git a/components/piggy/actions/create-contact-attribute/create-contact-attribute.mjs b/components/piggy/actions/create-contact-attribute/create-contact-attribute.mjs new file mode 100644 index 0000000000000..4ad8b2ac5b5f6 --- /dev/null +++ b/components/piggy/actions/create-contact-attribute/create-contact-attribute.mjs @@ -0,0 +1,51 @@ +import app from "../../piggy.app.mjs"; +import constants from "../common/constants.mjs"; + +export default { + name: "Create Contact Attribute", + version: "0.0.1", + key: "piggy-create-contact-attribute", + description: "Creates a contact attribute. [See the documentation](https://docs.piggy.eu/v3/oauth/contact-attributes#:~:text=Create%20Contact%20Attribute)", + type: "action", + props: { + app, + name: { + type: "string", + label: "Name", + description: "Name of the attribute", + }, + dataType: { + type: "string", + label: "Data type", + description: "Type of the attribute", + options: constants.DATA_TYPES, + }, + label: { + type: "string", + label: "Label", + description: "Label of the attribute", + }, + descripion: { + type: "string", + label: "Descripion", + description: "Description of the attribute", + }, + }, + async run({ $ }) { + const response = await this.app.createContactAttribute({ + $, + data: { + name: this.name, + data_type: this.dataType, + label: this.label, + description: this.description, + }, + }); + + if (response) { + $.export("$summary", `Successfully created contact attribute with name ${response.data.name}`); + } + + return response; + }, +}; diff --git a/components/piggy/actions/find-or-create-contact/find-or-create-contact.mjs b/components/piggy/actions/find-or-create-contact/find-or-create-contact.mjs new file mode 100644 index 0000000000000..16dfd568f2d80 --- /dev/null +++ b/components/piggy/actions/find-or-create-contact/find-or-create-contact.mjs @@ -0,0 +1,31 @@ +import app from "../../piggy.app.mjs"; + +export default { + name: "Find Or Create Contact", + version: "0.0.1", + key: "piggy-find-or-create-contact", + description: "Find or create a contact. [See the documentation](https://docs.piggy.eu/v3/oauth/contacts#:~:text=Possible%20errors-,Find%20or%20Create%20Contact,-Find%20Contact%20by)", + type: "action", + props: { + app, + email: { + type: "string", + label: "Email", + description: "Email of the contact", + }, + }, + async run({ $ }) { + const response = await this.app.findOrCreateContact({ + $, + data: { + email: this.email, + }, + }); + + if (response) { + $.export("$summary", "Successfully retrieved or created contact"); + } + + return response; + }, +}; diff --git a/components/piggy/app/piggy.app.ts b/components/piggy/app/piggy.app.ts deleted file mode 100644 index 9f8d28a54b484..0000000000000 --- a/components/piggy/app/piggy.app.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { defineApp } from "@pipedream/types"; - -export default defineApp({ - type: "app", - app: "piggy", - 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/piggy/package.json b/components/piggy/package.json index 257c339e70032..b0636b1fabe7c 100644 --- a/components/piggy/package.json +++ b/components/piggy/package.json @@ -1,16 +1,18 @@ { "name": "@pipedream/piggy", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Piggy Components", - "main": "dist/app/piggy.app.mjs", + "main": "piggy.app.mjs", "keywords": [ "pipedream", "piggy" ], - "files": ["dist"], "homepage": "https://pipedream.com/apps/piggy", "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^1.5.1" } -} \ No newline at end of file +} diff --git a/components/piggy/piggy.app.mjs b/components/piggy/piggy.app.mjs new file mode 100644 index 0000000000000..71a3746382fd4 --- /dev/null +++ b/components/piggy/piggy.app.mjs @@ -0,0 +1,72 @@ +import { axios } from "@pipedream/platform"; + +export default { + type: "app", + app: "piggy", + propDefinitions: { + contactId: { + label: "Contact ID", + description: "The contact ID", + type: "string", + async options({ page }) { + const { data: contacts } = await this.getContacts({ + params: { + page: page + 1, + }, + }); + + return contacts.map((contact) => ({ + label: contact.email, + value: contact.uuid, + })); + }, + }, + }, + methods: { + _apiKey() { + return this.$auth.api_key; + }, + _apiUrl() { + return "https://api.piggy.eu/api/v3/oauth"; + }, + async _makeRequest({ + $ = this, path, ...args + }) { + return axios($, { + url: `${this._apiUrl()}${path}`, + headers: { + Authorization: `Bearer ${this._apiKey()}`, + }, + ...args, + }); + }, + async findOrCreateContact(args = {}) { + return this._makeRequest({ + path: "/clients/contacts/find-or-create", + ...args, + }); + }, + async createContactAttribute(args = {}) { + return this._makeRequest({ + path: "/clients/contact-attributes", + method: "post", + ...args, + }); + }, + async getContacts(args = {}) { + return this._makeRequest({ + path: "/clients/contacts", + ...args, + }); + }, + async updateContact({ + contactId, ...args + }) { + return this._makeRequest({ + path: `/clients/contacts/${contactId}`, + method: "put", + ...args, + }); + }, + }, +}; diff --git a/components/piggy/sources/new-contact-created/new-contact-created.mjs b/components/piggy/sources/new-contact-created/new-contact-created.mjs new file mode 100644 index 0000000000000..deaf9d3aec599 --- /dev/null +++ b/components/piggy/sources/new-contact-created/new-contact-created.mjs @@ -0,0 +1,76 @@ +import app from "../../piggy.app.mjs"; +import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform"; + +export default { + name: "New Contact Created", + version: "0.0.1", + key: "piggy-new-contact-created", + description: "Emit new event on each new contact.", + type: "source", + dedupe: "unique", + props: { + app, + db: "$.service.db", + timer: { + type: "$.interface.timer", + static: { + intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, + }, + }, + }, + methods: { + emitEvent(data) { + this.$emit(data, { + id: data.uuid, + summary: `New contact created with ID ${data.uuid}`, + ts: new Date(), + }); + }, + _setLastResourceId(id) { + this.db.set("lastResourceId", id); + }, + _getLastResourceId() { + return this.db.get("lastResourceId"); + }, + }, + hooks: { + async deploy() { + const { data: contacts } = await this.app.getContacts({ + params: { + limit: 20, + }, + }); + + contacts.forEach(this.emitEvent); + }, + }, + async run() { + const lastResourceId = this._getLastResourceId(); + + let page = 1; + + while (page >= 0) { + const { data: contacts } = await this.app.getContacts({ + params: { + page, + limit: 100, + }, + }); + + if (contacts.length) { + this._setLastResourceId(contacts[0].uuid); + } + + contacts.forEach(this.emitEvent); + + if ( + contacts.length < 100 || + contacts.filter((contact) => contact.uuid === lastResourceId) + ) { + return; + } + + page++; + } + }, +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 071ef4ea36202..d06cab55a7cac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4101,7 +4101,10 @@ importers: '@pipedream/platform': 1.5.1 components/piggy: - specifiers: {} + specifiers: + '@pipedream/platform': ^1.5.1 + dependencies: + '@pipedream/platform': 1.5.1 components/pikaso: specifiers: From e0b5f6d95cecbb8df38d2dbfa099cc408b7212d0 Mon Sep 17 00:00:00 2001 From: michelle0927 Date: Tue, 17 Oct 2023 06:58:15 -0700 Subject: [PATCH 003/186] Slottable - New Components (#8495) * new components * pnpm-lock.yaml --- components/slottable/package.json | 7 ++- components/slottable/slottable.app.mjs | 49 +++++++++++++++-- .../booking-contact-updated.mjs | 25 +++++++++ components/slottable/sources/common/base.mjs | 53 +++++++++++++++++++ .../contact-updated/contact-updated.mjs | 25 +++++++++ pnpm-lock.yaml | 5 +- 6 files changed, 158 insertions(+), 6 deletions(-) create mode 100644 components/slottable/sources/booking-contact-updated/booking-contact-updated.mjs create mode 100644 components/slottable/sources/common/base.mjs create mode 100644 components/slottable/sources/contact-updated/contact-updated.mjs diff --git a/components/slottable/package.json b/components/slottable/package.json index d361d883be117..5b7020934afe3 100644 --- a/components/slottable/package.json +++ b/components/slottable/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/slottable", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Slottable Components", "main": "slottable.app.mjs", "keywords": [ @@ -11,5 +11,8 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^1.5.1" } -} \ No newline at end of file +} diff --git a/components/slottable/slottable.app.mjs b/components/slottable/slottable.app.mjs index c9dc9f11a6756..3fe7271c55880 100644 --- a/components/slottable/slottable.app.mjs +++ b/components/slottable/slottable.app.mjs @@ -1,11 +1,54 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "slottable", propDefinitions: {}, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _baseUrl() { + return "https://slottable.app/api/v1"; + }, + _headers() { + return { + "Authorization": `Bearer ${this.$auth.api_token}`, + "Accept": "application/json", + "Content-Type": "application/json", + }; + }, + _makeRequest({ + $ = this, + path, + ...args + }) { + return axios($, { + url: `${this._baseUrl()}${path}`, + headers: this._headers(), + ...args, + }); + }, + async getCompanyId() { + const { data: { attributes: { company_id } } } = await this._makeRequest({ + path: "/token", + }); + return company_id; + }, + createWebhook({ + companyId, ...args + }) { + return this._makeRequest({ + path: `/companies/${companyId}/webhooks`, + method: "POST", + ...args, + }); + }, + deleteWebhook({ + companyId, hookId, ...args + }) { + return this._makeRequest({ + path: `/companies/${companyId}/webhooks/${hookId}`, + method: "DELETE", + ...args, + }); }, }, }; diff --git a/components/slottable/sources/booking-contact-updated/booking-contact-updated.mjs b/components/slottable/sources/booking-contact-updated/booking-contact-updated.mjs new file mode 100644 index 0000000000000..c3a8b7cc35593 --- /dev/null +++ b/components/slottable/sources/booking-contact-updated/booking-contact-updated.mjs @@ -0,0 +1,25 @@ +import common from "../common/base.mjs"; + +export default { + ...common, + key: "slottable-booking-contact-updated", + name: "Booking Contact Updated", + version: "0.0.1", + description: "Emit new event when a booking contact is changed (new, updated, or deleted) in Slottable.", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getModel() { + return "BookingContact"; + }, + generateMeta(contact) { + const ts = Date.parse(contact.updated_at); + return { + id: `${contact.id}-${ts}`, + summary: `Booking Contact Updated with ID ${contact.id}`, + ts, + }; + }, + }, +}; diff --git a/components/slottable/sources/common/base.mjs b/components/slottable/sources/common/base.mjs new file mode 100644 index 0000000000000..6ba36e6e1e6ca --- /dev/null +++ b/components/slottable/sources/common/base.mjs @@ -0,0 +1,53 @@ +import slottable from "../../slottable.app.mjs"; + +export default { + props: { + slottable, + db: "$.service.db", + http: "$.interface.http", + }, + hooks: { + async activate() { + const companyId = await this.slottable.getCompanyId(); + const { data: { id } } = await this.slottable.createWebhook({ + companyId, + data: { + url: this.http.endpoint, + method: "post", + model: this.getModel(), + events: "changed", + }, + }); + this._setHookId(id); + }, + async deactivate() { + const companyId = await this.slottable.getCompanyId(); + const hookId = this._getHookId(); + if (hookId) { + await this.slottable.deleteWebhook({ + companyId, + hookId, + }); + } + }, + }, + methods: { + _getHookId() { + return this.db.get("hookId"); + }, + _setHookId(hookId) { + this.db.set("hookId", hookId); + }, + getModel() { + throw new Error("getModel is not implemented"); + }, + generateMeta() { + throw new Error("generateMeta is not implemented"); + }, + }, + async run(event) { + const { body } = event; + const meta = this.generateMeta(body.data); + this.$emit(body, meta); + }, +}; diff --git a/components/slottable/sources/contact-updated/contact-updated.mjs b/components/slottable/sources/contact-updated/contact-updated.mjs new file mode 100644 index 0000000000000..865b84a1fa2e8 --- /dev/null +++ b/components/slottable/sources/contact-updated/contact-updated.mjs @@ -0,0 +1,25 @@ +import common from "../common/base.mjs"; + +export default { + ...common, + key: "slottable-contact-updated", + name: "Contact Updated", + version: "0.0.1", + description: "Emit new event when a contact is changed (new, updated, or deleted) in Slottable.", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getModel() { + return "Contact"; + }, + generateMeta(contact) { + const ts = Date.parse(contact.updated_at); + return { + id: `${contact.id}-${ts}`, + summary: `Contact Updated with ID ${contact.id}`, + ts, + }; + }, + }, +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d06cab55a7cac..e08023e6929b6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5273,7 +5273,10 @@ importers: specifiers: {} components/slottable: - specifiers: {} + specifiers: + '@pipedream/platform': ^1.5.1 + dependencies: + '@pipedream/platform': 1.5.1 components/slybroadcast: specifiers: {} From 2197356a2cb12bd3b40e895f90685defb92fd16a Mon Sep 17 00:00:00 2001 From: Luan Cazarine Date: Wed, 18 Oct 2023 09:03:54 -0300 Subject: [PATCH 004/186] 3824 upviral (#8437) * UpViral #3824 Actions - Add Contact - Add Points * pnpm update * some adjusts --- .../actions/add-contact/add-contact.mjs | 105 ++++++++++++++ .../upviral/actions/add-points/add-points.mjs | 51 +++++++ components/upviral/common/constants.mjs | 1 + components/upviral/package.json | 19 +++ components/upviral/upviral.app.mjs | 132 +++++++++++++++++- pnpm-lock.yaml | 8 ++ 6 files changed, 312 insertions(+), 4 deletions(-) create mode 100644 components/upviral/actions/add-contact/add-contact.mjs create mode 100644 components/upviral/actions/add-points/add-points.mjs create mode 100644 components/upviral/common/constants.mjs create mode 100644 components/upviral/package.json diff --git a/components/upviral/actions/add-contact/add-contact.mjs b/components/upviral/actions/add-contact/add-contact.mjs new file mode 100644 index 0000000000000..5e2fff791b713 --- /dev/null +++ b/components/upviral/actions/add-contact/add-contact.mjs @@ -0,0 +1,105 @@ +import { ConfigurationError } from "@pipedream/platform"; +import FormData from "form-data"; +import upviral from "../../upviral.app.mjs"; + +export default { + key: "upviral-add-contact", + name: "Add Contact", + version: "0.0.1", + description: "Add a new contact in your particular campaign. [See the documentation](https://api.upviral.com/#add-contact)", + type: "action", + props: { + upviral, + campaignId: { + propDefinition: [ + upviral, + "campaignId", + ], + reloadProps: true, + }, + email: { + type: "string", + label: "Email", + description: "The user's email address.", + }, + name: { + type: "string", + label: "Name", + description: "The user's name.", + optional: true, + }, + ipAddress: { + type: "string", + label: "IP Address", + description: "The user's IP Address.", + optional: true, + }, + referralCode: { + type: "string", + label: "Referral Code", + description: "The unique referral code (Last part of unique Referral URL). For example - https://upvir.al/ref/XXXX, Referral Code will be XXXX.This will be the referral code of the person who referred this new contact. The original participant will get the credit for this new contact.", + optional: true, + }, + }, + async additionalProps() { + const props = {}; + if (this.campaignId) { + let count = 0; + let data = new FormData(); + data.append("campaign_id", this.campaignId); + + const { custom_fields: customFields } = await this.upviral.listCustomFields({ + data, + headers: data.getHeaders(), + }); + + for (const field of customFields) { + props[`customField-${field}`] = { + type: "string", + label: field, + description: `Custom field ${++count}`, + optional: true, + }; + } + } + return props; + }, + methods: { + parseCustomFields() { + const customFields = Object.entries(this).filter(([ + key, + ]) => key.includes("customField-")) + .map(([ + key, + value, + ]) => ([ + key.split("-")[1], + value, + ])); + + return JSON.stringify(Object.fromEntries(customFields)) || null; + }, + }, + async run({ $ }) { + var bodyFormData = new FormData(); + bodyFormData.append("campaign_id", this.campaignId); + bodyFormData.append("email", this.email); + if (this.name) bodyFormData.append("name", this.name); + if (this.ipAddress) bodyFormData.append("ip_address", this.ipAddress); + if (this.referralCode) bodyFormData.append("referral_code", this.referralCode); + bodyFormData.append("custom_fields", this.parseCustomFields() ); + + const response = await this.upviral.addContact({ + $, + data: bodyFormData, + headers: bodyFormData.getHeaders(), + }); + + if (response.result === "error") { + throw new ConfigurationError(response.message); + } + + $.export("$summary", `A new contact with UID: '${response.uid}' was successfully created!`); + return response; + }, +}; diff --git a/components/upviral/actions/add-points/add-points.mjs b/components/upviral/actions/add-points/add-points.mjs new file mode 100644 index 0000000000000..27dc11b028e60 --- /dev/null +++ b/components/upviral/actions/add-points/add-points.mjs @@ -0,0 +1,51 @@ +import { ConfigurationError } from "@pipedream/platform"; +import FormData from "form-data"; +import upviral from "../../upviral.app.mjs"; + +export default { + key: "upviral-add-points", + name: "Add Points", + version: "0.0.1", + description: "Add points in user profile. [See the documentation](https://api.upviral.com/#add-points)", + type: "action", + props: { + upviral, + campaignId: { + propDefinition: [ + upviral, + "campaignId", + ], + }, + leadId: { + propDefinition: [ + upviral, + "leadId", + ({ campaignId }) => ({ + campaignId, + }), + ], + }, + points: { + type: "string", + label: "Points", + description: "The points to add.", + }, + }, + async run({ $ }) { + var bodyFormData = new FormData(); + bodyFormData.append("campaign_id", this.campaignId); + bodyFormData.append("lead_id", this.leadId); + bodyFormData.append("points", this.points); + + const response = await this.upviral.addPoints({ + $, + data: bodyFormData, + headers: bodyFormData.getHeaders(), + }); + + if (response.result === "error") throw new ConfigurationError(response.message); + + $.export("$summary", `${this.points} points were successfully added!`); + return response; + }, +}; diff --git a/components/upviral/common/constants.mjs b/components/upviral/common/constants.mjs new file mode 100644 index 0000000000000..ea830c15a04cb --- /dev/null +++ b/components/upviral/common/constants.mjs @@ -0,0 +1 @@ +export const LIMIT = 100; diff --git a/components/upviral/package.json b/components/upviral/package.json new file mode 100644 index 0000000000000..acc3df365493d --- /dev/null +++ b/components/upviral/package.json @@ -0,0 +1,19 @@ +{ + "name": "@pipedream/upviral", + "version": "0.1.0", + "description": "Pipedream UpViral Components", + "main": "upviral.app.mjs", + "keywords": [ + "pipedream", + "upviral" + ], + "homepage": "https://pipedream.com/apps/upviral", + "author": "Pipedream (https://pipedream.com/)", + "publishConfig": { + "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^1.5.1", + "form-data": "^4.0.0" + } +} diff --git a/components/upviral/upviral.app.mjs b/components/upviral/upviral.app.mjs index 4e443c7110a33..4698f7acfdf21 100644 --- a/components/upviral/upviral.app.mjs +++ b/components/upviral/upviral.app.mjs @@ -1,11 +1,135 @@ +import { axios } from "@pipedream/platform"; +import FormData from "form-data"; +import { LIMIT } from "./common/constants.mjs"; + export default { type: "app", app: "upviral", - propDefinitions: {}, + propDefinitions: { + campaignId: { + type: "string", + label: "Campaign Id", + description: "The Id of the campaign.", + async options() { + const { data } = await this.listCampaigns({}); + + return data.map(({ + id: value, name: label, + }) => ({ + label, + value, + })); + }, + }, + leadId: { + type: "string", + label: "Lead Id", + description: "The Id of the lead.", + async options({ + page, campaignId, + }) { + var formData = new FormData(); + formData.append("campaign_id", campaignId); + const { data } = await this.listLeads({ + params: { + start: LIMIT * page, + size: LIMIT, + }, + data: formData, + headers: formData.getHeaders(), + }); + + return data.leads.map(({ + id: value, email: label, + }) => ({ + label, + value, + })); + }, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _apiKey() { + return this.$auth.api_key; + }, + _apiUrl() { + return "https://app.upviral.com/api/v1"; + }, + _getParams(params) { + return { + uvapikey: this._apiKey(), + ...params, + }; + }, + _makeRequest({ + $ = this, params, ...opts + }) { + const config = { + url: `${this._apiUrl()}`, + params: this._getParams(params), + ...opts, + }; + + return axios($, config); + }, + addContact({ + params, ...args + }) { + return this._makeRequest({ + method: "POST", + params: { + uvmethod: "add_contact", + ...params, + }, + ...args, + }); + }, + addPoints({ + params, ...args + }) { + return this._makeRequest({ + method: "POST", + params: { + uvmethod: "add_points", + ...params, + }, + ...args, + }); + }, + listCampaigns({ + params = {}, ...args + }) { + return this._makeRequest({ + params: { + uvmethod: "lists", + ...params, + }, + ...args, + }); + }, + listCustomFields({ + params, ...args + }) { + return this._makeRequest({ + method: "POST", + params: { + uvmethod: "get_custom_fields", + ...params, + }, + ...args, + }); + }, + listLeads({ + params, ...args + }) { + return this._makeRequest({ + method: "POST", + params: { + uvmethod: "get_leads", + ...params, + }, + ...args, + }); }, }, }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e08023e6929b6..9135bb5cb34a6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6157,6 +6157,14 @@ importers: components/uptimerobot: specifiers: {} + components/upviral: + specifiers: + '@pipedream/platform': ^1.5.1 + form-data: ^4.0.0 + dependencies: + '@pipedream/platform': 1.5.1 + form-data: 4.0.0 + components/upwave: specifiers: {} From c6f5d71f7dc25c25f3d5332ed8e5b68d63d2c562 Mon Sep 17 00:00:00 2001 From: Jorge Cortes Date: Wed, 18 Oct 2023 07:33:18 -0500 Subject: [PATCH 005/186] [ACTIONS] Google Slides - Merge Data action (#8506) * Added new tested action * Fixed file name --- .../actions/merge-data/merge-data.mjs | 110 ++++++++++++++++++ components/google_slides/package.json | 2 +- 2 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 components/google_slides/actions/merge-data/merge-data.mjs diff --git a/components/google_slides/actions/merge-data/merge-data.mjs b/components/google_slides/actions/merge-data/merge-data.mjs new file mode 100644 index 0000000000000..d585f769ef2a0 --- /dev/null +++ b/components/google_slides/actions/merge-data/merge-data.mjs @@ -0,0 +1,110 @@ +import app from "../../google_slides.app.mjs"; + +export default { + key: "google_slides-merge-data", + name: "Merge Data", + description: "Merge data into a presentation. [See the docs here](https://developers.google.com/slides/api/guides/merge)", + version: "0.0.1", + type: "action", + props: { + app, + drive: { + propDefinition: [ + app, + "watchedDrive", + ], + description: "The drive to select a presentation from. If you are connected with any [Google Shared Drives](https://support.google.com/a/users/answer/9310351), you can select it here.", + }, + presentationId: { + propDefinition: [ + app, + "presentationId", + (c) => ({ + driveId: app.methods.getDriveId(c.drive), + }), + ], + description: "Select the presentation to make a copy of.", + }, + title: { + type: "string", + label: "Title", + description: "The title of the new presentation.", + }, + placeholdersAndTexts: { + type: "object", + label: "Placeholders And Texts", + description: "The placeholders and texts to be merged into the presentation. So the key should be the placeholder ID and the value should be the text to be merged. As a placeholder example you can use `{{name}}` and the value can be `John Doe`.", + }, + placeholdersAndImageUrls: { + type: "object", + label: "Placeholders And Image URLs", + description: "The placeholders and image URLs to be merged into the presentation. So the key should be the placeholder ID and the value should be the image URL to be merged. As a placeholder example you can use `{{image}}` and the value can be `https://example.com/image.jpg`.", + optional: true, + }, + }, + methods: { + getTextRequests(placeholdersAndTexts = {}) { + return Object.entries(placeholdersAndTexts) + .map(([ + key, + value, + ]) => ({ + replaceAllText: { + containsText: { + text: key, + matchCase: true, + }, + replaceText: value, + }, + })); + }, + getImageRequests(placeholdersAndImageUrls = {}) { + return Object.entries(placeholdersAndImageUrls) + .map(([ + key, + value, + ]) => ({ + replaceAllShapesWithImage: { + imageUrl: value, + replaceMethod: "CENTER_INSIDE", + containsText: { + text: key, + matchCase: true, + }, + }, + })); + }, + batchUpdate(args = {}) { + const slides = this.app.slides(); + return slides.presentations.batchUpdate(args); + }, + }, + async run({ $ }) { + const { + app, + batchUpdate, + presentationId, + title, + placeholdersAndTexts, + placeholdersAndImageUrls, + getTextRequests, + getImageRequests, + } = this; + + const presentation = await app.copyPresentation(presentationId, title); + + const { data: response } = await batchUpdate({ + presentationId: presentation.id, + resource: { + requests: [ + ...getTextRequests(placeholdersAndTexts), + ...getImageRequests(placeholdersAndImageUrls), + ], + }, + }); + + $.export("$summary", `Successfully merged data into presentation with ID: ${response.presentationId}`); + + return response; + }, +}; diff --git a/components/google_slides/package.json b/components/google_slides/package.json index 0fd2842538043..0b2020347857f 100644 --- a/components/google_slides/package.json +++ b/components/google_slides/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/google_slides", - "version": "0.0.4", + "version": "0.1.0", "description": "Pipedream Google Slides Components", "main": "google_slides.app.mjs", "keywords": [ From b2a90a8bb62205a9b65786d28a0c0dc9f80dad73 Mon Sep 17 00:00:00 2001 From: michelle0927 Date: Wed, 18 Oct 2023 07:11:12 -0700 Subject: [PATCH 006/186] Niftykit - New Components (#8512) * new components * pnpm-lock.yaml --- .../create-mint-link/create-mint-link.mjs | 83 +++++++++++++++++++ components/niftykit/niftykit.app.mjs | 40 +++++++-- components/niftykit/package.json | 7 +- components/niftykit/sources/common/base.mjs | 47 +++++++++++ .../sources/new-nft-minted/new-nft-minted.mjs | 29 +++++++ pnpm-lock.yaml | 5 +- 6 files changed, 203 insertions(+), 8 deletions(-) create mode 100644 components/niftykit/actions/create-mint-link/create-mint-link.mjs create mode 100644 components/niftykit/sources/common/base.mjs create mode 100644 components/niftykit/sources/new-nft-minted/new-nft-minted.mjs diff --git a/components/niftykit/actions/create-mint-link/create-mint-link.mjs b/components/niftykit/actions/create-mint-link/create-mint-link.mjs new file mode 100644 index 0000000000000..58ea8c0525027 --- /dev/null +++ b/components/niftykit/actions/create-mint-link/create-mint-link.mjs @@ -0,0 +1,83 @@ +import niftykit from "../../niftykit.app.mjs"; + +export default { + key: "niftykit-create-mint-link", + name: "Create Mint Link", + description: "Creates a mint link in NiftyKit. [See the documentation](https://api.niftykit.com/docs?_gl=1*d8mlfi*_ga*MTY5MTM2MjIwNi4xNjk0MDMzOTk3*_ga_B0DCGWCR37*MTY5NzE0MTUzNy40LjAuMTY5NzE0MTUzNy42MC4wLjA.#/onboarding/OnboardingController_createMintLink)", + version: "0.0.1", + type: "action", + props: { + niftykit, + name: { + type: "string", + label: "Name", + description: "Name of the new mint link", + }, + description: { + type: "string", + label: "Description", + description: "Description of the new mint link", + }, + image: { + type: "string", + label: "Image", + description: "URL of the new mint link image", + }, + maxAmount: { + type: "string", + label: "Max Amount", + description: "Max amount", + }, + maxPerWallet: { + type: "string", + label: "Max Per Wallet", + description: "Max per wallet", + }, + maxPerTx: { + type: "string", + label: "Max Per Tx", + description: "Max per transaction", + }, + price: { + type: "string", + label: "Price", + description: "Whether the NFT is `Free` or `Paid`", + options: [ + "Free", + "Paid", + ], + optional: true, + }, + pricePerNFT: { + type: "string", + label: "Price per NFT", + description: "Price per NFT", + optional: true, + }, + }, + async run({ $ }) { + const response = await this.niftykit.createMintLink({ + data: { + NFTMetadata: { + name: this.name, + description: this.description, + image: this.image, + }, + maxAmount: +this.maxAmount, + maxPerWallet: +this.maxPerWallet, + maxPerTx: +this.maxPerTx, + price: this.price, + pricePerNFT: this.pricePerNFT + ? +this.pricePerNFT + : undefined, + }, + $, + }); + + if (response?.id) { + $.export("$summary", `Successfully created Mint Link with ID ${response.id}.`); + } + + return response; + }, +}; diff --git a/components/niftykit/niftykit.app.mjs b/components/niftykit/niftykit.app.mjs index f3ae3df34a487..63b519ebc2d59 100644 --- a/components/niftykit/niftykit.app.mjs +++ b/components/niftykit/niftykit.app.mjs @@ -1,11 +1,41 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "niftykit", - propDefinitions: {}, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _baseUrl() { + return "https://api.niftykit.com"; + }, + _headers() { + return { + "accept": "application/json", + "x-api-key": `${this.$auth.api_access_key}`, + }; + }, + _makeRequest({ + $ = this, + path, + ...args + }) { + return axios($, { + url: `${this._baseUrl()}${path}`, + headers: this._headers(), + ...args, + }); + }, + listTokens(args = {}) { + return this._makeRequest({ + path: "/v3/collections/tokens", + ...args, + }); + }, + createMintLink(args = {}) { + return this._makeRequest({ + path: "/onboarding/mintLinks", + method: "POST", + ...args, + }); }, }, -}; \ No newline at end of file +}; diff --git a/components/niftykit/package.json b/components/niftykit/package.json index 2f75c34a3196b..c08dacf552686 100644 --- a/components/niftykit/package.json +++ b/components/niftykit/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/niftykit", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream NiftyKit Components", "main": "niftykit.app.mjs", "keywords": [ @@ -11,5 +11,8 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^1.5.1" } -} \ No newline at end of file +} diff --git a/components/niftykit/sources/common/base.mjs b/components/niftykit/sources/common/base.mjs new file mode 100644 index 0000000000000..58a87afdffc44 --- /dev/null +++ b/components/niftykit/sources/common/base.mjs @@ -0,0 +1,47 @@ +import niftykit from "../../niftykit.app.mjs"; +import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform"; + +export default { + props: { + niftykit, + db: "$.service.db", + timer: { + type: "$.interface.timer", + default: { + intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, + }, + }, + }, + methods: { + _getLastTs() { + return this.db.get("lastTs") || 0; + }, + _setLastTs(lastTs) { + this.db.set("lastTs", lastTs); + }, + getItems() { + throw new Error("getItems is not implemented"); + }, + generateMeta() { + throw new Error("generateMeta is not implemented"); + }, + }, + async run() { + const lastTs = this._getLastTs(); + let maxTs = lastTs; + const items = await this.getItems(); + + for (const item of items) { + const ts = Date.parse(item.createdAt); + if (ts > lastTs) { + const meta = this.generateMeta(item); + this.$emit(item, meta); + if (ts > maxTs) { + maxTs = ts; + } + } + } + + this._setLastTs(maxTs); + }, +}; diff --git a/components/niftykit/sources/new-nft-minted/new-nft-minted.mjs b/components/niftykit/sources/new-nft-minted/new-nft-minted.mjs new file mode 100644 index 0000000000000..8c9f175bc78bf --- /dev/null +++ b/components/niftykit/sources/new-nft-minted/new-nft-minted.mjs @@ -0,0 +1,29 @@ +import common from "../common/base.mjs"; + +export default { + ...common, + key: "niftykit-new-nft-minted", + name: "New NFT Minted", + description: "Emit new event when a new NFT is minted in NiftyKit. [See the documentation](https://api.niftykit.com/docs?_gl=1*d8mlfi*_ga*MTY5MTM2MjIwNi4xNjk0MDMzOTk3*_ga_B0DCGWCR37*MTY5NzE0MTUzNy40LjAuMTY5NzE0MTUzNy42MC4wLjA.#/collections/CollectionsController_getTokens)", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + async getItems() { + const { data } = await this.niftykit.listTokens({ + params: { + all: true, + }, + }); + return data; + }, + generateMeta(item) { + return { + id: item.id, + summary: `New NFT Minted ID ${item.id}`, + ts: Date.parse(item.createdAt), + }; + }, + }, +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9135bb5cb34a6..6ca2299b2b31a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3665,7 +3665,10 @@ importers: '@pipedream/types': 0.1.6 components/niftykit: - specifiers: {} + specifiers: + '@pipedream/platform': ^1.5.1 + dependencies: + '@pipedream/platform': 1.5.1 components/nightfall_ai: specifiers: {} From b0b7edb268de1b9370d18c5a940c5628ec422bfa Mon Sep 17 00:00:00 2001 From: Nick Reilingh Date: Wed, 18 Oct 2023 10:23:38 -0400 Subject: [PATCH 007/186] airtable_oauth: search-records.mjs bugfix field name with spaces (#8513) * airtable_oauth: search-records.mjs bugfix field name with spaces Per https://support.airtable.com/docs/formula-field-reference, field names with spaces must be wrapped in curly braces. (This is also acceptable for field names without spaces.) * airtable_oauth: bump version numbers --- .../airtable_oauth/actions/search-records/search-records.mjs | 4 ++-- components/airtable_oauth/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/airtable_oauth/actions/search-records/search-records.mjs b/components/airtable_oauth/actions/search-records/search-records.mjs index dcc8a97936de6..af5d9e58c50ad 100644 --- a/components/airtable_oauth/actions/search-records/search-records.mjs +++ b/components/airtable_oauth/actions/search-records/search-records.mjs @@ -5,7 +5,7 @@ export default { key: "airtable_oauth-search-records", name: "Search Records", description: "Searches for a record by field value. Search Field must accept string values. [See the documentation](https://airtable.com/developers/web/api/list-records)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { ...common.props, @@ -36,7 +36,7 @@ export default { }, async run({ $ }) { const params = { - filterByFormula: `FIND("${this.value}", ${this.fieldName})`, + filterByFormula: `FIND("${this.value}", {${this.fieldName}})`, }; if (this.searchFormula) { params.filterByFormula = `AND(${params.filterByFormula}, ${this.searchFormula})`; diff --git a/components/airtable_oauth/package.json b/components/airtable_oauth/package.json index 6ef5e0eafa651..b5cafc1a6391c 100644 --- a/components/airtable_oauth/package.json +++ b/components/airtable_oauth/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/airtable_oauth", - "version": "0.1.2", + "version": "0.2.0", "description": "Pipedream Airtable (OAuth) Components", "main": "airtable_oauth.app.mjs", "keywords": [ From e0a52e2b99240c5b0d4f8a37856861f152df2b81 Mon Sep 17 00:00:00 2001 From: Lucas Caresia Date: Wed, 18 Oct 2023 14:04:52 -0300 Subject: [PATCH 008/186] [Components] Airmeet #7862 (#8458) * Added actions * Added actions * Added requested improvements * Tipo * Improve start time description * Fix start time and end time type --------- Co-authored-by: Hung Vu --- components/airmeet/.gitignore | 3 - .../add-authorized-attendee.mjs | 50 ++++++++++++++ .../airmeet/actions/common/constants.mjs | 64 +++++++++++++++++ .../actions/create-airmeet/create-airmeet.mjs | 69 +++++++++++++++++++ components/airmeet/airmeet.app.mjs | 66 ++++++++++++++++++ components/airmeet/app/airmeet.app.ts | 13 ---- components/airmeet/package.json | 11 +-- pnpm-lock.yaml | 7 +- 8 files changed, 262 insertions(+), 21 deletions(-) delete mode 100644 components/airmeet/.gitignore create mode 100644 components/airmeet/actions/add-authorized-attendee/add-authorized-attendee.mjs create mode 100644 components/airmeet/actions/common/constants.mjs create mode 100644 components/airmeet/actions/create-airmeet/create-airmeet.mjs create mode 100644 components/airmeet/airmeet.app.mjs delete mode 100644 components/airmeet/app/airmeet.app.ts diff --git a/components/airmeet/.gitignore b/components/airmeet/.gitignore deleted file mode 100644 index ec761ccab7595..0000000000000 --- a/components/airmeet/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.js -*.mjs -dist \ No newline at end of file diff --git a/components/airmeet/actions/add-authorized-attendee/add-authorized-attendee.mjs b/components/airmeet/actions/add-authorized-attendee/add-authorized-attendee.mjs new file mode 100644 index 0000000000000..cf1c0b00dfe09 --- /dev/null +++ b/components/airmeet/actions/add-authorized-attendee/add-authorized-attendee.mjs @@ -0,0 +1,50 @@ +import app from "../../airmeet.app.mjs"; + +export default { + name: "Add Authorized Attendee", + version: "0.0.1", + key: "airmeet-add-authorized-attendee", + description: "Add authorized Attendee. [See the documentation](https://help.airmeet.com/support/solutions/articles/82000467794-airmeet-public-apis-v2-0#5.1-Add-Authorized-Attendee)", + type: "action", + props: { + app, + airmeetId: { + propDefinition: [ + app, + "airmeetId", + ], + }, + email: { + type: "string", + label: "Email", + description: "Email of the atendee", + }, + firstName: { + type: "string", + label: "First name", + description: "First name of the atendee", + }, + lastName: { + type: "string", + label: "Last name", + description: "Last name of the atendee", + }, + }, + async run({ $ }) { + const response = await this.app.addAuthorizedAttendee({ + $, + airmeetId: this.airmeetId, + data: { + email: this.email, + firstName: this.firstName, + lastName: this.lastName, + }, + }); + + if (response) { + $.export("$summary", `Successfully added authorized attendee with email \`${response.email}\``); + } + + return response; + }, +}; diff --git a/components/airmeet/actions/common/constants.mjs b/components/airmeet/actions/common/constants.mjs new file mode 100644 index 0000000000000..04672ddf96276 --- /dev/null +++ b/components/airmeet/actions/common/constants.mjs @@ -0,0 +1,64 @@ +export default { + TIME_ZONES: [ + { + label: "America/New_York", + value: "America/New_York", + }, + { + label: "America/Los_Angeles", + value: "America/Los_Angeles", + }, + { + label: "America/Chicago", + value: "America/Chicago", + }, + { + label: "America/Denver", + value: "America/Denver", + }, + { + label: "America/Toronto", + value: "America/Toronto", + }, + { + label: "Europe/London", + value: "Europe/London", + }, + { + label: "Europe/Paris", + value: "Europe/Paris", + }, + { + label: "Asia/Tokyo", + value: "Asia/Tokyo", + }, + { + label: "Asia/Shanghai", + value: "Asia/Shanghai", + }, + { + label: "Australia/Sydney", + value: "Australia/Sydney", + }, + { + label: "Africa/Johannesburg", + value: "Africa/Johannesburg", + }, + { + label: "Pacific/Honolulu", + value: "Pacific/Honolulu", + }, + { + label: "Asia/Dubai", + value: "Asia/Dubai", + }, + { + label: "Asia/Kolkata", + value: "Asia/Kolkata", + }, + { + label: "Europe/Berlin", + value: "Europe/Berlin", + }, + ], +}; diff --git a/components/airmeet/actions/create-airmeet/create-airmeet.mjs b/components/airmeet/actions/create-airmeet/create-airmeet.mjs new file mode 100644 index 0000000000000..75012522a7387 --- /dev/null +++ b/components/airmeet/actions/create-airmeet/create-airmeet.mjs @@ -0,0 +1,69 @@ +import dayjs from "dayjs"; +import app from "../../airmeet.app.mjs"; +import constants from "../common/constants.mjs"; + +export default { + name: "Create Airmeet", + version: "0.0.1", + key: "airmeet-create-airmeet", + description: "Creates an airmeet. [See the documentation](https://help.airmeet.com/support/solutions/articles/82000467794-airmeet-public-apis-v2-0#6.1-Create-Airmeet)", + type: "action", + props: { + app, + hostEmail: { + type: "string", + label: "Host Email", + description: "Email of the host", + }, + eventName: { + type: "string", + label: "Event Name", + description: "Name of the event", + }, + shortDesc: { + type: "string", + label: "Short Description", + description: "Short description of the event", + }, + startTime: { + type: "string", + label: "Start Time", + description: "Start time for the event in milliseconds or ISO 8601. E.g. `1697458790918` or `2023-10-16T12:18:38+00:00`", + }, + endTime: { + type: "string", + label: "End Time", + description: "End time for the event in milliseconds or ISO 8601. E.g. `1697458790918` or `2023-10-16T12:18:38+00:00`", + }, + timezone: { + type: "string", + label: "Timezone", + description: "Timezone for the event in the canonical tz name. E.g. 'Asia/Kolkata'", + options: constants.TIME_ZONES, + }, + }, + async run({ $ }) { + const startTime = dayjs(this.startTime).valueOf(); + const endTime = dayjs(this.endTime).valueOf(); + + const response = await this.app.createAirmeet({ + $, + data: { + hostEmail: this.hostEmail, + eventName: this.eventName, + shortDesc: this.shortDesc, + timing: { + startTime: startTime, + endTime: endTime, + timezone: this.timezone, + }, + }, + }); + + if (response) { + $.export("$summary", `Successfully created airmeet with UUID \`${response.uuid}\``); + } + + return response; + }, +}; diff --git a/components/airmeet/airmeet.app.mjs b/components/airmeet/airmeet.app.mjs new file mode 100644 index 0000000000000..8c0dfe5d4977d --- /dev/null +++ b/components/airmeet/airmeet.app.mjs @@ -0,0 +1,66 @@ +import { axios } from "@pipedream/platform"; + +export default { + type: "app", + app: "airmeet", + propDefinitions: { + airmeetId: { + type: "string", + label: "Airmeet ID", + description: "The Airmeet ID", + async options() { + const { data: airmeets } = await this.getAirmeets(); + + return airmeets.map((airmeet) => ({ + value: airmeet.uid, + label: airmeet.name, + })); + }, + }, + }, + methods: { + _oauthAccessToken() { + return this.$auth.oauth_access_token; + }, + _region() { + return this.$auth.region; + }, + _apiUrl() { + return `https://${this._region()}.airmeet.com/prod`; + }, + async _makeRequest({ + $ = this, path, ...args + }) { + return axios($, { + url: `${this._apiUrl()}${path}`, + ...args, + headers: { + ...args.headers, + "X-Airmeet-Access-Token": this._oauthAccessToken(), + }, + }); + }, + createAirmeet(args = {}) { + return this._makeRequest({ + path: "/airmeet", + method: "post", + ...args, + }); + }, + addAuthorizedAttendee({ + airmeetId, ...args + }) { + return this._makeRequest({ + path: `/airmeet/${airmeetId}/attendee`, + method: "post", + ...args, + }); + }, + getAirmeets(args = {}) { + return this._makeRequest({ + path: "/airmeets", + ...args, + }); + }, + }, +}; diff --git a/components/airmeet/app/airmeet.app.ts b/components/airmeet/app/airmeet.app.ts deleted file mode 100644 index f770d975a2baa..0000000000000 --- a/components/airmeet/app/airmeet.app.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { defineApp } from "@pipedream/types"; - -export default defineApp({ - type: "app", - app: "airmeet", - 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/airmeet/package.json b/components/airmeet/package.json index c35ac9a512cb2..2355ecad816b2 100644 --- a/components/airmeet/package.json +++ b/components/airmeet/package.json @@ -1,16 +1,19 @@ { "name": "@pipedream/airmeet", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Airmeet Components", - "main": "dist/app/airmeet.app.mjs", + "main": "airmeet.app.mjs", "keywords": [ "pipedream", "airmeet" ], - "files": ["dist"], "homepage": "https://pipedream.com/apps/airmeet", "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^1.5.1", + "dayjs": "^1.11.10" } -} \ No newline at end of file +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6ca2299b2b31a..69467bf8e24b1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -172,7 +172,12 @@ importers: specifiers: {} components/airmeet: - specifiers: {} + specifiers: + '@pipedream/platform': ^1.5.1 + dayjs: ^1.11.10 + dependencies: + '@pipedream/platform': 1.5.1 + dayjs: 1.11.10 components/airnow: specifiers: {} From 5b89ffb8ce613154923e8e5b57eb905b38bacbf5 Mon Sep 17 00:00:00 2001 From: Lucas Caresia Date: Wed, 18 Oct 2023 14:05:26 -0300 Subject: [PATCH 009/186] [Components] CleverTap #8362 (#8488) * Added actions * Removed some events from constants * Make Event Name prop free text --------- Co-authored-by: Hung Vu --- .../create-or-update-user.mjs | 57 +++++++++++++++++++ .../actions/upload-events/upload-events.mjs | 53 +++++++++++++++++ components/clevertap/clevertap.app.mjs | 36 +++++++++++- components/clevertap/package.json | 7 ++- pnpm-lock.yaml | 5 +- 5 files changed, 152 insertions(+), 6 deletions(-) create mode 100644 components/clevertap/actions/create-or-update-user/create-or-update-user.mjs create mode 100644 components/clevertap/actions/upload-events/upload-events.mjs diff --git a/components/clevertap/actions/create-or-update-user/create-or-update-user.mjs b/components/clevertap/actions/create-or-update-user/create-or-update-user.mjs new file mode 100644 index 0000000000000..fa59c5021de1d --- /dev/null +++ b/components/clevertap/actions/create-or-update-user/create-or-update-user.mjs @@ -0,0 +1,57 @@ +import app from "../../clevertap.app.mjs"; + +export default { + name: "Create Or Update User", + version: "0.0.1", + key: "clevertap-create-or-update-user", + description: "Create or update an user. [See the documentation](https://developer.clevertap.com/docs/upload-user-profiles-api)", + type: "action", + props: { + app, + email: { + type: "string", + label: "Email", + description: "Email of the user", + }, + name: { + type: "string", + label: "Name", + description: "Name of the user", + }, + phone: { + type: "string", + label: "Phone Number, e.g +15555555555", + description: "Phone number of the user", + }, + identity: { + type: "string", + label: "Identity", + description: "Identifier of the user", + }, + }, + async run({ $ }) { + const response = await this.app.uploadEvent({ + $, + data: { + d: [ + { + $source: "Pipedream", + type: "profile", + identity: this.identity, + profileData: { + Name: this.name, + Email: this.email, + Phone: this.phone, + }, + }, + ], + }, + }); + + if (response.status === "success") { + $.export("$summary", "Successfully created or updated user"); + } + + return response; + }, +}; diff --git a/components/clevertap/actions/upload-events/upload-events.mjs b/components/clevertap/actions/upload-events/upload-events.mjs new file mode 100644 index 0000000000000..1857f3c825c6b --- /dev/null +++ b/components/clevertap/actions/upload-events/upload-events.mjs @@ -0,0 +1,53 @@ +import app from "../../clevertap.app.mjs"; + +export default { + name: "Upload Events", + version: "0.0.1", + key: "clevertap-upload-events", + description: "Upload events. [See the documentation](https://developer.clevertap.com/docs/upload-events-api)", + type: "action", + props: { + app, + eventName: { + type: "string", + label: "Event Name", + description: "Name of the event", + }, + identity: { + type: "string", + label: "Identity", + description: "Identifier of the user", + }, + eventData: { + label: "Event Data", + type: "object", + description: "The event data to be uploaded. E.g. `{ \"Product name\": \"Casio Watch\", \"Category\": \"Mens Watch\" }`", + }, + }, + async run({ $ }) { + const eventData = typeof this.eventData === "string" + ? JSON.parse(this.eventData) + : this.eventData; + + const response = await this.app.uploadEvent({ + $, + data: { + d: [ + { + $source: "Pipedream", + type: "event", + evtName: this.eventName, + identity: this.identity, + evtData: eventData, + }, + ], + }, + }); + + if (response.status === "success") { + $.export("$summary", "Successfully uploaded event"); + } + + return response; + }, +}; diff --git a/components/clevertap/clevertap.app.mjs b/components/clevertap/clevertap.app.mjs index e3f69ba26f4ca..608198ca82db4 100644 --- a/components/clevertap/clevertap.app.mjs +++ b/components/clevertap/clevertap.app.mjs @@ -1,11 +1,41 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "clevertap", propDefinitions: {}, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _projectId() { + return this.$auth.project_id; + }, + _passCode() { + return this.$auth.pass_code; + }, + _region() { + return this.$auth.region; + }, + _apiUrl() { + return `https://${this._region()}.clevertap.com/1`; + }, + async _makeRequest({ + $ = this, path, ...args + }) { + return axios($, { + url: `${this._apiUrl()}${path}`, + ...args, + headers: { + ...args.headers, + "X-CleverTap-Account-Id": this._projectId(), + "X-CleverTap-Passcode": this._passCode(), + }, + }); + }, + async uploadEvent(args = {}) { + return this._makeRequest({ + path: "/upload", + method: "post", + ...args, + }); }, }, }; diff --git a/components/clevertap/package.json b/components/clevertap/package.json index 00c36e7c7765e..a4c4ed44a5aa7 100644 --- a/components/clevertap/package.json +++ b/components/clevertap/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/clevertap", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream CleverTap Components", "main": "clevertap.app.mjs", "keywords": [ @@ -11,5 +11,8 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^1.5.1" } -} \ No newline at end of file +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 69467bf8e24b1..5a6b2eb398047 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -888,7 +888,10 @@ importers: '@pipedream/platform': 1.5.1 components/clevertap: - specifiers: {} + specifiers: + '@pipedream/platform': ^1.5.1 + dependencies: + '@pipedream/platform': 1.5.1 components/clickfunnels: specifiers: {} From 773868a5f105f580e80b3c509f2f3bfaa8b21ccc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Oct 2023 14:39:55 -0300 Subject: [PATCH 010/186] Bump urllib3 from 2.0.6 to 2.0.7 in /packages/component_code_gen (#8515) Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.0.6 to 2.0.7. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/2.0.6...2.0.7) --- updated-dependencies: - dependency-name: urllib3 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/component_code_gen/poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/component_code_gen/poetry.lock b/packages/component_code_gen/poetry.lock index dad9904f2ebf6..94fcf5c020577 100644 --- a/packages/component_code_gen/poetry.lock +++ b/packages/component_code_gen/poetry.lock @@ -1882,13 +1882,13 @@ typing-extensions = ">=3.7.4" [[package]] name = "urllib3" -version = "2.0.6" +version = "2.0.7" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.7" files = [ - {file = "urllib3-2.0.6-py3-none-any.whl", hash = "sha256:7a7c7003b000adf9e7ca2a377c9688bbc54ed41b985789ed576570342a375cd2"}, - {file = "urllib3-2.0.6.tar.gz", hash = "sha256:b19e1a85d206b56d7df1d5e683df4a7725252a964e3993648dd0fb5a1c157564"}, + {file = "urllib3-2.0.7-py3-none-any.whl", hash = "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e"}, + {file = "urllib3-2.0.7.tar.gz", hash = "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84"}, ] [package.dependencies] From b52dcc5440bbaeb4ca94020208e6b711fd6a1bb0 Mon Sep 17 00:00:00 2001 From: Luan Cazarine Date: Wed, 18 Oct 2023 16:46:13 -0300 Subject: [PATCH 011/186] 3853 zoho workdrive (#8493) * Zoho WorkDrive #3853 Triggers - New File in Folder - New Folder Actions - Upload File * pnpm update * some adjusts --- .../actions/upload-file/upload-file.mjs | 73 +++++ .../zoho_workdrive/common/constants.mjs | 1 + components/zoho_workdrive/common/utils.mjs | 6 + components/zoho_workdrive/package.json | 19 ++ .../new-file-in-folder/new-file-in-folder.mjs | 92 +++++++ .../sources/new-file-in-folder/test-event.mjs | 259 ++++++++++++++++++ .../sources/new-folder/new-folder.mjs | 92 +++++++ .../sources/new-folder/test-event.mjs | 259 ++++++++++++++++++ .../zoho_workdrive/zoho_workdrive.app.mjs | 213 +++++++++++++- pnpm-lock.yaml | 8 + 10 files changed, 1018 insertions(+), 4 deletions(-) create mode 100644 components/zoho_workdrive/actions/upload-file/upload-file.mjs create mode 100644 components/zoho_workdrive/common/constants.mjs create mode 100644 components/zoho_workdrive/common/utils.mjs create mode 100644 components/zoho_workdrive/package.json create mode 100644 components/zoho_workdrive/sources/new-file-in-folder/new-file-in-folder.mjs create mode 100644 components/zoho_workdrive/sources/new-file-in-folder/test-event.mjs create mode 100644 components/zoho_workdrive/sources/new-folder/new-folder.mjs create mode 100644 components/zoho_workdrive/sources/new-folder/test-event.mjs diff --git a/components/zoho_workdrive/actions/upload-file/upload-file.mjs b/components/zoho_workdrive/actions/upload-file/upload-file.mjs new file mode 100644 index 0000000000000..6cc62d45378bd --- /dev/null +++ b/components/zoho_workdrive/actions/upload-file/upload-file.mjs @@ -0,0 +1,73 @@ +import { ConfigurationError } from "@pipedream/platform"; +import FormData from "form-data"; +import fs from "fs"; +import { getFilePath } from "../../common/utils.mjs"; +import app from "../../zoho_workdrive.app.mjs"; + +export default { + key: "zoho_workdrive-upload-file", + name: "Upload File", + version: "0.0.1", + description: "Upload a new file to your WorkDrive account. [See the documentation](https://workdrive.zoho.com/apidocs/v1/chunkupload/chunkuploadcreatesession)", + type: "action", + props: { + app, + teamId: { + propDefinition: [ + app, + "teamId", + ], + }, + parentId: { + propDefinition: [ + app, + "parentId", + ({ teamId }) => ({ + teamId, + }), + ], + }, + filename: { + label: "Filename", + description: "The name of the file should be URL encoded with UTF-8 Charset.", + type: "string", + optional: true, + }, + overrideNameExist: { + type: "boolean", + label: "Override Name Exist", + description: "If set as **true**, a file with the matching name will be uploaded as a top version over the existing file. If set as **false**, a file with the matching name will have the timestamp added to it on upload.", + optional: true, + }, + content: { + label: "File Path", + description: "Full path to the file in `/tmp/` directory. E.g. `/tmp/file.jpg`", + type: "string", + }, + }, + async run({ $ }) { + const path = getFilePath(this.content); + if (!fs.existsSync(path)) { + throw new ConfigurationError("File does not exist!"); + } + const file = fs.createReadStream(path); + const data = new FormData(); + const override = this.overrideNameExist?.toString(); + + data.append("content", file); + data.append("parent_id", this.parentId); + if (this.filename)data.append("filename", this.filename); + if (override)data.append("override-name-exist", override); + + const response = await this.app.uploadFile({ + $, + data, + headers: { + "Content-Type": `multipart/form-data; boundary=${data._boundary}`, + }, + }); + + $.export("$summary", "The file was successfully uploaded!"); + return response; + }, +}; diff --git a/components/zoho_workdrive/common/constants.mjs b/components/zoho_workdrive/common/constants.mjs new file mode 100644 index 0000000000000..9975390fe8151 --- /dev/null +++ b/components/zoho_workdrive/common/constants.mjs @@ -0,0 +1 @@ +export const LIMIT = 50; diff --git a/components/zoho_workdrive/common/utils.mjs b/components/zoho_workdrive/common/utils.mjs new file mode 100644 index 0000000000000..cfd711fb233cf --- /dev/null +++ b/components/zoho_workdrive/common/utils.mjs @@ -0,0 +1,6 @@ +export const getFilePath = (filename) => { + if (filename.indexOf("/tmp") === -1) { + return `/tmp/${filename}`; + } + return filename; +}; diff --git a/components/zoho_workdrive/package.json b/components/zoho_workdrive/package.json new file mode 100644 index 0000000000000..96ef4774cdd9e --- /dev/null +++ b/components/zoho_workdrive/package.json @@ -0,0 +1,19 @@ +{ + "name": "@pipedream/zoho_workdrive", + "version": "0.1.0", + "description": "Pipedream Zoho WorkDrive Components", + "main": "zoho_workdrive.app.mjs", + "keywords": [ + "pipedream", + "zoho_workdrive" + ], + "homepage": "https://pipedream.com/apps/zoho_workdrive", + "author": "Pipedream (https://pipedream.com/)", + "publishConfig": { + "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^1.5.1", + "axios": "^1.5.1" + } +} diff --git a/components/zoho_workdrive/sources/new-file-in-folder/new-file-in-folder.mjs b/components/zoho_workdrive/sources/new-file-in-folder/new-file-in-folder.mjs new file mode 100644 index 0000000000000..85b5c1891312a --- /dev/null +++ b/components/zoho_workdrive/sources/new-file-in-folder/new-file-in-folder.mjs @@ -0,0 +1,92 @@ +import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform"; +import app from "../../zoho_workdrive.app.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + key: "zoho_workdrive-new-file-in-folder", + name: "New File In Folder", + version: "0.0.1", + description: "Emit new event when a new file is created in a specific folder.", + type: "source", + dedupe: "unique", + props: { + app, + db: "$.service.db", + timer: { + label: "Polling interval", + description: "Pipedream will poll the Zoho WorkDrive on this schedule", + type: "$.interface.timer", + default: { + intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, + }, + }, + teamId: { + propDefinition: [ + app, + "teamId", + ], + }, + folderId: { + propDefinition: [ + app, + "parentId", + ({ teamId }) => ({ + teamId, + }), + ], + label: "Folder Id", + description: "The unique ID of the folder.", + }, + }, + methods: { + _getLastDate() { + return this.db.get("lastDate") || 0; + }, + _setLastDate(lastDate) { + this.db.set("lastDate", lastDate); + }, + async startEvent(maxResults = 0) { + const { + app, + folderId, + } = this; + + const lastDate = this._getLastDate(); + const items = app.paginate({ + fn: app.listFiles, + maxResults, + filter: "allfiles", + sort: "created_time", + folderId, + }); + + let responseArray = []; + + for await (const item of items) { + if (new Date(item.created_time) <= new Date(lastDate)) break; + responseArray.push(item); + } + if (responseArray.length) this._setLastDate(responseArray[0].created_time); + + for (const item of responseArray) { + this.$emit( + item, + { + id: item.id, + summary: `A new file with id: "${item.id}" was created!`, + ts: item.created_time, + }, + ); + } + }, + }, + hooks: { + async deploy() { + await this.startEvent(25); + }, + }, + async run() { + await this.startEvent(); + }, + sampleEmit, +}; diff --git a/components/zoho_workdrive/sources/new-file-in-folder/test-event.mjs b/components/zoho_workdrive/sources/new-file-in-folder/test-event.mjs new file mode 100644 index 0000000000000..ebfcda77612a0 --- /dev/null +++ b/components/zoho_workdrive/sources/new-file-in-folder/test-event.mjs @@ -0,0 +1,259 @@ +export default { + id: "cjrrr1b298cf52cf44acebc713ab5b73bbd77", + type: "files", + attributes: { + modified_by_zuid: "747938014", + is_locked: false, + conv_engine_type: 0, + is_fillable_resource: false, + is_published: false, + destination_id: "cjrrr27f73d5b59a54b16aaf3cd74478a0fa2", + storage_info: { + size: "0 bytes", + storage_used: "0 bytes", + files_count: 0, + folders_count: 0, + size_in_bytes: 0, + storage_used_in_bytes: 0 + }, + type: "file", + created_time_i18: "Apr 13, 10:58 AM", + modified_time_in_millisecond: 1618291736244, + opened_time: "Apr 13, 10:58 AM", + status_change_time: "Apr 13, 10:58 AM", + download_url: "https://www.zohoapis.com/workdrive/download/cjrrr1b298cf52cf44acebc713ab5b73bbd77", + comment_badge_count: 0, + is_app_associated: false, + created_time: "Apr 13, 10:58 AM", + lock_status: 2, + is_folder: false, + resource_type: 1001, + is_email_in_upload: false, + display_attr_name: "April", + created_by: "Zylker Creation", + display_html_name: "April", + labels: [], + parent_id: "cjrrr27f73d5b59a54b16aaf3cd74478a0fa2", + name: "April", + status_change_time_in_millisecond: 1618291736244, + permalink: "https://www.zohoapis.com/workdrive/folder/cjrrr1b298cf52cf44acebc713ab5b73bbd77", + favorite: false, + new_badge_count: 0, + status: 1, + modified_time_i18: "Apr 13, 10:58 AM", + opened_time_i18: "Apr 13, 10:58 AM", + extn: "", + view_pref: { + sort_by: "last_modified", + sort_order: "desc", + filtered_by: "all", + layout: "list" + }, + shortcut_link: "", + status_change_time_i18: "Apr 13, 10:58 AM", + description: "", + uploaded_time_in_millisecond: 1618291736244, + thumbnail_url: "", + title: "", + files_view_pref: { + sort_by: "last_modified", + sort_order: "desc", + filtered_by: "all", + layout: "list" + }, + modified_time: "Apr 13, 10:58 AM", + library_id: "ly9zm0170fb40015f4e2297a144e2b68cfa68", + icon_class: "folder", + created_time_in_millisecond: 1618291736244, + owner: "747937818", + creator: "747938014", + capabilities: { + can_read: true, + can_share: true, + can_remove_share: false, + can_delete: false, + can_edit: true, + can_create_files: true, + can_upload_files: true, + can_trash: true, + can_rename: true, + can_restore: false, + can_copy: true, + can_move: true, + can_zip: true, + can_download: true, + can_emailattach: true, + can_publish: true, + can_create_task: false, + can_share_support: true, + can_label: true, + can_trash_files: true + }, + uploaded_time_i18: "Apr 13, 10:58 AM", + is_external_upload: false, + watch_preference: { + watch: false, + notifyemail: false, + notifybell: false + }, + opened_time_in_millisecond: 1618291736244, + edit_badge_count: 0, + share_data: [], + uploaded_time: "Apr 13, 10:58 AM", + has_folders: false, + service_type: "upload", + display_url_name: "April", + is_unread: false, + modified_by: "Zylker Creation", + embed_props: {} + }, + relationships: { + folders: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/folders", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/folders" + } + }, + comments: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/comments", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/comments" + } + }, + previewinfo: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/previewinfo", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/previewinfo" + } + }, + unzip: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/unzip", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/unzip" + } + }, + publiclink: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/publiclink", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/publiclink" + } + }, + resourceproperty: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/resourceproperty", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/resourceproperty" + } + }, + parentfolders: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/parentfolders", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/parentfolders" + } + }, + shortcut: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/shortcut", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/shortcut" + } + }, + importfile: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/importfile", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/importfile" + } + }, + versions: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/versions", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/versions" + } + }, + supportshare: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/supportshare", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/supportshare" + } + }, + permissions: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/permissions", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/permissions" + } + }, + timeline: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/timeline", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/timeline" + } + }, + files: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/files", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/files" + } + }, + saveastemplate: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/saveastemplate", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/saveastemplate" + } + }, + links: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/links", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/links" + } + }, + copy: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/copy", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/copy" + } + }, + previewzip: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/previewzip", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/previewzip" + } + }, + tasks: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/tasks", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/tasks" + } + }, + breadcrumbs: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/breadcrumbs", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/breadcrumbs" + } + }, + entity: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/entity", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/entity" + } + }, + custommetadata: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/custommetadata", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/custommetadata" + } + }, + statistics: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/statistics", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/statistics" + } + }, + appdata: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/appdata", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/appdata" + } + } + }, + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77" + } +} \ No newline at end of file diff --git a/components/zoho_workdrive/sources/new-folder/new-folder.mjs b/components/zoho_workdrive/sources/new-folder/new-folder.mjs new file mode 100644 index 0000000000000..0a49fcfca1964 --- /dev/null +++ b/components/zoho_workdrive/sources/new-folder/new-folder.mjs @@ -0,0 +1,92 @@ +import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform"; +import app from "../../zoho_workdrive.app.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + key: "zoho_workdrive-new-folder", + name: "New Folder", + version: "0.0.1", + description: "Emit new event when a new folder is created in a specific folder.", + type: "source", + dedupe: "unique", + props: { + app, + db: "$.service.db", + timer: { + label: "Polling interval", + description: "Pipedream will poll the Zoho WorkDrive on this schedule", + type: "$.interface.timer", + default: { + intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, + }, + }, + teamId: { + propDefinition: [ + app, + "teamId", + ], + }, + folderId: { + propDefinition: [ + app, + "parentId", + ({ teamId }) => ({ + teamId, + }), + ], + label: "Folder Id", + description: "The unique ID of the folder.", + }, + }, + methods: { + _getLastDate() { + return this.db.get("lastDate") || 0; + }, + _setLastDate(lastDate) { + this.db.set("lastDate", lastDate); + }, + async startEvent(maxResults = 0) { + const { + app, + folderId, + } = this; + + const lastDate = this._getLastDate(); + const items = app.paginate({ + fn: app.listFiles, + maxResults, + filter: "folder", + sort: "created_time", + folderId, + }); + + let responseArray = []; + + for await (const item of items) { + if (new Date(item.created_time) <= new Date(lastDate)) break; + responseArray.push(item); + } + if (responseArray.length) this._setLastDate(responseArray[0].created_time); + + for (const item of responseArray) { + this.$emit( + item, + { + id: item.id, + summary: `A new folder with id: "${item.id}" was created!`, + ts: item.created_time, + }, + ); + } + }, + }, + hooks: { + async deploy() { + await this.startEvent(25); + }, + }, + async run() { + await this.startEvent(); + }, + sampleEmit, +}; diff --git a/components/zoho_workdrive/sources/new-folder/test-event.mjs b/components/zoho_workdrive/sources/new-folder/test-event.mjs new file mode 100644 index 0000000000000..a6b2247d763ce --- /dev/null +++ b/components/zoho_workdrive/sources/new-folder/test-event.mjs @@ -0,0 +1,259 @@ +export default { + id: "cjrrr1b298cf52cf44acebc713ab5b73bbd77", + type: "files", + attributes: { + modified_by_zuid: "747938014", + is_locked: false, + conv_engine_type: 0, + is_fillable_resource: false, + is_published: false, + destination_id: "cjrrr27f73d5b59a54b16aaf3cd74478a0fa2", + storage_info: { + size: "0 bytes", + storage_used: "0 bytes", + files_count: 0, + folders_count: 0, + size_in_bytes: 0, + storage_used_in_bytes: 0 + }, + type: "folder", + created_time_i18: "Apr 13, 10:58 AM", + modified_time_in_millisecond: 1618291736244, + opened_time: "Apr 13, 10:58 AM", + status_change_time: "Apr 13, 10:58 AM", + download_url: "https://www.zohoapis.com/workdrive/download/cjrrr1b298cf52cf44acebc713ab5b73bbd77", + comment_badge_count: 0, + is_app_associated: false, + created_time: "Apr 13, 10:58 AM", + lock_status: 2, + is_folder: false, + resource_type: 1001, + is_email_in_upload: false, + display_attr_name: "April", + created_by: "Zylker Creation", + display_html_name: "April", + labels: [], + parent_id: "cjrrr27f73d5b59a54b16aaf3cd74478a0fa2", + name: "April", + status_change_time_in_millisecond: 1618291736244, + permalink: "https://www.zohoapis.com/workdrive/folder/cjrrr1b298cf52cf44acebc713ab5b73bbd77", + favorite: false, + new_badge_count: 0, + status: 1, + modified_time_i18: "Apr 13, 10:58 AM", + opened_time_i18: "Apr 13, 10:58 AM", + extn: "", + view_pref: { + sort_by: "last_modified", + sort_order: "desc", + filtered_by: "all", + layout: "list" + }, + shortcut_link: "", + status_change_time_i18: "Apr 13, 10:58 AM", + description: "", + uploaded_time_in_millisecond: 1618291736244, + thumbnail_url: "", + title: "", + files_view_pref: { + sort_by: "last_modified", + sort_order: "desc", + filtered_by: "all", + layout: "list" + }, + modified_time: "Apr 13, 10:58 AM", + library_id: "ly9zm0170fb40015f4e2297a144e2b68cfa68", + icon_class: "folder", + created_time_in_millisecond: 1618291736244, + owner: "747937818", + creator: "747938014", + capabilities: { + can_read: true, + can_share: true, + can_remove_share: false, + can_delete: false, + can_edit: true, + can_create_files: true, + can_upload_files: true, + can_trash: true, + can_rename: true, + can_restore: false, + can_copy: true, + can_move: true, + can_zip: true, + can_download: true, + can_emailattach: true, + can_publish: true, + can_create_task: false, + can_share_support: true, + can_label: true, + can_trash_files: true + }, + uploaded_time_i18: "Apr 13, 10:58 AM", + is_external_upload: false, + watch_preference: { + watch: false, + notifyemail: false, + notifybell: false + }, + opened_time_in_millisecond: 1618291736244, + edit_badge_count: 0, + share_data: [], + uploaded_time: "Apr 13, 10:58 AM", + has_folders: false, + service_type: "upload", + display_url_name: "April", + is_unread: false, + modified_by: "Zylker Creation", + embed_props: {} + }, + relationships: { + folders: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/folders", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/folders" + } + }, + comments: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/comments", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/comments" + } + }, + previewinfo: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/previewinfo", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/previewinfo" + } + }, + unzip: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/unzip", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/unzip" + } + }, + publiclink: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/publiclink", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/publiclink" + } + }, + resourceproperty: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/resourceproperty", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/resourceproperty" + } + }, + parentfolders: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/parentfolders", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/parentfolders" + } + }, + shortcut: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/shortcut", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/shortcut" + } + }, + importfile: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/importfile", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/importfile" + } + }, + versions: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/versions", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/versions" + } + }, + supportshare: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/supportshare", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/supportshare" + } + }, + permissions: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/permissions", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/permissions" + } + }, + timeline: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/timeline", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/timeline" + } + }, + files: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/files", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/files" + } + }, + saveastemplate: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/saveastemplate", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/saveastemplate" + } + }, + links: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/links", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/links" + } + }, + copy: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/copy", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/copy" + } + }, + previewzip: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/previewzip", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/previewzip" + } + }, + tasks: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/tasks", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/tasks" + } + }, + breadcrumbs: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/breadcrumbs", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/breadcrumbs" + } + }, + entity: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/entity", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/entity" + } + }, + custommetadata: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/custommetadata", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/custommetadata" + } + }, + statistics: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/statistics", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/statistics" + } + }, + appdata: { + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/relationships/appdata", + related: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77/appdata" + } + } + }, + links: { + self: "https://www.zohoapis.com/workdrive/files/cjrrr1b298cf52cf44acebc713ab5b73bbd77" + } +} \ No newline at end of file diff --git a/components/zoho_workdrive/zoho_workdrive.app.mjs b/components/zoho_workdrive/zoho_workdrive.app.mjs index e133f0f48aca4..159618bbc0720 100644 --- a/components/zoho_workdrive/zoho_workdrive.app.mjs +++ b/components/zoho_workdrive/zoho_workdrive.app.mjs @@ -1,11 +1,216 @@ +import axios from "axios"; +import qs from "qs"; +import { LIMIT } from "./common/constants.mjs"; + export default { type: "app", app: "zoho_workdrive", - propDefinitions: {}, + propDefinitions: { + teamId: { + type: "string", + label: "Team Id", + description: "The unique ID that represents a team.", + async options() { + const { data: { id: userId } } = await this.getUser(); + const { data } = await this.listTeams({ + userId, + }); + + return data.map(({ + id: value, attributes: { name: label }, + }) => ({ + label, + value, + })); + }, + }, + parentId: { + type: "string", + label: "Parent Id", + description: "The unique ID of the folder where files are to be uploaded.", + async options({ + page, teamId, + }) { + return await this.listRootFolders({ + teamId, + limit: LIMIT, + offset: LIMIT * page, + }); + }, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _apiUrl(path, params = "") { + return `https://workdrive.${this.$auth.base_api_uri}/api/v1/${path}${params + ? `?${params}` + : ""}`; + }, + _getHeaders(headers = {}) { + return { + "Authorization": `Bearer ${this.$auth.oauth_access_token}`, + ...headers, + }; + }, + async _makeRequest({ + path, params, headers, ...opts + }) { + const config = { + url: this._apiUrl(path, params), + headers: this._getHeaders(headers), + ...opts, + }; + + const { data } = await axios(config); + return data; + }, + getPrivateSpace({ + teamCurrentUserId, ...args + }) { + return this._makeRequest({ + path: `users/${teamCurrentUserId}/privatespace`, + ...args, + }); + }, + getTeamCurrentUser({ + teamId, ...args + }) { + return this._makeRequest({ + path: `teams/${teamId}/currentuser`, + ...args, + }); + }, + getUser(args = {}) { + return this._makeRequest({ + path: "users/me", + ...args, + }); + }, + listFiles({ + folderId, params = "", filter = "folder", sort = "name", ...args + }) { + return this._makeRequest({ + path: `files/${folderId}/files`, + params: `${params}&filter%5Btype%5D=${filter}&sort=${sort}`, + ...args, + }); + }, + async listRootFolders({ + teamId, limit, offset, params = {}, ...args + }) { + const { data: { id: teamCurrentUserId } } = await this.getTeamCurrentUser({ + teamId, + }); + + const { + data: [ + { id: privateSpaceId }, + ], + } = await this.getPrivateSpace({ + teamCurrentUserId, + }); + params["page[limit]"] = limit; + params["page[offset]"] = offset; + params["sort"] = "name"; + const reponseArray = []; + const { data: rootFolders } = await this._makeRequest({ + path: `privatespace/${privateSpaceId}/folders`, + params: qs.stringify(params), + ...args, + }); + + for (const { + id, attributes, + } of rootFolders) { + reponseArray.push({ + value: id, + label: attributes.name, + }); + const subFolders = await this.paginateFolders({ + folderId: id, + prefix: "- ", + }); + reponseArray.push(...subFolders); + } + return reponseArray; + }, + listTeams({ + userId, ...args + }) { + return this._makeRequest({ + path: `users/${userId}/teams`, + ...args, + }); + }, + uploadFile(args = {}) { + return this._makeRequest({ + method: "POST", + path: "upload", + ...args, + }); + }, + async paginateFolders({ + folderId, prefix = "", params = {}, + }) { + let hasMore = false; + let page = 0; + const responseArray = []; + + do { + params["page[limit]"] = LIMIT; + params["page[offset]"] = LIMIT * page; + page++; + + const { data: subFolders } = await this.listFiles({ + folderId, + params: qs.stringify(params), + }); + + for (const { + id, attributes: { name }, + } of subFolders) { + responseArray.push({ + value: id, + label: `${prefix}${name}`, + }); + responseArray.push(...await this.paginateFolders({ + folderId: id, + prefix: `${prefix}- `, + })); + } + + hasMore = subFolders.length; + } while (hasMore); + + return responseArray; + }, + async *paginate({ + fn, params = {}, maxResults = null, ...args + }) { + let hasMore = false; + let count = 0; + let page = 0; + + do { + params["page[limit]"] = LIMIT; + params["page[offset]"] = LIMIT * page; + page++; + + const { data } = await fn({ + params: qs.stringify(params), + ...args, + }); + + for (const d of data) { + yield d; + + if (maxResults && ++count === maxResults) { + return count; + } + } + + hasMore = data.length; + + } while (hasMore); }, }, }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5a6b2eb398047..9d0194db7688f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6876,6 +6876,14 @@ importers: dependencies: moment: 2.29.4 + components/zoho_workdrive: + specifiers: + '@pipedream/platform': ^1.5.1 + axios: ^1.5.1 + dependencies: + '@pipedream/platform': 1.5.1 + axios: 1.5.1 + components/zonka_feedback: specifiers: '@pipedream/platform': ^1.2.0 From b829c5ca63158f165430870fe3ce03e0ec19ccd1 Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Wed, 18 Oct 2023 18:32:58 -0700 Subject: [PATCH 012/186] Adding app scaffolding for flodesk --- components/flodesk/flodesk.app.mjs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 components/flodesk/flodesk.app.mjs diff --git a/components/flodesk/flodesk.app.mjs b/components/flodesk/flodesk.app.mjs new file mode 100644 index 0000000000000..9c7ef691a9d71 --- /dev/null +++ b/components/flodesk/flodesk.app.mjs @@ -0,0 +1,11 @@ +export default { + type: "app", + app: "flodesk", + propDefinitions: {}, + methods: { + // this.$auth contains connected account data + authKeys() { + console.log(Object.keys(this.$auth)); + }, + }, +}; \ No newline at end of file From d2d270cb1fa497763189b2b57d14a43ba64fb90a Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Wed, 18 Oct 2023 18:32:59 -0700 Subject: [PATCH 013/186] Adding app scaffolding for flodesk --- components/flodesk/package.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 components/flodesk/package.json diff --git a/components/flodesk/package.json b/components/flodesk/package.json new file mode 100644 index 0000000000000..31a5101f61b61 --- /dev/null +++ b/components/flodesk/package.json @@ -0,0 +1,15 @@ +{ + "name": "@pipedream/flodesk", + "version": "0.0.1", + "description": "Pipedream Flodesk Components", + "main": "flodesk.app.mjs", + "keywords": [ + "pipedream", + "flodesk" + ], + "homepage": "https://pipedream.com/apps/flodesk", + "author": "Pipedream (https://pipedream.com/)", + "publishConfig": { + "access": "public" + } +} \ No newline at end of file From 258c5b62eb61c1e990e6873c16dffd41288356fd Mon Sep 17 00:00:00 2001 From: Luan Cazarine Date: Thu, 19 Oct 2023 09:02:56 -0300 Subject: [PATCH 014/186] 8427 components mamo business (#8510) * [Components] Mamo Business #8427 Triggers - New Failed Payment (Instant) - New Successful Payment (Instant) Actions: - Create Payment Link * pnpm update * fix props --- .../create-payment-link.mjs | 251 ++++++++++++++++++ components/mamo_business/common/utils.mjs | 6 + .../mamo_business/mamo_business.app.mjs | 46 +++- components/mamo_business/package.json | 7 +- .../mamo_business/sources/common/base.mjs | 56 ++++ .../new-failed-payment/new-failed-payment.mjs | 25 ++ .../sources/new-failed-payment/test-event.mjs | 12 + .../new-successful-payment.mjs | 24 ++ .../new-successful-payment/test-event.mjs | 12 + pnpm-lock.yaml | 5 +- 10 files changed, 436 insertions(+), 8 deletions(-) create mode 100644 components/mamo_business/actions/create-payment-link/create-payment-link.mjs create mode 100644 components/mamo_business/common/utils.mjs create mode 100644 components/mamo_business/sources/common/base.mjs create mode 100644 components/mamo_business/sources/new-failed-payment/new-failed-payment.mjs create mode 100644 components/mamo_business/sources/new-failed-payment/test-event.mjs create mode 100644 components/mamo_business/sources/new-successful-payment/new-successful-payment.mjs create mode 100644 components/mamo_business/sources/new-successful-payment/test-event.mjs diff --git a/components/mamo_business/actions/create-payment-link/create-payment-link.mjs b/components/mamo_business/actions/create-payment-link/create-payment-link.mjs new file mode 100644 index 0000000000000..2a51d40bfe50e --- /dev/null +++ b/components/mamo_business/actions/create-payment-link/create-payment-link.mjs @@ -0,0 +1,251 @@ +import { parseObject } from "../../common/utils.mjs"; +import app from "../../mamo_business.app.mjs"; + +export default { + key: "mamo_business-create-payment-link", + name: "Create Payment Link", + version: "0.0.1", + description: "Generate a vanilla or subscription payment link. [See the documentation](https://mamopay.readme.io/reference/post_links)", + type: "action", + props: { + app, + title: { + type: "string", + label: "Title", + description: "The title of the payment link.", + }, + description: { + type: "string", + label: "Description", + description: "Payment description. This will appear on the payment checkout page.", + optional: true, + }, + capacity: { + type: "integer", + label: "Capacity", + description: "The capacity will be ignored when the subscription params exist and value will be null.", + optional: true, + }, + active: { + type: "boolean", + label: "Active", + description: "Whether the payment is active or not.", + optional: true, + }, + returnUrl: { + type: "string", + label: "Return URL", + description: "The URL which the customer will be redirected to after a successful payment.", + optional: true, + }, + failureReturnUrl: { + type: "string", + label: "Failure Return URL", + description: "The URL which the customer will be redirected to after a failure payment.", + optional: true, + }, + processingFeePercentage: { + type: "integer", + label: "Processing Fee Percentage", + description: "The percentage of the transaction that is the fee.", + optional: true, + }, + amount: { + type: "string", + label: "Amount", + description: "The value number of the payment.", + optional: true, + }, + amountCurrency: { + type: "string", + label: "Amount Currency", + description: "The currency that the transaction will be charged.", + default: "AED", + options: [ + "AED", + "USD", + "EUR", + "GBP", + "SAR", + ], + }, + isWidget: { + type: "boolean", + label: "Is Widget", + description: "Generate widget payment link.", + optional: true, + }, + enableTabby: { + type: "boolean", + label: "Enable Tabby", + description: "Enables the ability for customers to buy now and pay later.", + optional: true, + }, + enableMessage: { + type: "boolean", + label: "Enable Message", + description: "Enables the ability for customers to add a message during the checkout process.", + optional: true, + }, + enableTips: { + type: "boolean", + label: "Enable Tips", + description: "Enables the tips option. This will be displayed on the first screen.", + optional: true, + }, + enableCustomerDetails: { + type: "boolean", + label: "Enable Customer Details", + description: "Enables adding customer details such as the name, email, and phone number. This screen will be displayed before the payment details screen.", + optional: true, + }, + enableQuantity: { + type: "boolean", + label: "Enable Quantity", + description: "Enable the payment link to be used multiple times.", + optional: true, + }, + enableQrCode: { + type: "boolean", + label: "Enable QR Code", + description: "Adds the ability to verify a payment through a QR code.", + optional: true, + }, + sendCustomerReceipt: { + type: "boolean", + label: "Send Customer Receipt", + description: "Enables the sending of customer receipts.", + optional: true, + }, + firstName: { + type: "string", + label: "First Name", + description: "The first name of customer which will pre-populate in card info step.", + optional: true, + }, + lastName: { + type: "string", + label: "Last Name", + description: "The last name of customer which will pre-populate in card info step.", + optional: true, + }, + email: { + type: "string", + label: "Email", + description: "The email of customer which will pre-populate in card info step.", + optional: true, + }, + externalId: { + type: "string", + label: "External Id", + description: "The external ID of your choice to associate with payments captured by this payment link.", + optional: true, + }, + customData: { + type: "object", + label: "Custom Data", + description: "An object with custom data of the payment link.", + optional: true, + }, + isRecurring: { + type: "boolean", + label: "Is Recurring", + description: "Whether this payment link is for a recurring payment.", + reloadProps: true, + }, + }, + async additionalProps() { + const props = {}; + if (this.isRecurring) { + props.frequency = { + type: "string", + label: "Frequency", + description: "Defines the interval that this subscription will be run on.", + options: [ + "weekly", + "monthly", + "annually", + ], + }; + props.frequencyInterval = { + type: "integer", + label: "Frequency Interval", + description: "Defines how often this subscription will run. This will be based on the frequency property defined above.", + }; + props.endDate = { + type: "string", + label: "End Date", + description: "The last date this subscription could run on. Format: YYYY/MM/DD", + }; + props.paymentQuantity = { + type: "string", + label: "Payment Quantity", + description: "Number of times this subscription will occur. If end_date defined, end_date takes precedence.", + }; + } + return props; + }, + async run({ $ }) { + const { + app, + returnUrl, + failureReturnUrl, + processingFeePercentage, + amountCurrency, + isWidget, + enableTabby, + enableMessage, + enableTips, + enableCustomerDetails, + enableQuantity, + enableQrCode, + sendCustomerReceipt, + firstName, + lastName, + externalId, + customData, + isRecurring, + frequency, + frequencyInterval, + endDate, + paymentQuantity, + ...data + } = this; + + const obj = { + return_url: returnUrl, + failure_return_url: failureReturnUrl, + processing_fee_percentage: processingFeePercentage, + amount_currency: amountCurrency, + is_widget: isWidget, + enable_tabby: enableTabby, + enable_message: enableMessage, + enable_tips: enableTips, + enable_customer_details: enableCustomerDetails, + enable_quantity: enableQuantity, + enable_qr_code: enableQrCode, + send_customer_receipt: sendCustomerReceipt, + first_name: firstName, + last_name: lastName, + external_id: externalId, + custom_data: customData && parseObject(customData), + ...data, + }; + if (isRecurring) { + obj.subscription = { + frequency, + frequency_interval: frequencyInterval, + end_ate: endDate, + payment_quantity: paymentQuantity, + }; + } + + const response = await app.createPaymentLink({ + $, + data: obj, + }); + + $.export("$summary", `A new payment link with Id: ${response.id} was successfully created!`); + return response; + }, +}; diff --git a/components/mamo_business/common/utils.mjs b/components/mamo_business/common/utils.mjs new file mode 100644 index 0000000000000..9f49a5c4c8c2f --- /dev/null +++ b/components/mamo_business/common/utils.mjs @@ -0,0 +1,6 @@ +export const parseObject = (obj) => { + if (typeof obj != "object") { + return JSON.parse(obj); + } + return obj; +}; diff --git a/components/mamo_business/mamo_business.app.mjs b/components/mamo_business/mamo_business.app.mjs index fbbfa91e64876..db2295c720698 100644 --- a/components/mamo_business/mamo_business.app.mjs +++ b/components/mamo_business/mamo_business.app.mjs @@ -1,11 +1,47 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "mamo_business", - propDefinitions: {}, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _apiUrl() { + return `https://${this.$auth.environment}.mamopay.com/manage_api/v1`; + }, + _getHeaders() { + return { + "Authorization": `Bearer ${this.$auth.api_key}`, + }; + }, + _makeRequest({ + $ = this, path, ...opts + }) { + const config = { + url: `${this._apiUrl()}/${path}`, + headers: this._getHeaders(), + ...opts, + }; + + return axios($, config); + }, + createHook(args = {}) { + return this._makeRequest({ + method: "POST", + path: "webhooks", + ...args, + }); + }, + createPaymentLink(args = {}) { + return this._makeRequest({ + method: "POST", + path: "links", + ...args, + }); + }, + deleteHook(hookId) { + return this._makeRequest({ + method: "DELETE", + path: `webhooks/${hookId}`, + }); }, }, -}; \ No newline at end of file +}; diff --git a/components/mamo_business/package.json b/components/mamo_business/package.json index 55ce3eeb94015..f3dfd7fd2c978 100644 --- a/components/mamo_business/package.json +++ b/components/mamo_business/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/mamo_business", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Mamo Business Components", "main": "mamo_business.app.mjs", "keywords": [ @@ -11,5 +11,8 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^1.5.1" } -} \ No newline at end of file +} diff --git a/components/mamo_business/sources/common/base.mjs b/components/mamo_business/sources/common/base.mjs new file mode 100644 index 0000000000000..678bfa43679f0 --- /dev/null +++ b/components/mamo_business/sources/common/base.mjs @@ -0,0 +1,56 @@ +import app from "../../mamo_business.app.mjs"; + +export default { + dedupe: "unique", + props: { + app, + http: { + type: "$.interface.http", + customResponse: true, + }, + db: "$.service.db", + }, + hooks: { + async activate() { + const data = await this.app.createHook({ + data: { + url: this.http.endpoint, + enabled_events: this.getEvent(), + }, + }); + + this._setHookId(data.id); + }, + async deactivate() { + const id = this._getHookId("hookId"); + await this.app.deleteHook(id); + }, + }, + methods: { + emitEvent(body) { + const meta = this.generateMeta(body); + this.$emit(body, meta); + }, + _getHookId() { + return this.db.get("hookId"); + }, + _setHookId(hookId) { + this.db.set("hookId", hookId); + }, + generateMeta(body) { + return { + id: `${body.id}${body.created_date}`, + summary: this.getSummary(body), + ts: new Date(), + }; + }, + }, + async run({ body }) { + if (body.ping) { + return this.http.respond({ + status: 200, + }); + } + this.emitEvent(body); + }, +}; diff --git a/components/mamo_business/sources/new-failed-payment/new-failed-payment.mjs b/components/mamo_business/sources/new-failed-payment/new-failed-payment.mjs new file mode 100644 index 0000000000000..057811449f02c --- /dev/null +++ b/components/mamo_business/sources/new-failed-payment/new-failed-payment.mjs @@ -0,0 +1,25 @@ +import common from "../common/base.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + ...common, + key: "mamo_business-new-failed-payment", + name: "New Failed Payment (Instant)", + description: "Emit new event when a payment is failed.", + version: "0.0.1", + type: "source", + methods: { + ...common.methods, + getEvent() { + return [ + "charge.failed", + "subscription.failed", + ]; + }, + getSummary(body) { + const { id } = body; + return `A new payment with id ${id} has been failed!`; + }, + }, + sampleEmit, +}; diff --git a/components/mamo_business/sources/new-failed-payment/test-event.mjs b/components/mamo_business/sources/new-failed-payment/test-event.mjs new file mode 100644 index 0000000000000..2590c8406b457 --- /dev/null +++ b/components/mamo_business/sources/new-failed-payment/test-event.mjs @@ -0,0 +1,12 @@ +export default { + "status": "failed", + "id": "MPB-CHRG-E0CE93E071", + "amount": 10, + "refund_amount": 0, + "refund_status": "No refund", + "created_date": "2023-05-31-11-18-57", + "subscription_id": "MPB-SUB-B764EDCBA2", + "settlement_amount": 356.42, + "settlement_currency": "AED", + "settlement_date": "05/06/2023" +}; diff --git a/components/mamo_business/sources/new-successful-payment/new-successful-payment.mjs b/components/mamo_business/sources/new-successful-payment/new-successful-payment.mjs new file mode 100644 index 0000000000000..394fe989df968 --- /dev/null +++ b/components/mamo_business/sources/new-successful-payment/new-successful-payment.mjs @@ -0,0 +1,24 @@ +import common from "../common/base.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + ...common, + key: "mamo_business-new-successful-payment", + name: "New Successful Payment (Instant)", + description: "Emit new event when a payment is charged.", + version: "0.0.1", + type: "source", + methods: { + ...common.methods, + getEvent() { + return [ + "charge.succeeded", + ]; + }, + getSummary(body) { + const { id } = body; + return `A new payment with id ${id} was successfully charged!`; + }, + }, + sampleEmit, +}; diff --git a/components/mamo_business/sources/new-successful-payment/test-event.mjs b/components/mamo_business/sources/new-successful-payment/test-event.mjs new file mode 100644 index 0000000000000..be9d0e596d558 --- /dev/null +++ b/components/mamo_business/sources/new-successful-payment/test-event.mjs @@ -0,0 +1,12 @@ +export default { + "status": "captured", + "id": "MPB-CHRG-E0CE93E071", + "amount": 10, + "refund_amount": 0, + "refund_status": "No refund", + "created_date": "2023-05-31-11-18-57", + "subscription_id": "MPB-SUB-B764EDCBA2", + "settlement_amount": 356.42, + "settlement_currency": "AED", + "settlement_date": "05/06/2023" +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9d0194db7688f..6f67af2b2fc4c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3201,7 +3201,10 @@ importers: specifiers: {} components/mamo_business: - specifiers: {} + specifiers: + '@pipedream/platform': ^1.5.1 + dependencies: + '@pipedream/platform': 1.5.1 components/manifestly_checklists: specifiers: {} From a79c8945b2948a7468f4f0d84f66e46cc6cd0ffc Mon Sep 17 00:00:00 2001 From: Luan Cazarine Date: Thu, 19 Oct 2023 12:02:12 -0300 Subject: [PATCH 015/186] 8193 components modeck (#8416) * [Components] Uplisting #7860 Triggers - New Render Completed Actions - Create Render * pnpm update * some adjusts * pnpm update * fix async option * fix deck prop --- components/modeck/.gitignore | 3 - .../actions/create-render/create-render.mjs | 63 ++++++++++++++ components/modeck/app/modeck.app.ts | 13 --- components/modeck/common/utils.mjs | 11 +++ components/modeck/modeck.app.mjs | 54 ++++++++++++ components/modeck/package.json | 10 ++- .../render-complete/render-complete.mjs | 82 +++++++++++++++++++ .../sources/render-complete/test-event.mjs | 8 ++ pnpm-lock.yaml | 5 +- 9 files changed, 228 insertions(+), 21 deletions(-) delete mode 100644 components/modeck/.gitignore create mode 100644 components/modeck/actions/create-render/create-render.mjs delete mode 100644 components/modeck/app/modeck.app.ts create mode 100644 components/modeck/common/utils.mjs create mode 100644 components/modeck/modeck.app.mjs create mode 100644 components/modeck/sources/render-complete/render-complete.mjs create mode 100644 components/modeck/sources/render-complete/test-event.mjs diff --git a/components/modeck/.gitignore b/components/modeck/.gitignore deleted file mode 100644 index ec761ccab7595..0000000000000 --- a/components/modeck/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.js -*.mjs -dist \ No newline at end of file diff --git a/components/modeck/actions/create-render/create-render.mjs b/components/modeck/actions/create-render/create-render.mjs new file mode 100644 index 0000000000000..bec0a6a31bbf4 --- /dev/null +++ b/components/modeck/actions/create-render/create-render.mjs @@ -0,0 +1,63 @@ +import { ConfigurationError } from "@pipedream/platform"; +import { parseArray } from "../../common/utils.mjs"; +import modeck from "../../modeck.app.mjs"; + +export default { + key: "modeck-create-render", + name: "Create Render", + version: "0.0.1", + description: "Create a new edit with the data supplied. [See the documentation](https://modeck.io/docs#modeckapi)", + type: "action", + props: { + modeck, + deck: { + propDefinition: [ + modeck, + "deck", + ], + }, + name: { + type: "string", + label: "Name", + description: "The name of this edit.", + }, + editId: { + type: "string", + label: "Edit Id", + description: "The identifier of this edit.", + optional: true, + }, + notificationEmail: { + type: "string", + label: "Notification Email", + description: "The email that will be notified on render finishing.", + optional: true, + }, + mogrtSeq: { + type: "string[]", + label: "MogrtSeq", + description: "An array of mogrtSeq objects.", + }, + }, + async run({ $ }) { + const { + modeck, + mogrtSeq, + ...data + } = this; + + const response = await modeck.createRender({ + $, + data: { + ...data, + mogrtSeq: parseArray(mogrtSeq), + }, + }); + + if (!response.success) throw new ConfigurationError(response.info); + + $.export("$summary", `A new edit with Id: ${response.editId} was successfully created!`); + return response; + }, +}; + diff --git a/components/modeck/app/modeck.app.ts b/components/modeck/app/modeck.app.ts deleted file mode 100644 index 659c873d79cb6..0000000000000 --- a/components/modeck/app/modeck.app.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { defineApp } from "@pipedream/types"; - -export default defineApp({ - type: "app", - app: "modeck", - 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/modeck/common/utils.mjs b/components/modeck/common/utils.mjs new file mode 100644 index 0000000000000..dd2b52ebc43b2 --- /dev/null +++ b/components/modeck/common/utils.mjs @@ -0,0 +1,11 @@ +export const parseArray = (array) => { + if (Array.isArray(array)) { + return array.map((item) => { + if (typeof item != "object") { + item = JSON.parse(item); + } + return item; + }); + } + return JSON.parse(array); +}; diff --git a/components/modeck/modeck.app.mjs b/components/modeck/modeck.app.mjs new file mode 100644 index 0000000000000..f8aa7ee5ff76f --- /dev/null +++ b/components/modeck/modeck.app.mjs @@ -0,0 +1,54 @@ +import { axios } from "@pipedream/platform"; + +export default { + type: "app", + app: "modeck", + propDefinitions: { + deck: { + type: "string", + label: "Deck Name", + description: "The deck name you want to edit.", + async options() { + const response = await this.listDecks(); + return response.decks?.map(({ name }) => name) || []; + }, + }, + }, + methods: { + _apiUrl() { + return "https://api.modeck.io"; + }, + _makeRequest({ + $ = this, data = {}, path, ...opts + }) { + const config = { + url: `${this._apiUrl()}/${path}`, + data: { + apiKey: this.$auth.api_key, + ...data, + }, + ...opts, + }; + return axios($, config); + }, + createRender(args = {}) { + return this._makeRequest({ + method: "POST", + path: "render", + ...args, + }); + }, + listDecks(args = {}) { + return this._makeRequest({ + path: "listdecks", + ...args, + }); + }, + listRenders(args = {}) { + return this._makeRequest({ + path: "listrenders", + ...args, + }); + }, + }, +}; diff --git a/components/modeck/package.json b/components/modeck/package.json index 47c3ac636475a..6b0aea43661c3 100644 --- a/components/modeck/package.json +++ b/components/modeck/package.json @@ -1,16 +1,18 @@ { "name": "@pipedream/modeck", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream MoDeck Components", - "main": "dist/app/modeck.app.mjs", + "main": "modeck.app.mjs", "keywords": [ "pipedream", "modeck" ], - "files": ["dist"], "homepage": "https://pipedream.com/apps/modeck", "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^1.5.1" } -} \ No newline at end of file +} diff --git a/components/modeck/sources/render-complete/render-complete.mjs b/components/modeck/sources/render-complete/render-complete.mjs new file mode 100644 index 0000000000000..1594c79067b0b --- /dev/null +++ b/components/modeck/sources/render-complete/render-complete.mjs @@ -0,0 +1,82 @@ +import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform"; +import modeck from "../../modeck.app.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + key: "modeck-render-complete", + name: "New Render Completed", + version: "0.0.1", + description: "Emit new event when a render is completed.", + type: "source", + dedupe: "unique", + props: { + modeck, + db: "$.service.db", + timer: { + label: "Polling interval", + description: "Pipedream will poll the MoDeck on this schedule", + type: "$.interface.timer", + default: { + intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, + }, + }, + deck: { + propDefinition: [ + modeck, + "deck", + ], + }, + }, + methods: { + _getLastDate() { + return this.db.get("lastDate") || 0; + }, + _setLastDate(lastDate) { + this.db.set("lastDate", lastDate); + }, + async startEvent(maxResults = 0) { + const { + modeck, + deck, + } = this; + + const lastDate = this._getLastDate(); + + const { renderList } = await modeck.listRenders({ + data: { + deck, + }, + }); + + let responseArray = []; + let count = 0; + + for (const render of renderList) { + if (new Date(render.data) <= new Date(lastDate)) break; + responseArray.push(render); + if (maxResults && (++count === maxResults)) break; + } + if (responseArray.length) this._setLastDate(responseArray[0].date); + + for (const render of responseArray.reverse()) { + this.$emit( + render, + { + id: render.id, + summary: `The render with id: "${render.id}" has been completed!`, + ts: render.date, + }, + ); + } + }, + }, + hooks: { + async deploy() { + await this.startEvent(25); + }, + }, + async run() { + await this.startEvent(); + }, + sampleEmit, +}; diff --git a/components/modeck/sources/render-complete/test-event.mjs b/components/modeck/sources/render-complete/test-event.mjs new file mode 100644 index 0000000000000..fc83b9cdfa68c --- /dev/null +++ b/components/modeck/sources/render-complete/test-event.mjs @@ -0,0 +1,8 @@ +export default { + "name": "renderName", + "editName": "editName", + "format": "mp4", + "url": "https://modeck-media.s3.us-east-1.amazonaws.com/884c1234567a123456789/editIdTest/render/render.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=ASDSDFGDFGFGHFGH%2F20231005%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20231005T202702Z&X-Amz-Expires=7200&X-Amz-Signature=12345678ac4d411ab6f63dfc5e4e972fb78ee7db2266eecf90387481a82e&X-Amz-SignedHeaders=host&response-content-disposition=attachment%3B%20filename%20%3D%22TEST01.mp4%22&versionId=sdfSFsdsdfgSfWsPpu_GwbhbhHrM86hntl&x-id=GetObject", + "date": "2023-10-05T20:26:15.000Z", + "id": 123456789000 +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6f67af2b2fc4c..0aaac4ea5bf9d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3460,7 +3460,10 @@ importers: specifiers: {} components/modeck: - specifiers: {} + specifiers: + '@pipedream/platform': ^1.5.1 + dependencies: + '@pipedream/platform': 1.5.1 components/mojo_helpdesk: specifiers: From 3907dca7cc230944b46dab9b06c8314f01a097d5 Mon Sep 17 00:00:00 2001 From: vellames <91911778+vellames@users.noreply.github.com> Date: Thu, 19 Oct 2023 17:49:00 -0300 Subject: [PATCH 016/186] Add conference room as prop (#8524) --- .../actions/create-event/create-event.mjs | 27 ++++++++++++++++--- components/google_calendar/package.json | 2 +- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/components/google_calendar/actions/create-event/create-event.mjs b/components/google_calendar/actions/create-event/create-event.mjs index 5933bb929408a..c47e639d8b457 100644 --- a/components/google_calendar/actions/create-event/create-event.mjs +++ b/components/google_calendar/actions/create-event/create-event.mjs @@ -1,11 +1,12 @@ import googleCalendar from "../../google_calendar.app.mjs"; import createEventCommon from "../common/create-event-common.mjs"; +import { v4 as uuidv4 } from "uuid"; export default { key: "google_calendar-create-event", name: "Create Event", description: "Create an event to the Google Calendar. [See the documentation](https://googleapis.dev/nodejs/googleapis/latest/calendar/classes/Resource$Events.html#insert)", - version: "0.1.6", + version: "0.1.7", type: "action", props: { googleCalendar, @@ -15,6 +16,12 @@ export default { "calendarId", ], }, + createMeetRoom: { + label: "Create Meet Room", + description: "Create a Google Meet room for this event.", + type: "boolean", + optional: true, + }, ...createEventCommon.props({ isUpdate: false, }), @@ -26,7 +33,7 @@ export default { const timeZone = this.getTimeZone(this.timeZone); const attendees = this.formatAttendees(this.attendees); - const response = await this.googleCalendar.createEvent({ + const data = { calendarId: this.calendarId, sendUpdates: this.sendUpdates, sendNotifications: this.sendNotifications, @@ -44,7 +51,21 @@ export default { }), attendees, }, - }); + }; + + if (this.createMeetRoom) { + data.conferenceDataVersion = 1; + data.resource.conferenceData = { + createRequest: { + requestId: uuidv4(), + conferenceSolutionKey: { + type: "hangoutsMeet", + }, + }, + }; + } + + const response = await this.googleCalendar.createEvent(data); $.export("$summary", `Successfully created event: "${response.id}"`); diff --git a/components/google_calendar/package.json b/components/google_calendar/package.json index 1b00f94ad8f5f..5747c92713505 100644 --- a/components/google_calendar/package.json +++ b/components/google_calendar/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/google_calendar", - "version": "0.3.15", + "version": "0.3.16", "description": "Pipedream Google_calendar Components", "main": "google_calendar.app.mjs", "keywords": [ From 643673708b92204dd21c0ccc3371909486653763 Mon Sep 17 00:00:00 2001 From: Dylan Pierce Date: Thu, 19 Oct 2023 16:28:12 -0700 Subject: [PATCH 017/186] Adding pinning for cacheDirectory on puppeteer (#8545) * Adding pinning for cacheDirectory on puppeteer * pinning new versions * pinning new versions --- components/puppeteer/actions/get-html/get-html.mjs | 2 +- components/puppeteer/actions/get-page-title/get-page-title.mjs | 2 +- components/puppeteer/actions/get-pdf/get-pdf.mjs | 2 +- .../puppeteer/actions/screenshot-page/screenshot-page.mjs | 2 +- components/puppeteer/package.json | 2 +- components/puppeteer/puppeteer.app.mjs | 2 ++ packages/browsers/index.mjs | 1 + packages/browsers/package.json | 2 +- pnpm-lock.yaml | 3 +++ 9 files changed, 12 insertions(+), 6 deletions(-) diff --git a/components/puppeteer/actions/get-html/get-html.mjs b/components/puppeteer/actions/get-html/get-html.mjs index 0e01438780156..70c72e3b10c56 100644 --- a/components/puppeteer/actions/get-html/get-html.mjs +++ b/components/puppeteer/actions/get-html/get-html.mjs @@ -4,7 +4,7 @@ export default { key: "puppeteer-get-html", name: "Get HTML", description: "Get the HTML of a webpage using Puppeteer. [See the documentation](https://pptr.dev/api/puppeteer.page.content)", - version: "0.0.6", + version: "0.0.7", type: "action", props: { puppeteer, diff --git a/components/puppeteer/actions/get-page-title/get-page-title.mjs b/components/puppeteer/actions/get-page-title/get-page-title.mjs index 27e3c035aa416..23f555cf63bb8 100644 --- a/components/puppeteer/actions/get-page-title/get-page-title.mjs +++ b/components/puppeteer/actions/get-page-title/get-page-title.mjs @@ -4,7 +4,7 @@ export default { key: "puppeteer-get-page-title", name: "Get Page Title", description: "Get the title of a webpage using Puppeteer. [See the documentation](https://pptr.dev/api/puppeteer.page.title)", - version: "0.0.6", + version: "0.0.7", type: "action", props: { puppeteer, diff --git a/components/puppeteer/actions/get-pdf/get-pdf.mjs b/components/puppeteer/actions/get-pdf/get-pdf.mjs index ece72a710be4f..64cbdebb3ad66 100644 --- a/components/puppeteer/actions/get-pdf/get-pdf.mjs +++ b/components/puppeteer/actions/get-pdf/get-pdf.mjs @@ -6,7 +6,7 @@ export default { key: "puppeteer-get-pdf", name: "Get PDF", description: "Generate a PDF of a page using Puppeteer. [See the documentation](https://pptr.dev/api/puppeteer.page.pdf)", - version: "0.0.6", + version: "0.0.7", type: "action", props: { puppeteer, diff --git a/components/puppeteer/actions/screenshot-page/screenshot-page.mjs b/components/puppeteer/actions/screenshot-page/screenshot-page.mjs index 06f021289b006..443fdc7124ef7 100644 --- a/components/puppeteer/actions/screenshot-page/screenshot-page.mjs +++ b/components/puppeteer/actions/screenshot-page/screenshot-page.mjs @@ -7,7 +7,7 @@ export default { key: "puppeteer-screenshot-page", name: "Screenshot a Page", description: "Captures a screenshot of a page using Puppeteer. [See the documentation](https://pptr.dev/api/puppeteer.page.screenshot)", - version: "0.0.7", + version: "0.0.8", type: "action", props: { puppeteer, diff --git a/components/puppeteer/package.json b/components/puppeteer/package.json index 709fb3e5a9fde..7a94b3067c22c 100644 --- a/components/puppeteer/package.json +++ b/components/puppeteer/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/puppeteer", - "version": "0.7.0", + "version": "0.8.0", "description": "Pipedream Puppeteer Components", "main": "puppeteer.app.mjs", "keywords": [ diff --git a/components/puppeteer/puppeteer.app.mjs b/components/puppeteer/puppeteer.app.mjs index 3ec238c903a4c..c2d67254e57c4 100644 --- a/components/puppeteer/puppeteer.app.mjs +++ b/components/puppeteer/puppeteer.app.mjs @@ -21,12 +21,14 @@ export default { const browser = await puppeteer.launch({ executablePath: await chromium.executablePath(), headless: chromium.headless, + cacheDirectory: "/tmp", ignoreHTTPSErrors: true, defaultViewport: chromium.defaultViewport, args: [ ...chromium.args, "--hide-scrollbars", "--disable-web-security", + "--font-render-hinting=none", ], ...opts, }); diff --git a/packages/browsers/index.mjs b/packages/browsers/index.mjs index a6de78b3a2cc8..bc8424fee630f 100644 --- a/packages/browsers/index.mjs +++ b/packages/browsers/index.mjs @@ -17,6 +17,7 @@ export const puppeteer = { headless: chromium.headless, ignoreHTTPSErrors: true, defaultViewport: chromium.defaultViewport, + cacheDirectory: "/tmp", args: [ ...chromium.args, "--hide-scrollbars", diff --git a/packages/browsers/package.json b/packages/browsers/package.json index 18915ee4d33a8..0b2499138fdac 100644 --- a/packages/browsers/package.json +++ b/packages/browsers/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/browsers", - "version": "1.0.0", + "version": "1.0.1", "description": "For using puppeeter or playwright in Pipedream Node.js Code Steps. Includes the prebuilt binaries and specific versions for compatiblity with Pipedream.", "main": "index.mjs", "scripts": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0aaac4ea5bf9d..9ef536774d764 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1785,6 +1785,9 @@ importers: components/float: specifiers: {} + components/flodesk: + specifiers: {} + components/fluent_support: specifiers: {} From a30c7ae8afb01c0eb5c66080a1f62b4688f77336 Mon Sep 17 00:00:00 2001 From: vellames <91911778+vellames@users.noreply.github.com> Date: Thu, 19 Oct 2023 21:17:42 -0300 Subject: [PATCH 018/186] Add timer as editable prop (#8526) --- components/gumroad/package.json | 2 +- components/gumroad/sources/common/common.mjs | 2 +- .../gumroad/sources/new-cancellation/new-cancellation.mjs | 2 +- components/gumroad/sources/new-product/new-product.mjs | 2 +- components/gumroad/sources/new-refund/new-refund.mjs | 2 +- components/gumroad/sources/new-sale/new-sale.mjs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/components/gumroad/package.json b/components/gumroad/package.json index b18b0b1c306ff..59821236d84ec 100644 --- a/components/gumroad/package.json +++ b/components/gumroad/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/gumroad", - "version": "0.0.4", + "version": "0.0.5", "description": "Pipedream Gumroad Components", "main": "gumroad.app.mjs", "keywords": [ diff --git a/components/gumroad/sources/common/common.mjs b/components/gumroad/sources/common/common.mjs index 78cc66f6cd5f6..8c264be1c4528 100644 --- a/components/gumroad/sources/common/common.mjs +++ b/components/gumroad/sources/common/common.mjs @@ -7,7 +7,7 @@ export default { db: "$.service.db", timer: { type: "$.interface.timer", - static: { + default: { intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, }, }, diff --git a/components/gumroad/sources/new-cancellation/new-cancellation.mjs b/components/gumroad/sources/new-cancellation/new-cancellation.mjs index 3ca03b557d114..bbe3fb949f0c7 100644 --- a/components/gumroad/sources/new-cancellation/new-cancellation.mjs +++ b/components/gumroad/sources/new-cancellation/new-cancellation.mjs @@ -3,7 +3,7 @@ import common from "../common/common.mjs"; export default { ...common, name: "New Cancellation", - version: "0.0.3", + version: "0.0.4", key: "gumroad-new-cancellation", description: "Emit new event on a sale is cancelled.", type: "source", diff --git a/components/gumroad/sources/new-product/new-product.mjs b/components/gumroad/sources/new-product/new-product.mjs index f41ca1f5ec47a..5ee1e9895b735 100644 --- a/components/gumroad/sources/new-product/new-product.mjs +++ b/components/gumroad/sources/new-product/new-product.mjs @@ -3,7 +3,7 @@ import common from "../common/common.mjs"; export default { ...common, name: "New Product", - version: "0.0.3", + version: "0.0.4", key: "gumroad-new-product", description: "Emit new event on each new product.", type: "source", diff --git a/components/gumroad/sources/new-refund/new-refund.mjs b/components/gumroad/sources/new-refund/new-refund.mjs index 000a80ca59234..4568a7304da83 100644 --- a/components/gumroad/sources/new-refund/new-refund.mjs +++ b/components/gumroad/sources/new-refund/new-refund.mjs @@ -3,7 +3,7 @@ import common from "../common/common.mjs"; export default { ...common, name: "New Refund", - version: "0.0.3", + version: "0.0.4", key: "gumroad-new-refund", description: "Emit new event on a sale is refunded.", type: "source", diff --git a/components/gumroad/sources/new-sale/new-sale.mjs b/components/gumroad/sources/new-sale/new-sale.mjs index 8528972967ab9..ec25632414523 100644 --- a/components/gumroad/sources/new-sale/new-sale.mjs +++ b/components/gumroad/sources/new-sale/new-sale.mjs @@ -3,7 +3,7 @@ import common from "../common/common.mjs"; export default { ...common, name: "New Sale", - version: "0.0.3", + version: "0.0.4", key: "gumroad-new-sale", description: "Emit new event on each new sale.", type: "source", From a25b68ff992caa07fed4efeab98454700e85b8ac Mon Sep 17 00:00:00 2001 From: Alyson Freitas Date: Fri, 20 Oct 2023 10:50:09 -0300 Subject: [PATCH 019/186] Google Drive - allow replace file if exists (#8463) * Google Drive - allow replace file if exists * drive's package.json --- .../actions/upload-file/upload-file.mjs | 62 +++++++++++++++---- components/google_drive/package.json | 2 +- 2 files changed, 52 insertions(+), 12 deletions(-) diff --git a/components/google_drive/actions/upload-file/upload-file.mjs b/components/google_drive/actions/upload-file/upload-file.mjs index 0b73e78def468..f66e670ef2462 100644 --- a/components/google_drive/actions/upload-file/upload-file.mjs +++ b/components/google_drive/actions/upload-file/upload-file.mjs @@ -10,7 +10,7 @@ export default { key: "google_drive-upload-file", name: "Upload File", description: "Copy an existing file to Google Drive. [See the docs](https://developers.google.com/drive/api/v3/manage-uploads) for more information", - version: "0.1.1", + version: "0.1.2", type: "action", props: { googleDrive, @@ -69,6 +69,27 @@ export default { default: GOOGLE_DRIVE_UPLOAD_TYPE_MULTIPART, optional: true, }, + replaceFile: { + type: "boolean", + label: "Replace File", + description: "Whether should replace file case it exists, default: `false`", + optional: true, + default: false, + }, + }, + methods: { + async getFileIdForReplace(filename, parentId) { + if (this.replaceFile) { + const { files } = await this.googleDrive.listFilesInPage(null, { + q: `name = '${filename}' and '${parentId || "root"}' in parents and trashed = false`, + fields: "files/id,files/name,files/parents", + }); + if (files.length) { + return files[0].id; + } + } + return null; + }, }, async run({ $ }) { const { @@ -83,21 +104,40 @@ export default { throw new Error("One of File URL and File Path is required."); } const driveId = this.googleDrive.getDriveId(this.drive); + + const filename = name || path.basename(fileUrl || filePath); + const fileId = await this.getFileIdForReplace(filename, parentId); + const file = await getFileStream({ $, fileUrl, filePath, }); console.log(`Upload type: ${uploadType}.`); - const resp = await this.googleDrive.createFile(omitEmptyStringValues({ - file, - mimeType, - name: name || path.basename(fileUrl || filePath), - parentId, - driveId, - uploadType, - })); - $.export("$summary", `Successfully uploaded a new file, "${resp.name}"`); - return resp; + + let result = null; + if (fileId) { + await this.googleDrive.updateFileMedia(fileId, file, omitEmptyStringValues({ + mimeType, + uploadType, + })); + result = await this.googleDrive.updateFile(fileId, omitEmptyStringValues({ + name: filename, + mimeType, + uploadType, + })); + $.export("$summary", `Successfully updated file, "${result.name}"`); + } else { + result = await this.googleDrive.createFile(omitEmptyStringValues({ + file, + mimeType, + name: filename, + parentId, + driveId, + uploadType, + })); + $.export("$summary", `Successfully uploaded a new file, "${result.name}"`); + } + return result; }, }; diff --git a/components/google_drive/package.json b/components/google_drive/package.json index 0fb992cd553c0..b18d25428ef76 100644 --- a/components/google_drive/package.json +++ b/components/google_drive/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/google_drive", - "version": "0.6.10", + "version": "0.6.11", "description": "Pipedream Google_drive Components", "main": "google_drive.app.mjs", "keywords": [ From 0b1ad3f1e2770bceb652604d7d405a5102801c00 Mon Sep 17 00:00:00 2001 From: michelle0927 Date: Fri, 20 Oct 2023 07:08:40 -0700 Subject: [PATCH 020/186] Hellosign - New Components (#8504) * new components * package.json * pnpm-lock.yaml --- .../send-signature-request-from-template.mjs | 105 ++++++++++++++ .../send-signature-request.mjs | 91 ++++++++++++ components/hellosign/hellosign.app.mjs | 135 +++++++++++++++++- components/hellosign/package.json | 18 +++ pnpm-lock.yaml | 6 + 5 files changed, 351 insertions(+), 4 deletions(-) create mode 100644 components/hellosign/actions/send-signature-request-from-template/send-signature-request-from-template.mjs create mode 100644 components/hellosign/actions/send-signature-request/send-signature-request.mjs create mode 100644 components/hellosign/package.json diff --git a/components/hellosign/actions/send-signature-request-from-template/send-signature-request-from-template.mjs b/components/hellosign/actions/send-signature-request-from-template/send-signature-request-from-template.mjs new file mode 100644 index 0000000000000..fb87ab27359f4 --- /dev/null +++ b/components/hellosign/actions/send-signature-request-from-template/send-signature-request-from-template.mjs @@ -0,0 +1,105 @@ +import hellosign from "../../hellosign.app.mjs"; + +export default { + key: "hellosign-send-signature-request-from-template", + name: "Send Signature Request From Template", + description: "Send a signature request from a template with Dropbox Sign. [See the documentation](https://developers.hellosign.com/api/reference/operation/signatureRequestSendWithTemplate/)", + version: "0.0.1", + type: "action", + props: { + hellosign, + templateId: { + propDefinition: [ + hellosign, + "templateId", + ], + }, + signers: { + propDefinition: [ + hellosign, + "signers", + ], + }, + role: { + propDefinition: [ + hellosign, + "role", + (c) => ({ + templateId: c.templateId, + }), + ], + }, + fileUrls: { + propDefinition: [ + hellosign, + "fileUrls", + ], + optional: true, + }, + allowDecline: { + propDefinition: [ + hellosign, + "allowDecline", + ], + }, + message: { + propDefinition: [ + hellosign, + "message", + ], + }, + subject: { + propDefinition: [ + hellosign, + "subject", + ], + }, + title: { + propDefinition: [ + hellosign, + "title", + ], + }, + testMode: { + propDefinition: [ + hellosign, + "testMode", + ], + }, + }, + async run({ $ }) { + const signers = []; + for (const [ + name, + email, + ] of Object.entries(this.signers)) { + signers.push({ + role: this.role, + name, + email_address: email, + }); + } + + const response = await this.hellosign.sendSignatureRequestWithTemplate({ + data: { + template_ids: [ + this.templateId, + ], + file_urls: this.fileUrls, + signers, + cc_email_addresses: this.ccEmailAddresses, + allow_decline: this.allowDecline, + message: this.message, + subject: this.subject, + title: this.title, + test_mode: this.testMode, + }, + }); + + if (response) { + $.export("$summary", "Successfully sent signature request"); + } + + return response; + }, +}; diff --git a/components/hellosign/actions/send-signature-request/send-signature-request.mjs b/components/hellosign/actions/send-signature-request/send-signature-request.mjs new file mode 100644 index 0000000000000..b76a800963a40 --- /dev/null +++ b/components/hellosign/actions/send-signature-request/send-signature-request.mjs @@ -0,0 +1,91 @@ +import hellosign from "../../hellosign.app.mjs"; + +export default { + key: "hellosign-send-signature-request", + name: "Send Signature Request", + description: "Send a signature request with Dropbox Sign. [See the documentation](https://developers.hellosign.com/api/reference/operation/signatureRequestSend/)", + version: "0.0.1", + type: "action", + props: { + hellosign, + fileUrls: { + propDefinition: [ + hellosign, + "fileUrls", + ], + }, + signers: { + propDefinition: [ + hellosign, + "signers", + ], + }, + ccEmailAddresses: { + propDefinition: [ + hellosign, + "ccEmailAddresses", + ], + }, + allowDecline: { + propDefinition: [ + hellosign, + "allowDecline", + ], + }, + message: { + propDefinition: [ + hellosign, + "message", + ], + }, + subject: { + propDefinition: [ + hellosign, + "subject", + ], + }, + title: { + propDefinition: [ + hellosign, + "title", + ], + }, + testMode: { + propDefinition: [ + hellosign, + "testMode", + ], + }, + }, + async run({ $ }) { + const signers = []; + for (const [ + name, + email, + ] of Object.entries(this.signers)) { + signers.push({ + name, + email_address: email, + }); + } + + const response = await this.hellosign.sendSignatureRequest({ + data: { + file_urls: this.fileUrls, + signers, + cc_email_addresses: this.ccEmailAddresses, + allow_decline: this.allowDecline, + message: this.message, + subject: this.subject, + title: this.title, + test_mode: this.testMode, + }, + }); + + if (response) { + $.export("$summary", "Successfully sent signature request"); + } + + return response; + }, +}; diff --git a/components/hellosign/hellosign.app.mjs b/components/hellosign/hellosign.app.mjs index 6b2a9ce6909d2..db4d13634311e 100644 --- a/components/hellosign/hellosign.app.mjs +++ b/components/hellosign/hellosign.app.mjs @@ -1,11 +1,138 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "hellosign", - propDefinitions: {}, + propDefinitions: { + templateId: { + type: "string", + label: "Template", + description: "Identifier of a template", + async options({ page }) { + const { templates } = await this.listTemplates({ + params: { + account_id: this.accountId(), + page: page + 1, + }, + }); + return templates?.map(({ + template_id: value, title: label, + }) => ({ + value, + label, + })) || []; + }, + }, + role: { + type: "string", + label: "Role", + description: "The role of the signer(s)", + async options({ templateId }) { + const { template: { signer_roles: roles } } = await this.getTemplate({ + templateId, + }); + return roles?.map(({ name }) => name ) || []; + }, + }, + signers: { + type: "object", + label: "Signers", + description: "Enter names & email addresses as key/value pairs with name as the key and email as the value.", + }, + fileUrls: { + type: "string[]", + label: "File URLs", + description: "An array of file URLs to send for signature", + }, + ccEmailAddresses: { + type: "string[]", + label: "CC Email Addresses", + description: "The email addresses that should be CCed.", + optional: true, + }, + allowDecline: { + type: "boolean", + label: "Allow Decline", + description: "Allows signers to decline to sign a document", + default: false, + optional: true, + }, + message: { + type: "string", + label: "Message", + description: "The custom message in the email that will be sent to the signers.", + optional: true, + }, + subject: { + type: "string", + label: "Subject", + description: "The subject in the email that will be sent to the signers.", + optional: true, + }, + title: { + type: "string", + label: "Title", + description: "The title you want to assign to the SignatureRequest.", + optional: true, + }, + testMode: { + type: "boolean", + label: "Test Mode", + description: "Whether this is a test, the signature request will not be legally binding if set to `true`.", + default: false, + optional: true, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _baseUrl() { + return "https://api.hellosign.com/v3"; + }, + _headers() { + return { + Authorization: `Bearer ${this.$auth.oauth_access_token}`, + }; + }, + _makeRequest({ + $ = this, + path, + ...args + }) { + return axios($, { + url: `${this._baseUrl()}${path}`, + headers: this._headers(), + ...args, + }); + }, + accountId() { + return this.$auth.oauth_uid; + }, + getTemplate({ + templateId, ...args + }) { + return this._makeRequest({ + path: `/template/${templateId}`, + ...args, + }); + }, + listTemplates(args = {}) { + return this._makeRequest({ + path: "/template/list", + ...args, + }); + }, + sendSignatureRequest(args = {}) { + return this._makeRequest({ + path: "/signature_request/send", + method: "POST", + ...args, + }); + }, + sendSignatureRequestWithTemplate(args = {}) { + return this._makeRequest({ + path: "/signature_request/send_with_template", + method: "POST", + ...args, + }); }, }, }; diff --git a/components/hellosign/package.json b/components/hellosign/package.json new file mode 100644 index 0000000000000..f88436baa7a06 --- /dev/null +++ b/components/hellosign/package.json @@ -0,0 +1,18 @@ +{ + "name": "@pipedream/hellosign", + "version": "0.0.1", + "description": "Pipedream Hellosign Components", + "main": "hellosign.app.mjs", + "keywords": [ + "pipedream", + "hellosign" + ], + "homepage": "https://pipedream.com/apps/hellosign", + "author": "Pipedream (https://pipedream.com/)", + "publishConfig": { + "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^1.5.1" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9ef536774d764..f7d94d4a62357 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2409,6 +2409,12 @@ importers: components/helcim: specifiers: {} + components/hellosign: + specifiers: + '@pipedream/platform': ^1.5.1 + dependencies: + '@pipedream/platform': 1.5.1 + components/helper_functions: specifiers: '@pipedream/platform': ^1.1.1 From c12258e832a3ce37726c6ecc1b7b6320fd7a35ac Mon Sep 17 00:00:00 2001 From: michelle0927 Date: Fri, 20 Oct 2023 07:13:48 -0700 Subject: [PATCH 021/186] Mocean API - New Components (#8533) * new components * pnpm-lock.yaml --- .../actions/get-balance/get-balance.mjs | 23 ++++++++ .../mocean_api/actions/send-sms/send-sms.mjs | 43 +++++++++++++++ components/mocean_api/mocean_api.app.mjs | 52 +++++++++++++++++-- components/mocean_api/package.json | 7 ++- .../balance-updated/balance-updated.mjs | 35 +++++++++++++ components/mocean_api/sources/common/base.mjs | 20 +++++++ pnpm-lock.yaml | 41 +++++++-------- 7 files changed, 192 insertions(+), 29 deletions(-) create mode 100644 components/mocean_api/actions/get-balance/get-balance.mjs create mode 100644 components/mocean_api/actions/send-sms/send-sms.mjs create mode 100644 components/mocean_api/sources/balance-updated/balance-updated.mjs create mode 100644 components/mocean_api/sources/common/base.mjs diff --git a/components/mocean_api/actions/get-balance/get-balance.mjs b/components/mocean_api/actions/get-balance/get-balance.mjs new file mode 100644 index 0000000000000..138f55433b9a6 --- /dev/null +++ b/components/mocean_api/actions/get-balance/get-balance.mjs @@ -0,0 +1,23 @@ +import mocean from "../../mocean_api.app.mjs"; + +export default { + key: "mocean_api-get-balance", + name: "Get Balance", + description: "Retrieve your current account balance with Mocean API. [See the documentation](https://moceanapi.com/docs/#get-balance)", + version: "0.0.1", + type: "action", + props: { + mocean, + }, + async run({ $ }) { + const response = await this.mocean.getBalance({ + $, + }); + + if (response) { + $.export("$summary", "Successfully retrieved balance."); + } + + return response; + }, +}; diff --git a/components/mocean_api/actions/send-sms/send-sms.mjs b/components/mocean_api/actions/send-sms/send-sms.mjs new file mode 100644 index 0000000000000..e6a92aeade49d --- /dev/null +++ b/components/mocean_api/actions/send-sms/send-sms.mjs @@ -0,0 +1,43 @@ +import mocean from "../../mocean_api.app.mjs"; + +export default { + key: "mocean_api-send-sms", + name: "Send SMS", + description: "Send an outbound SMS from your Mocean account. [See the documentation](https://moceanapi.com/docs/#send-sms)", + version: "0.0.1", + type: "action", + props: { + mocean, + from: { + type: "string", + label: "From", + description: "The information that is displayed to the recipient as the sender of the SMS when a message is received at a mobile device.", + }, + to: { + type: "string", + label: "To", + description: "Phone number of the receiver. To send to multiple receivers, separate each entry with white space (‘ ’) or comma (,). Phone number must include country code, for example, a Malaysian phone number will be like 60123456789.", + }, + text: { + type: "string", + label: "Text", + description: "Contents of the message, URL encoded as necessary (e.g. Text+message+test%21). If you are sending binary content, this will be a hex string.", + }, + }, + async run({ $ }) { + const response = await this.mocean.sendSMS({ + data: { + "mocean-from": this.from, + "mocean-to": this.to, + "mocean-text": this.text, + }, + $, + }); + + if (response) { + $.export("$summary", "Successfully sent SMS message."); + } + + return response; + }, +}; diff --git a/components/mocean_api/mocean_api.app.mjs b/components/mocean_api/mocean_api.app.mjs index 07de90a7f8166..9702337011b73 100644 --- a/components/mocean_api/mocean_api.app.mjs +++ b/components/mocean_api/mocean_api.app.mjs @@ -1,11 +1,55 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "mocean_api", propDefinitions: {}, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _baseUrl() { + return "https://rest.moceanapi.com/rest/2"; + }, + _authParams(params) { + return { + ...params, + "mocean-api-key": `${this.$auth.api_key}`, + "mocean-api-secret": `${this.$auth.api_secret}`, + }; + }, + _makeRequest({ + $ = this, + path, + params = {}, + data, + ...args + }) { + if (data) { + args = { + ...args, + data: this._authParams(data), + }; + } else { + args = { + ...args, + params: this._authParams(params), + }; + } + return axios($, { + url: `${this._baseUrl()}${path}`, + ...args, + }); + }, + getBalance(args = {}) { + return this._makeRequest({ + path: "/account/balance", + ...args, + }); + }, + sendSMS(args = {}) { + return this._makeRequest({ + path: "/sms", + method: "POST", + ...args, + }); }, }, -}; \ No newline at end of file +}; diff --git a/components/mocean_api/package.json b/components/mocean_api/package.json index efb1011b54e68..cf6c0f506ed5c 100644 --- a/components/mocean_api/package.json +++ b/components/mocean_api/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/mocean_api", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Mocean API Components", "main": "mocean_api.app.mjs", "keywords": [ @@ -11,5 +11,8 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^1.5.1" } -} \ No newline at end of file +} diff --git a/components/mocean_api/sources/balance-updated/balance-updated.mjs b/components/mocean_api/sources/balance-updated/balance-updated.mjs new file mode 100644 index 0000000000000..922c25104710d --- /dev/null +++ b/components/mocean_api/sources/balance-updated/balance-updated.mjs @@ -0,0 +1,35 @@ +import common from "../common/base.mjs"; + +export default { + ...common, + key: "mocean_api-balance-updated", + name: "Balance Updated", + description: "Emit new event when the account balance has been updated. [See the documentation](https://moceanapi.com/docs/#get-balance)", + version: "0.0.1", + type: "source", + methods: { + ...common.methods, + _getPreviousBalance() { + return this.db.get("previousBalance"); + }, + _setPreviousBalance(previousBalance) { + this.db.set("previousBalance", previousBalance); + }, + generateMeta(balance) { + return { + id: Date.now(), + summary: `New Balance ${balance.value}`, + ts: Date.now(), + }; + }, + }, + async run() { + const previousBalance = this._getPreviousBalance(); + const balance = await this.mocean.getBalance(); + if (balance.value !== previousBalance) { + const meta = this.generateMeta(balance); + this.$emit(balance, meta); + } + this._setPreviousBalance(balance.value); + }, +}; diff --git a/components/mocean_api/sources/common/base.mjs b/components/mocean_api/sources/common/base.mjs new file mode 100644 index 0000000000000..23f335c3786be --- /dev/null +++ b/components/mocean_api/sources/common/base.mjs @@ -0,0 +1,20 @@ +import mocean from "../../mocean_api.app.mjs"; +import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform"; + +export default { + props: { + mocean, + db: "$.service.db", + timer: { + type: "$.interface.timer", + default: { + intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, + }, + }, + }, + methods: { + generateMeta() { + throw new Error("generateMeta is not implemented"); + }, + }, +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f7d94d4a62357..714c544ed9c31 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3460,7 +3460,10 @@ importers: specifiers: {} components/mocean_api: - specifiers: {} + specifiers: + '@pipedream/platform': ^1.5.1 + dependencies: + '@pipedream/platform': 1.5.1 components/moco: specifiers: {} @@ -9893,22 +9896,22 @@ packages: kuler: 2.0.0 dev: false - /@definitelytyped/header-parser/0.0.178: - resolution: {integrity: sha512-16FFuaWW2Hq+a0Abyt+9gvPAT0w/ezy4eph3RbtLSqxH3T/UHDla1jgnp1DMvfNeBWaIqHxcr+Vrr7BPquw7mw==} + /@definitelytyped/header-parser/0.0.179: + resolution: {integrity: sha512-mOZ2iWairIcwsroDmnKZ6AjSLhjDizXh2Dk1bzUpPYhDxfzQaI+mxN/bKMicFcpTMzI6THwp6eGRr8yrg7NGyQ==} dependencies: - '@definitelytyped/typescript-versions': 0.0.178 - '@types/parsimmon': 1.10.7 - parsimmon: 1.18.1 + '@definitelytyped/typescript-versions': 0.0.179 + '@definitelytyped/utils': 0.0.179 + semver: 7.5.4 dev: true - /@definitelytyped/typescript-versions/0.0.178: - resolution: {integrity: sha512-pPXy3z5gE4xnVgqIRApFcQ6M6kqtRK1gnqyGx/I0Yo1CH8RAsRvumCDB/KiZmQDpCHiy//E9dOIUFdquvC5t7g==} + /@definitelytyped/typescript-versions/0.0.179: + resolution: {integrity: sha512-E0VjIZkVtOt2ozagGlmWULKJYvFZwMjS6A335QJX8dmn21idRP/0RodxRpjtMU2//ChtvCZZUuKrPZQ2D/owww==} dev: true - /@definitelytyped/utils/0.0.178: - resolution: {integrity: sha512-nYg3E51XpTodS0/5w5r1wM/DhPYhyqa9BP8ili4XgB5s9j4v4mDPX9Jwjns2q24derBvyhdUpzshKDh43aqwZw==} + /@definitelytyped/utils/0.0.179: + resolution: {integrity: sha512-aUNyshFuHT+tDRlLH5pUd9acIzTim5CMiuOZmVHvjlIi7BzMxRBbG7MtzYkpwA5TxHQo2gwumLN2u9UfEklrkQ==} dependencies: - '@definitelytyped/typescript-versions': 0.0.178 + '@definitelytyped/typescript-versions': 0.0.179 '@qiwi/npm-registry-client': 8.9.1 '@types/node': 14.18.63 charm: 1.0.2 @@ -13929,10 +13932,6 @@ packages: resolution: {integrity: sha512-i/rtaJFCsPljrZvP/akBqEwUP2y5cZLOmvO+JaYnz01aPknrQ+hB5MRcO7iqCUsFaYfTG8kGfKUyboA07xeDHQ==} dev: true - /@types/parsimmon/1.10.7: - resolution: {integrity: sha512-QnO7brOMB4XCVJzU0GZAYhpay7CZLiXowKBOyAmiRcJ4SIGlrh6/cfWdTod+yfSsyli9tx7aunwQij50yHX9Fg==} - dev: true - /@types/phoenix/1.6.2: resolution: {integrity: sha512-I3mm7x5XIi+5NsIY3nfreY+H4PmQdyBwJ84SiUSOxSg1axwEPNmkKWYVm56y+emDpPPUL3cPzrLcgRWSd9gI7g==} dev: false @@ -16688,7 +16687,7 @@ packages: peerDependencies: typescript: '*' dependencies: - '@definitelytyped/header-parser': 0.0.178 + '@definitelytyped/header-parser': 0.0.179 command-exists: 1.2.9 rimraf: 3.0.2 semver: 6.3.1 @@ -16704,9 +16703,9 @@ packages: peerDependencies: typescript: '>= 3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.7.0-dev || >= 3.8.0-dev || >= 3.9.0-dev || >= 4.0.0-dev' dependencies: - '@definitelytyped/header-parser': 0.0.178 - '@definitelytyped/typescript-versions': 0.0.178 - '@definitelytyped/utils': 0.0.178 + '@definitelytyped/header-parser': 0.0.179 + '@definitelytyped/typescript-versions': 0.0.179 + '@definitelytyped/utils': 0.0.179 dts-critic: 3.3.11_typescript@4.9.5 fs-extra: 6.0.1 json-stable-stringify: 1.0.2 @@ -23450,10 +23449,6 @@ packages: nearley: 2.20.1 dev: false - /parsimmon/1.18.1: - resolution: {integrity: sha512-u7p959wLfGAhJpSDJVYXoyMCXWYwHia78HhRBWqk7AIbxdmlrfdp5wX0l3xv/iTSH5HvhN9K7o26hwwpgS5Nmw==} - dev: true - /path-exists/4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} From f8427a2bac364501d928f736f7e53515b69f07d5 Mon Sep 17 00:00:00 2001 From: Jorge Cortes Date: Fri, 20 Oct 2023 09:35:44 -0500 Subject: [PATCH 022/186] [ACTIONS] Webinarfuel action components (#8465) * Added untested action components * new line at the EOF * fixed summary --- .../add-new-registrant/add-new-registrant.mjs | 89 ++++++++++++++ .../add-tags-to-registrant.mjs | 48 ++++++++ components/webinarfuel/common/constants.mjs | 7 ++ components/webinarfuel/package.json | 4 +- components/webinarfuel/webinarfuel.app.mjs | 112 +++++++++++++++++- 5 files changed, 253 insertions(+), 7 deletions(-) create mode 100644 components/webinarfuel/actions/add-new-registrant/add-new-registrant.mjs create mode 100644 components/webinarfuel/actions/add-tags-to-registrant/add-tags-to-registrant.mjs create mode 100644 components/webinarfuel/common/constants.mjs diff --git a/components/webinarfuel/actions/add-new-registrant/add-new-registrant.mjs b/components/webinarfuel/actions/add-new-registrant/add-new-registrant.mjs new file mode 100644 index 0000000000000..ef3b0e02c2f56 --- /dev/null +++ b/components/webinarfuel/actions/add-new-registrant/add-new-registrant.mjs @@ -0,0 +1,89 @@ +import app from "../../webinarfuel.app.mjs"; + +export default { + key: "webinarfuel-add-new-registrant", + name: "Add New Registrant", + description: "Creates a new registrant for a selected webinar. [See the documentation](https://webinarfuel.docs.apiary.io/#/reference/registrant/registrants-collection/create-registrant/200?mc=reference%2Fregistrant%2Fregistrants-collection%2Fcreate-registrant%2F200)", + version: "0.0.1", + type: "action", + props: { + app, + webinarId: { + propDefinition: [ + app, + "webinarId", + ], + }, + email: { + propDefinition: [ + app, + "email", + ], + }, + firstName: { + propDefinition: [ + app, + "firstName", + ], + }, + tags: { + optional: true, + propDefinition: [ + app, + "tags", + ], + }, + webinarSessionId: { + propDefinition: [ + app, + "webinarSessionId", + ({ webinarId }) => ({ + webinarId, + }), + ], + }, + timeZone: { + optional: true, + propDefinition: [ + app, + "timeZone", + ], + }, + }, + methods: { + createRegistrant(args = {}) { + return this.app.post({ + path: "/registrants", + ...args, + }); + }, + }, + async run({ $: step }) { + const { + createRegistrant, + webinarId, + email, + firstName, + tags, + webinarSessionId, + timeZone, + } = this; + + return createRegistrant({ + step, + data: { + webinar_id: webinarId, + registrant: { + email, + first_name: firstName, + tags, + }, + session: { + webinar_session_id: webinarSessionId, + timezone: timeZone, + }, + }, + summary: (response) => `Successfully added new registrant with email: ${response.email}`, + }); + }, +}; diff --git a/components/webinarfuel/actions/add-tags-to-registrant/add-tags-to-registrant.mjs b/components/webinarfuel/actions/add-tags-to-registrant/add-tags-to-registrant.mjs new file mode 100644 index 0000000000000..838d7b81c257f --- /dev/null +++ b/components/webinarfuel/actions/add-tags-to-registrant/add-tags-to-registrant.mjs @@ -0,0 +1,48 @@ +import app from "../../webinarfuel.app.mjs"; + +export default { + key: "webinarfuel-add-tags-to-registrant", + name: "Add Tags To Registrant", + description: "Adds tags to an existing registrant. [See the documentation](https://webinarfuel.docs.apiary.io/#/reference/registrant/add-tags)", + version: "0.0.1", + type: "action", + props: { + app, + email: { + propDefinition: [ + app, + "email", + ], + }, + tags: { + propDefinition: [ + app, + "tags", + ], + }, + }, + methods: { + addTags(args = {}) { + return this.app.post({ + path: "/registrants/add_tags", + ...args, + }); + }, + }, + async run({ $: step }) { + const { + addTags, + email, + tags, + } = this; + + return addTags({ + step, + data: { + email, + tags, + }, + summary: (response) => `Successfully added tags to registrant email ${response.registrant.email}.`, + }); + }, +}; diff --git a/components/webinarfuel/common/constants.mjs b/components/webinarfuel/common/constants.mjs new file mode 100644 index 0000000000000..0c5b2cbd964c9 --- /dev/null +++ b/components/webinarfuel/common/constants.mjs @@ -0,0 +1,7 @@ +const SUMMARY_LABEL = "$summary"; +const BASE_URL = "https://api.webinarfuel.com"; + +export default { + SUMMARY_LABEL, + BASE_URL, +}; diff --git a/components/webinarfuel/package.json b/components/webinarfuel/package.json index 28a3c843f2b6b..dfb039417f348 100644 --- a/components/webinarfuel/package.json +++ b/components/webinarfuel/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/webinarfuel", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream WebinarFuel Components", "main": "webinarfuel.app.mjs", "keywords": [ @@ -12,4 +12,4 @@ "publishConfig": { "access": "public" } -} \ No newline at end of file +} diff --git a/components/webinarfuel/webinarfuel.app.mjs b/components/webinarfuel/webinarfuel.app.mjs index 2f1091730f141..05f6dc5f1332f 100644 --- a/components/webinarfuel/webinarfuel.app.mjs +++ b/components/webinarfuel/webinarfuel.app.mjs @@ -1,11 +1,113 @@ +import { + axios, ConfigurationError, +} from "@pipedream/platform"; +import constants from "./common/constants.mjs"; + export default { type: "app", app: "webinarfuel", - propDefinitions: {}, + propDefinitions: { + webinarId: { + type: "string", + label: "Webinar ID", + description: "The ID of the webinar", + async options({ page }) { + const { webinars } = await this.getWebinars({ + params: { + page: page + 1, + }, + }); + return webinars.map(({ + id: value, name: label, + }) => ({ + value, + label, + })); + }, + }, + webinarSessionId: { + type: "string", + label: "Session ID", + description: "The webinar session id.", + async options({ webinarId }) { + const { webinar: { sessions } } = await this.getWebinar({ + webinarId, + }); + return sessions.map(({ + id: value, formatted_scheduled_at: label, + }) => ({ + value, + label, + })); + }, + }, + timeZone: { + type: "string", + label: "Time Zone", + description: "Session [TimeZone name](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). Required if webinar timezone is `registrant`. Example: `America/New_York`.", + }, + email: { + type: "string", + label: "Email", + description: "The email of the registrant", + }, + firstName: { + type: "string", + label: "First Name", + description: "The first name of the registrant", + }, + tags: { + type: "string[]", + label: "Tags", + description: "The tags to add to the registrant", + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + exportSummary(step) { + if (!step?.export) { + throw new ConfigurationError("The summary method should be bind to the step object aka `$`"); + } + return (msg = "") => step.export(constants.SUMMARY_LABEL, msg); + }, + async makeRequest({ + step = this, path, headers, summary, ...args + } = {}) { + const config = { + ...args, + url: constants.BASE_URL + path, + headers: { + ...headers, + "Authorization": `Bearer ${this.$auth.api_key}`, + }, + }; + + const response = await axios(step, config); + + if (typeof summary === "function") { + this.exportSummary(step)(summary(response)); + } + + return response; + }, + post(args = {}) { + return this.makeRequest({ + method: "post", + ...args, + }); + }, + getWebinars(args = {}) { + return this.makeRequest({ + path: "/webinars", + ...args, + }); + }, + getWebinar({ + webinarId, ...args + } = {}) { + return this.makeRequest({ + path: `/webinars/${webinarId}`, + ...args, + }); }, }, -}; \ No newline at end of file +}; From f7a3b6918d1e63e61e992bf2a46bf50cd03b4d80 Mon Sep 17 00:00:00 2001 From: Jorge Cortes Date: Fri, 20 Oct 2023 09:36:04 -0500 Subject: [PATCH 023/186] [ACTIONS/SOURCE] Starloop Added actions and source components (#8522) * Added untested actions and source components * Increased version in package.json file * Fixed component key * Fixes addressed by QA * pnpm-lock.yaml --- .../starloop/actions/list-ids/list-ids.mjs | 18 +++ .../actions/send-invite/send-invite.mjs | 80 +++++++++++ components/starloop/common/constants.mjs | 13 ++ components/starloop/package.json | 6 +- .../new-profile-created.mjs | 32 +++++ components/starloop/starloop.app.mjs | 124 +++++++++++++++++- 6 files changed, 265 insertions(+), 8 deletions(-) create mode 100644 components/starloop/actions/list-ids/list-ids.mjs create mode 100644 components/starloop/actions/send-invite/send-invite.mjs create mode 100644 components/starloop/common/constants.mjs create mode 100644 components/starloop/sources/new-profile-created/new-profile-created.mjs diff --git a/components/starloop/actions/list-ids/list-ids.mjs b/components/starloop/actions/list-ids/list-ids.mjs new file mode 100644 index 0000000000000..f907ab2a9b3cc --- /dev/null +++ b/components/starloop/actions/list-ids/list-ids.mjs @@ -0,0 +1,18 @@ +import app from "../../starloop.app.mjs"; + +export default { + key: "starloop-list-ids", + name: "List IDs", + description: "Returns your business id and a list of all profile id’s and names. [See the documentation](https://help.starloop.com/article/46-api-documentation)", + version: "0.0.1", + type: "action", + props: { + app, + }, + run({ $: step }) { + return this.app.listIds({ + step, + summary: () => "Successfully listed ids", + }); + }, +}; diff --git a/components/starloop/actions/send-invite/send-invite.mjs b/components/starloop/actions/send-invite/send-invite.mjs new file mode 100644 index 0000000000000..6f6d7e6810134 --- /dev/null +++ b/components/starloop/actions/send-invite/send-invite.mjs @@ -0,0 +1,80 @@ +import app from "../../starloop.app.mjs"; + +export default { + key: "starloop-send-invite", + name: "Send Invite", + description: "Creates a new recipient and sends a Starloop invite (Email | SMS | both) to your customer to leave a review. [See the documentation](https://help.starloop.com/article/46-api-documentation)", + version: "0.0.1", + type: "action", + props: { + app, + firstName: { + propDefinition: [ + app, + "firstName", + ], + }, + email: { + propDefinition: [ + app, + "email", + ], + }, + phone: { + propDefinition: [ + app, + "phone", + ], + }, + businessId: { + propDefinition: [ + app, + "businessId", + ], + }, + profileId: { + propDefinition: [ + app, + "profileId", + ], + }, + testMode: { + propDefinition: [ + app, + "testMode", + ], + }, + }, + methods: { + sendInvite(args = {}) { + return this.app.post({ + path: "/send_invite", + ...args, + }); + }, + }, + run({ $: step }) { + const { + sendInvite, + firstName, + email, + phone, + businessId, + profileId, + testMode, + } = this; + + return sendInvite({ + step, + params: { + first_name: firstName, + email, + phone, + business_id: businessId, + profile_id: profileId, + test_mode: testMode, + }, + summary: () => "Successfully sent invite", + }); + }, +}; diff --git a/components/starloop/common/constants.mjs b/components/starloop/common/constants.mjs new file mode 100644 index 0000000000000..ec8ced447a178 --- /dev/null +++ b/components/starloop/common/constants.mjs @@ -0,0 +1,13 @@ +const SUMMARY_LABEL = "$summary"; +const BASE_URL = "https://go.starloop.com"; +const VERSION_PATH = "/api"; +const LAST_CREATED_AT = "lastCreatedAt"; +const DEFAULT_MAX = 600; + +export default { + SUMMARY_LABEL, + BASE_URL, + VERSION_PATH, + DEFAULT_MAX, + LAST_CREATED_AT, +}; diff --git a/components/starloop/package.json b/components/starloop/package.json index b12b6fddb861b..f2bd8dfaf2bdc 100644 --- a/components/starloop/package.json +++ b/components/starloop/package.json @@ -1,7 +1,7 @@ { "name": "@pipedream/starloop", - "version": "0.0.1", - "description": "Pipedream Starloop Components", + "version": "0.1.0", + "description": "Pipedream Starloop Components", "main": "starloop.app.mjs", "keywords": [ "pipedream", @@ -12,4 +12,4 @@ "publishConfig": { "access": "public" } -} \ No newline at end of file +} diff --git a/components/starloop/sources/new-profile-created/new-profile-created.mjs b/components/starloop/sources/new-profile-created/new-profile-created.mjs new file mode 100644 index 0000000000000..25f26f52a952b --- /dev/null +++ b/components/starloop/sources/new-profile-created/new-profile-created.mjs @@ -0,0 +1,32 @@ +import app from "../../starloop.app.mjs"; +import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform"; + +export default { + key: "starloop-new-profile-created", + name: "New Profile Created", + description: "This source triggers when a new profile is created in Starloop.", + version: "0.0.1", + type: "source", + dedupe: "unique", + props: { + app, + db: "$.service.db", + timer: { + type: "$.interface.timer", + default: { + intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, + }, + }, + }, + async run() { + const { profile_ids: profiles } = await this.app.listIds(); + + profiles.forEach((profile) => { + this.$emit(profile, { + id: profile.id, + summary: `New Profile: ${profile.id}`, + ts: Date.now(), + }); + }); + }, +}; diff --git a/components/starloop/starloop.app.mjs b/components/starloop/starloop.app.mjs index 633acfe08d124..dce48f4b0d692 100644 --- a/components/starloop/starloop.app.mjs +++ b/components/starloop/starloop.app.mjs @@ -1,11 +1,125 @@ +import { + axios, ConfigurationError, +} from "@pipedream/platform"; +import constants from "./common/constants.mjs"; + export default { type: "app", app: "starloop", - propDefinitions: {}, + propDefinitions: { + businessId: { + type: "string", + label: "Business ID", + description: "The ID of the business", + optional: true, + async options() { + const { business_id: businessId } = await this.listIds(); + return [ + businessId, + ]; + }, + }, + profileId: { + type: "string", + label: "Profile ID", + description: "The ID of the profile", + optional: true, + async options() { + const { profile_ids: profileIds } = await this.listIds(); + return profileIds.map(({ + id: value, name: label, + }) => ({ + label, + value, + })); + }, + }, + firstName: { + type: "string", + label: "First Name", + description: "The first name of the recipient", + }, + email: { + type: "string", + label: "Email", + description: "The email of the recipient", + optional: true, + }, + phone: { + type: "string", + label: "Phone", + description: "The phone number of the recipient", + optional: true, + }, + testMode: { + type: "boolean", + label: "Test Mode", + description: "If set to true, the invite will not be sent", + optional: true, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + exportSummary(step) { + if (!step?.export) { + throw new ConfigurationError("The summary method should be bind to the step object aka `$`"); + } + return (msg = "") => step.export(constants.SUMMARY_LABEL, msg); + }, + getUrl(path) { + return `${constants.BASE_URL}${constants.VERSION_PATH}${path}`; + }, + getParams(params = {}) { + return { + token: this.$auth.api_key, + ...params, + }; + }, + getHeaders(headers = {}) { + return { + "Content-Type": "application/x-www-form-urlencoded", + "accept": "application/json", + ...headers, + }; + }, + async makeRequest({ + step = this, path, headers, params, summary, ...args + } = {}) { + const { + getUrl, + getParams, + getHeaders, + } = this; + + const config = { + url: getUrl(path), + params: getParams(params), + headers: getHeaders(headers), + ...args, + }; + + const response = await axios(step, config); + + if (typeof summary === "function") { + this.exportSummary(step)(summary(response)); + } + + if (response.error_msg) { + throw new Error(JSON.stringify(response, null, 2)); + } + + return response; + }, + post(args = {}) { + return this.makeRequest({ + method: "post", + ...args, + }); + }, + listIds(args = {}) { + return this.post({ + path: "/list_ids", + ...args, + }); }, }, -}; \ No newline at end of file +}; From 1ec061d5d5edbc75471059420d287ac85d1acc4b Mon Sep 17 00:00:00 2001 From: michelle0927 Date: Fri, 20 Oct 2023 09:33:44 -0700 Subject: [PATCH 024/186] Jumpseller - New Components (#8544) * new components * pnpm-lock.yaml --- components/jumpseller/.gitignore | 3 - .../create-product-variant.mjs | 79 +++++++++++ .../actions/create-product/create-product.mjs | 69 +++++++++ .../actions/update-product/update-product.mjs | 79 +++++++++++ components/jumpseller/app/jumpseller.app.ts | 13 -- components/jumpseller/jumpseller.app.mjs | 132 ++++++++++++++++++ components/jumpseller/package.json | 11 +- components/jumpseller/sources/common/base.mjs | 52 +++++++ .../sources/order-paid/order-paid.mjs | 24 ++++ .../sources/order-updated/order-updated.mjs | 24 ++++ pnpm-lock.yaml | 15 +- 11 files changed, 476 insertions(+), 25 deletions(-) delete mode 100644 components/jumpseller/.gitignore create mode 100644 components/jumpseller/actions/create-product-variant/create-product-variant.mjs create mode 100644 components/jumpseller/actions/create-product/create-product.mjs create mode 100644 components/jumpseller/actions/update-product/update-product.mjs delete mode 100644 components/jumpseller/app/jumpseller.app.ts create mode 100644 components/jumpseller/jumpseller.app.mjs create mode 100644 components/jumpseller/sources/common/base.mjs create mode 100644 components/jumpseller/sources/order-paid/order-paid.mjs create mode 100644 components/jumpseller/sources/order-updated/order-updated.mjs diff --git a/components/jumpseller/.gitignore b/components/jumpseller/.gitignore deleted file mode 100644 index ec761ccab7595..0000000000000 --- a/components/jumpseller/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.js -*.mjs -dist \ No newline at end of file diff --git a/components/jumpseller/actions/create-product-variant/create-product-variant.mjs b/components/jumpseller/actions/create-product-variant/create-product-variant.mjs new file mode 100644 index 0000000000000..7df828613cfd4 --- /dev/null +++ b/components/jumpseller/actions/create-product-variant/create-product-variant.mjs @@ -0,0 +1,79 @@ +import jumpseller from "../../jumpseller.app.mjs"; + +export default { + key: "jumpseller-create-product-variant", + name: "Create Product Variant", + description: "Create a new product variant in Jumpseller. [See the documentation](https://jumpseller.com/support/api/#tag/Product-Variants/paths/~1products~1%7Bid%7D~1variants.json/post)", + version: "0.0.1", + type: "action", + props: { + jumpseller, + productId: { + propDefinition: [ + jumpseller, + "productId", + ], + }, + price: { + propDefinition: [ + jumpseller, + "price", + ], + description: "The price of the product variant.", + optional: true, + }, + sku: { + propDefinition: [ + jumpseller, + "sku", + ], + description: "The sku of the product variant.", + }, + stock: { + propDefinition: [ + jumpseller, + "stock", + ], + description: "Quantity in stock for the product variant.", + }, + options: { + type: "object", + label: "Options", + description: "Enter the name and value of options as key/value pairs.", + optional: true, + }, + }, + async run({ $ }) { + const options = []; + if (this.options) { + for (const [ + key, + value, + ] of Object.entries(this.options)) { + options.push({ + name: key, + value, + }); + } + } + + const { variant } = await this.jumpseller.createProductVariant({ + productId: this.productId, + data: { + variant: { + price: +this.price, + sku: this.sku, + stock: this.stock, + options, + }, + }, + $, + }); + + if (variant?.id) { + $.export("$summary", `Successfully created product variant with ID ${variant.id}.`); + } + + return variant; + }, +}; diff --git a/components/jumpseller/actions/create-product/create-product.mjs b/components/jumpseller/actions/create-product/create-product.mjs new file mode 100644 index 0000000000000..44190bc70bf74 --- /dev/null +++ b/components/jumpseller/actions/create-product/create-product.mjs @@ -0,0 +1,69 @@ +import jumpseller from "../../jumpseller.app.mjs"; + +export default { + key: "jumpseller-create-product", + name: "Create Product", + description: "Create a new product in Jumpseller. [See the documentation](https://jumpseller.com/support/api/#tag/Products/paths/~1products.json/post)", + version: "0.0.1", + type: "action", + props: { + jumpseller, + name: { + propDefinition: [ + jumpseller, + "name", + ], + }, + price: { + propDefinition: [ + jumpseller, + "price", + ], + }, + description: { + propDefinition: [ + jumpseller, + "description", + ], + }, + stock: { + propDefinition: [ + jumpseller, + "stock", + ], + }, + sku: { + propDefinition: [ + jumpseller, + "sku", + ], + }, + status: { + propDefinition: [ + jumpseller, + "status", + ], + }, + }, + async run({ $ }) { + const { product } = await this.jumpseller.createProduct({ + data: { + product: { + name: this.name, + price: +this.price, + description: this.description, + stock: this.stock, + sku: this.sku, + status: this.status, + }, + }, + $, + }); + + if (product?.id) { + $.export("$summary", `Successfully created product with ID ${product.id}.`); + } + + return product; + }, +}; diff --git a/components/jumpseller/actions/update-product/update-product.mjs b/components/jumpseller/actions/update-product/update-product.mjs new file mode 100644 index 0000000000000..fbba94a67fd92 --- /dev/null +++ b/components/jumpseller/actions/update-product/update-product.mjs @@ -0,0 +1,79 @@ +import jumpseller from "../../jumpseller.app.mjs"; +import lodash from "lodash"; + +export default { + key: "jumpseller-update-product", + name: "Update Product", + description: "Update an existing product in Jumpseller. [See the documentation](https://jumpseller.com/support/api/#tag/Products/paths/~1products~1%7Bid%7D.json/put)", + version: "0.0.1", + type: "action", + props: { + jumpseller, + productId: { + propDefinition: [ + jumpseller, + "productId", + ], + }, + name: { + propDefinition: [ + jumpseller, + "name", + ], + optional: true, + }, + price: { + propDefinition: [ + jumpseller, + "price", + ], + optional: true, + }, + description: { + propDefinition: [ + jumpseller, + "description", + ], + }, + stock: { + propDefinition: [ + jumpseller, + "stock", + ], + }, + sku: { + propDefinition: [ + jumpseller, + "sku", + ], + }, + status: { + propDefinition: [ + jumpseller, + "status", + ], + }, + }, + async run({ $ }) { + const { product } = await this.jumpseller.updateProduct({ + productId: this.productId, + data: { + product: lodash.pickBy({ + name: this.name, + price: +this.price, + description: this.description, + stock: this.stock, + sku: this.sku, + status: this.status, + }), + }, + $, + }); + + if (product?.id) { + $.export("$summary", `Successfully updated product with ID ${product.id}.`); + } + + return product; + }, +}; diff --git a/components/jumpseller/app/jumpseller.app.ts b/components/jumpseller/app/jumpseller.app.ts deleted file mode 100644 index acddc34d24698..0000000000000 --- a/components/jumpseller/app/jumpseller.app.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { defineApp } from "@pipedream/types"; - -export default defineApp({ - type: "app", - app: "jumpseller", - 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/jumpseller/jumpseller.app.mjs b/components/jumpseller/jumpseller.app.mjs new file mode 100644 index 0000000000000..86cfa6e47b799 --- /dev/null +++ b/components/jumpseller/jumpseller.app.mjs @@ -0,0 +1,132 @@ +import { axios } from "@pipedream/platform"; + +export default { + type: "app", + app: "jumpseller", + propDefinitions: { + productId: { + type: "string", + label: "Product", + description: "Identifier of a product", + async options({ page }) { + const products = await this.listProducts({ + params: { + page: page + 1, + }, + }); + return products?.map(({ product }) => ({ + value: product.id, + label: product.name, + })) || []; + }, + }, + name: { + type: "string", + label: "Name", + description: "The name of the product.", + }, + price: { + type: "string", + label: "Price", + description: "The price of the product.", + }, + description: { + type: "string", + label: "Description", + description: "The description of the product.", + optional: true, + }, + stock: { + type: "integer", + label: "Stock", + description: "Quantity in stock for the product.", + optional: true, + }, + sku: { + type: "integer", + label: "SKU", + description: "Stock Keeping Unit of the product.", + optional: true, + }, + status: { + type: "string", + label: "Status", + description: "Status of the product", + options: [ + "available", + "not-available", + "disabled", + ], + optional: true, + }, + }, + methods: { + _baseUrl() { + return "https://api.jumpseller.com/v1"; + }, + _headers() { + return { + "Authorization": `Bearer ${this.$auth.oauth_access_token}`, + "Content-Type": "application/json", + }; + }, + _makeRequest({ + $ = this, + path, + ...args + }) { + return axios($, { + url: `${this._baseUrl()}${path}`, + headers: this._headers(), + ...args, + }); + }, + createWebhook(args = {}) { + return this._makeRequest({ + path: "/hooks.json", + method: "POST", + ...args, + }); + }, + deleteWebhook({ + hookId, ...args + }) { + return this._makeRequest({ + path: `/hooks/${hookId}.json`, + method: "DELETE", + ...args, + }); + }, + listProducts(args = {}) { + return this._makeRequest({ + path: "/products.json", + ...args, + }); + }, + createProduct(args = {}) { + return this._makeRequest({ + path: "/products.json", + method: "POST", + ...args, + }); + }, + createProductVariant({ + productId, ...args + }) { + return this._makeRequest({ + path: `/products/${productId}/variants.json`, + method: "POST", + ...args, + }); + }, + updateProduct({ + productId, ...args + }) { + return this._makeRequest({ + path: `/products/${productId}.json`, + method: "PUT", + ...args, + }); + }, + }, +}; diff --git a/components/jumpseller/package.json b/components/jumpseller/package.json index 8b89280c24cab..c88de7b4d30d4 100644 --- a/components/jumpseller/package.json +++ b/components/jumpseller/package.json @@ -1,16 +1,19 @@ { "name": "@pipedream/jumpseller", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Jumpseller Components", - "main": "dist/app/jumpseller.app.mjs", + "main": "jumpseller.app.mjs", "keywords": [ "pipedream", "jumpseller" ], - "files": ["dist"], "homepage": "https://pipedream.com/apps/jumpseller", "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^1.5.1", + "lodash": "^4.17.21" } -} \ No newline at end of file +} diff --git a/components/jumpseller/sources/common/base.mjs b/components/jumpseller/sources/common/base.mjs new file mode 100644 index 0000000000000..a9cba36d28c8e --- /dev/null +++ b/components/jumpseller/sources/common/base.mjs @@ -0,0 +1,52 @@ +import jumpseller from "../../jumpseller.app.mjs"; + +export default { + props: { + jumpseller, + db: "$.service.db", + http: "$.interface.http", + }, + hooks: { + async activate() { + const { hook } = await this.jumpseller.createWebhook({ + data: { + hook: { + url: this.http.endpoint, + event: this.getEvent(), + }, + }, + }); + this._setHookId(hook.id); + }, + async deactivate() { + const hookId = this._getHookId(); + if (hookId) { + await this.jumpseller.deleteWebhook({ + hookId, + }); + } + }, + }, + methods: { + _getHookId() { + return this.db.get("hookId"); + }, + _setHookId(hookId) { + this.db.set("hookId", hookId); + }, + getEvent() { + throw new Error("getEvent is not implemented"); + }, + generateMeta() { + throw new Error("generateMeta is not implemented"); + }, + }, + async run(event) { + const { body } = event; + if (!body?.order) { + return; + } + const meta = this.generateMeta(body.order); + this.$emit(body.order, meta); + }, +}; diff --git a/components/jumpseller/sources/order-paid/order-paid.mjs b/components/jumpseller/sources/order-paid/order-paid.mjs new file mode 100644 index 0000000000000..547a6095b8041 --- /dev/null +++ b/components/jumpseller/sources/order-paid/order-paid.mjs @@ -0,0 +1,24 @@ +import common from "../common/base.mjs"; + +export default { + ...common, + key: "jumpseller-order-paid", + name: "Order Paid", + description: "Emit new event when an order is paid in Jumpseller. [See the documentation](https://jumpseller.com/support/api/#tag/Hooks/paths/~1hooks.json/post)", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getEvent() { + return "order_paid"; + }, + generateMeta(order) { + return { + id: order.id, + summary: `Order Paid ID ${order.id}`, + ts: Date.now(), + }; + }, + }, +}; diff --git a/components/jumpseller/sources/order-updated/order-updated.mjs b/components/jumpseller/sources/order-updated/order-updated.mjs new file mode 100644 index 0000000000000..8c27166c17e36 --- /dev/null +++ b/components/jumpseller/sources/order-updated/order-updated.mjs @@ -0,0 +1,24 @@ +import common from "../common/base.mjs"; + +export default { + ...common, + key: "jumpseller-order-updated", + name: "Order Updated", + description: "Emit new event when an order is updaetd in Jumpseller. [See the documentation](https://jumpseller.com/support/api/#tag/Hooks/paths/~1hooks.json/post)", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getEvent() { + return "order_updated"; + }, + generateMeta(order) { + return { + id: `${order.id}-${Date.now()}`, + summary: `Order Updated ID ${order.id}`, + ts: Date.now(), + }; + }, + }, +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 714c544ed9c31..770b69185b253 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2788,7 +2788,12 @@ importers: '@pipedream/platform': 1.5.1 components/jumpseller: - specifiers: {} + specifiers: + '@pipedream/platform': ^1.5.1 + lodash: ^4.17.21 + dependencies: + '@pipedream/platform': 1.5.1 + lodash: 4.17.21 components/junip: specifiers: {} @@ -9896,8 +9901,8 @@ packages: kuler: 2.0.0 dev: false - /@definitelytyped/header-parser/0.0.179: - resolution: {integrity: sha512-mOZ2iWairIcwsroDmnKZ6AjSLhjDizXh2Dk1bzUpPYhDxfzQaI+mxN/bKMicFcpTMzI6THwp6eGRr8yrg7NGyQ==} + /@definitelytyped/header-parser/0.0.180: + resolution: {integrity: sha512-fCTevUtPRjolPR8SjTOsThoEHKXT0LndD4rCZQV+PWTxJc6YjkSUVCyr2iD8Btb8nOcJdSHt2JMF8xf1OEBZKA==} dependencies: '@definitelytyped/typescript-versions': 0.0.179 '@definitelytyped/utils': 0.0.179 @@ -16687,7 +16692,7 @@ packages: peerDependencies: typescript: '*' dependencies: - '@definitelytyped/header-parser': 0.0.179 + '@definitelytyped/header-parser': 0.0.180 command-exists: 1.2.9 rimraf: 3.0.2 semver: 6.3.1 @@ -16703,7 +16708,7 @@ packages: peerDependencies: typescript: '>= 3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.7.0-dev || >= 3.8.0-dev || >= 3.9.0-dev || >= 4.0.0-dev' dependencies: - '@definitelytyped/header-parser': 0.0.179 + '@definitelytyped/header-parser': 0.0.180 '@definitelytyped/typescript-versions': 0.0.179 '@definitelytyped/utils': 0.0.179 dts-critic: 3.3.11_typescript@4.9.5 From a1b24492dfb0ad7e9993d327a8683187b0a99f6d Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Sun, 22 Oct 2023 13:58:21 -0700 Subject: [PATCH 025/186] Removing en default for OpenAI transcription action (#8563) --- .../actions/create-transcription/create-transcription.mjs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/components/openai/actions/create-transcription/create-transcription.mjs b/components/openai/actions/create-transcription/create-transcription.mjs index 969e5cd0bae7d..4717cb5b7db3c 100644 --- a/components/openai/actions/create-transcription/create-transcription.mjs +++ b/components/openai/actions/create-transcription/create-transcription.mjs @@ -22,7 +22,7 @@ const pipelineAsync = promisify(stream.pipeline); export default { name: "Create Transcription", - version: "0.0.9", + version: "0.1.0", key: "openai-create-transcription", description: "Transcribes audio into the input language. [See docs here](https://platform.openai.com/docs/api-reference/audio/create).", type: "action", @@ -43,7 +43,6 @@ export default { description: "**Optional**. The language of the input audio. Supplying the input language will improve accuracy and latency.", type: "string", optional: true, - default: "en", options: lang.LANGUAGES.map((l) => ({ label: l.label, value: l.value, From f3f0f58cd4ac24c86fdd1947e2a8f1b422ae5386 Mon Sep 17 00:00:00 2001 From: Dylan Pierce Date: Sun, 22 Oct 2023 20:29:33 -0400 Subject: [PATCH 026/186] Update browser autonation README.md --- docs/docs/code/nodejs/browser-automation/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/code/nodejs/browser-automation/README.md b/docs/docs/code/nodejs/browser-automation/README.md index 0f27447ba5c1d..1738606ac8bc2 100644 --- a/docs/docs/code/nodejs/browser-automation/README.md +++ b/docs/docs/code/nodejs/browser-automation/README.md @@ -524,7 +524,7 @@ export default defineComponent({ await page.keyboard.type("Hello, from a Pipedream workflow."); await page.click('input[type=submit]'); - await page.context().browser(); + await page.context().close(); await browser.close(); }, }); From 0f7de2b824bae2cb3eab1240c4ff3e791080a6fc Mon Sep 17 00:00:00 2001 From: Jorge Cortes Date: Mon, 23 Oct 2023 08:56:14 -0500 Subject: [PATCH 027/186] [ACTIONS/SOURCES] Redmine new actions and sources (#8549) * Added first version * Added tested actions and sources * Removed issuedId prop --- .../actions/create-issue/create-issue.mjs | 69 ++++++ .../actions/delete-user/delete-user.mjs | 40 ++++ .../actions/update-project/update-project.mjs | 75 ++++++ components/redmine/common/constants.mjs | 15 ++ components/redmine/common/utils.mjs | 43 ++++ components/redmine/package.json | 4 +- components/redmine/redmine.app.mjs | 225 +++++++++++++++++- components/redmine/sources/common/base.mjs | 14 ++ components/redmine/sources/common/polling.mjs | 58 +++++ .../sources/issue-created/issue-created.mjs | 34 +++ .../project-updated/project-updated.mjs | 35 +++ 11 files changed, 605 insertions(+), 7 deletions(-) create mode 100644 components/redmine/actions/create-issue/create-issue.mjs create mode 100644 components/redmine/actions/delete-user/delete-user.mjs create mode 100644 components/redmine/actions/update-project/update-project.mjs create mode 100644 components/redmine/common/constants.mjs create mode 100644 components/redmine/common/utils.mjs create mode 100644 components/redmine/sources/common/base.mjs create mode 100644 components/redmine/sources/common/polling.mjs create mode 100644 components/redmine/sources/issue-created/issue-created.mjs create mode 100644 components/redmine/sources/project-updated/project-updated.mjs diff --git a/components/redmine/actions/create-issue/create-issue.mjs b/components/redmine/actions/create-issue/create-issue.mjs new file mode 100644 index 0000000000000..91ed70602d2a5 --- /dev/null +++ b/components/redmine/actions/create-issue/create-issue.mjs @@ -0,0 +1,69 @@ +import app from "../../redmine.app.mjs"; +import utils from "../../common/utils.mjs"; + +export default { + key: "redmine-create-issue", + name: "Create Issue", + description: "Creates a new issue in Redmine. [See the documentation](https://www.redmine.org/projects/redmine/wiki/rest_issues#creating-an-issue)", + version: "0.0.1", + type: "action", + props: { + app, + projectId: { + propDefinition: [ + app, + "projectId", + ], + }, + trackerId: { + propDefinition: [ + app, + "trackerId", + ], + }, + subject: { + type: "string", + label: "Subject", + description: "The subject of the issue", + }, + description: { + type: "string", + label: "Description", + description: "The description of the issue", + }, + statusId: { + propDefinition: [ + app, + "statusId", + ], + }, + priorityId: { + propDefinition: [ + app, + "priorityId", + ], + }, + }, + methods: { + createIssue(args = {}) { + return this.app.post({ + path: "/issues.json", + ...args, + }); + }, + }, + run({ $: step }) { + const { + createIssue, + ...issue + } = this; + + return createIssue({ + step, + data: { + issue: utils.transformProps(issue), + }, + summary: (response) => `Successfully created issue with ID: \`${response.issue?.id}\``, + }); + }, +}; diff --git a/components/redmine/actions/delete-user/delete-user.mjs b/components/redmine/actions/delete-user/delete-user.mjs new file mode 100644 index 0000000000000..177f0853833ff --- /dev/null +++ b/components/redmine/actions/delete-user/delete-user.mjs @@ -0,0 +1,40 @@ +import app from "../../redmine.app.mjs"; + +export default { + key: "redmine-delete-user", + name: "Delete User", + description: "Deletes a user from the Redmine platform. [See the documentation](https://www.redmine.org/projects/redmine/wiki/rest_users#delete)", + version: "0.0.1", + type: "action", + props: { + app, + userId: { + propDefinition: [ + app, + "userId", + ], + }, + }, + methods: { + deleteUser({ + userId, ...args + } = {}) { + return this.app.delete({ + path: `/users/${userId}.json`, + ...args, + }); + }, + }, + run({ $: step }) { + const { + deleteUser, + userId, + } = this; + + return deleteUser({ + step, + userId, + summary: () => "Successfully deleted user", + }); + }, +}; diff --git a/components/redmine/actions/update-project/update-project.mjs b/components/redmine/actions/update-project/update-project.mjs new file mode 100644 index 0000000000000..73eb6c95ba9c5 --- /dev/null +++ b/components/redmine/actions/update-project/update-project.mjs @@ -0,0 +1,75 @@ +import app from "../../redmine.app.mjs"; +import utils from "../../common/utils.mjs"; + +export default { + key: "redmine-update-project", + name: "Update Project", + description: "Updates an existing project in Redmine. [See the documentation](https://www.redmine.org/projects/redmine/wiki/rest_projects#updating-a-project)", + version: "0.0.1", + type: "action", + props: { + app, + projectId: { + propDefinition: [ + app, + "projectId", + ], + }, + name: { + type: "string", + label: "Name", + description: "The name of the project", + optional: true, + }, + description: { + type: "string", + label: "Description", + description: "The description of the project", + optional: true, + }, + homepage: { + type: "string", + label: "Homepage", + description: "The homepage of the project", + optional: true, + }, + isPublic: { + type: "boolean", + label: "Is Public", + description: "Whether the project is public", + optional: true, + }, + inheritMembers: { + type: "boolean", + label: "Inherit Members", + description: "Whether the project should inherit members from its parent", + optional: true, + }, + }, + methods: { + updateProject({ + projectId, ...args + } = {}) { + return this.app.put({ + path: `/projects/${projectId}.json`, + ...args, + }); + }, + }, + run({ $: step }) { + const { + updateProject, + projectId, + ...project + } = this; + + return updateProject({ + step, + projectId, + data: { + project: utils.transformProps(project), + }, + summary: () => "Successfully updated project", + }); + }, +}; diff --git a/components/redmine/common/constants.mjs b/components/redmine/common/constants.mjs new file mode 100644 index 0000000000000..4f26a9a20e03f --- /dev/null +++ b/components/redmine/common/constants.mjs @@ -0,0 +1,15 @@ +const SUMMARY_LABEL = "$summary"; +const DOMAIN_PLACEHOLDER = "{domain}"; +const BASE_URL = `https://${DOMAIN_PLACEHOLDER}`; +const LAST_CREATED_AT = "lastCreatedAt"; +const DEFAULT_MAX = 600; +const DEFAULT_LIMIT = 60; + +export default { + SUMMARY_LABEL, + DOMAIN_PLACEHOLDER, + BASE_URL, + DEFAULT_MAX, + DEFAULT_LIMIT, + LAST_CREATED_AT, +}; diff --git a/components/redmine/common/utils.mjs b/components/redmine/common/utils.mjs new file mode 100644 index 0000000000000..2bcc3ad0a1e86 --- /dev/null +++ b/components/redmine/common/utils.mjs @@ -0,0 +1,43 @@ +function toSnakeCase(str) { + return str?.replace(/([A-Z])/g, "_$1").toLowerCase(); +} + +function keysToSnakeCase(data = {}) { + return Object.entries(data) + .reduce((acc, [ + key, + value, + ]) => ({ + ...acc, + [toSnakeCase(key)]: value, + }), {}); +} + +function transformProps(props) { + if (!props) { + return; + } + + return keysToSnakeCase( + Object.fromEntries( + Object.entries(props) + .filter(([ + key, + value, + ]) => typeof(value) !== "function" && key !== "app"), + ), + ); +} + +async function iterate(iterations) { + const items = []; + for await (const item of iterations) { + items.push(item); + } + return items; +} + +export default { + transformProps, + iterate, +}; diff --git a/components/redmine/package.json b/components/redmine/package.json index 56a5906166039..17144e2e3db94 100644 --- a/components/redmine/package.json +++ b/components/redmine/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/redmine", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Redmine Components", "main": "redmine.app.mjs", "keywords": [ @@ -12,4 +12,4 @@ "publishConfig": { "access": "public" } -} \ No newline at end of file +} diff --git a/components/redmine/redmine.app.mjs b/components/redmine/redmine.app.mjs index 830f6ecc68ca3..0bc99f353ddbe 100644 --- a/components/redmine/redmine.app.mjs +++ b/components/redmine/redmine.app.mjs @@ -1,11 +1,226 @@ +import { + axios, ConfigurationError, +} from "@pipedream/platform"; +import constants from "./common/constants.mjs"; +import utils from "./common/utils.mjs"; + export default { type: "app", app: "redmine", - propDefinitions: {}, + propDefinitions: { + projectId: { + type: "integer", + label: "Project ID", + description: "The ID of the project", + async options() { + const response = await this.listProjects(); + console.log(response); + const { projects } = response; + return projects.map(({ + id: value, name: label, + }) => ({ + label, + value, + })); + }, + }, + trackerId: { + type: "integer", + label: "Tracker ID", + description: "The ID of the tracker", + async options() { + const { trackers } = await this.listTrackers(); + return trackers.map(({ + id: value, name: label, + }) => ({ + label, + value, + })); + }, + }, + statusId: { + type: "integer", + label: "Status ID", + description: "The ID of the status", + async options() { + const { issue_statuses: statuses } = await this.listIssueStatuses(); + return statuses.map(({ + id: value, name: label, + }) => ({ + label, + value, + })); + }, + }, + priorityId: { + type: "integer", + label: "Priority ID", + description: "The ID of the priority", + async options() { + const { issue_priorities: priorities } = await this.listIssuePriorities(); + return priorities.map(({ + id: value, name: label, + }) => ({ + label, + value, + })); + }, + }, + userId: { + type: "integer", + label: "User ID", + description: "The ID of the user", + async options() { + const { users } = await this.listUsers(); + return users.map(({ + id: value, login: label, + }) => ({ + label, + value, + })); + }, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + exportSummary(step) { + if (!step?.export) { + throw new ConfigurationError("The summary method should be bind to the step object aka `$`"); + } + return (msg = "") => step.export(constants.SUMMARY_LABEL, msg); + }, + getUrl(path) { + const baseUrl = constants.BASE_URL + .replace(constants.DOMAIN_PLACEHOLDER, this.$auth.hostname); + return `${baseUrl}${path}`; + }, + async makeRequest({ + step = this, path, headers, summary, ...args + } = {}) { + const { + getUrl, + exportSummary, + $auth: { api_key: apiKey }, + } = this; + + const config = { + ...args, + url: getUrl(path), + headers: { + ...headers, + "X-Redmine-API-Key": apiKey, + }, + }; + + const response = await axios(step, config); + + if (typeof(summary) === "function") { + exportSummary(step)(summary(response)); + } + + return response || { + success: true, + }; + }, + post(args = {}) { + return this.makeRequest({ + method: "post", + ...args, + }); + }, + put(args = {}) { + return this.makeRequest({ + method: "put", + ...args, + }); + }, + delete(args = {}) { + return this.makeRequest({ + method: "delete", + ...args, + }); + }, + listIssues(args = {}) { + return this.makeRequest({ + path: "/issues.json", + ...args, + }); + }, + listProjects(args = {}) { + return this.makeRequest({ + path: "/projects.json", + ...args, + }); + }, + listTrackers(args = {}) { + return this.makeRequest({ + path: "/trackers.json", + ...args, + }); + }, + listIssueStatuses(args = {}) { + return this.makeRequest({ + path: "/issue_statuses.json", + ...args, + }); + }, + listIssuePriorities(args = {}) { + return this.makeRequest({ + path: "/enumerations/issue_priorities.json", + ...args, + }); + }, + listUsers(args = {}) { + return this.makeRequest({ + path: "/users.json", + ...args, + }); + }, + async *getIterations({ + resourceFn, + resourceFnArgs, + resourceName, + max = constants.DEFAULT_MAX, + }) { + let offset = 0; + let resourcesCount = 0; + + while (true) { + const response = + await resourceFn({ + ...resourceFnArgs, + params: { + offset, + limit: constants.DEFAULT_LIMIT, + ...resourceFnArgs?.params, + }, + }); + + const nextResources = resourceName && response[resourceName] || response; + + if (!nextResources?.length) { + console.log("No more resources found"); + return; + } + + for (const resource of nextResources) { + yield resource; + resourcesCount += 1; + + if (resourcesCount >= max) { + return; + } + } + + if (nextResources.length < constants.DEFAULT_LIMIT) { + console.log("Less resources than the limit found, no more resources to fetch"); + return; + } + + offset += constants.DEFAULT_LIMIT; + } + }, + paginate(args = {}) { + return utils.iterate(this.getIterations(args)); }, }, -}; \ No newline at end of file +}; diff --git a/components/redmine/sources/common/base.mjs b/components/redmine/sources/common/base.mjs new file mode 100644 index 0000000000000..59b0f195959dd --- /dev/null +++ b/components/redmine/sources/common/base.mjs @@ -0,0 +1,14 @@ +import { ConfigurationError } from "@pipedream/platform"; +import app from "../../redmine.app.mjs"; + +export default { + props: { + app, + db: "$.service.db", + }, + methods: { + generateMeta() { + throw new ConfigurationError("generateMeta is not implemented"); + }, + }, +}; diff --git a/components/redmine/sources/common/polling.mjs b/components/redmine/sources/common/polling.mjs new file mode 100644 index 0000000000000..418eb4b8534ab --- /dev/null +++ b/components/redmine/sources/common/polling.mjs @@ -0,0 +1,58 @@ +import { + ConfigurationError, + DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, +} from "@pipedream/platform"; +import common from "./base.mjs"; + +export default { + ...common, + props: { + ...common.props, + timer: { + type: "$.interface.timer", + label: "Polling schedule", + description: "How often to poll the API", + default: { + intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, + }, + }, + }, + methods: { + ...common.methods, + getResourceName() { + throw new ConfigurationError("getResourceName is not implemented"); + }, + getResourceFn() { + throw new ConfigurationError("getResourceFn is not implemented"); + }, + getResourceFnArgs() { + throw new ConfigurationError("getResourceFnArgs is not implemented"); + }, + processEvent(resource) { + const meta = this.generateMeta(resource); + this.$emit(resource, meta); + }, + async processResources(resources) { + Array.from(resources) + .reverse() + .forEach(this.processEvent); + }, + }, + async run() { + const { + app, + getResourceFn, + getResourceFnArgs, + getResourceName, + processResources, + } = this; + + const resources = await app.paginate({ + resourceFn: getResourceFn(), + resourceFnArgs: getResourceFnArgs(), + resourceName: getResourceName(), + }); + + processResources(resources); + }, +}; diff --git a/components/redmine/sources/issue-created/issue-created.mjs b/components/redmine/sources/issue-created/issue-created.mjs new file mode 100644 index 0000000000000..70ce8122c3b07 --- /dev/null +++ b/components/redmine/sources/issue-created/issue-created.mjs @@ -0,0 +1,34 @@ +import common from "../common/polling.mjs"; + +export default { + ...common, + key: "redmine-issue-created", + name: "New Issue Created", + description: "Emit new event when a new issue is created in Redmine", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getResourceName() { + return "issues"; + }, + getResourceFn() { + return this.app.listIssues; + }, + getResourceFnArgs() { + return { + params: { + sort: "created_on:desc", + }, + }; + }, + generateMeta(resource) { + return { + id: resource.id, + summary: `New Issue: ${resource.subject}`, + ts: Date.parse(resource.created_on), + }; + }, + }, +}; diff --git a/components/redmine/sources/project-updated/project-updated.mjs b/components/redmine/sources/project-updated/project-updated.mjs new file mode 100644 index 0000000000000..89762b3b5f663 --- /dev/null +++ b/components/redmine/sources/project-updated/project-updated.mjs @@ -0,0 +1,35 @@ +import common from "../common/polling.mjs"; + +export default { + ...common, + key: "redmine-project-updated", + name: "Project Updated", + description: "Emits an event whenever a project is updated in Redmine", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getResourceName() { + return "projects"; + }, + getResourceFn() { + return this.app.listProjects; + }, + getResourceFnArgs() { + return { + params: { + sort: "updated_on:desc", + }, + }; + }, + generateMeta(resource) { + const ts = Date.parse(resource.updated_on); + return { + id: `${resource.id}-${ts}`, + summary: `Project Updated: ${resource.name}`, + ts, + }; + }, + }, +}; From f97fe42af938d0194f6cee3555e5704d5e0402c8 Mon Sep 17 00:00:00 2001 From: michelle0927 Date: Mon, 23 Oct 2023 07:31:10 -0700 Subject: [PATCH 028/186] update moduleInfo prop (#8391) --- components/zoho_crm/package.json | 2 +- .../zoho_crm/sources/common/http-based/common-custom-module.mjs | 1 + .../zoho_crm/sources/new-module-entry/new-module-entry.mjs | 2 +- .../new-or-updated-module-entry/new-or-updated-module-entry.mjs | 2 +- .../sources/updated-module-entry/updated-module-entry.mjs | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/components/zoho_crm/package.json b/components/zoho_crm/package.json index b61af031ba0a5..2834317469d94 100644 --- a/components/zoho_crm/package.json +++ b/components/zoho_crm/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/zoho_crm", - "version": "0.5.0", + "version": "0.5.1", "description": "Pipedream Zoho CRM Components", "main": "zoho_crm.app.mjs", "keywords": [ diff --git a/components/zoho_crm/sources/common/http-based/common-custom-module.mjs b/components/zoho_crm/sources/common/http-based/common-custom-module.mjs index 4020f97b119d4..b612fd3291973 100644 --- a/components/zoho_crm/sources/common/http-based/common-custom-module.mjs +++ b/components/zoho_crm/sources/common/http-based/common-custom-module.mjs @@ -14,6 +14,7 @@ export default { const { modules } = await this.zohoCrm.listModules(); const options = modules .filter(this.areEventsSupportedByModule) + .filter(({ generated_type: type }) => type !== "custom") .map(({ api_name: type, singular_label: name, diff --git a/components/zoho_crm/sources/new-module-entry/new-module-entry.mjs b/components/zoho_crm/sources/new-module-entry/new-module-entry.mjs index 740b22447a367..0fd9c4fac28c9 100644 --- a/components/zoho_crm/sources/new-module-entry/new-module-entry.mjs +++ b/components/zoho_crm/sources/new-module-entry/new-module-entry.mjs @@ -6,7 +6,7 @@ export default { key: "zoho_crm-new-module-entry", name: "New Module Entry (Instant)", description: "Emit new events each time a new module/record is created in Zoho CRM", - version: "0.0.13", + version: "0.0.14", type: "source", methods: { ...common.methods, diff --git a/components/zoho_crm/sources/new-or-updated-module-entry/new-or-updated-module-entry.mjs b/components/zoho_crm/sources/new-or-updated-module-entry/new-or-updated-module-entry.mjs index 459f14f767a6e..6423c0de434e8 100644 --- a/components/zoho_crm/sources/new-or-updated-module-entry/new-or-updated-module-entry.mjs +++ b/components/zoho_crm/sources/new-or-updated-module-entry/new-or-updated-module-entry.mjs @@ -6,7 +6,7 @@ export default { key: "zoho_crm-new-or-updated-module-entry", name: "New or Updated Module Entry (Instant)", description: "Emits an event each time a module/record is created or edited in Zoho CRM", - version: "0.0.12", + version: "0.0.13", type: "source", methods: { ...common.methods, diff --git a/components/zoho_crm/sources/updated-module-entry/updated-module-entry.mjs b/components/zoho_crm/sources/updated-module-entry/updated-module-entry.mjs index fd8fc88d35f93..0aee287ad3a52 100644 --- a/components/zoho_crm/sources/updated-module-entry/updated-module-entry.mjs +++ b/components/zoho_crm/sources/updated-module-entry/updated-module-entry.mjs @@ -6,7 +6,7 @@ export default { key: "zoho_crm-updated-module-entry", name: "Updated Module Entry (Instant)", description: "Emits an event each time a new module/record is updated in Zoho CRM", - version: "0.0.12", + version: "0.0.13", type: "source", methods: { ...common.methods, From 53483ec9ff7f7a0b348d013d995d9372cc103e16 Mon Sep 17 00:00:00 2001 From: Nikhila Gurusinghe Date: Tue, 24 Oct 2023 00:26:42 +0930 Subject: [PATCH 029/186] [ACTION] Added Github Create Pull Request (#8467) * Implementing pull request code in github.app.mjs * Adding and implementing create-pull-request.mjs * Adding dynamic props to create-pull-request.mjs * Moving around optional props + fixes to create-pull-request.mjs * Revising prop options in create-pull-request.mjs * Adding org prop error handling to github.app.mjs * Updating version numbers * Fixing up head and base prop * Adding configuration error for when issue and title are both present * minor update --------- Co-authored-by: michelle0927 --- .../actions/create-branch/create-branch.mjs | 2 +- .../create-issue-comment.mjs | 2 +- .../actions/create-issue/create-issue.mjs | 2 +- .../create-or-update-file-contents.mjs | 2 +- .../create-pull-request.mjs | 151 +++ .../create-repository/create-repository.mjs | 2 +- .../get-issue-assignees.mjs | 2 +- .../get-repository-content.mjs | 2 +- .../actions/get-repository/get-repository.mjs | 2 +- .../actions/get-reviewers/get-reviewers.mjs | 2 +- .../search-issues-and-pull-requests.mjs | 2 +- .../actions/update-issue/update-issue.mjs | 2 +- components/github/github.app.mjs | 1068 +++++++++-------- components/github/package.json | 2 +- .../new-card-in-column/new-card-in-column.mjs | 2 +- .../github/sources/new-commit/new-commit.mjs | 2 +- .../sources/new-discussion/new-discussion.mjs | 2 +- .../github/sources/new-gist/new-gist.mjs | 2 +- .../new-issue-with-status.mjs | 2 +- .../sources/new-mention/new-mention.mjs | 2 +- .../new-notification/new-notification.mjs | 2 +- .../new-organization/new-organization.mjs | 2 +- .../sources/new-repository/new-repository.mjs | 2 +- .../new-review-request/new-review-request.mjs | 2 +- .../new-security-alert/new-security-alert.mjs | 2 +- .../github/sources/new-team/new-team.mjs | 2 +- .../sources/webhook-events/webhook-events.mjs | 2 +- 27 files changed, 715 insertions(+), 554 deletions(-) create mode 100644 components/github/actions/create-pull-request/create-pull-request.mjs diff --git a/components/github/actions/create-branch/create-branch.mjs b/components/github/actions/create-branch/create-branch.mjs index 9b7d123453493..fba4078a871cd 100644 --- a/components/github/actions/create-branch/create-branch.mjs +++ b/components/github/actions/create-branch/create-branch.mjs @@ -5,7 +5,7 @@ export default { key: "github-create-branch", name: "Create Branch", description: "Create a new branch in a Github repo. [See docs here](https://docs.github.com/en/rest/git/refs?apiVersion=2022-11-28#create-a-reference)", - version: "0.0.4", + version: "0.0.5", type: "action", props: { github, diff --git a/components/github/actions/create-issue-comment/create-issue-comment.mjs b/components/github/actions/create-issue-comment/create-issue-comment.mjs index b4c70aac04e79..e7ae93f328f33 100644 --- a/components/github/actions/create-issue-comment/create-issue-comment.mjs +++ b/components/github/actions/create-issue-comment/create-issue-comment.mjs @@ -4,7 +4,7 @@ export default { key: "github-create-issue-comment", name: "Create Issue Comment", description: "Create a new comment in a issue. [See docs here](https://docs.github.com/en/rest/issues/comments#create-an-issue-comment)", - version: "0.0.10", + version: "0.0.11", type: "action", props: { github, diff --git a/components/github/actions/create-issue/create-issue.mjs b/components/github/actions/create-issue/create-issue.mjs index d8d9f607d0be7..8736bcd53ebc5 100644 --- a/components/github/actions/create-issue/create-issue.mjs +++ b/components/github/actions/create-issue/create-issue.mjs @@ -4,7 +4,7 @@ export default { key: "github-create-issue", name: "Create Issue", description: "Create a new issue in a Gihub repo. [See docs here](https://docs.github.com/en/rest/issues/issues#create-an-issue)", - version: "0.2.9", + version: "0.2.10", type: "action", props: { github, diff --git a/components/github/actions/create-or-update-file-contents/create-or-update-file-contents.mjs b/components/github/actions/create-or-update-file-contents/create-or-update-file-contents.mjs index e72aed55ce89f..e6fa3237ae9bb 100644 --- a/components/github/actions/create-or-update-file-contents/create-or-update-file-contents.mjs +++ b/components/github/actions/create-or-update-file-contents/create-or-update-file-contents.mjs @@ -4,7 +4,7 @@ export default { key: "github-create-or-update-file-contents", name: "Create or update file contents", description: "Create or update a file in a repository. This will replace an existing file. [See docs here](https://docs.github.com/en/rest/repos/contents#create-or-update-file-contents)", - version: "0.0.6", + version: "0.0.7", type: "action", props: { github, diff --git a/components/github/actions/create-pull-request/create-pull-request.mjs b/components/github/actions/create-pull-request/create-pull-request.mjs new file mode 100644 index 0000000000000..9c4b71da1837e --- /dev/null +++ b/components/github/actions/create-pull-request/create-pull-request.mjs @@ -0,0 +1,151 @@ +import { ConfigurationError } from "@pipedream/platform"; +import { toSingleLineString } from "../../common/utils.mjs"; +import github from "../../github.app.mjs"; + +export default { + key: "github-create-pull-request", + name: "Create Pull Request", + description: toSingleLineString(` + Creates a new pull request for a specified repository. + [See docs here](https://docs.github.com/en/rest/pulls/pulls#create-a-pull-request) + `), + version: "0.0.2", + type: "action", + props: { + github, + repoFullname: { + propDefinition: [ + github, + "repoFullname", + ], + }, + head: { + propDefinition: [ + github, + "branch", + (c) => ({ + repoFullname: c.repoFullname, + }), + ], + label: "Head Branch", + description: toSingleLineString(` + The name of the branch where your changes are implemented. + For cross-repository pull requests in the same network, \`namespace\` head with a user like this: \`username:branch\`. + `), + }, + base: { + propDefinition: [ + github, + "branch", + (c) => ({ + repoFullname: c.repoFullname, + }), + ], + label: "Base Branch", + description: toSingleLineString(` + The name of the branch you want the changes pulled into. + This should be an existing branch on the current repository. + You cannot submit a pull request to one repository that requests a merge to a base of another repository. + `), + }, + org: { + propDefinition: [ + github, + "orgName", + ], + optional: true, + }, + headRepo: { + propDefinition: [ + github, + "repoOrg", + (c) => ({ + org: c.org, + }), + ], + label: "Head Repository's Name", + description: toSingleLineString(` + The name of the repository where the changes in the pull request were made. + This field is required for cross-repository pull requests if both repositories are owned by the same organization. + `), + optional: true, + }, + body: { + label: "Body", + description: "The contents of the pull request.", + type: "string", + optional: true, + }, + maintainerCanModify: { + label: "Maintainer Can Modify", + description: "Indicates whether [maintainers can modify](https://docs.github.com/articles/allowing-changes-to-a-pull-request-branch-created-from-a-fork/) the pull request.", + type: "boolean", + optional: true, + }, + draft: { + label: "Is Draft", + description: toSingleLineString(` + Indicates whether the pull request is a draft. + See "[Draft Pull Requests](https://docs.github.com/articles/about-pull-requests#draft-pull-requests)" in the GitHub Help documentation to learn more. + `), + type: "boolean", + optional: true, + }, + title: { + label: "Title", + description: "The title of the new pull request.", + type: "string", + optional: true, + }, + issue: { + propDefinition: [ + github, + "issueNumber", + (c) => ({ + repoFullname: c.repoFullname, + }), + ], + label: "Issue", + description: toSingleLineString(` + An issue in the repository to convert to a pull request. + The issue title, body, and comments will become the title, body, and comments on the new pull request. + `), + min: 1, + optional: true, + }, + }, + async run({ $ }) { + + if (!this.issue && !this.title) { + throw new ConfigurationError(toSingleLineString(` + Title is required if Issue is unspecified. + You can either specify a new pull request with Title or convert an existing issue to a pull request with Issue. + `)); + } + + if (this.issue && this.title) { + throw new ConfigurationError("You can't specify both Title and Issue at the same time."); + } + + const data = { + title: this.title, + head: this.head.split("/")[1], + base: this.base.split("/")[1], + head_repo: this.headRepo, + body: this.body, + maintainer_can_modify: this.maintainerCanModify, + draft: this.draft, + issue: this.issue, + }; + + const response = await this.github.createPullRequest({ + owner: this.owner, + repoFullname: this.repoFullname, + data: data, + }); + + $.export("$summary", `Successfully created pull request: ${response.title}.`); + + return response; + }, +}; diff --git a/components/github/actions/create-repository/create-repository.mjs b/components/github/actions/create-repository/create-repository.mjs index b19b7a78f6470..ba26bb9871611 100644 --- a/components/github/actions/create-repository/create-repository.mjs +++ b/components/github/actions/create-repository/create-repository.mjs @@ -4,7 +4,7 @@ export default { key: "github-create-repository", name: "Create Repository", description: "Creates a new repository for the authenticated user. [See docs here](https://docs.github.com/en/rest/repos/repos#create-a-repository-for-the-authenticated-user)", - version: "0.0.5", + version: "0.0.6", type: "action", props: { github, diff --git a/components/github/actions/get-issue-assignees/get-issue-assignees.mjs b/components/github/actions/get-issue-assignees/get-issue-assignees.mjs index 3f130701deb53..2a0db0c1c50e0 100644 --- a/components/github/actions/get-issue-assignees/get-issue-assignees.mjs +++ b/components/github/actions/get-issue-assignees/get-issue-assignees.mjs @@ -4,7 +4,7 @@ export default { key: "github-get-issue-assignees", name: "Get Issue Assignees", description: "Get assignees for an issue in a Gihub repo. [See docs here](https://docs.github.com/en/rest/issues/issues#get-an-issue)", - version: "0.0.10", + version: "0.0.11", type: "action", props: { github, diff --git a/components/github/actions/get-repository-content/get-repository-content.mjs b/components/github/actions/get-repository-content/get-repository-content.mjs index 9d814dac1f978..201ca82b7b740 100644 --- a/components/github/actions/get-repository-content/get-repository-content.mjs +++ b/components/github/actions/get-repository-content/get-repository-content.mjs @@ -8,7 +8,7 @@ export default { Get the content of a file or directory in a specific repository. [See docs here](https://docs.github.com/en/rest/repos/contents#get-repository-content) `), - version: "0.0.9", + version: "0.0.10", type: "action", props: { github, diff --git a/components/github/actions/get-repository/get-repository.mjs b/components/github/actions/get-repository/get-repository.mjs index da245abd40137..9584aea8546cf 100644 --- a/components/github/actions/get-repository/get-repository.mjs +++ b/components/github/actions/get-repository/get-repository.mjs @@ -4,7 +4,7 @@ export default { key: "github-get-repository", name: "Get Repository", description: "Get specific repository. [See docs here](https://docs.github.com/en/rest/repos/repos#get-a-repository)", - version: "0.0.10", + version: "0.0.11", type: "action", props: { github, diff --git a/components/github/actions/get-reviewers/get-reviewers.mjs b/components/github/actions/get-reviewers/get-reviewers.mjs index e0be76300c8ea..9ee9ab535dba8 100644 --- a/components/github/actions/get-reviewers/get-reviewers.mjs +++ b/components/github/actions/get-reviewers/get-reviewers.mjs @@ -6,7 +6,7 @@ export default { key: "github-get-reviewers", name: "Get Reviewers", description: "Get reviewers for a PR ([see docs](https://docs.github.com/en/rest/pulls/reviews#list-reviews-for-a-pull-request)) or Commit SHA ([see docs](https://docs.github.com/en/rest/commits/commits#list-pull-requests-associated-with-a-commit)).", - version: "0.0.10", + version: "0.0.11", type: "action", props: { github, diff --git a/components/github/actions/search-issues-and-pull-requests/search-issues-and-pull-requests.mjs b/components/github/actions/search-issues-and-pull-requests/search-issues-and-pull-requests.mjs index dc0502634ea6b..619980304be4a 100644 --- a/components/github/actions/search-issues-and-pull-requests/search-issues-and-pull-requests.mjs +++ b/components/github/actions/search-issues-and-pull-requests/search-issues-and-pull-requests.mjs @@ -4,7 +4,7 @@ export default { key: "github-search-issues-and-pull-requests", name: "Search Issues and Pull Requests", description: "Find issues and pull requests by state and keyword. [See docs here](https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests)", - version: "0.1.9", + version: "0.1.10", type: "action", props: { github, diff --git a/components/github/actions/update-issue/update-issue.mjs b/components/github/actions/update-issue/update-issue.mjs index 5e1794311cf17..2b5bb37628cd6 100644 --- a/components/github/actions/update-issue/update-issue.mjs +++ b/components/github/actions/update-issue/update-issue.mjs @@ -4,7 +4,7 @@ export default { key: "github-update-issue", name: "Update Issue", description: "Update a new issue in a Gihub repo. [See docs here](https://docs.github.com/en/rest/issues/issues#update-an-issue)", - version: "0.1.9", + version: "0.1.10", type: "action", props: { github, diff --git a/components/github/github.app.mjs b/components/github/github.app.mjs index feabb1424759c..b37d064669238 100644 --- a/components/github/github.app.mjs +++ b/components/github/github.app.mjs @@ -1,529 +1,539 @@ -import { Octokit } from "@octokit/core"; -import { paginateRest } from "@octokit/plugin-paginate-rest"; -import queries from "./common/queries.mjs"; -import { axios } from "@pipedream/platform"; -import { ConfigurationError } from "@pipedream/platform"; - -const CustomOctokit = Octokit.plugin(paginateRest); - -export default { - type: "app", - app: "github", - propDefinitions: { - orgName: { - label: "Organization", - description: "The name of the Github organization. The name is not case sensitive.", - type: "string", - async options() { - const organizations = await this.getOrganizations(); - - return organizations.map((organization) => organization.login); - }, - }, - repoFullname: { - label: "Repository", - description: "The name of the repository. The name is not case sensitive", - type: "string", - async options({ org }) { - const repositories = await this.getRepos({ - org, - }); - - return repositories.map((repository) => repository.full_name); - }, - }, - repoOrg: { - label: "Organization Repository", - description: "The repository in a organization", - type: "string", - async options({ org }) { - const repositories = await this.getOrgRepos({ - org, - }); - return repositories.map((repository) => repository.full_name.split("/")[1]); - }, - }, - project: { - label: "Project", - description: "The project in a repository", - type: "integer", - async options({ repoFullname }) { - const projects = await this.getRepositoryProjects({ - repoFullname, - }); - - return projects.map((project) => ({ - label: project.name, - value: project.id, - })); - }, - }, - projectV2: { - label: "Project V2", - description: "The project (V2) in a repository", - type: "integer", - async options({ - prevContext, org, repo, - }) { - const cursor = prevContext?.cursor ?? null; - - const { - projects, nextCursor, - } = await this.getProjectsV2({ - repoOwner: org, - repoName: repo, - cursor, - }); - - if (cursor && projects.length === 0) { - return []; - } - - return { - options: projects.map((project) => ({ - label: project.title, - value: project.number, - })), - context: { - cursor: nextCursor, - }, - }; - }, - }, - status: { - label: "Item Status", - description: "The status for a project item", - type: "string", - async options({ - org, repo, project, - }) { - const { statuses } = await this.getProjectV2Statuses({ - repoOwner: org, - repoName: repo, - project, - }); - - return statuses.map((status) => ({ - label: status.name, - value: status.id, - })); - }, - }, - labels: { - label: "Labels", - description: "The labels", - type: "string[]", - async options({ repoFullname }) { - const labels = await this.getRepositoryLabels({ - repoFullname, - }); - - return labels.map((label) => label.name); - }, - }, - collaborators: { - label: "Collaborators", - description: "The collaborators", - type: "string[]", - async options({ repoFullname }) { - const collaborators = await this.getRepositoryCollaborators({ - repoFullname, - }); - - return collaborators.map((collaborator) => collaborator.login); - }, - }, - issueNumber: { - label: "Issue Number", - description: "The issue number", - type: "integer", - async options({ repoFullname }) { - const issues = await this.getRepositoryIssues({ - repoFullname, - }); - - return issues.map((issue) => ({ - label: issue.title, - value: +issue.number, - })); - }, - }, - branch: { - label: "Branch", - description: "Branch to monitor for new commits", - type: "string", - async options({ - page, repoFullname, - }) { - const branches = await this.getBranches({ - repoFullname, - params: { - page: page + 1, - }, - }); - - return branches.map((branch) => ({ - label: branch.name, - value: `${branch.commit.sha}/${branch.name}`, - })); - }, - }, - pullNumber: { - type: "integer", - label: "PR Number", - description: "A pull request number", - async options({ repoFullname }) { - const prs = await this.getRepositoryPullRequests({ - repoFullname, - }); - - return prs.map((pr) => ({ - label: pr.title, - value: +pr.number, - })); - }, - }, - column: { - label: "Column", - description: "The column in a project board", - type: "integer", - async options({ project }) { - const columns = await this.getProjectColumns({ - project, - }); - - return columns.map((column) => ({ - label: column.name, - value: column.id, - })); - }, - }, - teamId: { - label: "Team Id", - description: "The id of the team that will be granted access to this repository. This is only valid when creating a repository in an organization.", - type: "integer", - async options() { - const teams = await this.getTeams(); - return teams.map((team) => ({ - label: team.name, - value: team.id, - })); - }, - }, - }, - methods: { - _baseApiUrl() { - return "https://api.github.com"; - }, - _accessToken() { - return this.$auth.oauth_access_token; - }, - _client() { - const client = new CustomOctokit({ - auth: this._accessToken(), - }); - client.hook.error("request", this.handleRequestException); - return client; - }, - async _makeRequest({ - $ = this, - path, - headers = {}, - ...args - } = {}) { - return axios($, { - url: `${this._baseApiUrl()}${path}`, - headers: { - Authorization: `Bearer ${this._accessToken()}`, - Accept: "application/vnd.github+json", - ...headers, - }, - ...args, - }); - }, - async graphql(query, opts = {}) { - return this._client().graphql(query, opts); - }, - handleRequestException(exception) { - console.error(exception); - const status = exception?.status; - if (status && (status === 404 || status === 403)) { - throw new ConfigurationError(`The request failed with status "${status}". It is likely that your token doesn't have sufficient permissions to execute that request. [see mor information here](https://docs.github.com/en/rest/overview/authenticating-to-the-rest-api?apiVersion=2022-11-28#about-authentication).`); - } - throw exception; - }, - async createWebhook({ - repoFullname, data, - }) { - const response = await this._client().request(`POST /repos/${repoFullname}/hooks`, data); - - return response.data; - }, - async createOrgWebhook({ - org, data, - }) { - const response = await this._client().request(`POST /orgs/${org}/hooks`, data); - - return response.data; - }, - async removeWebhook({ - repoFullname, webhookId, - }) { - return this._client().request(`DELETE /repos/${repoFullname}/hooks/${webhookId}`, {}); - }, - async removeOrgWebhook({ - org, webhookId, - }) { - return this._client().request(`DELETE /orgs/${org}/hooks/${webhookId}`, {}); - }, - async getOrganizations() { - const response = await this._client().request("GET /user/orgs", {}); - - return response.data; - }, - async getRepos() { - return this._client().paginate("GET /user/repos", {}); - }, - async getOrgRepos({ org }) { - return this._client().paginate(`GET /orgs/${org}/repos`, {}); - }, - async getRepo({ repoFullname }) { - const response = await this._client().request(`GET /repos/${repoFullname}`, {}); - - return response.data; - }, - async getRepoContent({ - repoFullname, - path, - mediaType, - }) { - return this._makeRequest({ - path: `/repos/${repoFullname}/contents/${path}`, - ...(mediaType && { - headers: { - Accept: mediaType, - }, - }), - }); - }, - async getRepositoryLabels({ repoFullname }) { - return this._client().paginate(`GET /repos/${repoFullname}/labels`, {}); - }, - async getRepositoryCollaborators({ repoFullname }) { - return this._client().paginate(`GET /repos/${repoFullname}/collaborators`, {}); - }, - async getRepositoryIssues({ repoFullname }) { - return this._client().paginate(`GET /repos/${repoFullname}/issues`, { - state: "all", - }); - }, - async getRepositoryProjects({ repoFullname }) { - return this._client().paginate(`GET /repos/${repoFullname}/projects`, {}); - }, - async getProjectsV2({ - repoOwner, repoName, cursor, - }) { - const response = await this.graphql(repoName - ? queries.projectsQuery - : queries.organizationProjectsQuery, { - repoOwner, - repoName, - cursor, - }); - return { - projects: response?.repository?.projectsV2?.nodes ?? - response?.organization?.projectsV2?.nodes, - nextCursor: response?.repository?.projectsV2?.pageInfo?.endCursor ?? - response?.organization?.projectsV2?.pageInfo?.endCursor, - }; - }, - async getProjectV2Statuses({ - repoOwner, repoName, project, - }) { - const response = await this.graphql(repoName ? - queries.statusFieldsQuery : - queries.organizationStatusFieldsQuery, { - repoOwner, - repoName, - project, - }); - - return { - statuses: response?.repository?.projectV2?.field?.options ?? - response?.organization?.projectV2?.field?.options, - }; - }, - async getProjectColumns({ project }) { - return this._client().paginate(`GET /projects/${project}/columns`, {}); - }, - async getGists() { - return this._client().paginate("GET /gists", {}); - }, - async getTeams() { - return this._client().paginate("GET /user/teams", {}); - }, - async getFilteredNotifications({ - reason, data, - }) { - const notifications = await this._client().paginate("GET /notifications", data); - - if (reason) { - return notifications.filter((notification) => notification.reason === reason); - } - - return notifications; - }, - async getAuthenticatedUser() { - const response = await this._client().request("GET /user", {}); - - return response.data; - }, - async getFromUrl({ url }) { - const response = await this._client().request(`GET ${url.replace(this._baseApiUrl(), "")}`, {}); - - return response.data; - }, - async createIssue({ - repoFullname, data, - }) { - const response = await this._client().request(`POST /repos/${repoFullname}/issues`, data); - - return response.data; - }, - async createBranch({ - repoFullname, data, - }) { - const response = await this._client().request(`POST /repos/${repoFullname}/git/refs`, data); - - return response.data; - }, - async createRepository({ data }) { - const response = await this._client().request("POST /user/repos", data); - - return response.data; - }, - async getIssue({ - repoFullname, issueNumber, - }) { - const response = await this._client().request(`GET /repos/${repoFullname}/issues/${issueNumber}`, {}); - - return response.data; - }, - async updateIssue({ - repoFullname, issueNumber, data, - }) { - const response = await this._client().request(`PATCH /repos/${repoFullname}/issues/${issueNumber}`, data); - - return response.data; - }, - async createIssueComment({ - repoFullname, issueNumber, data, - }) { - const response = await this._client().request(`POST /repos/${repoFullname}/issues/${issueNumber}/comments`, data); - - return response.data; - }, - async getIssueFromProjectCard({ - repoFullname, cardId, - }) { - const { data: card } = await this._client().request(`GET /projects/columns/cards/${cardId}`, {}); - if (!card?.content_url) { - console.log("No issue associated with this card"); - return; - } - const issueId = card.content_url.split("/").pop(); - const { data: issue } = await this._client().request(`GET /repos/${repoFullname}/issues/${issueId}`, {}); - return issue; - }, - async searchIssueAndPullRequests({ - query, maxResults, - }) { - let issues = []; - - for await (const response of this._client().paginate.iterator( - "GET /search/issues", - { - q: query, - per_page: 100, - }, - )) { - issues = issues.concat(response.data); - - if (issues.length >= maxResults) { - break; - } - } - - return issues; - }, - async getRepositoryPullRequests({ repoFullname }) { - return this._client().paginate(`GET /repos/${repoFullname}/pulls`, {}); - }, - async getPullRequestForCommit({ - repoFullname, sha, - }) { - const response = await this._client().request(`GET /repos/${repoFullname}/commits/${sha}/pulls`, {}); - - return response.data[0]; - }, - async getReviewsForPullRequest({ - repoFullname, pullNumber, - }) { - const response = await this._client().request(`GET /repos/${repoFullname}/pulls/${pullNumber}/reviews`, {}); - - return response.data; - }, - async getCommits({ - repoFullname, ...data - }) { - const { data: commits } = await this._client().request(`GET /repos/${repoFullname}/commits`, { - ...data, - }); - return commits; - }, - async getBranches({ - repoFullname, ...data - }) { - const { data: branches } = await this._client().request(`GET /repos/${repoFullname}/branches`, { - ...data, - }); - return branches; - }, - async getProjectCards({ - columnId, ...data - }) { - const { data: cards } = await this._client().request(`GET /projects/columns/${columnId}/cards`, { - ...data, - }); - return cards; - }, - async createOrUpdateFileContent({ - repoFullname, - path, - fileContent, - commitMessage, - branch = null, - }) { - const data = { - message: commitMessage, - content: Buffer.from(fileContent).toString("base64"), - }; - const fileExists = await this._makeRequest({ - path: `/repos/${repoFullname}/contents/${path}`, - validateStatus: () => true, - }); - if (fileExists.sha) { - console.log("File exists, overwriting."); - data.sha = fileExists.sha; - } - if (branch) { - data.branch = branch; - } - return this._makeRequest({ - path: `/repos/${repoFullname}/contents/${path}`, - method: "put", - data: data, - }); - }, - }, -}; +import { Octokit } from "@octokit/core"; +import { paginateRest } from "@octokit/plugin-paginate-rest"; +import queries from "./common/queries.mjs"; +import { axios } from "@pipedream/platform"; +import { ConfigurationError } from "@pipedream/platform"; + +const CustomOctokit = Octokit.plugin(paginateRest); + +export default { + type: "app", + app: "github", + propDefinitions: { + orgName: { + label: "Organization", + description: "The name of the Github organization. The name is not case sensitive.", + type: "string", + async options() { + const organizations = await this.getOrganizations(); + + return organizations.map((organization) => organization.login); + }, + }, + repoFullname: { + label: "Repository", + description: "The name of the repository. The name is not case sensitive", + type: "string", + async options({ org }) { + const repositories = await this.getRepos({ + org, + }); + + return repositories.map((repository) => repository.full_name); + }, + }, + repoOrg: { + label: "Organization Repository", + description: "The repository in a organization", + type: "string", + async options({ org }) { + if (!org) { + throw new ConfigurationError("Must specify `org` to display repository options."); + } + const repositories = await this.getOrgRepos({ + org, + }); + return repositories.map((repository) => repository.full_name.split("/")[1]); + }, + }, + project: { + label: "Project", + description: "The project in a repository", + type: "integer", + async options({ repoFullname }) { + const projects = await this.getRepositoryProjects({ + repoFullname, + }); + + return projects.map((project) => ({ + label: project.name, + value: project.id, + })); + }, + }, + projectV2: { + label: "Project V2", + description: "The project (V2) in a repository", + type: "integer", + async options({ + prevContext, org, repo, + }) { + const cursor = prevContext?.cursor ?? null; + + const { + projects, nextCursor, + } = await this.getProjectsV2({ + repoOwner: org, + repoName: repo, + cursor, + }); + + if (cursor && projects.length === 0) { + return []; + } + + return { + options: projects.map((project) => ({ + label: project.title, + value: project.number, + })), + context: { + cursor: nextCursor, + }, + }; + }, + }, + status: { + label: "Item Status", + description: "The status for a project item", + type: "string", + async options({ + org, repo, project, + }) { + const { statuses } = await this.getProjectV2Statuses({ + repoOwner: org, + repoName: repo, + project, + }); + + return statuses.map((status) => ({ + label: status.name, + value: status.id, + })); + }, + }, + labels: { + label: "Labels", + description: "The labels", + type: "string[]", + async options({ repoFullname }) { + const labels = await this.getRepositoryLabels({ + repoFullname, + }); + + return labels.map((label) => label.name); + }, + }, + collaborators: { + label: "Collaborators", + description: "The collaborators", + type: "string[]", + async options({ repoFullname }) { + const collaborators = await this.getRepositoryCollaborators({ + repoFullname, + }); + + return collaborators.map((collaborator) => collaborator.login); + }, + }, + issueNumber: { + label: "Issue Number", + description: "The issue number", + type: "integer", + async options({ repoFullname }) { + const issues = await this.getRepositoryIssues({ + repoFullname, + }); + + return issues.map((issue) => ({ + label: issue.title, + value: +issue.number, + })); + }, + }, + branch: { + label: "Branch", + description: "Branch to monitor for new commits", + type: "string", + async options({ + page, repoFullname, + }) { + const branches = await this.getBranches({ + repoFullname, + params: { + page: page + 1, + }, + }); + + return branches.map((branch) => ({ + label: branch.name, + value: `${branch.commit.sha}/${branch.name}`, + })); + }, + }, + pullNumber: { + type: "integer", + label: "PR Number", + description: "A pull request number", + async options({ repoFullname }) { + const prs = await this.getRepositoryPullRequests({ + repoFullname, + }); + + return prs.map((pr) => ({ + label: pr.title, + value: +pr.number, + })); + }, + }, + column: { + label: "Column", + description: "The column in a project board", + type: "integer", + async options({ project }) { + const columns = await this.getProjectColumns({ + project, + }); + + return columns.map((column) => ({ + label: column.name, + value: column.id, + })); + }, + }, + teamId: { + label: "Team Id", + description: "The id of the team that will be granted access to this repository. This is only valid when creating a repository in an organization.", + type: "integer", + async options() { + const teams = await this.getTeams(); + return teams.map((team) => ({ + label: team.name, + value: team.id, + })); + }, + }, + }, + methods: { + _baseApiUrl() { + return "https://api.github.com"; + }, + _accessToken() { + return this.$auth.oauth_access_token; + }, + _client() { + const client = new CustomOctokit({ + auth: this._accessToken(), + }); + client.hook.error("request", this.handleRequestException); + return client; + }, + async _makeRequest({ + $ = this, + path, + headers = {}, + ...args + } = {}) { + return axios($, { + url: `${this._baseApiUrl()}${path}`, + headers: { + Authorization: `Bearer ${this._accessToken()}`, + Accept: "application/vnd.github+json", + ...headers, + }, + ...args, + }); + }, + async graphql(query, opts = {}) { + return this._client().graphql(query, opts); + }, + handleRequestException(exception) { + console.error(exception); + const status = exception?.status; + if (status && (status === 404 || status === 403)) { + throw new ConfigurationError(`The request failed with status "${status}". It is likely that your token doesn't have sufficient permissions to execute that request. [see mor information here](https://docs.github.com/en/rest/overview/authenticating-to-the-rest-api?apiVersion=2022-11-28#about-authentication).`); + } + throw exception; + }, + async createWebhook({ + repoFullname, data, + }) { + const response = await this._client().request(`POST /repos/${repoFullname}/hooks`, data); + + return response.data; + }, + async createOrgWebhook({ + org, data, + }) { + const response = await this._client().request(`POST /orgs/${org}/hooks`, data); + + return response.data; + }, + async removeWebhook({ + repoFullname, webhookId, + }) { + return this._client().request(`DELETE /repos/${repoFullname}/hooks/${webhookId}`, {}); + }, + async removeOrgWebhook({ + org, webhookId, + }) { + return this._client().request(`DELETE /orgs/${org}/hooks/${webhookId}`, {}); + }, + async getOrganizations() { + const response = await this._client().request("GET /user/orgs", {}); + + return response.data; + }, + async getRepos() { + return this._client().paginate("GET /user/repos", {}); + }, + async getOrgRepos({ org }) { + return this._client().paginate(`GET /orgs/${org}/repos`, {}); + }, + async getRepo({ repoFullname }) { + const response = await this._client().request(`GET /repos/${repoFullname}`, {}); + + return response.data; + }, + async getRepoContent({ + repoFullname, + path, + mediaType, + }) { + return this._makeRequest({ + path: `/repos/${repoFullname}/contents/${path}`, + ...(mediaType && { + headers: { + Accept: mediaType, + }, + }), + }); + }, + async getRepositoryLabels({ repoFullname }) { + return this._client().paginate(`GET /repos/${repoFullname}/labels`, {}); + }, + async getRepositoryCollaborators({ repoFullname }) { + return this._client().paginate(`GET /repos/${repoFullname}/collaborators`, {}); + }, + async getRepositoryIssues({ repoFullname }) { + return this._client().paginate(`GET /repos/${repoFullname}/issues`, { + state: "all", + }); + }, + async getRepositoryProjects({ repoFullname }) { + return this._client().paginate(`GET /repos/${repoFullname}/projects`, {}); + }, + async getProjectsV2({ + repoOwner, repoName, cursor, + }) { + const response = await this.graphql(repoName + ? queries.projectsQuery + : queries.organizationProjectsQuery, { + repoOwner, + repoName, + cursor, + }); + return { + projects: response?.repository?.projectsV2?.nodes ?? + response?.organization?.projectsV2?.nodes, + nextCursor: response?.repository?.projectsV2?.pageInfo?.endCursor ?? + response?.organization?.projectsV2?.pageInfo?.endCursor, + }; + }, + async getProjectV2Statuses({ + repoOwner, repoName, project, + }) { + const response = await this.graphql(repoName ? + queries.statusFieldsQuery : + queries.organizationStatusFieldsQuery, { + repoOwner, + repoName, + project, + }); + + return { + statuses: response?.repository?.projectV2?.field?.options ?? + response?.organization?.projectV2?.field?.options, + }; + }, + async getProjectColumns({ project }) { + return this._client().paginate(`GET /projects/${project}/columns`, {}); + }, + async getGists() { + return this._client().paginate("GET /gists", {}); + }, + async getTeams() { + return this._client().paginate("GET /user/teams", {}); + }, + async getFilteredNotifications({ + reason, data, + }) { + const notifications = await this._client().paginate("GET /notifications", data); + + if (reason) { + return notifications.filter((notification) => notification.reason === reason); + } + + return notifications; + }, + async getAuthenticatedUser() { + const response = await this._client().request("GET /user", {}); + + return response.data; + }, + async getFromUrl({ url }) { + const response = await this._client().request(`GET ${url.replace(this._baseApiUrl(), "")}`, {}); + + return response.data; + }, + async createIssue({ + repoFullname, data, + }) { + const response = await this._client().request(`POST /repos/${repoFullname}/issues`, data); + + return response.data; + }, + async createBranch({ + repoFullname, data, + }) { + const response = await this._client().request(`POST /repos/${repoFullname}/git/refs`, data); + + return response.data; + }, + async createRepository({ data }) { + const response = await this._client().request("POST /user/repos", data); + + return response.data; + }, + async createPullRequest({ + repoFullname, data, + }) { + const response = await this._client().request(`POST /repos/${repoFullname}/pulls`, data); + + return response.data; + }, + async getIssue({ + repoFullname, issueNumber, + }) { + const response = await this._client().request(`GET /repos/${repoFullname}/issues/${issueNumber}`, {}); + + return response.data; + }, + async updateIssue({ + repoFullname, issueNumber, data, + }) { + const response = await this._client().request(`PATCH /repos/${repoFullname}/issues/${issueNumber}`, data); + + return response.data; + }, + async createIssueComment({ + repoFullname, issueNumber, data, + }) { + const response = await this._client().request(`POST /repos/${repoFullname}/issues/${issueNumber}/comments`, data); + + return response.data; + }, + async getIssueFromProjectCard({ + repoFullname, cardId, + }) { + const { data: card } = await this._client().request(`GET /projects/columns/cards/${cardId}`, {}); + if (!card?.content_url) { + console.log("No issue associated with this card"); + return; + } + const issueId = card.content_url.split("/").pop(); + const { data: issue } = await this._client().request(`GET /repos/${repoFullname}/issues/${issueId}`, {}); + return issue; + }, + async searchIssueAndPullRequests({ + query, maxResults, + }) { + let issues = []; + + for await (const response of this._client().paginate.iterator( + "GET /search/issues", + { + q: query, + per_page: 100, + }, + )) { + issues = issues.concat(response.data); + + if (issues.length >= maxResults) { + break; + } + } + + return issues; + }, + async getRepositoryPullRequests({ repoFullname }) { + return this._client().paginate(`GET /repos/${repoFullname}/pulls`, {}); + }, + async getPullRequestForCommit({ + repoFullname, sha, + }) { + const response = await this._client().request(`GET /repos/${repoFullname}/commits/${sha}/pulls`, {}); + + return response.data[0]; + }, + async getReviewsForPullRequest({ + repoFullname, pullNumber, + }) { + const response = await this._client().request(`GET /repos/${repoFullname}/pulls/${pullNumber}/reviews`, {}); + + return response.data; + }, + async getCommits({ + repoFullname, ...data + }) { + const { data: commits } = await this._client().request(`GET /repos/${repoFullname}/commits`, { + ...data, + }); + return commits; + }, + async getBranches({ + repoFullname, ...data + }) { + const { data: branches } = await this._client().request(`GET /repos/${repoFullname}/branches`, { + ...data, + }); + return branches; + }, + async getProjectCards({ + columnId, ...data + }) { + const { data: cards } = await this._client().request(`GET /projects/columns/${columnId}/cards`, { + ...data, + }); + return cards; + }, + async createOrUpdateFileContent({ + repoFullname, + path, + fileContent, + commitMessage, + branch = null, + }) { + const data = { + message: commitMessage, + content: Buffer.from(fileContent).toString("base64"), + }; + const fileExists = await this._makeRequest({ + path: `/repos/${repoFullname}/contents/${path}`, + validateStatus: () => true, + }); + if (fileExists.sha) { + console.log("File exists, overwriting."); + data.sha = fileExists.sha; + } + if (branch) { + data.branch = branch; + } + return this._makeRequest({ + path: `/repos/${repoFullname}/contents/${path}`, + method: "put", + data: data, + }); + }, + }, +}; diff --git a/components/github/package.json b/components/github/package.json index dab10cf104232..4d84c2fc49567 100644 --- a/components/github/package.json +++ b/components/github/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/github", - "version": "0.3.16", + "version": "0.3.17", "description": "Pipedream Github Components", "main": "github.app.mjs", "keywords": [ diff --git a/components/github/sources/new-card-in-column/new-card-in-column.mjs b/components/github/sources/new-card-in-column/new-card-in-column.mjs index 2ee6582a224f9..08c64914fa4af 100644 --- a/components/github/sources/new-card-in-column/new-card-in-column.mjs +++ b/components/github/sources/new-card-in-column/new-card-in-column.mjs @@ -6,7 +6,7 @@ export default { key: "github-new-card-in-column", name: "New Card in Column (Classic Projects)", description: "Emit new event when a (classic) project card is created or moved to a specific column. For Projects V2 use `New Issue with Status` trigger. [More information here](https://docs.github.com/en/issues/organizing-your-work-with-project-boards/tracking-work-with-project-boards/adding-issues-and-pull-requests-to-a-project-board)", - version: "0.1.11", + version: "0.1.12", type: "source", props: { ...common.props, diff --git a/components/github/sources/new-commit/new-commit.mjs b/components/github/sources/new-commit/new-commit.mjs index facc97780c11e..7f77cc8f7ed9c 100644 --- a/components/github/sources/new-commit/new-commit.mjs +++ b/components/github/sources/new-commit/new-commit.mjs @@ -6,7 +6,7 @@ export default { key: "github-new-commit", name: "New Commit (Instant)", description: "Emit new events on new commits to a repo or branch", - version: "0.1.10", + version: "0.1.11", type: "source", dedupe: "unique", props: { diff --git a/components/github/sources/new-discussion/new-discussion.mjs b/components/github/sources/new-discussion/new-discussion.mjs index 2878fa6914749..e5d32593d77b5 100644 --- a/components/github/sources/new-discussion/new-discussion.mjs +++ b/components/github/sources/new-discussion/new-discussion.mjs @@ -5,7 +5,7 @@ export default { key: "github-new-discussion", name: "New Discussion (Instant)", description: "Emit new events on new discussion to a repository", - version: "0.0.3", + version: "0.0.4", type: "source", dedupe: "unique", methods: { diff --git a/components/github/sources/new-gist/new-gist.mjs b/components/github/sources/new-gist/new-gist.mjs index c651e55da5c14..a47411384ed3e 100644 --- a/components/github/sources/new-gist/new-gist.mjs +++ b/components/github/sources/new-gist/new-gist.mjs @@ -5,7 +5,7 @@ export default { key: "github-new-gist", name: "New Gist", description: "Emit new events when new gists are created by the authenticated user", - version: "0.1.9", + version: "0.1.10", type: "source", dedupe: "unique", async run() { diff --git a/components/github/sources/new-issue-with-status/new-issue-with-status.mjs b/components/github/sources/new-issue-with-status/new-issue-with-status.mjs index 16d5a14ecdf20..f39fe5435f142 100644 --- a/components/github/sources/new-issue-with-status/new-issue-with-status.mjs +++ b/components/github/sources/new-issue-with-status/new-issue-with-status.mjs @@ -7,7 +7,7 @@ export default { key: "github-new-issue-with-status", name: "New Issue with Status (Projects V2)", description: "Emit new event when a project issue is tagged with a specific status. Currently supports Organization Projects only. [More information here](https://docs.github.com/en/issues/planning-and-tracking-with-projects/managing-items-in-your-project/adding-items-to-your-project)", - version: "0.0.10", + version: "0.0.11", type: "source", dedupe: "unique", props: { diff --git a/components/github/sources/new-mention/new-mention.mjs b/components/github/sources/new-mention/new-mention.mjs index 7759173f622a7..809fd8a527191 100644 --- a/components/github/sources/new-mention/new-mention.mjs +++ b/components/github/sources/new-mention/new-mention.mjs @@ -5,7 +5,7 @@ export default { key: "github-new-mention", name: "New Mention", description: "Emit new events when you are @mentioned in a new commit, comment, issue or pull request", - version: "0.1.9", + version: "0.1.11", type: "source", hooks: { async activate() { diff --git a/components/github/sources/new-notification/new-notification.mjs b/components/github/sources/new-notification/new-notification.mjs index 7c53304d5d314..7e2895fbfcd47 100644 --- a/components/github/sources/new-notification/new-notification.mjs +++ b/components/github/sources/new-notification/new-notification.mjs @@ -5,7 +5,7 @@ export default { key: "github-new-notification", name: "New Notification", description: "Emit new events when you received a new notification", - version: "0.1.9", + version: "0.1.10", type: "source", dedupe: "unique", async run() { diff --git a/components/github/sources/new-organization/new-organization.mjs b/components/github/sources/new-organization/new-organization.mjs index 2c49e9e79f06e..5e5b1c022c993 100644 --- a/components/github/sources/new-organization/new-organization.mjs +++ b/components/github/sources/new-organization/new-organization.mjs @@ -5,7 +5,7 @@ export default { key: "github-new-organization", name: "New Organization", description: "Emit new events when the authenticated user is added to a new organization", - version: "0.1.9", + version: "0.1.10", type: "source", dedupe: "unique", async run() { diff --git a/components/github/sources/new-repository/new-repository.mjs b/components/github/sources/new-repository/new-repository.mjs index 09826adae044e..a7548b3345c37 100644 --- a/components/github/sources/new-repository/new-repository.mjs +++ b/components/github/sources/new-repository/new-repository.mjs @@ -5,7 +5,7 @@ export default { key: "github-new-repository", name: "New Repository", description: "Emit new events when new repositories are created", - version: "0.1.9", + version: "0.1.10", type: "source", dedupe: "unique", async run() { diff --git a/components/github/sources/new-review-request/new-review-request.mjs b/components/github/sources/new-review-request/new-review-request.mjs index 0ca5495b012d7..bc79091d2a9e3 100644 --- a/components/github/sources/new-review-request/new-review-request.mjs +++ b/components/github/sources/new-review-request/new-review-request.mjs @@ -5,7 +5,7 @@ export default { key: "github-new-review-request", name: "New Review Request", description: "Emit new events when you or a team you're a member of are requested to review a pull request", - version: "0.1.9", + version: "0.1.10", type: "source", dedupe: "unique", async run() { diff --git a/components/github/sources/new-security-alert/new-security-alert.mjs b/components/github/sources/new-security-alert/new-security-alert.mjs index a57d010eaf81d..742074c5e0140 100644 --- a/components/github/sources/new-security-alert/new-security-alert.mjs +++ b/components/github/sources/new-security-alert/new-security-alert.mjs @@ -5,7 +5,7 @@ export default { key: "github-new-security-alert", name: "New Security Alert", description: "Emit new events when GitHub discovers a security vulnerability in one of your repositories", - version: "0.1.11", + version: "0.1.12", type: "source", dedupe: "unique", async run() { diff --git a/components/github/sources/new-team/new-team.mjs b/components/github/sources/new-team/new-team.mjs index f0842742de1d7..5a74e02485c0b 100644 --- a/components/github/sources/new-team/new-team.mjs +++ b/components/github/sources/new-team/new-team.mjs @@ -5,7 +5,7 @@ export default { key: "github-new-team", name: "New Team", description: "Emit new events when the user is added to a new team", - version: "0.1.9", + version: "0.1.10", type: "source", dedupe: "unique", async run() { diff --git a/components/github/sources/webhook-events/webhook-events.mjs b/components/github/sources/webhook-events/webhook-events.mjs index e1be24cc03892..76458774ad58d 100644 --- a/components/github/sources/webhook-events/webhook-events.mjs +++ b/components/github/sources/webhook-events/webhook-events.mjs @@ -7,7 +7,7 @@ export default { name: "New Webhook Event (Instant)", description: "Emit new event for each selected event type", type: "source", - version: "0.0.12", + version: "0.0.13", props: { ...common.props, events: { From 4ff10c9179b49ca7e4e3ec5103c65b65f3198772 Mon Sep 17 00:00:00 2001 From: michelle0927 Date: Mon, 23 Oct 2023 09:10:17 -0700 Subject: [PATCH 030/186] Flodesk - New Components (#8548) * new components * pnpm-lock.yaml --- .../add-subscriber-to-segments.mjs | 39 +++++ .../create-or-update-subscriber.mjs | 89 +++++++++++ .../find-subscriber/find-subscriber.mjs | 29 ++++ components/flodesk/flodesk.app.mjs | 142 +++++++++++++++++- components/flodesk/package.json | 8 +- components/flodesk/sources/common/base.mjs | 48 ++++++ .../subscriber-added-to-segment.mjs | 28 ++++ .../test-event.mjs | 30 ++++ .../subscriber-created/subscriber-created.mjs | 28 ++++ .../sources/subscriber-created/test-event.mjs | 26 ++++ .../subscriber-unsubscribed.mjs | 28 ++++ .../subscriber-unsubscribed/test-event.mjs | 26 ++++ pnpm-lock.yaml | 7 +- 13 files changed, 520 insertions(+), 8 deletions(-) create mode 100644 components/flodesk/actions/add-subscriber-to-segments/add-subscriber-to-segments.mjs create mode 100644 components/flodesk/actions/create-or-update-subscriber/create-or-update-subscriber.mjs create mode 100644 components/flodesk/actions/find-subscriber/find-subscriber.mjs create mode 100644 components/flodesk/sources/common/base.mjs create mode 100644 components/flodesk/sources/subscriber-added-to-segment/subscriber-added-to-segment.mjs create mode 100644 components/flodesk/sources/subscriber-added-to-segment/test-event.mjs create mode 100644 components/flodesk/sources/subscriber-created/subscriber-created.mjs create mode 100644 components/flodesk/sources/subscriber-created/test-event.mjs create mode 100644 components/flodesk/sources/subscriber-unsubscribed/subscriber-unsubscribed.mjs create mode 100644 components/flodesk/sources/subscriber-unsubscribed/test-event.mjs diff --git a/components/flodesk/actions/add-subscriber-to-segments/add-subscriber-to-segments.mjs b/components/flodesk/actions/add-subscriber-to-segments/add-subscriber-to-segments.mjs new file mode 100644 index 0000000000000..081556bae34bf --- /dev/null +++ b/components/flodesk/actions/add-subscriber-to-segments/add-subscriber-to-segments.mjs @@ -0,0 +1,39 @@ +import flodesk from "../../flodesk.app.mjs"; + +export default { + key: "flodesk-add-subscriber-to-segments", + name: "Add Subscriber To Segments", + description: "Add a subscriber to one or more segments in Flodesk. [See the documentation](https://developers.flodesk.com/#tag/subscriber/operation/addSubscriberToSegments)", + version: "0.0.1", + type: "action", + props: { + flodesk, + subscriberId: { + propDefinition: [ + flodesk, + "subscriberId", + ], + }, + segmentIds: { + propDefinition: [ + flodesk, + "segmentIds", + ], + }, + }, + async run({ $ }) { + const response = await this.flodesk.addSubscriberToSegment({ + subscriberId: this.subscriberId, + data: { + segment_ids: this.segmentIds, + }, + $, + }); + + if (response?.id) { + $.export("$summary", "Successfully added subscriber to segment(s)."); + } + + return response; + }, +}; diff --git a/components/flodesk/actions/create-or-update-subscriber/create-or-update-subscriber.mjs b/components/flodesk/actions/create-or-update-subscriber/create-or-update-subscriber.mjs new file mode 100644 index 0000000000000..d345d1de21b0a --- /dev/null +++ b/components/flodesk/actions/create-or-update-subscriber/create-or-update-subscriber.mjs @@ -0,0 +1,89 @@ +import flodesk from "../../flodesk.app.mjs"; +import { ConfigurationError } from "@pipedream/platform"; +import lodash from "lodash"; + +export default { + key: "flodesk-create-or-update-subscriber", + name: "Create or Update Subscriber", + description: "Creates or updates a subscriber in Flodesk. [See the documentation](https://developers.flodesk.com/#tag/subscriber/operation/createOrUpdateSubscriber)", + version: "0.0.1", + type: "action", + props: { + flodesk, + subscriberId: { + propDefinition: [ + flodesk, + "subscriberId", + ], + description: "The subscriber's id. Either `email` or `subscriberId` must be included.", + optional: true, + }, + email: { + type: "string", + label: "Email", + description: "The subscriber's email. Either `email` or `subscriberId` must be included.", + optional: true, + }, + firstName: { + type: "string", + label: "First Name", + description: "The subscriber's first name.", + optional: true, + }, + lastName: { + type: "string", + label: "Last Name", + description: "The subscriber's last name.", + optional: true, + }, + customFields: { + propDefinition: [ + flodesk, + "customFields", + ], + reloadProps: true, + }, + }, + async additionalProps() { + const props = {}; + if (!this.customFields?.length) { + return props; + } + for (const field of this.customFields) { + props[field.value] = { + type: "string", + label: `${field.label} Value`, + }; + } + return props; + }, + async run({ $ }) { + if (!this.subscriberId && !this.email) { + throw new ConfigurationError("Either `email` or `subscriberId` must be included."); + } + + const customFields = {}; + if (this.customFields?.length) { + for (const field of this.customFields) { + customFields[field.value] = this[field.value]; + } + } + + const response = await this.flodesk.createOrUpdateSubscriber({ + data: lodash.pickBy({ + id: this.subscriberId, + email: this.email, + first_name: this.firstName, + last_name: this.lastName, + custom_fields: customFields, + }), + $, + }); + + if (response?.id) { + $.export("$summary", `Successfully created or updated subscriber with ID ${response.id}`); + } + + return response; + }, +}; diff --git a/components/flodesk/actions/find-subscriber/find-subscriber.mjs b/components/flodesk/actions/find-subscriber/find-subscriber.mjs new file mode 100644 index 0000000000000..1d086064d5e7f --- /dev/null +++ b/components/flodesk/actions/find-subscriber/find-subscriber.mjs @@ -0,0 +1,29 @@ +import flodesk from "../../flodesk.app.mjs"; + +export default { + key: "flodesk-find-subscriber", + name: "Find Subscriber By Email", + description: "Find a subscriber by email address in Flodesk. [See the documentation](https://developers.flodesk.com/#tag/subscriber/operation/retrieveSubscriber)", + version: "0.0.1", + type: "action", + props: { + flodesk, + email: { + type: "string", + label: "Email", + description: "Email address of the subscriber", + }, + }, + async run({ $ }) { + const response = await this.flodesk.findSubscriber({ + email: this.email, + $, + }); + + if (response?.id) { + $.export("$summary", `Successfully retrieved subscriber with ID ${response.id}.`); + } + + return response; + }, +}; diff --git a/components/flodesk/flodesk.app.mjs b/components/flodesk/flodesk.app.mjs index 9c7ef691a9d71..37de24f3b0c8b 100644 --- a/components/flodesk/flodesk.app.mjs +++ b/components/flodesk/flodesk.app.mjs @@ -1,11 +1,143 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "flodesk", - propDefinitions: {}, + propDefinitions: { + subscriberId: { + type: "string", + label: "Subscriber", + description: "Identifier of the subscriber to update", + async options({ page }) { + const { data } = await this.listSubscribers({ + params: { + page: page + 1, + }, + }); + return data?.map(({ + id: value, email: label, + }) => ({ + value, + label, + })) || []; + }, + }, + segmentIds: { + type: "string[]", + label: "Segments", + description: "Array of segment Ids to add subscriber to", + async options({ page }) { + const { data } = await this.listSegments({ + params: { + page: page + 1, + }, + }); + return data?.map(({ + id: value, name: label, + }) => ({ + value, + label, + })) || []; + }, + }, + customFields: { + type: "string[]", + label: "Custom Fields", + description: "Custom fields to enter values for", + withLabel: true, + optional: true, + async options({ page }) { + const { data } = await this.listCustomFields({ + params: { + page: page + 1, + }, + }); + return data?.map(({ + key: value, label, + }) => ({ + value, + label, + })) || []; + }, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _baseUrl() { + return "https://api.flodesk.com/v1"; + }, + _headers() { + return { + Authorization: `Bearer ${this.$auth.oauth_access_token}`, + }; + }, + _makeRequest({ + $ = this, + path, + ...args + }) { + return axios($, { + url: `${this._baseUrl()}${path}`, + headers: this._headers(), + ...args, + }); + }, + createWebhook(args = {}) { + return this._makeRequest({ + path: "/webhooks", + method: "POST", + ...args, + }); + }, + deleteWebhook({ + hookId, ...args + }) { + return this._makeRequest({ + path: `/webhooks/${hookId}`, + method: "DELETE", + ...args, + }); + }, + listSegments(args = {}) { + return this._makeRequest({ + path: "/segments", + ...args, + }); + }, + listSubscribers(args = {}) { + return this._makeRequest({ + path: "/subscribers", + ...args, + }); + }, + listCustomFields(args = {}) { + return this._makeRequest({ + path: "/custom-fields", + ...args, + }); + }, + findSubscriber({ + email, ...args + }) { + return this._makeRequest({ + path: `/subscribers/${email}`, + ...args, + }); + }, + addSubscriberToSegment({ + subscriberId, ...args + }) { + return this._makeRequest({ + path: `/subscribers/${subscriberId}/segments`, + method: "POST", + ...args, + }); + }, + createOrUpdateSubscriber(args = {}) { + return this._makeRequest({ + path: "/subscribers", + method: "POST", + ...args, + }); }, }, -}; \ No newline at end of file +}; diff --git a/components/flodesk/package.json b/components/flodesk/package.json index 31a5101f61b61..631c41717bec0 100644 --- a/components/flodesk/package.json +++ b/components/flodesk/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/flodesk", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Flodesk Components", "main": "flodesk.app.mjs", "keywords": [ @@ -11,5 +11,9 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^1.5.1", + "lodash": "^4.17.21" } -} \ No newline at end of file +} diff --git a/components/flodesk/sources/common/base.mjs b/components/flodesk/sources/common/base.mjs new file mode 100644 index 0000000000000..27f41eabd46c3 --- /dev/null +++ b/components/flodesk/sources/common/base.mjs @@ -0,0 +1,48 @@ +import flodesk from "../../flodesk.app.mjs"; + +export default { + props: { + flodesk, + db: "$.service.db", + http: "$.interface.http", + }, + hooks: { + async activate() { + const response = await this.flodesk.createWebhook({ + data: { + name: "Pipedream Webhook", + post_url: this.http.endpoint, + events: this.getEvents(), + }, + }); + this._setHookId(response?.id); + }, + async deactivate() { + const hookId = this._getHookId(); + if (hookId) { + await this.flodesk.deleteWebhook({ + hookId, + }); + } + }, + }, + methods: { + _getHookId() { + return this.db.get("hookId"); + }, + _setHookId(hookId) { + this.db.set("hookId", hookId); + }, + getEvents() { + throw new Error("getEvents is not implemented"); + }, + generateMeta() { + throw new Error("generateMeta is not implemented"); + }, + }, + async run(event) { + const { body } = event; + const meta = this.generateMeta(body); + this.$emit(body, meta); + }, +}; diff --git a/components/flodesk/sources/subscriber-added-to-segment/subscriber-added-to-segment.mjs b/components/flodesk/sources/subscriber-added-to-segment/subscriber-added-to-segment.mjs new file mode 100644 index 0000000000000..a5536dc4b0595 --- /dev/null +++ b/components/flodesk/sources/subscriber-added-to-segment/subscriber-added-to-segment.mjs @@ -0,0 +1,28 @@ +import common from "../common/base.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + ...common, + key: "flodesk-subscriber-added-to-segment", + name: "Subscriber Added To Segment", + description: "Emit new event when a subscriber is added to a segment in Flodesk. [See the documentation](https://developers.flodesk.com/#tag/webhook-event/operation/subscriber.added_to_segment)", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getEvents() { + return [ + "subscriber.added_to_segment", + ]; + }, + generateMeta(event) { + return { + id: `${event.subscriber.id}-${event.segment.id}`, + summary: `Subscriber ${event.subscriber.id} added to segment ${event.segment.id}`, + ts: Date.parse(event.event_time), + }; + }, + }, + sampleEmit, +}; diff --git a/components/flodesk/sources/subscriber-added-to-segment/test-event.mjs b/components/flodesk/sources/subscriber-added-to-segment/test-event.mjs new file mode 100644 index 0000000000000..8dcea4482d434 --- /dev/null +++ b/components/flodesk/sources/subscriber-added-to-segment/test-event.mjs @@ -0,0 +1,30 @@ +export default { + "event_name": "string", + "event_time": "2019-08-24T14:15:22Z", + "subscriber": { + "id": "string", + "status": "active", + "email": "string", + "source": "manual", + "first_name": "string", + "last_name": "string", + "segments": [ + { + "id": "string", + "name": "string" + } + ], + "custom_fields": { + "property1": "string", + "property2": "string" + }, + "optin_ip": "string", + "optin_timestamp": "2019-08-24T14:15:22Z", + "created_at": "2019-08-24T14:15:22Z" + }, + "segment": { + "id": "string", + "name": "string" + }, + "webhook_id": "string" +} \ No newline at end of file diff --git a/components/flodesk/sources/subscriber-created/subscriber-created.mjs b/components/flodesk/sources/subscriber-created/subscriber-created.mjs new file mode 100644 index 0000000000000..af34ca68dd8a6 --- /dev/null +++ b/components/flodesk/sources/subscriber-created/subscriber-created.mjs @@ -0,0 +1,28 @@ +import common from "../common/base.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + ...common, + key: "flodesk-subscriber-created", + name: "Subscriber Created", + description: "Emit new event when a subscriber is created in Flodesk. [See the documentation](https://developers.flodesk.com/#tag/webhook-event/operation/subscriber.created)", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getEvents() { + return [ + "subscriber.created", + ]; + }, + generateMeta(event) { + return { + id: event.subscriber.id, + summary: `New Subscriber ${event.subscriber.id}`, + ts: Date.parse(event.event_time), + }; + }, + }, + sampleEmit, +}; diff --git a/components/flodesk/sources/subscriber-created/test-event.mjs b/components/flodesk/sources/subscriber-created/test-event.mjs new file mode 100644 index 0000000000000..449737c259712 --- /dev/null +++ b/components/flodesk/sources/subscriber-created/test-event.mjs @@ -0,0 +1,26 @@ +export default { + "event_name": "string", + "event_time": "2019-08-24T14:15:22Z", + "subscriber": { + "id": "string", + "status": "active", + "email": "string", + "source": "manual", + "first_name": "string", + "last_name": "string", + "segments": [ + { + "id": "string", + "name": "string" + } + ], + "custom_fields": { + "property1": "string", + "property2": "string" + }, + "optin_ip": "string", + "optin_timestamp": "2019-08-24T14:15:22Z", + "created_at": "2019-08-24T14:15:22Z" + }, + "webhook_id": "string" +} \ No newline at end of file diff --git a/components/flodesk/sources/subscriber-unsubscribed/subscriber-unsubscribed.mjs b/components/flodesk/sources/subscriber-unsubscribed/subscriber-unsubscribed.mjs new file mode 100644 index 0000000000000..0e649664e9ceb --- /dev/null +++ b/components/flodesk/sources/subscriber-unsubscribed/subscriber-unsubscribed.mjs @@ -0,0 +1,28 @@ +import common from "../common/base.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + ...common, + key: "flodesk-subscriber-unsubscribed", + name: "Subscriber Unsubscribed", + description: "Emit new event when a subscriber is unsubscribed in Flodesk. [See the documentation](https://developers.flodesk.com/#tag/webhook-event/operation/subscriber.unsubscribed)", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getEvents() { + return [ + "subscriber.unsubscribed", + ]; + }, + generateMeta(event) { + return { + id: event.subscriber.id, + summary: `Subscriber Unsubscribed ${event.subscriber.id}`, + ts: Date.parse(event.event_time), + }; + }, + }, + sampleEmit, +}; diff --git a/components/flodesk/sources/subscriber-unsubscribed/test-event.mjs b/components/flodesk/sources/subscriber-unsubscribed/test-event.mjs new file mode 100644 index 0000000000000..449737c259712 --- /dev/null +++ b/components/flodesk/sources/subscriber-unsubscribed/test-event.mjs @@ -0,0 +1,26 @@ +export default { + "event_name": "string", + "event_time": "2019-08-24T14:15:22Z", + "subscriber": { + "id": "string", + "status": "active", + "email": "string", + "source": "manual", + "first_name": "string", + "last_name": "string", + "segments": [ + { + "id": "string", + "name": "string" + } + ], + "custom_fields": { + "property1": "string", + "property2": "string" + }, + "optin_ip": "string", + "optin_timestamp": "2019-08-24T14:15:22Z", + "created_at": "2019-08-24T14:15:22Z" + }, + "webhook_id": "string" +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 770b69185b253..2c293e25496cf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1786,7 +1786,12 @@ importers: specifiers: {} components/flodesk: - specifiers: {} + specifiers: + '@pipedream/platform': ^1.5.1 + lodash: ^4.17.21 + dependencies: + '@pipedream/platform': 1.5.1 + lodash: 4.17.21 components/fluent_support: specifiers: {} From 375f9e98544d86ba78984bd2d163bac64060c9b5 Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Mon, 23 Oct 2023 11:32:59 -0700 Subject: [PATCH 031/186] Adding app scaffolding for insites --- components/insites/insites.app.mjs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 components/insites/insites.app.mjs diff --git a/components/insites/insites.app.mjs b/components/insites/insites.app.mjs new file mode 100644 index 0000000000000..f05bea5d0282d --- /dev/null +++ b/components/insites/insites.app.mjs @@ -0,0 +1,11 @@ +export default { + type: "app", + app: "insites", + propDefinitions: {}, + methods: { + // this.$auth contains connected account data + authKeys() { + console.log(Object.keys(this.$auth)); + }, + }, +}; \ No newline at end of file From 207e58ee2e3ffcb4a323827ce18270cab395601c Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Mon, 23 Oct 2023 11:33:00 -0700 Subject: [PATCH 032/186] Adding app scaffolding for insites --- components/insites/package.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 components/insites/package.json diff --git a/components/insites/package.json b/components/insites/package.json new file mode 100644 index 0000000000000..c947e328c85c6 --- /dev/null +++ b/components/insites/package.json @@ -0,0 +1,15 @@ +{ + "name": "@pipedream/insites", + "version": "0.0.1", + "description": "Pipedream Insites Components", + "main": "insites.app.mjs", + "keywords": [ + "pipedream", + "insites" + ], + "homepage": "https://pipedream.com/apps/insites", + "author": "Pipedream (https://pipedream.com/)", + "publishConfig": { + "access": "public" + } +} \ No newline at end of file From 45cf7f72e6e90a04780b4556c991db7249769612 Mon Sep 17 00:00:00 2001 From: Andrew Chuang Date: Mon, 23 Oct 2023 12:02:48 -0700 Subject: [PATCH 033/186] Notion updated page trigger fix (#8575) * trigger was exiting early on first non new page * chores --- components/notion/package.json | 2 +- .../notion/sources/updated-page/updated-page.mjs | 12 +++++++++--- pnpm-lock.yaml | 3 +++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/components/notion/package.json b/components/notion/package.json index fbf2b8ffc4220..5713d47fb0d23 100644 --- a/components/notion/package.json +++ b/components/notion/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/notion", - "version": "0.1.2", + "version": "0.1.3", "description": "Pipedream Notion Components", "main": "notion.app.mjs", "keywords": [ diff --git a/components/notion/sources/updated-page/updated-page.mjs b/components/notion/sources/updated-page/updated-page.mjs index fd35a8b330a61..55d5a3e9818a2 100644 --- a/components/notion/sources/updated-page/updated-page.mjs +++ b/components/notion/sources/updated-page/updated-page.mjs @@ -8,7 +8,7 @@ export default { key: "notion-updated-page", name: "Updated Page in Database", /* eslint-disable-line pipedream/source-name */ description: "Emit new event when a page in a database is updated. To select a specific page, use `Updated Page ID` instead", - version: "0.0.7", + version: "0.0.8", type: "source", dedupe: "unique", props: { @@ -23,12 +23,13 @@ export default { async run() { const params = this.lastUpdatedSortParam(); const lastCheckedTimestamp = this.getLastUpdatedTimestamp(); + let newLastUpdatedTimestamp = lastCheckedTimestamp; const pagesStream = this.notion.getPages(this.databaseId, params); for await (const page of pagesStream) { if (!this.isResultNew(page.last_edited_time, lastCheckedTimestamp)) { - break; + continue; } const meta = this.generateMeta( @@ -41,8 +42,13 @@ export default { this.$emit(page, meta); - this.setLastUpdatedTimestamp(Date.parse(page?.last_edited_time)); + newLastUpdatedTimestamp = Math.max( + newLastUpdatedTimestamp, + Date.parse(page?.last_edited_time), + ); } + + this.setLastUpdatedTimestamp(newLastUpdatedTimestamp); }, sampleEmit, }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2c293e25496cf..cf3d356671d9b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2658,6 +2658,9 @@ importers: dependencies: '@pipedream/platform': 1.5.1 + components/insites: + specifiers: {} + components/instagram_business: specifiers: '@pipedream/platform': ^1.5.1 From 71c250947759b0c079d37b83ea20cca71fad1d3e Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Mon, 23 Oct 2023 12:33:00 -0700 Subject: [PATCH 034/186] Adding app scaffolding for spotlightr --- components/spotlightr/spotlightr.app.mjs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 components/spotlightr/spotlightr.app.mjs diff --git a/components/spotlightr/spotlightr.app.mjs b/components/spotlightr/spotlightr.app.mjs new file mode 100644 index 0000000000000..6ee7739fdbed6 --- /dev/null +++ b/components/spotlightr/spotlightr.app.mjs @@ -0,0 +1,11 @@ +export default { + type: "app", + app: "spotlightr", + propDefinitions: {}, + methods: { + // this.$auth contains connected account data + authKeys() { + console.log(Object.keys(this.$auth)); + }, + }, +}; \ No newline at end of file From 98dcc09a84fbfba285093d753ad48dc1a902aa9d Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Mon, 23 Oct 2023 12:33:01 -0700 Subject: [PATCH 035/186] Adding app scaffolding for spotlightr --- components/spotlightr/package.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 components/spotlightr/package.json diff --git a/components/spotlightr/package.json b/components/spotlightr/package.json new file mode 100644 index 0000000000000..5cfd974938446 --- /dev/null +++ b/components/spotlightr/package.json @@ -0,0 +1,15 @@ +{ + "name": "@pipedream/spotlightr", + "version": "0.0.1", + "description": "Pipedream Spotlightr Components", + "main": "spotlightr.app.mjs", + "keywords": [ + "pipedream", + "spotlightr" + ], + "homepage": "https://pipedream.com/apps/spotlightr", + "author": "Pipedream (https://pipedream.com/)", + "publishConfig": { + "access": "public" + } +} \ No newline at end of file From 3012f1b524d46cdab0acb0260dcf30f087fc350c Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Mon, 23 Oct 2023 12:33:02 -0700 Subject: [PATCH 036/186] Adding app scaffolding for function --- components/function/function.app.mjs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 components/function/function.app.mjs diff --git a/components/function/function.app.mjs b/components/function/function.app.mjs new file mode 100644 index 0000000000000..c8f49aec17bf9 --- /dev/null +++ b/components/function/function.app.mjs @@ -0,0 +1,11 @@ +export default { + type: "app", + app: "function", + propDefinitions: {}, + methods: { + // this.$auth contains connected account data + authKeys() { + console.log(Object.keys(this.$auth)); + }, + }, +}; \ No newline at end of file From fb08577272159fd3f247b65ac30aacedd523fecd Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Mon, 23 Oct 2023 12:33:02 -0700 Subject: [PATCH 037/186] Adding app scaffolding for function --- components/function/package.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 components/function/package.json diff --git a/components/function/package.json b/components/function/package.json new file mode 100644 index 0000000000000..a3121d2734509 --- /dev/null +++ b/components/function/package.json @@ -0,0 +1,15 @@ +{ + "name": "@pipedream/function", + "version": "0.0.1", + "description": "Pipedream Function Components", + "main": "function.app.mjs", + "keywords": [ + "pipedream", + "function" + ], + "homepage": "https://pipedream.com/apps/function", + "author": "Pipedream (https://pipedream.com/)", + "publishConfig": { + "access": "public" + } +} \ No newline at end of file From f4fcca52d20d7ffeeb40c2e2457fdd2f8ca249b4 Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Mon, 23 Oct 2023 12:33:03 -0700 Subject: [PATCH 038/186] Adding app scaffolding for imejis_io --- components/imejis_io/imejis_io.app.mjs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 components/imejis_io/imejis_io.app.mjs diff --git a/components/imejis_io/imejis_io.app.mjs b/components/imejis_io/imejis_io.app.mjs new file mode 100644 index 0000000000000..ec11c1ab082a8 --- /dev/null +++ b/components/imejis_io/imejis_io.app.mjs @@ -0,0 +1,11 @@ +export default { + type: "app", + app: "imejis_io", + propDefinitions: {}, + methods: { + // this.$auth contains connected account data + authKeys() { + console.log(Object.keys(this.$auth)); + }, + }, +}; \ No newline at end of file From c83a57cd95f6c9c2572e1110f77a980a28c94acc Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Mon, 23 Oct 2023 12:33:03 -0700 Subject: [PATCH 039/186] Adding app scaffolding for imejis_io --- components/imejis_io/package.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 components/imejis_io/package.json diff --git a/components/imejis_io/package.json b/components/imejis_io/package.json new file mode 100644 index 0000000000000..ec298d3482f24 --- /dev/null +++ b/components/imejis_io/package.json @@ -0,0 +1,15 @@ +{ + "name": "@pipedream/imejis_io", + "version": "0.0.1", + "description": "Pipedream Imejis.io Components", + "main": "imejis_io.app.mjs", + "keywords": [ + "pipedream", + "imejis_io" + ], + "homepage": "https://pipedream.com/apps/imejis_io", + "author": "Pipedream (https://pipedream.com/)", + "publishConfig": { + "access": "public" + } +} \ No newline at end of file From e2dee5bd82f734dd0b6b2cf6052cdc6095a1deeb Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Mon, 23 Oct 2023 12:33:04 -0700 Subject: [PATCH 040/186] Adding app scaffolding for neetoinvoice --- components/neetoinvoice/neetoinvoice.app.mjs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 components/neetoinvoice/neetoinvoice.app.mjs diff --git a/components/neetoinvoice/neetoinvoice.app.mjs b/components/neetoinvoice/neetoinvoice.app.mjs new file mode 100644 index 0000000000000..08104045566e9 --- /dev/null +++ b/components/neetoinvoice/neetoinvoice.app.mjs @@ -0,0 +1,11 @@ +export default { + type: "app", + app: "neetoinvoice", + propDefinitions: {}, + methods: { + // this.$auth contains connected account data + authKeys() { + console.log(Object.keys(this.$auth)); + }, + }, +}; \ No newline at end of file From 3d760955932d10819ded6a4d6184595157f2901c Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Mon, 23 Oct 2023 12:33:05 -0700 Subject: [PATCH 041/186] Adding app scaffolding for neetoinvoice --- components/neetoinvoice/package.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 components/neetoinvoice/package.json diff --git a/components/neetoinvoice/package.json b/components/neetoinvoice/package.json new file mode 100644 index 0000000000000..931809c761eb1 --- /dev/null +++ b/components/neetoinvoice/package.json @@ -0,0 +1,15 @@ +{ + "name": "@pipedream/neetoinvoice", + "version": "0.0.1", + "description": "Pipedream neetoinvoice Components", + "main": "neetoinvoice.app.mjs", + "keywords": [ + "pipedream", + "neetoinvoice" + ], + "homepage": "https://pipedream.com/apps/neetoinvoice", + "author": "Pipedream (https://pipedream.com/)", + "publishConfig": { + "access": "public" + } +} \ No newline at end of file From 2d91942fa801e86ae9f0e8a2194f324dddcffe1d Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Mon, 23 Oct 2023 12:33:05 -0700 Subject: [PATCH 042/186] Adding app scaffolding for neetokb --- components/neetokb/neetokb.app.mjs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 components/neetokb/neetokb.app.mjs diff --git a/components/neetokb/neetokb.app.mjs b/components/neetokb/neetokb.app.mjs new file mode 100644 index 0000000000000..4bb9cd9aecbbf --- /dev/null +++ b/components/neetokb/neetokb.app.mjs @@ -0,0 +1,11 @@ +export default { + type: "app", + app: "neetokb", + propDefinitions: {}, + methods: { + // this.$auth contains connected account data + authKeys() { + console.log(Object.keys(this.$auth)); + }, + }, +}; \ No newline at end of file From 2691d4f731472f4633e4146c5ca8f5999db1c67f Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Mon, 23 Oct 2023 12:33:06 -0700 Subject: [PATCH 043/186] Adding app scaffolding for neetokb --- components/neetokb/package.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 components/neetokb/package.json diff --git a/components/neetokb/package.json b/components/neetokb/package.json new file mode 100644 index 0000000000000..4f32b697bd870 --- /dev/null +++ b/components/neetokb/package.json @@ -0,0 +1,15 @@ +{ + "name": "@pipedream/neetokb", + "version": "0.0.1", + "description": "Pipedream neetoKB Components", + "main": "neetokb.app.mjs", + "keywords": [ + "pipedream", + "neetokb" + ], + "homepage": "https://pipedream.com/apps/neetokb", + "author": "Pipedream (https://pipedream.com/)", + "publishConfig": { + "access": "public" + } +} \ No newline at end of file From edb4e25ac9e6437d78e2a68bff87bcbeebd9a88c Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Mon, 23 Oct 2023 12:33:06 -0700 Subject: [PATCH 044/186] Adding app scaffolding for astica_ai --- components/astica_ai/astica_ai.app.mjs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 components/astica_ai/astica_ai.app.mjs diff --git a/components/astica_ai/astica_ai.app.mjs b/components/astica_ai/astica_ai.app.mjs new file mode 100644 index 0000000000000..20a45aa020a67 --- /dev/null +++ b/components/astica_ai/astica_ai.app.mjs @@ -0,0 +1,11 @@ +export default { + type: "app", + app: "astica_ai", + propDefinitions: {}, + methods: { + // this.$auth contains connected account data + authKeys() { + console.log(Object.keys(this.$auth)); + }, + }, +}; \ No newline at end of file From 823eb36ffc3b898636fb359d5f5d69ab6d756985 Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Mon, 23 Oct 2023 12:33:07 -0700 Subject: [PATCH 045/186] Adding app scaffolding for astica_ai --- components/astica_ai/package.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 components/astica_ai/package.json diff --git a/components/astica_ai/package.json b/components/astica_ai/package.json new file mode 100644 index 0000000000000..7d3e3e6b8b8ae --- /dev/null +++ b/components/astica_ai/package.json @@ -0,0 +1,15 @@ +{ + "name": "@pipedream/astica_ai", + "version": "0.0.1", + "description": "Pipedream astica.ai Components", + "main": "astica_ai.app.mjs", + "keywords": [ + "pipedream", + "astica_ai" + ], + "homepage": "https://pipedream.com/apps/astica_ai", + "author": "Pipedream (https://pipedream.com/)", + "publishConfig": { + "access": "public" + } +} \ No newline at end of file From 72337ce6c82c05e0d8cb18afbc712508f48589b6 Mon Sep 17 00:00:00 2001 From: Danny Roosevelt Date: Mon, 23 Oct 2023 12:44:47 -0700 Subject: [PATCH 046/186] Update pnpm-lock.yaml --- pnpm-lock.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cf3d356671d9b..4d6e5c54ef0b9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -373,6 +373,9 @@ importers: dependencies: '@pipedream/platform': 1.5.1 + components/astica_ai: + specifiers: {} + components/astrology_api: specifiers: {} @@ -1918,6 +1921,9 @@ importers: '@pipedream/platform': 1.5.1 crypto-js: 4.1.1 + components/function: + specifiers: {} + components/funnelcockpit: specifiers: {} @@ -2619,6 +2625,9 @@ importers: stream: 0.0.2 util: 0.12.5 + components/imejis_io: + specifiers: {} + components/imgbb: specifiers: {} @@ -3633,6 +3642,12 @@ importers: dependencies: '@pipedream/platform': 1.5.1 + components/neetoinvoice: + specifiers: {} + + components/neetokb: + specifiers: {} + components/neon_api_keys: specifiers: '@pipedream/platform': ^1.5.1 @@ -5484,6 +5499,9 @@ importers: dependencies: '@pipedream/platform': 1.5.1 + components/spotlightr: + specifiers: {} + components/spreadsheet_com: specifiers: '@pipedream/platform': ^1.5.1 From b6171fe3fb77d54fbd6c763b75855ff5aa207fe9 Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Mon, 23 Oct 2023 13:32:58 -0700 Subject: [PATCH 047/186] Adding app scaffolding for click2mail2 --- components/click2mail2/click2mail2.app.mjs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 components/click2mail2/click2mail2.app.mjs diff --git a/components/click2mail2/click2mail2.app.mjs b/components/click2mail2/click2mail2.app.mjs new file mode 100644 index 0000000000000..684afdcc86f3d --- /dev/null +++ b/components/click2mail2/click2mail2.app.mjs @@ -0,0 +1,11 @@ +export default { + type: "app", + app: "click2mail2", + propDefinitions: {}, + methods: { + // this.$auth contains connected account data + authKeys() { + console.log(Object.keys(this.$auth)); + }, + }, +}; \ No newline at end of file From b7857343bfce94db214f76377d03c52bf37b4420 Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Mon, 23 Oct 2023 13:32:59 -0700 Subject: [PATCH 048/186] Adding app scaffolding for click2mail2 --- components/click2mail2/package.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 components/click2mail2/package.json diff --git a/components/click2mail2/package.json b/components/click2mail2/package.json new file mode 100644 index 0000000000000..2672ffdca9cba --- /dev/null +++ b/components/click2mail2/package.json @@ -0,0 +1,15 @@ +{ + "name": "@pipedream/click2mail2", + "version": "0.0.1", + "description": "Pipedream Click2Mail Components", + "main": "click2mail2.app.mjs", + "keywords": [ + "pipedream", + "click2mail2" + ], + "homepage": "https://pipedream.com/apps/click2mail2", + "author": "Pipedream (https://pipedream.com/)", + "publishConfig": { + "access": "public" + } +} \ No newline at end of file From 0bf9742c5c490e88af60646e8c822e8f19262b35 Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Mon, 23 Oct 2023 13:32:59 -0700 Subject: [PATCH 049/186] Adding app scaffolding for riskadvisor --- components/riskadvisor/riskadvisor.app.mjs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 components/riskadvisor/riskadvisor.app.mjs diff --git a/components/riskadvisor/riskadvisor.app.mjs b/components/riskadvisor/riskadvisor.app.mjs new file mode 100644 index 0000000000000..4d55990056670 --- /dev/null +++ b/components/riskadvisor/riskadvisor.app.mjs @@ -0,0 +1,11 @@ +export default { + type: "app", + app: "riskadvisor", + propDefinitions: {}, + methods: { + // this.$auth contains connected account data + authKeys() { + console.log(Object.keys(this.$auth)); + }, + }, +}; \ No newline at end of file From 6e05156e78f0f87da6d47720f27c128e35376d47 Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Mon, 23 Oct 2023 13:33:00 -0700 Subject: [PATCH 050/186] Adding app scaffolding for riskadvisor --- components/riskadvisor/package.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 components/riskadvisor/package.json diff --git a/components/riskadvisor/package.json b/components/riskadvisor/package.json new file mode 100644 index 0000000000000..e5f668f7eef7d --- /dev/null +++ b/components/riskadvisor/package.json @@ -0,0 +1,15 @@ +{ + "name": "@pipedream/riskadvisor", + "version": "0.0.1", + "description": "Pipedream RiskAdvisor Components", + "main": "riskadvisor.app.mjs", + "keywords": [ + "pipedream", + "riskadvisor" + ], + "homepage": "https://pipedream.com/apps/riskadvisor", + "author": "Pipedream (https://pipedream.com/)", + "publishConfig": { + "access": "public" + } +} \ No newline at end of file From b820ccdb3c82f379c9987640230f8bf28e25c2e2 Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Mon, 23 Oct 2023 13:33:01 -0700 Subject: [PATCH 051/186] Adding app scaffolding for centralstationcrm --- .../centralstationcrm/centralstationcrm.app.mjs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 components/centralstationcrm/centralstationcrm.app.mjs diff --git a/components/centralstationcrm/centralstationcrm.app.mjs b/components/centralstationcrm/centralstationcrm.app.mjs new file mode 100644 index 0000000000000..6cb0b6c3f653f --- /dev/null +++ b/components/centralstationcrm/centralstationcrm.app.mjs @@ -0,0 +1,11 @@ +export default { + type: "app", + app: "centralstationcrm", + propDefinitions: {}, + methods: { + // this.$auth contains connected account data + authKeys() { + console.log(Object.keys(this.$auth)); + }, + }, +}; \ No newline at end of file From 8d1e4c41e436996c0774aaf6ea3db8b717efbc1c Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Mon, 23 Oct 2023 13:33:01 -0700 Subject: [PATCH 052/186] Adding app scaffolding for centralstationcrm --- components/centralstationcrm/package.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 components/centralstationcrm/package.json diff --git a/components/centralstationcrm/package.json b/components/centralstationcrm/package.json new file mode 100644 index 0000000000000..8b36d5ac117e8 --- /dev/null +++ b/components/centralstationcrm/package.json @@ -0,0 +1,15 @@ +{ + "name": "@pipedream/centralstationcrm", + "version": "0.0.1", + "description": "Pipedream CentralStationCRM Components", + "main": "centralstationcrm.app.mjs", + "keywords": [ + "pipedream", + "centralstationcrm" + ], + "homepage": "https://pipedream.com/apps/centralstationcrm", + "author": "Pipedream (https://pipedream.com/)", + "publishConfig": { + "access": "public" + } +} \ No newline at end of file From 3876616f912f7ccf3afbd6a048555e76aac287d1 Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Mon, 23 Oct 2023 13:33:02 -0700 Subject: [PATCH 053/186] Adding app scaffolding for algomo --- components/algomo/algomo.app.mjs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 components/algomo/algomo.app.mjs diff --git a/components/algomo/algomo.app.mjs b/components/algomo/algomo.app.mjs new file mode 100644 index 0000000000000..8f78fb6e76a2e --- /dev/null +++ b/components/algomo/algomo.app.mjs @@ -0,0 +1,11 @@ +export default { + type: "app", + app: "algomo", + propDefinitions: {}, + methods: { + // this.$auth contains connected account data + authKeys() { + console.log(Object.keys(this.$auth)); + }, + }, +}; \ No newline at end of file From 04ae3ceda24eac88d8c7ca3f814b0fe12a9a2d8f Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Mon, 23 Oct 2023 13:33:03 -0700 Subject: [PATCH 054/186] Adding app scaffolding for algomo --- components/algomo/package.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 components/algomo/package.json diff --git a/components/algomo/package.json b/components/algomo/package.json new file mode 100644 index 0000000000000..7f01b783292d9 --- /dev/null +++ b/components/algomo/package.json @@ -0,0 +1,15 @@ +{ + "name": "@pipedream/algomo", + "version": "0.0.1", + "description": "Pipedream Algomo Components", + "main": "algomo.app.mjs", + "keywords": [ + "pipedream", + "algomo" + ], + "homepage": "https://pipedream.com/apps/algomo", + "author": "Pipedream (https://pipedream.com/)", + "publishConfig": { + "access": "public" + } +} \ No newline at end of file From a93ad7fc7885eff3180cfa68e0c1c656abf1b01e Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Mon, 23 Oct 2023 13:33:03 -0700 Subject: [PATCH 055/186] Adding app scaffolding for webvizio --- components/webvizio/webvizio.app.mjs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 components/webvizio/webvizio.app.mjs diff --git a/components/webvizio/webvizio.app.mjs b/components/webvizio/webvizio.app.mjs new file mode 100644 index 0000000000000..f67113dab9847 --- /dev/null +++ b/components/webvizio/webvizio.app.mjs @@ -0,0 +1,11 @@ +export default { + type: "app", + app: "webvizio", + propDefinitions: {}, + methods: { + // this.$auth contains connected account data + authKeys() { + console.log(Object.keys(this.$auth)); + }, + }, +}; \ No newline at end of file From 2d1397157235b20840a6d6e38a35addd127f6494 Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Mon, 23 Oct 2023 13:33:04 -0700 Subject: [PATCH 056/186] Adding app scaffolding for webvizio --- components/webvizio/package.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 components/webvizio/package.json diff --git a/components/webvizio/package.json b/components/webvizio/package.json new file mode 100644 index 0000000000000..97e607ffa4337 --- /dev/null +++ b/components/webvizio/package.json @@ -0,0 +1,15 @@ +{ + "name": "@pipedream/webvizio", + "version": "0.0.1", + "description": "Pipedream Webvizio Components", + "main": "webvizio.app.mjs", + "keywords": [ + "pipedream", + "webvizio" + ], + "homepage": "https://pipedream.com/apps/webvizio", + "author": "Pipedream (https://pipedream.com/)", + "publishConfig": { + "access": "public" + } +} \ No newline at end of file From 48f11e5192e4487da1bfa1f556dffba8801c6182 Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Mon, 23 Oct 2023 13:33:04 -0700 Subject: [PATCH 057/186] Adding app scaffolding for cometly --- components/cometly/cometly.app.mjs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 components/cometly/cometly.app.mjs diff --git a/components/cometly/cometly.app.mjs b/components/cometly/cometly.app.mjs new file mode 100644 index 0000000000000..18181797d57c8 --- /dev/null +++ b/components/cometly/cometly.app.mjs @@ -0,0 +1,11 @@ +export default { + type: "app", + app: "cometly", + propDefinitions: {}, + methods: { + // this.$auth contains connected account data + authKeys() { + console.log(Object.keys(this.$auth)); + }, + }, +}; \ No newline at end of file From a3fa01e83abbb4d88f85a51ccb257ad426b71dd4 Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Mon, 23 Oct 2023 13:33:05 -0700 Subject: [PATCH 058/186] Adding app scaffolding for cometly --- components/cometly/package.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 components/cometly/package.json diff --git a/components/cometly/package.json b/components/cometly/package.json new file mode 100644 index 0000000000000..cb9f19fc8b6fc --- /dev/null +++ b/components/cometly/package.json @@ -0,0 +1,15 @@ +{ + "name": "@pipedream/cometly", + "version": "0.0.1", + "description": "Pipedream Cometly Components", + "main": "cometly.app.mjs", + "keywords": [ + "pipedream", + "cometly" + ], + "homepage": "https://pipedream.com/apps/cometly", + "author": "Pipedream (https://pipedream.com/)", + "publishConfig": { + "access": "public" + } +} \ No newline at end of file From 9b8443bc1bc638c17398c7cfa00fd70ef396e3ec Mon Sep 17 00:00:00 2001 From: Danny Roosevelt Date: Mon, 23 Oct 2023 16:56:31 -0700 Subject: [PATCH 059/186] Premium apps list update (#8594) * Update README.md * Update pnpm-lock.yaml * Update README.md * Update README.md --- docs/docs/apps/README.md | 32 +++++++++++++++++++++++++++++++- docs/docs/pricing/README.md | 2 +- pnpm-lock.yaml | 18 ++++++++++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/docs/docs/apps/README.md b/docs/docs/apps/README.md index 8e9fb5139c991..3682c8ed12b70 100644 --- a/docs/docs/apps/README.md +++ b/docs/docs/apps/README.md @@ -13,29 +13,59 @@ But Pipedream-integrated apps provide a few benefits: The vast majority of integrated apps on Pipedream are free to use in your workflows across any plan. However, in order to use any of the below apps in an active workflow, your workspace will need to have a paid plan (Basic or higher): - [ActiveCampaign](https://pipedream.com/apps/activecampaign) +- [Amazon Advertising](https://pipedream.com/apps/amazon_advertising) - [Asana](https://pipedream.com/apps/asana) +- [AWS](https://pipedream.com/apps/aws) - [Azure OpenAI Service](https://pipedream.com/apps/azure-openai-service) +- [BigCommerce](https://pipedream.com/apps/bigcommerce) +- [Cisco Webex](https://pipedream.com/apps/cisco-webex) +- [Cisco Webex (Custom App)](https://pipedream.com/apps/cisco-webex-custom-app) - [Close](https://pipedream.com/apps/close) +- [Cloudinary](https://pipedream.com/apps/cloudinary) +- [Customer.io](https://pipedream.com/apps/customer-io) +- [Datadog](https://pipedream.com/apps/datadog) +- [dbt Cloud](https://pipedream.com/apps/dbt) - [ERPNext](https://pipedream.com/apps/erpnext) +- [Exact](https://pipedream.com/apps/exact) +- [Freshdesk](https://pipedream.com/apps/freshdesk) +- [Google Cloud](https://pipedream.com/apps/google-cloud) +- [Gorgias](https://pipedream.com/apps/gorgias-oauth) - [HubSpot](https://pipedream.com/apps/hubspot) - [Intercom](https://pipedream.com/apps/intercom) +- [Jira](https://pipedream.com/apps/jira) +- [Jira Service Desk](https://pipedream.com/apps/jira-service-desk) - [Klaviyo](https://pipedream.com/apps/klaviyo) - [Linkedin](https://pipedream.com/apps/linkedin) +- [Linkedin Ads](https://pipedream.com/apps/linkedin-ads) +- [Mailchimp](https://pipedream.com/apps/mailchimp) - [Mailgun](https://pipedream.com/apps/mailgun) +- [MongoDB](https://pipedream.com/apps/mongodb) +- [Outreach](https://pipedream.com/apps/outreach) +- [PagerDuty](https://pipedream.com/apps/pagerduty) - [Pipedrive](https://pipedream.com/apps/pipedrive) - [Pipefy](https://pipedream.com/apps/pipefy) +- [Propeller](https://pipedream.com/apps/propeller) - [Quickbooks](https://pipedream.com/apps/quickbooks) +- [Rebrandly](https://pipedream.com/apps/rebrandly) - [ReCharge](https://pipedream.com/apps/recharge) - [Salesforce (REST API)](https://pipedream.com/apps/salesforce_rest_api) +- [Segment](https://pipedream.com/apps/segment) - [SendinBlue](https://pipedream.com/apps/sendinblue) - [ServiceNow](https://pipedream.com/apps/servicenow) +- [ShipStation](https://pipedream.com/apps/shipstation) +- [Shopify](https://pipedream.com/apps/shopify) - [Snowflake](https://pipedream.com/apps/snowflake) +- [Stripe](https://pipedream.com/apps/stripe) - [Twilio SendGrid](https://pipedream.com/apps/sendgrid) +- [WhatsApp Business](https://pipedream.com/apps/whatsapp-business) +- [WooCommerce](https://pipedream.com/apps/woocommerce) - [Xero Accounting](https://pipedream.com/apps/xero_accounting_api) - [Zendesk](https://pipedream.com/apps/zendesk) +- [Zoom Admin](https://pipedream.com/apps/zoom_admin) - [Zoho Books](https://pipedream.com/apps/zoho_books) - [Zoho CRM](https://pipedream.com/apps/zoho_crm) -- [Zoom Admin](https://pipedream.com/apps/zoom_admin) +- [Zoho People](https://pipedream.com/apps/zoho_people) +- [Zoho SalesIQ](https://pipedream.com/apps/zoho_salesiq)

diff --git a/docs/docs/pricing/README.md b/docs/docs/pricing/README.md index e29f8f154ecbf..3c2c0a088e8ed 100644 --- a/docs/docs/pricing/README.md +++ b/docs/docs/pricing/README.md @@ -7,7 +7,7 @@ next: false We believe anyone should be able to run simple, low-volume workflows at no cost. We also hope that you share your [sources](/components#sources), [workflows](/workflows), [actions](/components#actions), and other integration components so that other Pipedream users benefit from your work. -To support these goals, **Pipedream offers a [free trial of our Advanced plan](#free-trial) and a generous [free tier](#free-tier)**. You can run sources and workflows for free within the limits of the free tier. If you hit these limits, you can upgrade to one of our [paid tiers](#paid-tiers). +To support these goals, Pipedream offers a generous [free tier](#free-tier), and you can **[request a free trial of our Advanced or Business plan](https://pipedream.com/pricing)**. You can run sources and workflows for free within the limits of the free tier. If you hit these limits, you can upgrade to one of our [paid tiers](#paid-tiers). [Read more about our plans and pricing here](https://pipedream.com/pricing). diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4d6e5c54ef0b9..197f8d92af03f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -240,6 +240,9 @@ importers: dependencies: algoliasearch: 4.20.0 + components/algomo: + specifiers: {} + components/alpaca: specifiers: '@pipedream/platform': ^1.1.1 @@ -797,6 +800,9 @@ importers: components/census_bureau: specifiers: {} + components/centralstationcrm: + specifiers: {} + components/cflow: specifiers: {} @@ -896,6 +902,9 @@ importers: dependencies: '@pipedream/platform': 1.5.1 + components/click2mail2: + specifiers: {} + components/clickfunnels: specifiers: {} @@ -1039,6 +1048,9 @@ importers: components/college_football_data: specifiers: {} + components/cometly: + specifiers: {} + components/commcare: specifiers: {} @@ -4805,6 +4817,9 @@ importers: dependencies: '@pipedream/platform': 1.5.1 + components/riskadvisor: + specifiers: {} + components/rkvst: specifiers: {} @@ -6463,6 +6478,9 @@ importers: components/webscraping_ai: specifiers: {} + components/webvizio: + specifiers: {} + components/weglot: specifiers: '@pipedream/platform': ^1.5.1 From 487fca82a77f30d0233741fc145ead1964d71c38 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Oct 2023 09:37:22 -0300 Subject: [PATCH 060/186] Bump actions/checkout from 4.1.0 to 4.1.1 (#8564) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.0 to 4.1.1. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.1.0...v4.1.1) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docs.yaml | 2 +- .github/workflows/publish-components.yaml | 4 ++-- .github/workflows/publish-marketplace-content.yaml | 2 +- .github/workflows/publish-packages.yaml | 2 +- .github/workflows/pull-request-checks.yaml | 12 ++++++------ 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 64761ad36101e..b69e9b6171497 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.0 + - uses: actions/checkout@v4.1.1 name: Checkout repo with: # See https://github.com/actions/checkout#checkout-v2 diff --git a/.github/workflows/publish-components.yaml b/.github/workflows/publish-components.yaml index a87db198f25b4..ba4df6c13e7f0 100644 --- a/.github/workflows/publish-components.yaml +++ b/.github/workflows/publish-components.yaml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v4.1.0 + uses: actions/checkout@v4.1.1 - uses: pnpm/action-setup@v2.4.0 with: version: 7.33.6 @@ -115,7 +115,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4.1.0 + uses: actions/checkout@v4.1.1 - uses: pnpm/action-setup@v2.4.0 with: version: 7.33.6 diff --git a/.github/workflows/publish-marketplace-content.yaml b/.github/workflows/publish-marketplace-content.yaml index 2989f76dc4c83..f4e5da59bf681 100644 --- a/.github/workflows/publish-marketplace-content.yaml +++ b/.github/workflows/publish-marketplace-content.yaml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v4.1.0 + uses: actions/checkout@v4.1.1 - uses: pnpm/action-setup@v2.4.0 with: version: 7.33.6 diff --git a/.github/workflows/publish-packages.yaml b/.github/workflows/publish-packages.yaml index 4fcb63dee6fe4..bab468a2e947a 100644 --- a/.github/workflows/publish-packages.yaml +++ b/.github/workflows/publish-packages.yaml @@ -8,7 +8,7 @@ jobs: publish: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.0 + - uses: actions/checkout@v4.1.1 - uses: pnpm/action-setup@v2.4.0 with: version: 7.33.6 diff --git a/.github/workflows/pull-request-checks.yaml b/.github/workflows/pull-request-checks.yaml index 597834df12de4..d8af07c0f682c 100644 --- a/.github/workflows/pull-request-checks.yaml +++ b/.github/workflows/pull-request-checks.yaml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.0 + - uses: actions/checkout@v4.1.1 name: Checkout repo with: # See https://github.com/actions/checkout#checkout-v2 @@ -45,7 +45,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.0 + - uses: actions/checkout@v4.1.1 name: Checkout - uses: jitterbit/get-changed-files@v1 id: changed_files @@ -77,7 +77,7 @@ jobs: steps: - name: Checkout Code - uses: actions/checkout@v4.1.0 + uses: actions/checkout@v4.1.1 with: # Full git history is needed to get a proper list of changed files # within `super-linter` @@ -133,7 +133,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.0 + - uses: actions/checkout@v4.1.1 - uses: pnpm/action-setup@v2.4.0 with: version: 7.33.6 @@ -167,7 +167,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4.1.0 + uses: actions/checkout@v4.1.1 - uses: pnpm/action-setup@v2.4.0 with: version: 7.33.6 @@ -256,7 +256,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4.1.0 + uses: actions/checkout@v4.1.1 - uses: pnpm/action-setup@v2.4.0 with: version: 7.33.6 From 9df19e7fa408ffe90889e9912efb9f222312476c Mon Sep 17 00:00:00 2001 From: Luan Cazarine Date: Tue, 24 Oct 2023 10:26:29 -0300 Subject: [PATCH 061/186] 8497 components copperx (#8542) * [Components] Copperx #8497 Triggers - Invoice Paid - Customer Subscription Created Actions - Create invoice - Create customer * pnpm update --- .../create-customer/create-customer.mjs | 178 ++++++++++++++++++ .../actions/create-invoice/create-invoice.mjs | 97 ++++++++++ components/copperx/common/utils.mjs | 30 +++ components/copperx/copperx.app.mjs | 81 +++++++- components/copperx/package.json | 7 +- components/copperx/sources/common/base.mjs | 51 +++++ .../customer-subscription-created.mjs | 23 +++ .../test-event.mjs | 19 ++ .../sources/invoice-paid/invoice-paid.mjs | 23 +++ .../sources/invoice-paid/test-event.mjs | 23 +++ pnpm-lock.yaml | 5 +- 11 files changed, 529 insertions(+), 8 deletions(-) create mode 100644 components/copperx/actions/create-customer/create-customer.mjs create mode 100644 components/copperx/actions/create-invoice/create-invoice.mjs create mode 100644 components/copperx/common/utils.mjs create mode 100644 components/copperx/sources/common/base.mjs create mode 100644 components/copperx/sources/customer-subscription-created/customer-subscription-created.mjs create mode 100644 components/copperx/sources/customer-subscription-created/test-event.mjs create mode 100644 components/copperx/sources/invoice-paid/invoice-paid.mjs create mode 100644 components/copperx/sources/invoice-paid/test-event.mjs diff --git a/components/copperx/actions/create-customer/create-customer.mjs b/components/copperx/actions/create-customer/create-customer.mjs new file mode 100644 index 0000000000000..c3bfce8e0be90 --- /dev/null +++ b/components/copperx/actions/create-customer/create-customer.mjs @@ -0,0 +1,178 @@ +import copperx from "../../copperx.app.mjs"; + +export default { + key: "copperx-create-customer", + name: "Create Customer", + version: "0.0.1", + description: "Create a new customer [See the documentation](https://copperx.readme.io/reference/customercontroller_create)", + type: "action", + props: { + copperx, + email: { + type: "string", + label: "Email", + description: "The customer's email.", + }, + name: { + type: "string", + label: "Name", + description: "The customer's name.", + optional: true, + }, + phone: { + type: "string", + label: "Phone", + description: "The customer's phone.", + optional: true, + }, + addressLine1: { + type: "string", + label: "Address Line 1", + description: "The customer's address line 1.", + }, + addressLine2: { + type: "string", + label: "Address Line 2", + description: "The customer's address line 2.", + optional: true, + }, + addressCity: { + type: "string", + label: "City", + description: "The city of the customer's address.", + }, + addressState: { + type: "string", + label: "State", + description: "The state of the customer's address.", + }, + addressPostalCode: { + type: "string", + label: "Postal Code", + description: "The postal code of the customer's address.", + }, + addressCountry: { + type: "string", + label: "Country", + description: "The country of the customer's address.", + }, + customerReferenceId: { + type: "string", + label: "Customer Reference Id.", + description: "The customer's reference Id.", + optional: true, + }, + shippingAddressName: { + type: "string", + label: "Shipping Address Name", + description: "The name of the shipping address receiver.", + optional: true, + }, + shippingAddressEmail: { + type: "string", + label: "Shipping Address Email", + description: "The email of the shipping address.", + optional: true, + }, + shippingAddressPhone: { + type: "string", + label: "Shipping Address Phone", + description: "The phone of the shipping address.", + optional: true, + }, + shippingAddressLine1: { + type: "string", + label: "Shipping Address Line 1", + description: "The shipping address line 1.", + optional: true, + }, + shippingAddressLine2: { + type: "string", + label: "Shipping Address Line 2", + description: "The shipping address line 2.", + optional: true, + }, + shippingAddressCity: { + type: "string", + label: "Shipping Address City", + description: "The city of the shipping address.", + optional: true, + }, + shippingAddressState: { + type: "string", + label: "Shipping Address State", + description: "The state of the shipping address.", + optional: true, + }, + shippingAddressPostalCode: { + type: "string", + label: "Shipping Address Postal Code", + description: "The postal code of the shipping address.", + optional: true, + }, + shippingAddressCountry: { + type: "string", + label: "Shipping Address Country", + description: "The country of the shipping address.", + optional: true, + }, + metadata: { + type: "object", + label: "Metadata", + description: "Customer's metadata.", + optional: true, + }, + }, + async run({ $ }) { + const { + copperx, + addressLine1, + addressLine2, + addressCity, + addressState, + addressPostalCode, + addressCountry, + shippingAddressName, + shippingAddressEmail, + shippingAddressPhone, + shippingAddressLine1, + shippingAddressLine2, + shippingAddressCity, + shippingAddressState, + shippingAddressPostalCode, + shippingAddressCountry, + ...data + } = this; + + const response = await copperx.createCustomer({ + $, + data: { + "address": { + "line1": addressLine1, + "line2": addressLine2, + "country": addressCountry, + "postalCode": addressPostalCode, + "state": addressState, + "city": addressCity, + }, + "shipping": { + "address": { + "country": shippingAddressCountry, + "postalCode": shippingAddressPostalCode, + "state": shippingAddressState, + "city": shippingAddressCity, + "line2": shippingAddressLine2, + "line1": shippingAddressLine1, + }, + "phone": shippingAddressPhone, + "email": shippingAddressEmail, + "name": shippingAddressName, + }, + ...data, + }, + }); + + $.export("$summary", `A new customer with Id: ${response.id} was successfully created!`); + return response; + }, +}; diff --git a/components/copperx/actions/create-invoice/create-invoice.mjs b/components/copperx/actions/create-invoice/create-invoice.mjs new file mode 100644 index 0000000000000..21c1f1bc3980d --- /dev/null +++ b/components/copperx/actions/create-invoice/create-invoice.mjs @@ -0,0 +1,97 @@ +import { + objectToArray, parseString, +} from "../../common/utils.mjs"; +import copperx from "../../copperx.app.mjs"; + +export default { + key: "copperx-create-invoice", + name: "Create Invoice", + version: "0.0.1", + description: "Create a new invoice [See the documentation](https://copperx.readme.io/reference/invoicecontroller_create)", + type: "action", + props: { + copperx, + description: { + type: "string", + label: "Description", + description: "The invoice's description.", + optional: true, + }, + customFields: { + type: "object", + label: "Custom Fields", + description: "The invoice's custom fields.", + optional: true, + }, + dueDate: { + type: "string", + label: "Due Date", + description: "The invoice's due date.", + optional: true, + }, + footer: { + type: "string", + label: "Footer", + description: "The additional invoice's footer.", + optional: true, + }, + fromInvoiceId: { + type: "string", + label: "From Invoice Id", + description: "The invoice Id of this invoice is from.", + optional: true, + }, + metadata: { + type: "object", + label: "Metadata", + description: "The additional invoice's metadata.", + optional: true, + }, + clientReferenceId: { + type: "string", + label: "Client Reference Id.", + description: "The client's reference Id.", + optional: true, + }, + customerId: { + propDefinition: [ + copperx, + "customerId", + ], + optional: true, + }, + lineItems: { + type: "string", + label: "Line Items", + description: "The line items to be used in checkout session [See the documentation to further information about the Line Items object](https://copperx.readme.io/reference/invoicecontroller_create).", + }, + paymentSetting: { + type: "string", + label: "Payment Setting", + description: "The list of chains allowed for the payment. If not provided, all chains supported by the organization are enabled. [See the documentation to further information about the Payment Settings object](https://copperx.readme.io/reference/invoicecontroller_create).", + optional: true, + }, + }, + async run({ $ }) { + const { + copperx, + customFields, + lineItems, + paymentSetting, + ...data + } = this; + + const response = await copperx.createInvoice({ + $, + data: { + customFields: customFields && objectToArray(customFields), + lineItems: lineItems && parseString(lineItems), + paymentSetting: paymentSetting && parseString(paymentSetting), + ...data, + }, + }); + + $.export("$summary", `A new invoice with Id: ${response.id} was successfully created!`); + return response; + }, +}; diff --git a/components/copperx/common/utils.mjs b/components/copperx/common/utils.mjs new file mode 100644 index 0000000000000..aa8a90cfc4c07 --- /dev/null +++ b/components/copperx/common/utils.mjs @@ -0,0 +1,30 @@ +import { ConfigurationError } from "@pipedream/platform"; + +export const objectToArray = (obj) => { + const objArray = []; + obj = parseString(obj); + + if (Object.entries(obj).length) { + for (const [ + key, + value, + ] of Object.entries(obj)) { + objArray.push({ + name: key, + value: value, + }); + } + } + return objArray; +}; + +export const parseString = (str) => { + try { + if (typeof str === "string") { + return JSON.parse(str); + } + return str; + } catch (e) { + throw new ConfigurationError(e); + } +}; diff --git a/components/copperx/copperx.app.mjs b/components/copperx/copperx.app.mjs index 43472a7e7ebcf..c15645ca8beac 100644 --- a/components/copperx/copperx.app.mjs +++ b/components/copperx/copperx.app.mjs @@ -1,11 +1,82 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "copperx", - propDefinitions: {}, + propDefinitions: { + customerId: { + type: "string", + label: "Customer Id", + description: "The id of the customer the invoice is for.", + async options({ page }) { + const { data } = await this.listCustomers({ + params: { + page: page + 1, + }, + }); + + return data.map(({ + id: value, name: label, + }) => ({ + label, + value, + })); + }, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _apiUrl() { + return `https://${this.$auth.environment}/api/v1`; + }, + _getHeaders() { + return { + "Authorization": `Bearer ${this.$auth.api_key}`, + "accept": "application/json", + }; + }, + _makeRequest({ + $ = this, path, ...opts + }) { + const config = { + url: `${this._apiUrl()}/${path}`, + headers: this._getHeaders(), + ...opts, + }; + + return axios($, config); + }, + createCustomer(args = {}) { + return this._makeRequest({ + method: "POST", + path: "customers", + ...args, + }); + }, + createHook(args = {}) { + return this._makeRequest({ + method: "POST", + path: "webhook-endpoints", + ...args, + }); + }, + createInvoice(args = {}) { + return this._makeRequest({ + method: "POST", + path: "invoices", + ...args, + }); + }, + deleteHook(hookId) { + return this._makeRequest({ + method: "DELETE", + path: `webhook-endpoints/${hookId}`, + }); + }, + listCustomers(args = {}) { + return this._makeRequest({ + path: "customers", + ...args, + }); }, }, -}; \ No newline at end of file +}; diff --git a/components/copperx/package.json b/components/copperx/package.json index 845e136aae561..ac0a2fd126e03 100644 --- a/components/copperx/package.json +++ b/components/copperx/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/copperx", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Copperx Components", "main": "copperx.app.mjs", "keywords": [ @@ -11,5 +11,8 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^1.5.1" } -} \ No newline at end of file +} diff --git a/components/copperx/sources/common/base.mjs b/components/copperx/sources/common/base.mjs new file mode 100644 index 0000000000000..5d289dc610ccf --- /dev/null +++ b/components/copperx/sources/common/base.mjs @@ -0,0 +1,51 @@ +import copperx from "../../copperx.app.mjs"; + +export default { + dedupe: "unique", + props: { + copperx, + http: "$.interface.http", + db: "$.service.db", + }, + hooks: { + async activate() { + const data = await this.copperx.createHook({ + data: { + description: "Pipedream-customer-subscription-created", + url: this.http.endpoint, + enabledEvents: { + events: this.getEvent(), + }, + }, + }); + + this._setHookId(data.id); + }, + async deactivate() { + const id = this._getHookId("hookId"); + await this.copperx.deleteHook(id); + }, + }, + methods: { + emitEvent(body) { + const meta = this.generateMeta(body); + this.$emit(body, meta); + }, + _getHookId() { + return this.db.get("hookId"); + }, + _setHookId(hookId) { + this.db.set("hookId", hookId); + }, + generateMeta({ id }) { + return { + id, + summary: this.getSummary(id), + ts: new Date(), + }; + }, + }, + async run({ body }) { + this.emitEvent(body); + }, +}; diff --git a/components/copperx/sources/customer-subscription-created/customer-subscription-created.mjs b/components/copperx/sources/customer-subscription-created/customer-subscription-created.mjs new file mode 100644 index 0000000000000..fcc05f15c1e45 --- /dev/null +++ b/components/copperx/sources/customer-subscription-created/customer-subscription-created.mjs @@ -0,0 +1,23 @@ +import common from "../common/base.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + ...common, + key: "copperx-customer-subscription-created", + name: "New Customer Subscription Created (Instant)", + description: "Emit new event when a new customer subcription is created.", + version: "0.0.1", + type: "source", + methods: { + ...common.methods, + getEvent() { + return [ + "customer.subscription.created", + ]; + }, + getSummary(id) { + return `A new customer subscription with id: ${id} was created!`; + }, + }, + sampleEmit, +}; diff --git a/components/copperx/sources/customer-subscription-created/test-event.mjs b/components/copperx/sources/customer-subscription-created/test-event.mjs new file mode 100644 index 0000000000000..d8cad642d35b8 --- /dev/null +++ b/components/copperx/sources/customer-subscription-created/test-event.mjs @@ -0,0 +1,19 @@ +export default { + id: 'fdc5e9fb-52f8-4604-a8ec-0575c6996fa4', + apiVersion: '2023-01-11', + created: 1697735629533, + object: 'webhookEndpoint', + type: 'webhook_endpoint_test', + data: { + object: { + id: '366ff7e6-32af-4e2b-a94e-c6e8cab37762', + description: 'Pipedream-customer-subscription-created', + url: 'https://8d40d4079384e2e1ddd64e7af5fbd4b4.m.pipedream.net', + secret: 'wh_k8rxkaWJ0YN9kQGsqqb2lMNVQGjXpeEcwVIRNnvDJ0PleZwMhCXUepV8sg5zVjN6', + createdAt: '2023-10-19T17:13:30.922Z', + updatedAt: '2023-10-19T17:13:30.922Z', + enabledEvents: [Object], + isDisabled: false + } + } +} \ No newline at end of file diff --git a/components/copperx/sources/invoice-paid/invoice-paid.mjs b/components/copperx/sources/invoice-paid/invoice-paid.mjs new file mode 100644 index 0000000000000..509987818247e --- /dev/null +++ b/components/copperx/sources/invoice-paid/invoice-paid.mjs @@ -0,0 +1,23 @@ +import common from "../common/base.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + ...common, + key: "copperx-invoice-paid", + name: "New Invoice Paid (Instant)", + description: "Emit new event when an invoice is paid.", + version: "0.0.1", + type: "source", + methods: { + ...common.methods, + getEvent() { + return [ + "invoice.marked_as_paid", + ]; + }, + getSummary(id) { + return `A new payment with id: ${id} was created!`; + }, + }, + sampleEmit, +}; diff --git a/components/copperx/sources/invoice-paid/test-event.mjs b/components/copperx/sources/invoice-paid/test-event.mjs new file mode 100644 index 0000000000000..4c64aea1c0741 --- /dev/null +++ b/components/copperx/sources/invoice-paid/test-event.mjs @@ -0,0 +1,23 @@ +export default { + "id": "088fbde6-6464-486e-815d-a00734f213fb", + "apiVersion": "2023-01-11", + "created": 1697735924778, + "object": "webhookEndpoint", + "type": "webhook_endpoint_test", + "data": { + "object": { + "id": "3e2b5a91-521b-44ad-836e-e9bf44892a14", + "description": "Pipedream-customer-subscription-created", + "url": "https://e37d5e73f3b01d2043c1fa2f31a24875.m.pipedream.net", + "secret": "wh_NMDGsudIDW2AQ91TGEDQYzFIlWZSqdubyrgUQoVTBcjMh1j2vWPF7lPXm5w22vWq", + "createdAt": "2023-10-19T17:18:20.697Z", + "updatedAt": "2023-10-19T17:18:20.697Z", + "enabledEvents": { + "events": [ + "invoice.marked_as_paid" + ] + }, + "isDisabled": false + } + } +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 197f8d92af03f..ed72e43bac7ee 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1108,7 +1108,10 @@ importers: specifiers: {} components/copperx: - specifiers: {} + specifiers: + '@pipedream/platform': ^1.5.1 + dependencies: + '@pipedream/platform': 1.5.1 components/corrently: specifiers: {} From 04804e457ddca79a661bb832e3f9ca208d577fe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilherme=20Falc=C3=A3o?= <48412907+GTFalcao@users.noreply.github.com> Date: Tue, 24 Oct 2023 10:35:18 -0300 Subject: [PATCH 062/186] Formbricks new components (#8543) * Initial AI code generation * App file adjustments * Adjustments and webhook creation/deletion hooks * "Response Created" adjustments and event emitting * Payload format adjustments * pnpm * package update * pnpm --- components/formbricks/formbricks.app.mjs | 60 ++++++++++++++-- components/formbricks/package.json | 7 +- .../response-created/response-created.mjs | 71 +++++++++++++++++++ pnpm-lock.yaml | 5 +- 4 files changed, 135 insertions(+), 8 deletions(-) create mode 100644 components/formbricks/sources/response-created/response-created.mjs diff --git a/components/formbricks/formbricks.app.mjs b/components/formbricks/formbricks.app.mjs index 6cbc6e4c683c1..e82889e624277 100644 --- a/components/formbricks/formbricks.app.mjs +++ b/components/formbricks/formbricks.app.mjs @@ -1,11 +1,61 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "formbricks", - propDefinitions: {}, + propDefinitions: { + surveyIds: { + type: "string[]", + label: "Survey IDs", + description: "The survey(s) to watch for new responses. If not provided, events will be triggered for all surveys.", + async options() { + const surveys = await this.listSurveys(); + return surveys.map(({ + id, name, + }) => ({ + label: name, + value: id, + })); + }, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + async _makeRequest({ + $ = this, + headers, + ...otherOpts + }) { + return axios($, { + ...otherOpts, + baseURL: `https://${this.$auth.hostname}/api/v1`, + headers: { + ...headers, + "x-api-key": this.$auth.api_key, + }, + }); + }, + async listSurveys() { + const { data } = await this._makeRequest({ + url: "/management/surveys", + }); + return data; + }, + async createWebhook(args) { + const { data } = await this._makeRequest({ + method: "POST", + url: "/webhooks", + ...args, + }); + return data; + }, + async deleteWebhook({ + id, ...args + }) { + return this._makeRequest({ + method: "DELETE", + url: `/webhooks/${id}`, + ...args, + }); }, }, -}; \ No newline at end of file +}; diff --git a/components/formbricks/package.json b/components/formbricks/package.json index d328ee16a8656..9207d4e6a4c3c 100644 --- a/components/formbricks/package.json +++ b/components/formbricks/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/formbricks", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Formbricks Components", "main": "formbricks.app.mjs", "keywords": [ @@ -11,5 +11,8 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^1.5.1" } -} \ No newline at end of file +} diff --git a/components/formbricks/sources/response-created/response-created.mjs b/components/formbricks/sources/response-created/response-created.mjs new file mode 100644 index 0000000000000..2426ea1d2b534 --- /dev/null +++ b/components/formbricks/sources/response-created/response-created.mjs @@ -0,0 +1,71 @@ +import formbricks from "../../formbricks.app.mjs"; + +export default { + key: "formbricks-response-created", + name: "Response Created", + description: + "Emit new event when a response is created for a survey. [See the documentation](https://formbricks.com/docs/api/management/webhooks)", + version: "0.0.1", + type: "source", + dedupe: "unique", + props: { + formbricks, + http: "$.interface.http", + db: "$.service.db", + surveyIds: { + propDefinition: [ + formbricks, + "surveyIds", + ], + }, + }, + methods: { + getTriggers() { + return [ + "responseCreated", + ]; + }, + _getWebhookId() { + return this.db.get("webhookId"); + }, + _setWebhookId(value) { + this.db.set("webhookId", value); + }, + }, + hooks: { + async activate() { + const data = { + surveyIds: this.surveyIds, + triggers: this.getTriggers(), + url: this.http.endpoint, + }; + + const { id } = await this.formbricks.createWebhook({ + data, + }); + this._setWebhookId(id); + }, + async deactivate() { + const id = this._getWebhookId(); + if (id) { + await this.formbricks.deleteWebhook({ + id, + }); + } + }, + }, + async run({ body }) { + const { data } = body; + if (data) { + this.$emit(body, { + id: data.id, + summary: `New response by ${ + data.personAttributes?.email ?? + data.person?.attributes?.email ?? + "(unknown user)" + }`, + ts: Date.parse(data.createdAt), + }); + } + }, +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ed72e43bac7ee..6a2ac82488c55 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1851,7 +1851,10 @@ importers: title-case: 3.0.3 components/formbricks: - specifiers: {} + specifiers: + '@pipedream/platform': ^1.5.1 + dependencies: + '@pipedream/platform': 1.5.1 components/formdesk: specifiers: {} From 6a73949e3d176d3a8df056433db86f18f45c0585 Mon Sep 17 00:00:00 2001 From: michelle0927 Date: Tue, 24 Oct 2023 07:10:46 -0700 Subject: [PATCH 063/186] Poof - New Components (#8525) * new components * pnpm-lock.yaml --- .../create-deposit-address.mjs | 37 +++++++++++++ .../list-transactions/list-transactions.mjs | 21 ++++++++ .../send-transaction/send-transaction.mjs | 43 +++++++++++++++ components/poof/package.json | 7 ++- components/poof/poof.app.mjs | 52 +++++++++++++++++-- components/poof/sources/common/base.mjs | 32 ++++++++++++ components/poof/sources/common/constants.mjs | 13 +++++ .../new-payment-made/new-payment-made.mjs | 46 ++++++++++++++++ pnpm-lock.yaml | 5 +- 9 files changed, 248 insertions(+), 8 deletions(-) create mode 100644 components/poof/actions/create-deposit-address/create-deposit-address.mjs create mode 100644 components/poof/actions/list-transactions/list-transactions.mjs create mode 100644 components/poof/actions/send-transaction/send-transaction.mjs create mode 100644 components/poof/sources/common/base.mjs create mode 100644 components/poof/sources/common/constants.mjs create mode 100644 components/poof/sources/new-payment-made/new-payment-made.mjs diff --git a/components/poof/actions/create-deposit-address/create-deposit-address.mjs b/components/poof/actions/create-deposit-address/create-deposit-address.mjs new file mode 100644 index 0000000000000..8c958f31a2fb7 --- /dev/null +++ b/components/poof/actions/create-deposit-address/create-deposit-address.mjs @@ -0,0 +1,37 @@ +import poof from "../../poof.app.mjs"; + +export default { + key: "poof-create-deposit-address", + name: "Create Deposit Address", + description: "Creates a new deposit address in Poof. [See the documentation](https://docs.poof.io/reference/create_address)", + version: "0.0.1", + type: "action", + props: { + poof, + amount: { + type: "string", + label: "Amount", + description: "The transaction amount", + }, + crypto: { + type: "string", + label: "Crypto", + description: "The type of cryptocurrency. Example: `bitcoin`", + }, + }, + async run({ $ }) { + const response = await this.poof.createDepositAddress({ + data: { + amount: +this.amount, + crypto: this.crypto, + }, + $, + }); + + if (response?.address) { + $.export("$summary", `Successfully created deposit address ${response.address}.`); + } + + return response; + }, +}; diff --git a/components/poof/actions/list-transactions/list-transactions.mjs b/components/poof/actions/list-transactions/list-transactions.mjs new file mode 100644 index 0000000000000..3115a29c0e55a --- /dev/null +++ b/components/poof/actions/list-transactions/list-transactions.mjs @@ -0,0 +1,21 @@ +import poof from "../../poof.app.mjs"; + +export default { + key: "poof-list-transactions", + name: "List Transactions", + description: "Retrieve a list of transactions in Poof. [See the documentation](https://docs.poof.io/reference/fetch-transaction-list)", + version: "0.0.1", + type: "action", + props: { + poof, + }, + async run({ $ }) { + const response = await this.poof.listTransactions({ + $, + }); + + $.export("$summary", "Successfully retrieved transactions."); + + return response; + }, +}; diff --git a/components/poof/actions/send-transaction/send-transaction.mjs b/components/poof/actions/send-transaction/send-transaction.mjs new file mode 100644 index 0000000000000..53ae2a0627a15 --- /dev/null +++ b/components/poof/actions/send-transaction/send-transaction.mjs @@ -0,0 +1,43 @@ +import poof from "../../poof.app.mjs"; + +export default { + key: "poof-send-transaction", + name: "Send Transaction", + description: "Sends a transaction in Poof. [See the documentation](https://docs.poof.io/reference/sendtransaction)", + version: "0.0.1", + type: "action", + props: { + poof, + amount: { + type: "string", + label: "Amount", + description: "The transaction amount", + }, + crypto: { + type: "string", + label: "Crypto", + description: "The type of cryptocurrency. Example: `bitcoin`", + }, + address: { + type: "string", + label: "Address", + description: "The address to send the transaction to", + }, + }, + async run({ $ }) { + const response = await this.poof.sendTransaction({ + data: { + amount: +this.amount, + crypto: this.crypto, + address: this.address, + }, + $, + }); + + if (response?.message !== "invalid") { + $.export("$summary", "Successfully sent transaction."); + } + + return response; + }, +}; diff --git a/components/poof/package.json b/components/poof/package.json index c95d406448c55..70dad0c610542 100644 --- a/components/poof/package.json +++ b/components/poof/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/poof", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Poof Components", "main": "poof.app.mjs", "keywords": [ @@ -11,5 +11,8 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^1.5.1" } -} \ No newline at end of file +} diff --git a/components/poof/poof.app.mjs b/components/poof/poof.app.mjs index 6a300d036b7de..5380ef63e38e1 100644 --- a/components/poof/poof.app.mjs +++ b/components/poof/poof.app.mjs @@ -1,11 +1,53 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "poof", - propDefinitions: {}, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _baseUrl() { + return "https://www.poof.io/api"; + }, + _headers() { + return { + "Authorization": `${this.$auth.api_key}`, + "Content-Type": "application/json", + }; + }, + _makeRequest({ + $ = this, + path, + ...args + }) { + return axios($, { + url: `${this._baseUrl()}${path}`, + headers: this._headers(), + method: "POST", + ...args, + }); + }, + createWebhook(args = {}) { + return this._makeRequest({ + path: "/v1/create_webhook", + ...args, + }); + }, + listTransactions(args = {}) { + return this._makeRequest({ + path: "/v1/fetch_transactions", + ...args, + }); + }, + createDepositAddress(args = {}) { + return this._makeRequest({ + path: "/v2/create_charge", + ...args, + }); + }, + sendTransaction(args = {}) { + return this._makeRequest({ + path: "/v2/payouts", + ...args, + }); }, }, -}; \ No newline at end of file +}; diff --git a/components/poof/sources/common/base.mjs b/components/poof/sources/common/base.mjs new file mode 100644 index 0000000000000..23f97af5f211d --- /dev/null +++ b/components/poof/sources/common/base.mjs @@ -0,0 +1,32 @@ +import poof from "../../poof.app.mjs"; + +export default { + props: { + poof, + http: "$.interface.http", + }, + hooks: { + async deploy() { + await this.poof.createWebhook({ + data: { + url: this.http.endpoint, + }, + }); + }, + }, + methods: { + isRelevant() { + return true; + }, + generateMeta() { + throw new Error("generateMeta is not implemented"); + }, + }, + async run(event) { + const { body } = event; + if (this.isRelevant(body)) { + const meta = this.generateMeta(body); + this.$emit(body, meta); + } + }, +}; diff --git a/components/poof/sources/common/constants.mjs b/components/poof/sources/common/constants.mjs new file mode 100644 index 0000000000000..14db412e4bfed --- /dev/null +++ b/components/poof/sources/common/constants.mjs @@ -0,0 +1,13 @@ +const PAYMENT_TYPES = { + "yes": "Payment Complete", + "payout": "Crypto Payout Sent", + "paid_partial": "Crypto Payment Partially Paid", + "transfer_out": "Bank Transfer Sent", + "pending": "Payment Processing", + "transfer_in": "Bank Transfer/ Poof Balance Received", + "hold": "Third party payment method pending", +}; + +export default { + PAYMENT_TYPES, +}; diff --git a/components/poof/sources/new-payment-made/new-payment-made.mjs b/components/poof/sources/new-payment-made/new-payment-made.mjs new file mode 100644 index 0000000000000..77bac723feda0 --- /dev/null +++ b/components/poof/sources/new-payment-made/new-payment-made.mjs @@ -0,0 +1,46 @@ +import common from "../common/base.mjs"; +import constants from "../common/constants.mjs"; + +export default { + ...common, + key: "poof-new-payment-made", + name: "New Payment Made", + description: "Emit new events when a payment is made in Poof. [See the documentation](https://docs.poof.io/reference/notifications-api)", + version: "0.0.1", + type: "source", + dedupe: "unique", + props: { + ...common.props, + paymentTypes: { + type: "string[]", + label: "Payment Type(s)", + description: "Filter incoming events by payment type", + options() { + const paymentTypes = []; + for (const [ + key, + value, + ] of Object.entries(constants.PAYMENT_TYPES)) { + paymentTypes.push({ + value: key, + label: value, + }); + } + return paymentTypes; + }, + }, + }, + methods: { + ...common.methods, + isRelevant(payment) { + return this.paymentTypes.includes(payment.paid); + }, + generateMeta(payment) { + return { + id: payment.payment_id, + summary: `New ${constants.PAYMENT_TYPES[payment.paid]}`, + ts: Date.now(), + }; + }, + }, +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6a2ac82488c55..74e6a5b39c320 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4341,7 +4341,10 @@ importers: specifiers: {} components/poof: - specifiers: {} + specifiers: + '@pipedream/platform': ^1.5.1 + dependencies: + '@pipedream/platform': 1.5.1 components/popupsmart: specifiers: {} From 4df38b8728e1414276fe730fa9daf3938dca9f4f Mon Sep 17 00:00:00 2001 From: michelle0927 Date: Tue, 24 Oct 2023 07:13:14 -0700 Subject: [PATCH 064/186] enable customDatabaseUrl (#8570) --- .../actions/create-document/create-document.mjs | 2 +- .../create-realtime-db-record/create-realtime-db-record.mjs | 2 +- .../actions/list-documents/list-documents.mjs | 2 +- .../replicate-event-firestore/replicate-event-firestore.mjs | 2 +- .../actions/update-document/update-document.mjs | 2 +- components/firebase_admin_sdk/firebase_admin_sdk.app.mjs | 3 ++- components/firebase_admin_sdk/package.json | 2 +- .../sources/new-child-object/new-child-object.mjs | 2 +- .../new-doc-in-firestore-collection.mjs | 2 +- 9 files changed, 10 insertions(+), 9 deletions(-) diff --git a/components/firebase_admin_sdk/actions/create-document/create-document.mjs b/components/firebase_admin_sdk/actions/create-document/create-document.mjs index a0486adee7c3b..b210ec4951c1c 100644 --- a/components/firebase_admin_sdk/actions/create-document/create-document.mjs +++ b/components/firebase_admin_sdk/actions/create-document/create-document.mjs @@ -5,7 +5,7 @@ export default { key: "firebase_admin_sdk-create-document", name: "Create Document", description: "Creates a New Document. [See the docs here](https://googleapis.dev/nodejs/firestore/latest/CollectionReference.html#add)", - version: "0.0.6", + version: "0.0.7", type: "action", props: { ...common.props, diff --git a/components/firebase_admin_sdk/actions/create-realtime-db-record/create-realtime-db-record.mjs b/components/firebase_admin_sdk/actions/create-realtime-db-record/create-realtime-db-record.mjs index 71fd2f96d8ea5..147c5f63eb431 100644 --- a/components/firebase_admin_sdk/actions/create-realtime-db-record/create-realtime-db-record.mjs +++ b/components/firebase_admin_sdk/actions/create-realtime-db-record/create-realtime-db-record.mjs @@ -5,7 +5,7 @@ export default { key: "firebase_admin_sdk-create-realtime-db-record", name: "Create Firebase Realtime Database Record", description: "Creates or replaces a child object within your Firebase Realtime Database. [See the docs here](https://firebase.google.com/docs/reference/js/database#update)", - version: "0.0.3", + version: "0.0.4", type: "action", props: { ...common.props, diff --git a/components/firebase_admin_sdk/actions/list-documents/list-documents.mjs b/components/firebase_admin_sdk/actions/list-documents/list-documents.mjs index a8a7cd62ad6e5..23b1587ee2340 100644 --- a/components/firebase_admin_sdk/actions/list-documents/list-documents.mjs +++ b/components/firebase_admin_sdk/actions/list-documents/list-documents.mjs @@ -5,7 +5,7 @@ export default { key: "firebase_admin_sdk-list-documents", name: "List Documents", description: "Lists documents in a collection. [See the docs here](https://googleapis.dev/nodejs/firestore/latest/CollectionReference.html#listDocuments)", - version: "0.0.3", + version: "0.0.4", type: "action", props: { ...common.props, diff --git a/components/firebase_admin_sdk/actions/replicate-event-firestore/replicate-event-firestore.mjs b/components/firebase_admin_sdk/actions/replicate-event-firestore/replicate-event-firestore.mjs index b0ec2d5828b47..cacf5f186c533 100644 --- a/components/firebase_admin_sdk/actions/replicate-event-firestore/replicate-event-firestore.mjs +++ b/components/firebase_admin_sdk/actions/replicate-event-firestore/replicate-event-firestore.mjs @@ -6,7 +6,7 @@ export default { key: "firebase_admin_sdk-replicate-event-firestore", name: "Save Event to Firestore", description: "Replicate event in Firestore", - version: "0.4.3", + version: "0.4.4", type: "action", props: { firebase_admin_sdk: { diff --git a/components/firebase_admin_sdk/actions/update-document/update-document.mjs b/components/firebase_admin_sdk/actions/update-document/update-document.mjs index 92d8a73567b5a..4f14c8d495012 100644 --- a/components/firebase_admin_sdk/actions/update-document/update-document.mjs +++ b/components/firebase_admin_sdk/actions/update-document/update-document.mjs @@ -5,7 +5,7 @@ export default { key: "firebase_admin_sdk-update-document", name: "Update Documents", description: "Updates a Document. [See the docs here](https://googleapis.dev/nodejs/firestore/latest/DocumentReference.html#update)", - version: "0.0.3", + version: "0.0.4", type: "action", props: { ...common.props, diff --git a/components/firebase_admin_sdk/firebase_admin_sdk.app.mjs b/components/firebase_admin_sdk/firebase_admin_sdk.app.mjs index f948143059947..33df00e83c102 100644 --- a/components/firebase_admin_sdk/firebase_admin_sdk.app.mjs +++ b/components/firebase_admin_sdk/firebase_admin_sdk.app.mjs @@ -77,6 +77,7 @@ export default { projectId, clientEmail, privateKey, + customDatabaseUrl, } = this.$auth; const formattedPrivateKey = privateKey.replace(/\\n/g, "\n"); return admin.initializeApp({ @@ -85,7 +86,7 @@ export default { clientEmail, privateKey: formattedPrivateKey, }), - databaseURL: `https://${projectId}-default-rtdb.${region}/`, + databaseURL: customDatabaseUrl || `https://${projectId}-default-rtdb.${region}/`, }); }, /** diff --git a/components/firebase_admin_sdk/package.json b/components/firebase_admin_sdk/package.json index 3a4177c86301f..6c5b4f7472d96 100644 --- a/components/firebase_admin_sdk/package.json +++ b/components/firebase_admin_sdk/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/firebase_admin_sdk", - "version": "0.0.6", + "version": "0.0.7", "description": "Pipedream Firebase Admin SDK Components", "main": "firebase_admin_sdk.app.mjs", "keywords": [ diff --git a/components/firebase_admin_sdk/sources/new-child-object/new-child-object.mjs b/components/firebase_admin_sdk/sources/new-child-object/new-child-object.mjs index 3cd353ec1035c..d09a779ac8be5 100644 --- a/components/firebase_admin_sdk/sources/new-child-object/new-child-object.mjs +++ b/components/firebase_admin_sdk/sources/new-child-object/new-child-object.mjs @@ -5,7 +5,7 @@ export default { key: "firebase_admin_sdk-new-child-object", name: "New Child Object in a Realtime Database", description: "Emit new event when a new child object is discovered within a specific path", - version: "0.0.5", + version: "0.0.6", type: "source", dedupe: "unique", props: { diff --git a/components/firebase_admin_sdk/sources/new-doc-in-firestore-collection/new-doc-in-firestore-collection.mjs b/components/firebase_admin_sdk/sources/new-doc-in-firestore-collection/new-doc-in-firestore-collection.mjs index 7e225fe83af76..262d6d6827a52 100644 --- a/components/firebase_admin_sdk/sources/new-doc-in-firestore-collection/new-doc-in-firestore-collection.mjs +++ b/components/firebase_admin_sdk/sources/new-doc-in-firestore-collection/new-doc-in-firestore-collection.mjs @@ -5,7 +5,7 @@ export default { key: "firebase_admin_sdk-new-doc-in-firestore-collection", name: "New Document in Firestore Collection", description: "Emit new event when a structured query returns new documents", - version: "0.0.5", + version: "0.0.6", type: "source", dedupe: "unique", props: { From 7106f371db0079dc564e4b4d8a14c1d2bc1b6705 Mon Sep 17 00:00:00 2001 From: michelle0927 Date: Tue, 24 Oct 2023 07:16:11 -0700 Subject: [PATCH 065/186] Listmonk - New Components (#8541) * new components * pnpm-lock.yaml --- .../create-campaign/create-campaign.mjs | 93 ++++++++++++++++ .../actions/create-list/create-list.mjs | 53 +++++++++ .../create-subscriber/create-subscriber.mjs | 60 +++++++++++ components/listmonk/common/constants.mjs | 35 ++++++ components/listmonk/listmonk.app.mjs | 101 +++++++++++++++++- components/listmonk/package.json | 7 +- components/listmonk/sources/common/base.mjs | 72 +++++++++++++ .../new-subscriber-added.mjs | 24 +++++ pnpm-lock.yaml | 5 +- 9 files changed, 442 insertions(+), 8 deletions(-) create mode 100644 components/listmonk/actions/create-campaign/create-campaign.mjs create mode 100644 components/listmonk/actions/create-list/create-list.mjs create mode 100644 components/listmonk/actions/create-subscriber/create-subscriber.mjs create mode 100644 components/listmonk/common/constants.mjs create mode 100644 components/listmonk/sources/common/base.mjs create mode 100644 components/listmonk/sources/new-subscriber-added/new-subscriber-added.mjs diff --git a/components/listmonk/actions/create-campaign/create-campaign.mjs b/components/listmonk/actions/create-campaign/create-campaign.mjs new file mode 100644 index 0000000000000..1b9f6911fa619 --- /dev/null +++ b/components/listmonk/actions/create-campaign/create-campaign.mjs @@ -0,0 +1,93 @@ +import listmonk from "../../listmonk.app.mjs"; +import constants from "../../common/constants.mjs"; + +export default { + key: "listmonk-create-campaign", + name: "Create Campaign", + description: "Creates a new campaign in Listmonk. [See the documentation](https://listmonk.app/docs/apis/campaigns/#post-apicampaigns)", + version: "0.0.1", + type: "action", + props: { + listmonk, + name: { + type: "string", + label: "Campaign Name", + description: "The name of the campaign to create.", + }, + subject: { + type: "string", + label: "Subject", + description: "The subject of the campaign.", + }, + listIds: { + propDefinition: [ + listmonk, + "listIds", + ], + }, + type: { + type: "string", + label: "Type", + description: "The type of the campaign.", + options: constants.CAMPAIGN_TYPE_OPTIONS, + }, + contentType: { + type: "string", + label: "Content Type", + description: "The content type of the campaign.", + options: constants.CONTENT_TYPE_OPTIONS, + }, + body: { + type: "string", + label: "Body", + description: "The body of the campaign.", + }, + fromEmail: { + type: "string", + label: "From Email", + description: "From e-mail to show on the campaign e-mails. If left empty, the default value from settings is used.", + optional: true, + }, + tags: { + type: "string[]", + label: "Tags", + description: "Array of string tags to mark the campaign.", + optional: true, + }, + sendAt: { + type: "string", + label: "Send At", + description: "A timestamp to schedule the campaign at. Eg: 2021-12-25T06:00:00 (YYYY-MM-DDTHH:MM:SS)", + optional: true, + }, + templateId: { + propDefinition: [ + listmonk, + "templateId", + ], + }, + }, + async run({ $ }) { + const { data } = await this.listmonk.createCampaign({ + data: { + name: this.name, + subject: this.subject, + lists: this.listIds, + from_email: this.fromEmail, + type: this.type, + content_type: this.contentType, + body: this.body, + tags: this.tags, + send_at: this.sendAt, + template_id: this.templateId, + }, + $, + }); + + if (data?.id) { + $.export("$summary", `Successfully created campaign with ID ${data.id}.`); + } + + return data; + }, +}; diff --git a/components/listmonk/actions/create-list/create-list.mjs b/components/listmonk/actions/create-list/create-list.mjs new file mode 100644 index 0000000000000..52fd34fae1f6e --- /dev/null +++ b/components/listmonk/actions/create-list/create-list.mjs @@ -0,0 +1,53 @@ +import listmonk from "../../listmonk.app.mjs"; +import constants from "../../common/constants.mjs"; + +export default { + key: "listmonk-create-list", + name: "Create List", + description: "Creates a new list in Listmonk. [See the documentation](https://listmonk.app/docs/apis/lists/#post-apilists)", + version: "0.0.1", + type: "action", + props: { + listmonk, + name: { + type: "string", + label: "List Name", + description: "The name of the list to create.", + }, + type: { + type: "string", + label: "Type", + description: "The type of the list to create.", + options: constants.LIST_TYPE_OPTIONS, + }, + optin: { + type: "string", + label: "Optin", + description: "The type of optin for the list.", + options: constants.OPTIN_OPTIONS, + }, + tags: { + type: "string[]", + label: "Tags", + description: "The tags associated with the list.", + optional: true, + }, + }, + async run({ $ }) { + const { data } = await this.listmonk.createList({ + data: { + name: this.name, + type: this.type, + optin: this.optin, + tags: this.tags, + }, + $, + }); + + if (data?.id) { + $.export("$summary", `Successfully created list with ID ${data.id}.`); + } + + return data; + }, +}; diff --git a/components/listmonk/actions/create-subscriber/create-subscriber.mjs b/components/listmonk/actions/create-subscriber/create-subscriber.mjs new file mode 100644 index 0000000000000..0993e7200c6eb --- /dev/null +++ b/components/listmonk/actions/create-subscriber/create-subscriber.mjs @@ -0,0 +1,60 @@ +import listmonk from "../../listmonk.app.mjs"; +import constants from "../../common/constants.mjs"; + +export default { + key: "listmonk-create-subscriber", + name: "Create Subscriber", + description: "Create a new subscriber in Listmonk. [See the documentation](https://listmonk.app/docs/apis/subscribers/#post-apisubscribers)", + version: "0.0.1", + type: "action", + props: { + listmonk, + email: { + type: "string", + label: "Email", + description: "The email of the subscriber to create.", + }, + name: { + type: "string", + label: "Name", + description: "The name of the subscriber to create.", + }, + status: { + type: "string", + label: "Status", + description: "The status of the new subscriber.", + options: constants.STATUS_OPTIONS, + }, + listIds: { + propDefinition: [ + listmonk, + "listIds", + ], + optional: true, + }, + preconfirmSubscription: { + type: "boolean", + label: "Preconfirm Subscription", + description: "If `true`, marks subscription as `confirmed` and no-optin e-mails are sent for double opt-in lists.", + optional: true, + }, + }, + async run({ $ }) { + const { data } = await this.listmonk.createSubscriber({ + data: { + email: this.email, + name: this.name, + status: this.status, + lists: this.listIds, + preconfirm_subscriptions: this.preconfirmSubscription, + }, + $, + }); + + if (data?.id) { + $.export("$summary", `Successfully created subscriber with ID ${data.id}.`); + } + + return data; + }, +}; diff --git a/components/listmonk/common/constants.mjs b/components/listmonk/common/constants.mjs new file mode 100644 index 0000000000000..71c3d3544cbf0 --- /dev/null +++ b/components/listmonk/common/constants.mjs @@ -0,0 +1,35 @@ +const STATUS_OPTIONS = [ + "enabled", + "disabled", + "blocklisted", +]; + +const LIST_TYPE_OPTIONS = [ + "private", + "public", +]; + +const OPTIN_OPTIONS = [ + "single", + "double", +]; + +const CAMPAIGN_TYPE_OPTIONS = [ + "regular", + "optin", +]; + +const CONTENT_TYPE_OPTIONS = [ + "richtext", + "html", + "markdown", + "plain", +]; + +export default { + STATUS_OPTIONS, + LIST_TYPE_OPTIONS, + OPTIN_OPTIONS, + CAMPAIGN_TYPE_OPTIONS, + CONTENT_TYPE_OPTIONS, +}; diff --git a/components/listmonk/listmonk.app.mjs b/components/listmonk/listmonk.app.mjs index 1a78085290330..81f36d619a527 100644 --- a/components/listmonk/listmonk.app.mjs +++ b/components/listmonk/listmonk.app.mjs @@ -1,11 +1,102 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "listmonk", - propDefinitions: {}, + propDefinitions: { + listIds: { + type: "string[]", + label: "Lists", + description: "Array of list IDs to subscribe to (marked as unconfirmed by default).", + async options({ page }) { + const { data: { results } } = await this.listLists({ + params: { + page: page + 1, + }, + }); + return results?.map(({ + id: value, name: label, + }) => ({ + value, + label, + })) || []; + }, + }, + templateId: { + type: "string", + label: "Template", + description: "ID of the template to use. If left empty, the default template is used.", + optional: true, + async options() { + const { data } = await this.listTemplates(); + return data?.map(({ + id: value, name: label, + }) => ({ + value, + label, + })) || []; + }, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _baseUrl() { + return `https://${this.$auth.url}/api`; + }, + _getAuth() { + return { + username: `${this.$auth.username}`, + password: `${this.$auth.password}`, + }; + }, + _makeRequest({ + $ = this, + path, + ...args + }) { + return axios($, { + url: `${this._baseUrl()}${path}`, + auth: this._getAuth(), + ...args, + }); + }, + listSubscribers(args = {}) { + return this._makeRequest({ + path: "/subscribers", + ...args, + }); + }, + listLists(args = {}) { + return this._makeRequest({ + path: "/lists", + ...args, + }); + }, + listTemplates(args = {}) { + return this._makeRequest({ + path: "/templates", + ...args, + }); + }, + createSubscriber(args = {}) { + return this._makeRequest({ + path: "/subscribers", + method: "POST", + ...args, + }); + }, + createList(args = {}) { + return this._makeRequest({ + path: "/lists", + method: "POST", + ...args, + }); + }, + createCampaign(args = {}) { + return this._makeRequest({ + path: "/campaigns", + method: "POST", + ...args, + }); }, }, -}; \ No newline at end of file +}; diff --git a/components/listmonk/package.json b/components/listmonk/package.json index bf203ccd8aa05..a0b2e733bc319 100644 --- a/components/listmonk/package.json +++ b/components/listmonk/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/listmonk", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream listmonk Components", "main": "listmonk.app.mjs", "keywords": [ @@ -11,5 +11,8 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^1.5.1" } -} \ No newline at end of file +} diff --git a/components/listmonk/sources/common/base.mjs b/components/listmonk/sources/common/base.mjs new file mode 100644 index 0000000000000..a24f47764f9e8 --- /dev/null +++ b/components/listmonk/sources/common/base.mjs @@ -0,0 +1,72 @@ +import listmonk from "../../listmonk.app.mjs"; +import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform"; + +export default { + props: { + listmonk, + db: "$.service.db", + timer: { + type: "$.interface.timer", + default: { + intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, + }, + }, + }, + methods: { + _getLastTs() { + return this.db.get("lastTs") || 0; + }, + _setLastTs(lastTs) { + this.db.set("lastTs", lastTs); + }, + getResourceFn() { + throw new Error("getResourceFn is not implemented"); + }, + generateMeta() { + throw new Error("generateMeta is not implemented"); + }, + async *paginate({ + resourceFn, + args = {}, + }) { + args = { + ...args, + params: { + ...args.params, + page: 1, + per_page: 100, + }, + }; + let total = 0; + do { + const { data: { results } } = await resourceFn(args); + for (const item of results) { + yield item; + } + args.params.page++; + total = results?.length; + } while (total === args.params.per_page); + }, + }, + async run() { + const lastTs = this._getLastTs(); + let maxTs = lastTs; + + const items = this.paginate({ + resourceFn: this.getResourceFn(), + }); + + for await (const item of items) { + const ts = Date.parse(item.created_at); + if (ts > lastTs) { + const meta = this.generateMeta(item); + this.$emit(item, meta); + if (ts > maxTs) { + maxTs = ts; + } + } + } + + this._setLastTs(maxTs); + }, +}; diff --git a/components/listmonk/sources/new-subscriber-added/new-subscriber-added.mjs b/components/listmonk/sources/new-subscriber-added/new-subscriber-added.mjs new file mode 100644 index 0000000000000..1e81aaf5e47c7 --- /dev/null +++ b/components/listmonk/sources/new-subscriber-added/new-subscriber-added.mjs @@ -0,0 +1,24 @@ +import common from "../common/base.mjs"; + +export default { + ...common, + key: "listmonk-new-subscriber-added", + name: "New Subscriber Added", + description: "Emit new event when a new subscriber is added. [See the documentation](https://listmonk.app/docs/apis/subscribers/#get-apisubscribers_2)", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getResourceFn() { + return this.listmonk.listSubscribers; + }, + generateMeta(subscriber) { + return { + id: subscriber.id, + summary: `New Subscriber ${subscriber.name}`, + ts: Date.parse(subscriber.created_at), + }; + }, + }, +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 74e6a5b39c320..2d91f3104f0af 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3084,7 +3084,10 @@ importers: specifiers: {} components/listmonk: - specifiers: {} + specifiers: + '@pipedream/platform': ^1.5.1 + dependencies: + '@pipedream/platform': 1.5.1 components/little_green_light: specifiers: {} From 31dda2ef2cfd99a663670cac57bde4387da441f9 Mon Sep 17 00:00:00 2001 From: michelle0927 Date: Tue, 24 Oct 2023 07:21:28 -0700 Subject: [PATCH 066/186] fieldIds (#8573) --- .../podio/actions/common/common-item.mjs | 49 ++++++++++++------- .../podio/actions/create-item/create-item.mjs | 4 +- .../podio/actions/update-item/update-item.mjs | 4 +- components/podio/package.json | 2 +- 4 files changed, 37 insertions(+), 22 deletions(-) diff --git a/components/podio/actions/common/common-item.mjs b/components/podio/actions/common/common-item.mjs index 10a11de702e11..3542d68e755c8 100644 --- a/components/podio/actions/common/common-item.mjs +++ b/components/podio/actions/common/common-item.mjs @@ -53,11 +53,15 @@ export default { }, }, methods: { - getFields() { + async getFields() { const fields = {}; for (let key of Object.keys(this)) { if (key.startsWith("field_")) { - fields[key.split("_")[1]] = utils.extractPropValues(this[key]); + const fieldName = key.split("_")[1]; + const fieldId = await this.getFieldId(this.appId, fieldName); + if (fieldId) { + fields[fieldId] = utils.extractPropValues(this[key]); + } } } return fields; @@ -77,7 +81,25 @@ export default { })) || []; spaceFields.push(...fields); } - return spaceFields; + return this.eliminateDuplicateFields(spaceFields); + }, + eliminateDuplicateFields(fields) { + const seen = new Set(); + return fields.filter((field) => { + const isDuplicate = seen.has(field.label); + seen.add(field.label); + return !isDuplicate; + }); + }, + async getFieldId(appId, fieldName) { + const { fields } = await this.app.getApp({ + appId, + }); + const field = fields.find(({ label }) => label === fieldName); + if (!field) { + console.log(`Field "${fieldName}" not found in app with ID ${appId}.`); + } + return field?.field_id; }, getIfUpdate() { return false; @@ -94,29 +116,22 @@ export default { })).fields : await this.getSpaceFields(); - props.fieldIds = { - type: "integer[]", + props.fieldNames = { + type: "string[]", label: "Fields", description: `Fields to ${this.getIfUpdate() ? "update" : "create"}`, - options: fields.map(({ - field_id: value, label, app_label, - }) => ({ - value, - label: `${label}${app_label - ? " - for use with App \"" + app_label + "\"" - : ""}`, - })), + options: fields.map(({ label }) => label), reloadProps: true, }; - if (!this.fieldIds?.length) { + if (!this.fieldNames?.length) { return props; } - for (const id of this.fieldIds) { - const field = fields.find(({ field_id }) => field_id === id ); + for (const fieldName of this.fieldNames) { + const field = fields.find(({ label }) => fieldName === label ); if (field.type != "calculation") { const newProp = { type: utils.getType(field), @@ -134,7 +149,7 @@ export default { }; }); } - props[`field_${field.field_id}`] = newProp; + props[`field_${field.label}`] = newProp; } } return props; diff --git a/components/podio/actions/create-item/create-item.mjs b/components/podio/actions/create-item/create-item.mjs index c1b5612a2bd2e..cea4812290f27 100644 --- a/components/podio/actions/create-item/create-item.mjs +++ b/components/podio/actions/create-item/create-item.mjs @@ -6,13 +6,13 @@ delete props.itemId; export default { type: "action", key: "podio-create-item", - version: "0.0.2", + version: "0.0.3", name: "Create an Item", description: "Adds a new item to the given app. [See the documentation](https://developers.podio.com/doc/items/add-new-item-22362)", ...common, props, async run ({ $ }) { - const fields = this.getFields(); + const fields = await this.getFields(); const reminder = this.reminder ? { remind_delta: this.reminder, diff --git a/components/podio/actions/update-item/update-item.mjs b/components/podio/actions/update-item/update-item.mjs index 2ab3e4e7e0cbf..5b0f4185effcf 100644 --- a/components/podio/actions/update-item/update-item.mjs +++ b/components/podio/actions/update-item/update-item.mjs @@ -3,7 +3,7 @@ import common from "../common/common-item.mjs"; export default { type: "action", key: "podio-update-item", - version: "0.0.2", + version: "0.0.3", name: "Update an Item", description: "Updates an item. [See the documentation](https://developers.podio.com/doc/items/update-item-22363)", ...common, @@ -14,7 +14,7 @@ export default { }, }, async run ({ $ }) { - const fields = this.getFields(); + const fields = await this.getFields(); const reminder = this.reminder ? { remind_delta: this.reminder, diff --git a/components/podio/package.json b/components/podio/package.json index 9b3b01c926130..86c3484381910 100644 --- a/components/podio/package.json +++ b/components/podio/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/podio", - "version": "0.0.3", + "version": "0.0.4", "description": "Pipedream Podio Components", "main": "podio.app.mjs", "keywords": [ From 3b1af71dd0b94ae025bf56952ebffacfc6302ce4 Mon Sep 17 00:00:00 2001 From: Lucas Caresia Date: Tue, 24 Oct 2023 12:08:24 -0300 Subject: [PATCH 067/186] [Components] AirOps #8178 (#8509) * Added action * Fixed requested changes --- components/airops/.gitignore | 3 -- .../actions/run-workflow/run-workflow.mjs | 49 +++++++++++++++++++ components/airops/airops.app.mjs | 38 ++++++++++++++ components/airops/app/airops.app.ts | 13 ----- components/airops/package.json | 10 ++-- pnpm-lock.yaml | 5 +- 6 files changed, 97 insertions(+), 21 deletions(-) delete mode 100644 components/airops/.gitignore create mode 100644 components/airops/actions/run-workflow/run-workflow.mjs create mode 100644 components/airops/airops.app.mjs delete mode 100644 components/airops/app/airops.app.ts diff --git a/components/airops/.gitignore b/components/airops/.gitignore deleted file mode 100644 index ec761ccab7595..0000000000000 --- a/components/airops/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.js -*.mjs -dist \ No newline at end of file diff --git a/components/airops/actions/run-workflow/run-workflow.mjs b/components/airops/actions/run-workflow/run-workflow.mjs new file mode 100644 index 0000000000000..21efa541816ef --- /dev/null +++ b/components/airops/actions/run-workflow/run-workflow.mjs @@ -0,0 +1,49 @@ +import app from "../../airops.app.mjs"; + +export default { + name: "Run Workflow", + version: "0.0.1", + key: "airops-run-workflow", + description: "Run a workflow of an app. See the [sync documentation](https://docs.airops.com/reference/create-execution) or [async documentation](https://docs.airops.com/reference/create-async-execution)", + type: "action", + props: { + app, + appId: { + label: "App ID", + type: "string", + description: "The app ID. [You can get you app ID here](https://docs.airops.com/reference/uuid)", + }, + inputs: { + label: "Inputs", + type: "object", + description: "Input fields for executing the app", + }, + asynchronous: { + label: "Run Asynchronous", + type: "boolean", + description: "Execute the workflow asynchronous", + default: false, + optional: true, + }, + }, + async run({ $ }) { + const inputs = typeof this.inputs === "string" + ? JSON.parse(this.inputs) + : this.inputs; + + const response = await this.app.runWorkflow({ + $, + appId: this.appId, + async: this.asynchronous, + data: { + inputs, + }, + }); + + if (response) { + $.export("$summary", "Successfully ran workflow"); + } + + return response; + }, +}; diff --git a/components/airops/airops.app.mjs b/components/airops/airops.app.mjs new file mode 100644 index 0000000000000..e5c7e6fdcf1e6 --- /dev/null +++ b/components/airops/airops.app.mjs @@ -0,0 +1,38 @@ +import { axios } from "@pipedream/platform"; + +export default { + type: "app", + app: "airops", + propDefinitions: {}, + methods: { + _workspaceApiKey() { + return this.$auth.workspace_api_key; + }, + _apiUrl() { + return "https://app.airops.com/public_api"; + }, + async _makeRequest({ + $ = this, path, ...args + }) { + return axios($, { + url: `${this._apiUrl()}${path}`, + ...args, + headers: { + ...args.headers, + Authorization: `Bearer ${this._workspaceApiKey()}`, + }, + }); + }, + async runWorkflow({ + appId, async = false, ...args + }) { + return this._makeRequest({ + path: `/airops_apps/${appId}/${async + ? "async_execute" + : "execute"}`, + method: "post", + ...args, + }); + }, + }, +}; diff --git a/components/airops/app/airops.app.ts b/components/airops/app/airops.app.ts deleted file mode 100644 index 855d5b0dffe0d..0000000000000 --- a/components/airops/app/airops.app.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { defineApp } from "@pipedream/types"; - -export default defineApp({ - type: "app", - app: "airops", - 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/airops/package.json b/components/airops/package.json index ea724841f5962..974e8162d3438 100644 --- a/components/airops/package.json +++ b/components/airops/package.json @@ -1,16 +1,18 @@ { "name": "@pipedream/airops", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream AirOps Components", - "main": "dist/app/airops.app.mjs", + "main": "airops.app.mjs", "keywords": [ "pipedream", "airops" ], - "files": ["dist"], "homepage": "https://pipedream.com/apps/airops", "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^1.5.1" } -} \ No newline at end of file +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2d91f3104f0af..52ba58dac46b7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -183,7 +183,10 @@ importers: specifiers: {} components/airops: - specifiers: {} + specifiers: + '@pipedream/platform': ^1.5.1 + dependencies: + '@pipedream/platform': 1.5.1 components/airplane: specifiers: From 1c704b53ba653503d01bad0ceb9d590f62f3ceb4 Mon Sep 17 00:00:00 2001 From: Andrew Chuang Date: Tue, 24 Oct 2023 10:07:09 -0700 Subject: [PATCH 068/186] Auto Draft PR (#8420) * change eslint rule for ts macro to warn * init structure and comments * create new issue branch and reset to origin/master * work with abs paths * some sync commands * modify warning * add gh submit pr * remove url duplicates * use thefuzz to avoid duplicate scraped api docs * better subprocess commands * fix bug similar contents * add instructions to readme * add gh dep * remove anchor tags from docs urls --- .eslintrc | 2 +- packages/component_code_gen/README.md | 10 ++- .../component_code_gen/code_gen/generate.py | 6 +- .../code_gen/generate_for_github_issue.py | 72 ++++++++++++++++--- packages/component_code_gen/main.py | 8 ++- packages/component_code_gen/poetry.lock | 15 +++- packages/component_code_gen/pyproject.toml | 1 + 7 files changed, 94 insertions(+), 20 deletions(-) diff --git a/.eslintrc b/.eslintrc index c14d14a653d0d..ef96a1e33c839 100644 --- a/.eslintrc +++ b/.eslintrc @@ -33,7 +33,7 @@ "pipedream/props-description": "warn", "pipedream/source-name": "warn", "pipedream/source-description": "warn", - "pipedream/no-ts-version": "error" + "pipedream/no-ts-version": "warn" } }, { diff --git a/packages/component_code_gen/README.md b/packages/component_code_gen/README.md index 579aaaa2eda86..62cb80a829e79 100644 --- a/packages/component_code_gen/README.md +++ b/packages/component_code_gen/README.md @@ -75,12 +75,20 @@ poetry run python main.py --type action --app slack --instructions instructions. ### GitHub Issues The command below will parse through GitHub issue description and generate code for the list of components. -All the code will be written to a folder named `output`. Be sure to add `BROWSERLESS_API_KEY` to `.env` to parse API docs. +Be sure to add `BROWSERLESS_API_KEY` to `.env` to parse API docs. ``` poetry run python main.py --issue issue_number ``` +#### Draft PRs + +The default behaviour is to automatically create a branch and submit a Draft PR. The command above is equivalent to: + +``` +poetry run python main.py --issue issue_number --skip_pr=False +``` + #### Output Dir The default `output_dir` is where Pipedream components live in the repo: `pipedream/components`. The generated components diff --git a/packages/component_code_gen/code_gen/generate.py b/packages/component_code_gen/code_gen/generate.py index 255e6f6598374..d622e4255e863 100644 --- a/packages/component_code_gen/code_gen/generate.py +++ b/packages/component_code_gen/code_gen/generate.py @@ -1,5 +1,4 @@ import os -import time from selenium import webdriver from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC @@ -96,11 +95,10 @@ def parse_urls(driver, urls): EC.presence_of_element_located((By.TAG_NAME, 'body')) ) body = " ".join(element.text.split()) - content = { + contents.append({ "url": url, "content": body, - } - contents.append(content) + }) except Exception as e: print(f"Error scraping {url}: {e}") diff --git a/packages/component_code_gen/code_gen/generate_for_github_issue.py b/packages/component_code_gen/code_gen/generate_for_github_issue.py index 6b3de8b62b19b..e977d7b718903 100644 --- a/packages/component_code_gen/code_gen/generate_for_github_issue.py +++ b/packages/component_code_gen/code_gen/generate_for_github_issue.py @@ -1,7 +1,8 @@ from collections import OrderedDict import os -import json +import git import requests +import subprocess import markdown_to_json import config.logging_config as logging_config from code_gen.generate import main @@ -9,6 +10,10 @@ logger = logging_config.getLogger(__name__) +def run_command(command): + subprocess.run(command, shell=True) + + def extract_prompts(markdown_dict): prompts = [] for key, value in markdown_dict.items(): @@ -20,13 +25,20 @@ def extract_prompts(markdown_dict): def get_all_docs_urls(markdown_dict): - urls = [] - for key, value in markdown_dict.items(): - if key == "urls": - urls.extend(value) - elif isinstance(value, (dict, OrderedDict)): - urls.extend(get_all_docs_urls(value)) - return urls + def extract_urls(markdown_dict): + urls = [] + for key, value in markdown_dict.items(): + if key == "urls": + urls.extend(value) + elif isinstance(value, (dict, OrderedDict)): + urls.extend(extract_urls(value)) + return urls + all_urls = extract_urls(markdown_dict) + return unique_urls(all_urls) + + +def unique_urls(urls): + return list(set([url.split("#")[0] for url in urls])) def generate_app_file_prompt(requirements, app_file_content): @@ -45,7 +57,31 @@ def generate_app_file_prompt(requirements, app_file_content): {requirements}""" -def generate(issue_number, output_dir, verbose=False, tries=3): +def generate(issue_number, output_dir, generate_pr=True, clean=False, verbose=False, tries=3): + repo_path = os.path.abspath(os.path.join("..", "..")) + output_dir = os.path.abspath(output_dir) + + if generate_pr: + output_dir = os.path.join(repo_path, "components") + repo = git.Repo(repo_path) + + if not clean and repo.index.diff(None): + logger.warn( + "Your git stage is not clean. Please stash/commit your changes or use --clean to discard them") + return + + branch_name = f"issue-{issue_number}" + run_command("git fetch origin") + + if any(reference.name == branch_name for reference in repo.references): + # branch name already exists + run_command(f"git checkout {branch_name}") + else: + # create new branch + run_command(f"git checkout -b {branch_name}") + + run_command("git reset --hard origin/master") + # parse github issue description md = requests.get( f"https://api.github.com/repos/PipedreamHQ/pipedream/issues/{issue_number}").json()["body"].lower() @@ -54,7 +90,8 @@ def generate(issue_number, output_dir, verbose=False, tries=3): global_urls = [] requirements = [] - file_path = f"{output_dir}/{app}/{app}.app.mjs" + app_base_path = os.path.join(output_dir, app) + file_path = os.path.join(app_base_path, f"{app}.app.mjs") # If the directory at file_path doesn't exist, create it os.makedirs(os.path.dirname(file_path), exist_ok=True) @@ -121,7 +158,7 @@ def generate(issue_number, output_dir, verbose=False, tries=3): "type": component_type, "key": component_key, "instructions": f"The component key is {app}-{component_key}. {instructions}", - "urls": global_urls + urls, + "urls": unique_urls(global_urls + urls), }) for component in requirements: @@ -137,3 +174,16 @@ def generate(issue_number, output_dir, verbose=False, tries=3): os.makedirs(os.path.dirname(file_path), exist_ok=True) with open(file_path, 'w') as f: f.write(result) + + if generate_pr: + # XXX: add deps to package.json + # XXX: remove ts stuff and .gitignore + # GitPython requires to manually check .gitignore paths when adding files to index + # so this is easier + run_command(f"npx eslint {app_base_path} --fix") + run_command(["npx pnpm i"]) + run_command(f"git add -f {app_base_path} {repo_path}/pnpm-lock.yaml") + run_command(f"git commit --no-verify -m '{app} init'") + run_command(f"git push -f --set-upstream origin {branch_name}") + run_command( + f"gh pr create --draft --title 'New Components - {app}' --body 'Resolves #{issue_number}.'") diff --git a/packages/component_code_gen/main.py b/packages/component_code_gen/main.py index 4208a65f22ce3..595976c1401e3 100644 --- a/packages/component_code_gen/main.py +++ b/packages/component_code_gen/main.py @@ -8,6 +8,10 @@ parser = argparse.ArgumentParser() parser.add_argument('--issue', help='The issue number on github', type=int, required=False) + parser.add_argument('--skip-pr', dest='skip_pr', help='Generate a PR on github', + required=False, default=False, action='store_true') + parser.add_argument('--clean', dest='clean', help='Clean git stage', + required=False, default=False, action='store_true') parser.add_argument('--type', help='Which kind of code you want to generate?', choices=available_templates.keys()) parser.add_argument('--app', help='The app_name_slug') @@ -26,8 +30,8 @@ args = parser.parse_args() if args.issue: - generate(args.issue, output_dir=args.output_dir, - verbose=args.verbose, tries=args.tries) + generate(args.issue, output_dir=args.output_dir, generate_pr=not args.skip_pr, + clean=args.clean, verbose=args.verbose, tries=args.tries) else: if not args.type: raise argparse.ArgumentTypeError("--type is required") diff --git a/packages/component_code_gen/poetry.lock b/packages/component_code_gen/poetry.lock index 94fcf5c020577..989878dd7ddf7 100644 --- a/packages/component_code_gen/poetry.lock +++ b/packages/component_code_gen/poetry.lock @@ -583,6 +583,19 @@ files = [ {file = "frozenlist-1.4.0.tar.gz", hash = "sha256:09163bdf0b2907454042edb19f887c6d33806adc71fbd54afc14908bfdc22251"}, ] +[[package]] +name = "gh" +version = "0.0.4" +description = "" +optional = false +python-versions = "*" +files = [ + {file = "gh-0.0.4.tar.gz", hash = "sha256:db58819885a95807f963f8eb798e1d0df22ded41d9a80d5c3dc1fc8d695f1e1b"}, +] + +[package.dependencies] +gitpython = "*" + [[package]] name = "gitdb" version = "4.0.10" @@ -2122,4 +2135,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "c73e746679ac131dd4b5dc71b5a609c9c0e92ce9e886599760362b326dfa8c80" +content-hash = "fa2a277a57b56a56da069d7420e7214b1834812f15d49bd6f705f1442660a817" diff --git a/packages/component_code_gen/pyproject.toml b/packages/component_code_gen/pyproject.toml index 835c3f13597a5..dd0ef0b3f4717 100644 --- a/packages/component_code_gen/pyproject.toml +++ b/packages/component_code_gen/pyproject.toml @@ -13,6 +13,7 @@ langchain = "^0.0.312" supabase = "^1.0.3" selenium = "^4.12.0" markdown-to-json = "^2.1.0" +gh = "^0.0.4" [build-system] From 853baf6cdc9bc2e986c4b26a94f462d656b02627 Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Tue, 24 Oct 2023 10:32:59 -0700 Subject: [PATCH 069/186] Adding app scaffolding for signable --- components/signable/signable.app.mjs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 components/signable/signable.app.mjs diff --git a/components/signable/signable.app.mjs b/components/signable/signable.app.mjs new file mode 100644 index 0000000000000..e1725b9cbccea --- /dev/null +++ b/components/signable/signable.app.mjs @@ -0,0 +1,11 @@ +export default { + type: "app", + app: "signable", + propDefinitions: {}, + methods: { + // this.$auth contains connected account data + authKeys() { + console.log(Object.keys(this.$auth)); + }, + }, +}; \ No newline at end of file From caa71f50c56b9552329d284d3a64dd064d111d78 Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Tue, 24 Oct 2023 10:33:00 -0700 Subject: [PATCH 070/186] Adding app scaffolding for signable --- components/signable/package.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 components/signable/package.json diff --git a/components/signable/package.json b/components/signable/package.json new file mode 100644 index 0000000000000..a1351f149940f --- /dev/null +++ b/components/signable/package.json @@ -0,0 +1,15 @@ +{ + "name": "@pipedream/signable", + "version": "0.0.1", + "description": "Pipedream Signable Components", + "main": "signable.app.mjs", + "keywords": [ + "pipedream", + "signable" + ], + "homepage": "https://pipedream.com/apps/signable", + "author": "Pipedream (https://pipedream.com/)", + "publishConfig": { + "access": "public" + } +} \ No newline at end of file From a511d1da7cb999655b2f2851fc335c12def091f6 Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Tue, 24 Oct 2023 10:33:01 -0700 Subject: [PATCH 071/186] Adding app scaffolding for chmeetings --- components/chmeetings/chmeetings.app.mjs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 components/chmeetings/chmeetings.app.mjs diff --git a/components/chmeetings/chmeetings.app.mjs b/components/chmeetings/chmeetings.app.mjs new file mode 100644 index 0000000000000..d9a85cf0cd5ca --- /dev/null +++ b/components/chmeetings/chmeetings.app.mjs @@ -0,0 +1,11 @@ +export default { + type: "app", + app: "chmeetings", + propDefinitions: {}, + methods: { + // this.$auth contains connected account data + authKeys() { + console.log(Object.keys(this.$auth)); + }, + }, +}; \ No newline at end of file From 69d6d60d7fff239e0d9985f0b20f1815f5adaf7a Mon Sep 17 00:00:00 2001 From: "Dylan J. Sather" Date: Tue, 24 Oct 2023 10:33:02 -0700 Subject: [PATCH 072/186] Adding app scaffolding for chmeetings --- components/chmeetings/package.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 components/chmeetings/package.json diff --git a/components/chmeetings/package.json b/components/chmeetings/package.json new file mode 100644 index 0000000000000..9777b846770fd --- /dev/null +++ b/components/chmeetings/package.json @@ -0,0 +1,15 @@ +{ + "name": "@pipedream/chmeetings", + "version": "0.0.1", + "description": "Pipedream ChMeetings Components", + "main": "chmeetings.app.mjs", + "keywords": [ + "pipedream", + "chmeetings" + ], + "homepage": "https://pipedream.com/apps/chmeetings", + "author": "Pipedream (https://pipedream.com/)", + "publishConfig": { + "access": "public" + } +} \ No newline at end of file From 6afb6b1f2968bca55b1e081e92bc29565323abe1 Mon Sep 17 00:00:00 2001 From: Andrew Chuang Date: Tue, 24 Oct 2023 11:26:15 -0700 Subject: [PATCH 073/186] add ai-assisted label (#8609) --- .../component_code_gen/code_gen/generate_for_github_issue.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/component_code_gen/code_gen/generate_for_github_issue.py b/packages/component_code_gen/code_gen/generate_for_github_issue.py index e977d7b718903..d7a5a211c9bbe 100644 --- a/packages/component_code_gen/code_gen/generate_for_github_issue.py +++ b/packages/component_code_gen/code_gen/generate_for_github_issue.py @@ -186,4 +186,4 @@ def generate(issue_number, output_dir, generate_pr=True, clean=False, verbose=Fa run_command(f"git commit --no-verify -m '{app} init'") run_command(f"git push -f --set-upstream origin {branch_name}") run_command( - f"gh pr create --draft --title 'New Components - {app}' --body 'Resolves #{issue_number}.'") + f"gh pr create -d -l ai-assisted -t 'New Components - {app}' -b 'Resolves #{issue_number}.'") From da722c91e4c31a4470e5f4c3ee36a102ec393bd3 Mon Sep 17 00:00:00 2001 From: Michael Lim <42158621+malexanderlim@users.noreply.github.com> Date: Tue, 24 Oct 2023 11:36:56 -0700 Subject: [PATCH 074/186] =?UTF-8?q?Updating=20Google=20Developer=20apps=20?= =?UTF-8?q?with=20language=20for=20publishing=20to=20mainta=E2=80=A6=20(#8?= =?UTF-8?q?607)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Updating Google Developer apps with language for publishing to maintain account connection. * Fixing headers. --- components/gmail_custom_oauth/README.md | 16 ++++++++++++++++ components/google_fit_developer_app/README.md | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/components/gmail_custom_oauth/README.md b/components/gmail_custom_oauth/README.md index 1727ed1679576..37330411bb40e 100644 --- a/components/gmail_custom_oauth/README.md +++ b/components/gmail_custom_oauth/README.md @@ -84,3 +84,19 @@ At this point, you should have a Gmail App under your Google Project, and a set ![Check all scopes to include grant your integration permission](https://res.cloudinary.com/pipedreamin/image/upload/v1663269729/docs/components/CleanShot_2022-09-15_at_15.20.26_jlnyw4.gif) 7. Click the final **Connect** and your custom Gmail app should be integrated into Pipedream! + +## Publish your custom Gmail app +Google has a [7 day expiration window](https://developers.google.com/identity/protocols/oauth2#:~:text=A%20Google%20Cloud,Connect%20equivalents) on refresh tokens for applications with a publishing status of "Testing", so you will need to **Publish** your application in order to maintain your account connection. + +1. Navigate to your application, and click **OAuth Consent Screen** on the lefthand sidebar. +2. Under **Publishing status**, click **Publish App**. If you included any sensitive or restricted scopes in your app, there will be a disclosure stating that you will need to go through the process of verification. Click **Confirm**. +3. Your application will not be available externally unless you share your **client_id** with others, and you will not have to go through the verification process unless you intend to onboard over 100 users. +4. The publishing status should be set to **In production**, and your account should maintain its connection without an expiration window. + +![Publish your application](https://res.cloudinary.com/dpenc2lit/image/upload/v1698166716/Screenshot_2023-10-24_at_9.50.06_AM_lve7wq.png) + +![Confirmation of changes](https://res.cloudinary.com/dpenc2lit/image/upload/v1698166716/Screenshot_2023-10-24_at_9.50.18_AM_mndtyc.png) + +# Troubleshooting +**Application disconnects after 7 days**
+If your developer application disconnects after 7 days, you need to follow the steps above to Publish your custom Gmail app in order to keep your account connected. \ No newline at end of file diff --git a/components/google_fit_developer_app/README.md b/components/google_fit_developer_app/README.md index 39eae12c0f75a..c833533dc6d7a 100644 --- a/components/google_fit_developer_app/README.md +++ b/components/google_fit_developer_app/README.md @@ -83,3 +83,19 @@ At this point, you should have a Google Fit App under your Google Project, and a ![Check all scopes to include grant your integration permission](https://res.cloudinary.com/dpenc2lit/image/upload/v1692293421/Screenshot_2023-08-17_at_10.30.15_AM_ymeont.png) 7. Click the final **Connect** and your custom Google Fit app should be integrated into Pipedream! + +## Publish your Google Fit app +Google has a [7 day expiration window](https://developers.google.com/identity/protocols/oauth2#:~:text=A%20Google%20Cloud,Connect%20equivalents) on refresh tokens for applications with a publishing status of "Testing", so you will need to **Publish** your application in order to maintain your account connection. + +1. Navigate to your application, and click **OAuth Consent Screen** on the lefthand sidebar. +2. Under **Publishing status**, click **Publish App**. If you included any sensitive or restricted scopes in your app, there will be a disclosure stating that you will need to go through the process of verification. Click **Confirm**. +3. Your application will not be available externally unless you share your **client_id** with others, and you will not have to go through the verification process unless you intend to onboard over 100 users. +4. The publishing status should be set to **In production**, and your account should maintain its connection without an expiration window. + +![Publish your application](https://res.cloudinary.com/dpenc2lit/image/upload/v1698166716/Screenshot_2023-10-24_at_9.50.06_AM_lve7wq.png) + +![Confirmation of changes](https://res.cloudinary.com/dpenc2lit/image/upload/v1698166716/Screenshot_2023-10-24_at_9.50.18_AM_mndtyc.png) + +# Troubleshooting +**Application disconnects after 7 days**
+If your developer application disconnects after 7 days, you need to follow the steps above to Publish your Google Fit app in order to keep your account connected. \ No newline at end of file From 621823350c744b906e8ca4b214ba4777ae08ab02 Mon Sep 17 00:00:00 2001 From: Danny Roosevelt Date: Tue, 24 Oct 2023 12:10:07 -0700 Subject: [PATCH 075/186] Docs step notes (#8606) * Update README.md * Update README.md * Update docs/docs/workflows/steps/README.md Co-authored-by: Andrew Chuang * Update README.md --------- Co-authored-by: Andrew Chuang --- docs/docs/workflows/steps/README.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/docs/docs/workflows/steps/README.md b/docs/docs/workflows/steps/README.md index 8cb1fbc81ba90..4c6ebf58c2148 100644 --- a/docs/docs/workflows/steps/README.md +++ b/docs/docs/workflows/steps/README.md @@ -67,4 +67,30 @@ For examples of supported data types in your steps language, see the examples be * [Bash](/code/bash/#sharing-data-between-steps) * [Go](/code/go/#sharing-data-between-steps) +## Step Notes + +Pipedream lets you add notes to individual steps in your workflow so you can include helpful context to other workspace members or even yourself, and you can even write markdown! + +![Viewing step notes](https://res.cloudinary.com/pipedreamin/image/upload/v1698167274/view_notes_zto8bp.png) + +### Adding or editing a note +1. Enter build mode on any workflow +2. Click into the overflow menu (3 dots) at the top right of any step +3. Select **Add note** (or **Edit note** if making changes to an existing note) +4. Add any text or markdown, then click **Update** + +![Add note](https://res.cloudinary.com/pipedreamin/image/upload/v1698167274/add_note_kvvxju.png) + +![Adding step notes](https://res.cloudinary.com/pipedreamin/image/upload/v1698167274/add_note_zg62i2.gif) + +### Showing notes +1. Any step that has a note will indicate this with a special icon (shown below) +2. Click on the icon to hide or show the note + +![View notes](https://res.cloudinary.com/pipedreamin/image/upload/v1698167274/view_note_p5uvkg.gif) + +### Current limitations +- Step notes are not currently included when copying or [sharing](/workflows/sharing) a workflow +- Step notes are only accessible in Edit mode, and not from the Inspector +