diff --git a/components/jigsawstack/actions/object-detection/object-detection.mjs b/components/jigsawstack/actions/object-detection/object-detection.mjs new file mode 100644 index 0000000000000..dccd2d1bcdbcc --- /dev/null +++ b/components/jigsawstack/actions/object-detection/object-detection.mjs @@ -0,0 +1,73 @@ +import { ConfigurationError } from "@pipedream/platform"; +import fs from "fs"; +import mime from "mime"; +import { + checkTmp, + throwError, +} from "../../common/utils.mjs"; +import jigsawstack from "../../jigsawstack.app.mjs"; + +export default { + key: "jigsawstack-object-detection", + name: "Object Detection", + description: "Recognize objects within a provided image and retrieve it with great accuracy. [See the documentation](https://docs.jigsawstack.com/api-reference/ai/object-detection)", + version: "0.0.1", + type: "action", + props: { + jigsawstack, + url: { + type: "string", + label: "Image URL", + description: "The URL of the image to process.", + optional: true, + }, + fileStoreKey: { + type: "string", + label: "File Store Key", + description: "The key used to store the image on Jigsawstack file [Storage](https://docs.jigsawstack.com/api-reference/store/file/add).", + optional: true, + }, + imageFile: { + type: "string", + label: "Image File", + description: "The path to a file in the `/tmp` directory. [See the documentation on working with files](https://pipedream.com/docs/code/nodejs/working-with-files/#writing-a-file-to-tmp).", + optional: true, + }, + }, + async run({ $ }) { + const { + jigsawstack, + ...data + } = this; + + if (Object.keys(data).length > 1) { + throw new ConfigurationError("You must provide only one option, either the **Image URL**, the **Image File**, or the **File Storage Key**."); + } + + if (data.fileStoreKey) data.file_store_key = data.fileStoreKey; + + if (data.imageFile) { + const filePath = checkTmp(data.imageFile); + const file = fs.readFileSync(filePath); + const { key } = await jigsawstack.uploadFile({ + headers: { + "Content-Type": mime.getType(filePath), + }, + data: file, + }); + data.file_store_key = key; + } + + try { + const response = await jigsawstack.detectObjectsInImage({ + $, + data, + }); + $.export("$summary", "Successfully detected objects in the image"); + return response; + + } catch (e) { + return throwError(e); + } + }, +}; diff --git a/components/jigsawstack/actions/sentiment-analysis/sentiment-analysis.mjs b/components/jigsawstack/actions/sentiment-analysis/sentiment-analysis.mjs new file mode 100644 index 0000000000000..265fe66969bb9 --- /dev/null +++ b/components/jigsawstack/actions/sentiment-analysis/sentiment-analysis.mjs @@ -0,0 +1,33 @@ +import { throwError } from "../../common/utils.mjs"; +import jigsawstack from "../../jigsawstack.app.mjs"; + +export default { + key: "jigsawstack-sentiment-analysis", + name: "Sentiment Analysis", + description: "Assess sentiment of a provided text. Vibes can be positive, negative, or neutral. [See the documentation](https://docs.jigsawstack.com/api-reference/ai/sentiment)", + version: "0.0.1", + type: "action", + props: { + jigsawstack, + text: { + type: "string", + label: "Text", + description: "The text to analyze for sentiment.", + }, + }, + async run({ $ }) { + try { + const response = await this.jigsawstack.analyzeSentiment({ + $, + data: { + text: this.text, + }, + }); + + $.export("$summary", `Successfully analyzed sentiment with emotion: ${response.sentiment.emotion} and sentiment: ${response.sentiment.sentiment}`); + return response; + } catch (e) { + return throwError(e); + } + }, +}; diff --git a/components/jigsawstack/actions/verify-email/verify-email.mjs b/components/jigsawstack/actions/verify-email/verify-email.mjs new file mode 100644 index 0000000000000..4d9eb4e7bba07 --- /dev/null +++ b/components/jigsawstack/actions/verify-email/verify-email.mjs @@ -0,0 +1,33 @@ +import { throwError } from "../../common/utils.mjs"; +import jigsawstack from "../../jigsawstack.app.mjs"; + +export default { + key: "jigsawstack-verify-email", + name: "Verify Email", + description: "Validate any email address and determine deliverability as well as disposable status. [See the documentation](https://docs.jigsawstack.com/api-reference/validate/email)", + version: "0.0.1", + type: "action", + props: { + jigsawstack, + email: { + type: "string", + label: "Email Address", + description: "The email address to validate.", + }, + }, + async run({ $ }) { + try { + const response = await this.jigsawstack.validateEmail({ + $, + params: { + email: this.email, + }, + }); + + $.export("$summary", `Successfully validated email: ${this.email}`); + return response; + } catch (e) { + return throwError(e); + } + }, +}; diff --git a/components/jigsawstack/common/utils.mjs b/components/jigsawstack/common/utils.mjs new file mode 100644 index 0000000000000..c6da433bcc10e --- /dev/null +++ b/components/jigsawstack/common/utils.mjs @@ -0,0 +1,13 @@ +import { ConfigurationError } from "@pipedream/platform"; + +export const throwError = ({ message }) => { + const errorMessage = JSON.parse(message).message; + throw new ConfigurationError(errorMessage); +}; + +export const checkTmp = (filename) => { + if (!filename.startsWith("/tmp")) { + return `/tmp/${filename}`; + } + return filename; +}; diff --git a/components/jigsawstack/jigsawstack.app.mjs b/components/jigsawstack/jigsawstack.app.mjs index c60d813849f6f..4a1173aaa5047 100644 --- a/components/jigsawstack/jigsawstack.app.mjs +++ b/components/jigsawstack/jigsawstack.app.mjs @@ -1,11 +1,54 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "jigsawstack", - propDefinitions: {}, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _baseUrl() { + return "https://api.jigsawstack.com/v1"; + }, + _headers(headers = {}) { + return { + "x-api-key": this.$auth.api_key, + ...headers, + }; + }, + _makeRequest({ + $ = this, path, headers, ...opts + }) { + return axios($, { + url: this._baseUrl() + path, + headers: this._headers(headers), + ...opts, + }); + }, + validateEmail(opts = {}) { + return this._makeRequest({ + method: "GET", + path: "/validate/email", + ...opts, + }); + }, + detectObjectsInImage(opts = {}) { + return this._makeRequest({ + method: "POST", + path: "/ai/object_detection", + ...opts, + }); + }, + analyzeSentiment(opts = {}) { + return this._makeRequest({ + method: "POST", + path: "/ai/sentiment", + ...opts, + }); + }, + uploadFile(opts = {}) { + return this._makeRequest({ + method: "POST", + path: "/store/file", + ...opts, + }); }, }, -}; \ No newline at end of file +}; diff --git a/components/jigsawstack/package.json b/components/jigsawstack/package.json index 17425b3cfac14..f24bbbce6698c 100644 --- a/components/jigsawstack/package.json +++ b/components/jigsawstack/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/jigsawstack", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream JigsawStack Components", "main": "jigsawstack.app.mjs", "keywords": [ @@ -11,5 +11,10 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^3.0.1", + "form-data": "^4.0.0", + "mime": "^4.0.4" } -} \ No newline at end of file +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c60247f5bfb99..1b77b4bbbe8b4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4856,7 +4856,14 @@ importers: '@pipedream/platform': 1.5.1 components/jigsawstack: - specifiers: {} + specifiers: + '@pipedream/platform': ^3.0.1 + form-data: ^4.0.0 + mime: ^4.0.4 + dependencies: + '@pipedream/platform': 3.0.1 + form-data: 4.0.0 + mime: 4.0.4 components/jira: specifiers: @@ -29758,6 +29765,12 @@ packages: hasBin: true dev: false + /mime/4.0.4: + resolution: {integrity: sha512-v8yqInVjhXyqP6+Kw4fV3ZzeMRqEW6FotRsKXjRS5VMTNIuXsdRoAvklpoRgSqXm6o9VNH4/C0mgedko9DdLsQ==} + engines: {node: '>=16'} + hasBin: true + dev: false + /mimer/2.0.2: resolution: {integrity: sha512-izxvjsB7Ur5HrTbPu6VKTrzxSMBFBqyZQc6dWlZNQ4/wAvf886fD4lrjtFd8IQ8/WmZKdxKjUtqFFNaj3hQ52g==} engines: {node: '>= 12'}