diff --git a/components/bubble/actions/create-thing/create-thing.mjs b/components/bubble/actions/create-thing/create-thing.mjs new file mode 100644 index 0000000000000..4b5f10acc2f9e --- /dev/null +++ b/components/bubble/actions/create-thing/create-thing.mjs @@ -0,0 +1,30 @@ +import bubble from "../../bubble.app.mjs"; +import { axios } from "@pipedream/platform"; + +export default { + key: "bubble-create-thing", + name: "Create Thing", + description: "Creates a new thing in the Bubble database. [See the documentation](https://manual.bubble.io/core-resources/api/the-bubble-api/the-data-api/data-api-requests#create-a-thing)", + version: "0.0.{{ts}}", + type: "action", + props: { + bubble, + thingAttributes: { + propDefinition: [ + bubble, + "thingAttributes", + ], + type: "object", + label: "Thing Attributes", + description: "The attributes for the new thing to create in the Bubble database", + }, + }, + async run({ $ }) { + const response = await this.bubble.createNewThing({ + thingAttributes: this.thingAttributes, + }); + + $.export("$summary", `Successfully created thing with ID: ${response.id}`); + return response; + }, +}; diff --git a/components/bubble/actions/find-thing/find-thing.mjs b/components/bubble/actions/find-thing/find-thing.mjs new file mode 100644 index 0000000000000..82eb73bc1ed26 --- /dev/null +++ b/components/bubble/actions/find-thing/find-thing.mjs @@ -0,0 +1,32 @@ +import bubble from "../../bubble.app.mjs"; + +export default { + key: "bubble-find-thing", + name: "Find Thing", + description: "Searches for a thing in the Bubble database. [See the documentation](https://manual.bubble.io/core-resources/api/the-bubble-api/the-data-api/data-api-requests)", + version: "0.0.{{ts}}", + type: "action", + props: { + bubble, + searchQuery: { + type: "string", + label: "Search Query", + description: "The query to search for a thing in the Bubble database", + }, + searchParameters: { + type: "object", + label: "Search Parameters", + description: "Optional parameters to refine the search results", + optional: true, + }, + }, + async run({ $ }) { + const response = await this.bubble.searchForThings({ + searchQuery: this.searchQuery, + searchParameters: this.searchParameters, + }); + + $.export("$summary", `Successfully searched for things with query "${this.searchQuery}"`); + return response; + }, +}; diff --git a/components/bubble/actions/modify-thing/modify-thing.mjs b/components/bubble/actions/modify-thing/modify-thing.mjs new file mode 100644 index 0000000000000..6f7725159ee00 --- /dev/null +++ b/components/bubble/actions/modify-thing/modify-thing.mjs @@ -0,0 +1,43 @@ +import bubble from "../../bubble.app.mjs"; +import { axios } from "@pipedream/platform"; + +export default { + key: "bubble-modify-thing", + name: "Modify Thing", + description: "Modifies an existing thing in the Bubble database by providing the thing's ID. [See the documentation](https://manual.bubble.io/core-resources/api/the-bubble-api/the-data-api/data-api-requests)", + version: "0.0.{{ts}}", + type: "action", + props: { + bubble, + thingId: { + propDefinition: [ + bubble, + "thingId", + ], + }, + attributeToModify: { + propDefinition: [ + bubble, + "attributeToModify", + ], + optional: true, + }, + newValue: { + propDefinition: [ + bubble, + "newValue", + ], + optional: true, + }, + }, + async run({ $ }) { + const response = await this.bubble.modifyThingById({ + thingId: this.thingId, + attributeToModify: this.attributeToModify, + newValue: this.newValue, + }); + + $.export("$summary", `Successfully modified the thing with ID ${this.thingId}`); + return response; + }, +}; diff --git a/components/bubble/bubble.app.mjs b/components/bubble/bubble.app.mjs index ee0658e9c6ddc..6633d8395db86 100644 --- a/components/bubble/bubble.app.mjs +++ b/components/bubble/bubble.app.mjs @@ -1,11 +1,131 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "bubble", - propDefinitions: {}, + propDefinitions: { + workflowId: { + type: "string", + label: "Workflow ID", + description: "The ID for the Bubble workflow to monitor", + }, + thingId: { + type: "string", + label: "Thing ID", + description: "The unique ID of the thing in the Bubble database to modify", + }, + attributeToModify: { + type: "string", + label: "Attribute to Modify", + description: "The name of the attribute of the thing to change", + optional: true, + }, + newValue: { + type: "any", + label: "New Value", + description: "The new value for the specified attribute", + optional: true, + }, + searchQuery: { + type: "string", + label: "Search Query", + description: "The query to search for a thing in the Bubble database", + }, + searchParameters: { + type: "object", + label: "Search Parameters", + description: "Optional parameters to refine the search results", + optional: true, + }, + thingAttributes: { + type: "object", + label: "Thing Attributes", + description: "The attributes for the new thing to create in the Bubble database", + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _baseUrl() { + return `https://${this.$auth.appname}.bubbleapps.io/api/1.1/obj`; + }, + + async _makeRequest(opts = {}) { + const { + $ = this, method = "GET", path = "/", headers, ...otherOpts + } = opts; + return axios($, { + ...otherOpts, + method, + url: this._baseUrl() + path, + headers: { + ...headers, + "Content-Type": "application/json", + "Authorization": `Bearer ${this.$auth.api_token}`, + }, + }); + }, + + async listenForWorkflow(opts = {}) { + const { + workflowId, ...otherOpts + } = opts; + if (!workflowId) { + throw new Error("Workflow ID is required to listen for workflows."); + } + // Implement logic to listen for the workflow and emit an event + }, + + async modifyThingById(opts = {}) { + const { + thingId, attributeToModify, newValue, ...otherOpts + } = opts; + if (!thingId) { + throw new Error("A Thing ID is required to modify a thing."); + } + const data = attributeToModify + ? { + [attributeToModify]: newValue, + } + : {}; + return this._makeRequest({ + method: "PATCH", + path: `/${thingId}`, + data, + ...otherOpts, + }); + }, + + async searchForThings(opts = {}) { + const { + searchQuery, searchParameters, ...otherOpts + } = opts; + if (!searchQuery) { + throw new Error("A search query is required to search for a thing."); + } + const params = { + q: searchQuery, + ...searchParameters, + }; + return this._makeRequest({ + method: "GET", + path: "/search", + params, + ...otherOpts, + }); + }, + + async createNewThing(opts = {}) { + const { + thingAttributes, ...otherOpts + } = opts; + if (!thingAttributes || typeof thingAttributes !== "object") { + throw new Error("Thing attributes must be provided to create a new thing."); + } + return this._makeRequest({ + method: "POST", + data: thingAttributes, + ...otherOpts, + }); }, }, + version: "0.0.{{ts}}", }; diff --git a/components/bubble/sources/new-workflow-trigger-event-instant/new-workflow-trigger-event-instant.mjs b/components/bubble/sources/new-workflow-trigger-event-instant/new-workflow-trigger-event-instant.mjs new file mode 100644 index 0000000000000..d60a2ab68070a --- /dev/null +++ b/components/bubble/sources/new-workflow-trigger-event-instant/new-workflow-trigger-event-instant.mjs @@ -0,0 +1,55 @@ +import bubble from "../../bubble.app.mjs"; +import { axios } from "@pipedream/platform"; + +export default { + key: "bubble-new-workflow-trigger-event-instant", + name: "New Workflow Trigger Event", + description: "Emits new event when a Bubble workflow that incorporates the plugin action is initiated. [See the documentation](https://manual.bubble.io/core-resources/api/the-bubble-api/the-data-api/data-api-requests)", + version: "0.0.{{ts}}", + type: "source", + dedupe: "unique", + props: { + bubble, + db: "$.service.db", + workflowId: { + propDefinition: [ + bubble, + "workflowId", + ], + }, + timer: { + type: "$.interface.timer", + default: { + intervalSeconds: 60, + }, + }, + }, + hooks: { + async deploy() { + await this.emitEvents(); + }, + async activate() { + // Setup webhook or other necessary activation logic if required + }, + async deactivate() { + // Clean up webhook or other deactivation steps if required + }, + }, + methods: { + async emitEvents() { + const events = await this.bubble.listenForWorkflow({ + workflowId: this.workflowId, + }); + + for (const event of events.reverse()) { + this.$emit(event, { + summary: `New workflow event for ${event.workflow_id}`, + ts: new Date(event.timestamp).getTime(), + }); + } + }, + }, + async run() { + await this.emitEvents(); + }, +};