From b049151983e85aa0ea98f18cf6f519c837e4023f Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Thu, 26 Dec 2024 04:05:11 -0300 Subject: [PATCH 01/11] Cloudinary package update --- components/cloudinary/package.json | 4 +- pnpm-lock.yaml | 61 +++++++++++------------------- 2 files changed, 24 insertions(+), 41 deletions(-) diff --git a/components/cloudinary/package.json b/components/cloudinary/package.json index 34c788ff64dd6..42cacde9d0114 100644 --- a/components/cloudinary/package.json +++ b/components/cloudinary/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/cloudinary", - "version": "0.0.2", + "version": "0.1.0", "description": "Pipedream Cloudinary Components", "main": "cloudinary.app.mjs", "keywords": [ @@ -13,6 +13,6 @@ "access": "public" }, "dependencies": { - "cloudinary": "^1.36.1" + "cloudinary": "^2.5.1" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f962481c76f90..2663db8af24d8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -94,8 +94,8 @@ importers: specifier: ^12.3.4 version: 12.5.0(enquirer@2.4.1) pnpm: - specifier: 9.14.2 - version: 9.14.2 + specifier: 9.14.3 + version: 9.14.3 putout: specifier: '>=36' version: 36.13.1(eslint@8.57.1)(typescript@5.6.3) @@ -1233,8 +1233,7 @@ importers: components/bluecart_api: {} - components/bluesky: - specifiers: {} + components/bluesky: {} components/bluesky_by_unshape: dependencies: @@ -1973,8 +1972,8 @@ importers: components/cloudinary: dependencies: cloudinary: - specifier: ^1.36.1 - version: 1.41.3 + specifier: ^2.5.1 + version: 2.5.1 components/cloudlayer: {} @@ -12217,10 +12216,10 @@ importers: version: 14.2.19(@babel/core@8.0.0-alpha.13)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) nextra: specifier: latest - version: 3.3.0(@types/react@18.3.12)(acorn@8.14.0)(next@14.2.19(@babel/core@8.0.0-alpha.13)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3) + version: 3.3.1(@types/react@18.3.12)(acorn@8.14.0)(next@14.2.19(@babel/core@8.0.0-alpha.13)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3) nextra-theme-docs: specifier: latest - version: 3.3.0(next@14.2.19(@babel/core@8.0.0-alpha.13)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@3.3.0(@types/react@18.3.12)(acorn@8.14.0)(next@14.2.19(@babel/core@8.0.0-alpha.13)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 3.3.1(next@14.2.19(@babel/core@8.0.0-alpha.13)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@3.3.1(@types/react@18.3.12)(acorn@8.14.0)(next@14.2.19(@babel/core@8.0.0-alpha.13)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: specifier: ^18.3.1 version: 18.3.1 @@ -18040,14 +18039,9 @@ packages: cloudflare@2.9.1: resolution: {integrity: sha512-x8yXPPoloy7xQ9GCKnsvQ3U1nwvcLndA2B3nxwSjIWxgLTUJOyakeEDsrqxZO8Dr6FkGdaXwy554fQVMpOabiw==} - cloudinary-core@2.13.1: - resolution: {integrity: sha512-z53GPNWnvU0Zi+ns8CIVbZBfj7ps/++zDvwIyiFuq5p1MoK+KUCg0k5mBceDDHTnx1gHmHUd9aohS+gDxPNt6w==} - peerDependencies: - lodash: '>=4.0' - - cloudinary@1.41.3: - resolution: {integrity: sha512-4o84y+E7dbif3lMns+p3UW6w6hLHEifbX/7zBJvaih1E9QNMZITENQ14GPYJC4JmhygYXsuuBb9bRA3xWEoOfg==} - engines: {node: '>=0.6'} + cloudinary@2.5.1: + resolution: {integrity: sha512-CNg6uU53Hl4FEVynkTGpt5bQEAQWDHi3H+Sm62FzKf5uQHipSN2v7qVqS8GRVqeb0T1WNV+22+75DOJeRXYeSQ==} + engines: {node: '>=9'} clsx@2.1.1: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} @@ -18247,9 +18241,6 @@ packages: core-js-compat@3.39.0: resolution: {integrity: sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw==} - core-js@3.39.0: - resolution: {integrity: sha512-raM0ew0/jJUqkJ0E6e8UDtl+y/7ktFivgWvqw8dNSQeNWoSDLvQ1H/RN3aPXB9tBd4/FhyR4RDPGhsNIMsAn7g==} - core-util-is@1.0.2: resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} @@ -22396,16 +22387,16 @@ packages: sass: optional: true - nextra-theme-docs@3.3.0: - resolution: {integrity: sha512-4JSbDmsbtaYa2eKHsNymWy6So4/fAAXuNPSkjgQ3S+aLRiC730mR9djdkTd1iRca4+czetzBWaqxu+HwTVSSCA==} + nextra-theme-docs@3.3.1: + resolution: {integrity: sha512-P305m2UcW2IDyQhjrcAu0qpdPArikofinABslUCAyixYShsmcdDRUhIMd4QBHYru4gQuVjGWX9PhWZZCbNvzDQ==} peerDependencies: next: '>=13' - nextra: 3.3.0 + nextra: 3.3.1 react: '>=18' react-dom: '>=18' - nextra@3.3.0: - resolution: {integrity: sha512-//+bQW3oKrpLrrIFD5HJow310+YcNYhGIgdM4y+EjYuIXScJcgp6Q4Upsq8c2s2fQKEJjeuf+hXKusx9fvH/2w==} + nextra@3.3.1: + resolution: {integrity: sha512-jiwj+LfUPHHeAxJAEqFuglxnbjFgzAOnDWFsjv7iv3BWiX8OksDwd3I2Sv3j2zba00iIBDEPdNeylfzTtTLZVg==} engines: {node: '>=18'} peerDependencies: next: '>=13' @@ -23074,8 +23065,8 @@ packages: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} engines: {node: '>=4'} - pnpm@9.14.2: - resolution: {integrity: sha512-biuvd9Brk2IpQVLIUcTyeO3jerHro6Vf2jF6SheyCfTbuXP7JQp3q8Rjo0H8sfF/F8+iQJHE6zGc2g2bhCeDhw==} + pnpm@9.14.3: + resolution: {integrity: sha512-wPU+6ZR37ZabgrKJrQEaXRa/FiPJV+fynqvo0MALV0wpuMf1T2xn7nEMc/KFyBVNB85EtG/iwO60dqkEQbrDcQ==} engines: {node: '>=18.12'} hasBin: true @@ -33843,15 +33834,9 @@ snapshots: transitivePeerDependencies: - supports-color - cloudinary-core@2.13.1(lodash@4.17.21): + cloudinary@2.5.1: dependencies: lodash: 4.17.21 - - cloudinary@1.41.3: - dependencies: - cloudinary-core: 2.13.1(lodash@4.17.21) - core-js: 3.39.0 - lodash: 4.17.21 q: 1.5.1 clsx@2.1.1: {} @@ -34059,8 +34044,6 @@ snapshots: dependencies: browserslist: 4.24.2 - core-js@3.39.0: {} - core-util-is@1.0.2: {} core-util-is@1.0.3: {} @@ -39625,7 +39608,7 @@ snapshots: - '@babel/core' - babel-plugin-macros - nextra-theme-docs@3.3.0(next@14.2.19(@babel/core@8.0.0-alpha.13)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@3.3.0(@types/react@18.3.12)(acorn@8.14.0)(next@14.2.19(@babel/core@8.0.0-alpha.13)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + nextra-theme-docs@3.3.1(next@14.2.19(@babel/core@8.0.0-alpha.13)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@3.3.1(@types/react@18.3.12)(acorn@8.14.0)(next@14.2.19(@babel/core@8.0.0-alpha.13)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@headlessui/react': 2.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) clsx: 2.1.1 @@ -39633,13 +39616,13 @@ snapshots: flexsearch: 0.7.43 next: 14.2.19(@babel/core@8.0.0-alpha.13)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) next-themes: 0.4.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - nextra: 3.3.0(@types/react@18.3.12)(acorn@8.14.0)(next@14.2.19(@babel/core@8.0.0-alpha.13)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3) + nextra: 3.3.1(@types/react@18.3.12)(acorn@8.14.0)(next@14.2.19(@babel/core@8.0.0-alpha.13)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) scroll-into-view-if-needed: 3.1.0 zod: 3.23.8 - nextra@3.3.0(@types/react@18.3.12)(acorn@8.14.0)(next@14.2.19(@babel/core@8.0.0-alpha.13)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3): + nextra@3.3.1(@types/react@18.3.12)(acorn@8.14.0)(next@14.2.19(@babel/core@8.0.0-alpha.13)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3): dependencies: '@formatjs/intl-localematcher': 0.5.8 '@headlessui/react': 2.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -40448,7 +40431,7 @@ snapshots: pluralize@8.0.0: {} - pnpm@9.14.2: {} + pnpm@9.14.3: {} points-on-curve@0.2.0: {} From 531d3d92fa9ae408d19682698c04c76978e6b1a4 Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Thu, 26 Dec 2024 04:05:24 -0300 Subject: [PATCH 02/11] Get Account Usage improvements and error handling --- .../get-account-usage-details.mjs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/components/cloudinary/actions/get-account-usage-details/get-account-usage-details.mjs b/components/cloudinary/actions/get-account-usage-details/get-account-usage-details.mjs index 51ab42c2a2759..623587d99f4e8 100644 --- a/components/cloudinary/actions/get-account-usage-details/get-account-usage-details.mjs +++ b/components/cloudinary/actions/get-account-usage-details/get-account-usage-details.mjs @@ -3,15 +3,20 @@ import cloudinary from "../../cloudinary.app.mjs"; export default { key: "cloudinary-get-account-usage-details", name: "Get Account Usage Details", - description: "Enables you to get a report on the status of your Cloudinary account usage details, including storage, credits, bandwidth, requests, number of resources, and add-on usage. [See the documentation](https://cloudinary.com/documentation/admin_api#usage)", - version: "0.1.2", + description: "Gets a report of your Cloudinary account usage details, including storage, credits, bandwidth, requests, number of resources, and add-on usage. [See the documentation](https://cloudinary.com/documentation/admin_api#usage)", + version: "0.2.{{ts}}", type: "action", props: { cloudinary, + dateInfo: { + type: "alert", + alertType: "info", + content: "If `Date` is not specified, it defaults to the current date." + }, date: { type: "string", label: "Date", - description: "The date for the usage report. Must be within the last 3 months and given in the format: `dd-mm-yyyy`. Default: the current date", + description: "The date for the usage report, in the `yyyy-mm-dd` format, e.g. `2019-07-21`. Must be between yesterday and the last 3 months.", optional: true, }, }, @@ -20,12 +25,17 @@ export default { date: this.date, }; + try { const response = await this.cloudinary.getUsage(options); if (response) { - $.export("$summary", "Successfully retrieved usage details."); + $.export("$summary", "Successfully retrieved usage details"); } return response; + } + catch (err) { + throw new Error(`Cloudinary error response: ${err.error?.message ?? JSON.stringify(err)}`); + } }, }; From 13b882281bc0817f519f53e593f388e307341e1f Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Thu, 26 Dec 2024 04:16:30 -0300 Subject: [PATCH 03/11] Get Resources improvements & error handling --- .../get-account-usage-details.mjs | 18 +++--- .../actions/get-resources/get-resources.mjs | 58 +++++++++++-------- components/cloudinary/cloudinary.app.mjs | 4 +- 3 files changed, 46 insertions(+), 34 deletions(-) diff --git a/components/cloudinary/actions/get-account-usage-details/get-account-usage-details.mjs b/components/cloudinary/actions/get-account-usage-details/get-account-usage-details.mjs index 623587d99f4e8..f5f58dbf7b451 100644 --- a/components/cloudinary/actions/get-account-usage-details/get-account-usage-details.mjs +++ b/components/cloudinary/actions/get-account-usage-details/get-account-usage-details.mjs @@ -11,7 +11,7 @@ export default { dateInfo: { type: "alert", alertType: "info", - content: "If `Date` is not specified, it defaults to the current date." + content: "If `Date` is not specified, it defaults to the current date.", }, date: { type: "string", @@ -26,16 +26,16 @@ export default { }; try { - const response = await this.cloudinary.getUsage(options); + const response = await this.cloudinary.getUsage(options); - if (response) { - $.export("$summary", "Successfully retrieved usage details"); - } + if (response) { + $.export("$summary", "Successfully retrieved usage details"); + } - return response; - } - catch (err) { + return response; + } + catch (err) { throw new Error(`Cloudinary error response: ${err.error?.message ?? JSON.stringify(err)}`); - } + } }, }; diff --git a/components/cloudinary/actions/get-resources/get-resources.mjs b/components/cloudinary/actions/get-resources/get-resources.mjs index 4ef4f0c8eb191..ed4dd09d32fe4 100644 --- a/components/cloudinary/actions/get-resources/get-resources.mjs +++ b/components/cloudinary/actions/get-resources/get-resources.mjs @@ -4,7 +4,7 @@ export default { key: "cloudinary-get-resources", name: "Get Resources", description: "Lists resources (assets) uploaded to your product environment. [See the documentation](https://cloudinary.com/documentation/admin_api#get_resources)", - version: "0.0.1", + version: "0.1.{{ts}}", type: "action", props: { cloudinary, @@ -22,28 +22,35 @@ export default { }, prefix: { type: "string", - label: "Prefix", - description: "Find all assets with a public ID that starts with the specified prefix", + label: "Filter by Prefix", + description: "Find all assets with a public ID that starts with the specified prefix.", optional: true, }, tags: { type: "boolean", - label: "Tags", - description: "Whether to include the list of tag names assigned to each asset", + label: "Include Tags", + description: "Whether to include the list of tag names assigned to each asset.", default: false, optional: true, }, context: { type: "boolean", - label: "Context", - description: "Whether to include key-value pairs of contextual metadata associated with each asset", + label: "Include Context", + description: "Whether to include key-value pairs of contextual metadata associated with each asset.", + default: false, + optional: true, + }, + metadata: { + type: "boolean", + label: "Include Metadata", + description: "Whether to include the structured metadata fields and values assigned to each asset.", default: false, optional: true, }, moderation: { type: "boolean", - label: "Moderation", - description: "Whether to include the image moderation status of each asset", + label: "Include Moderation", + description: "Whether to include the image moderation status of each asset.", default: false, optional: true, }, @@ -66,22 +73,27 @@ export default { }; const resources = []; - let next; - do { - const response = await this.cloudinary.getResources(options); - resources.push(...response.resources); - next = response.next_cursor; - options.next_cursor = next; - } while (next && resources.length < this.maxResults); + try { + let next; + do { + const response = await this.cloudinary.getResources(options); + resources.push(...response.resources); + next = response.next_cursor; + options.next_cursor = next; + } while (next && resources.length < this.maxResults); - if (resources.length > this.maxResults) { - resources.length = this.maxResults; - } + if (resources.length > this.maxResults) { + resources.length = this.maxResults; + } - $.export("$summary", `Found ${resources.length} resource${resources.length === 1 - ? "" - : "s"}.`); + $.export("$summary", `Retrieved ${resources.length} resource${resources.length === 1 + ? "" + : "s"}`); - return resources; + return resources; + } + catch (err) { + throw new Error(`Cloudinary error response: ${err.error?.message ?? JSON.stringify(err)}`); + } }, }; diff --git a/components/cloudinary/cloudinary.app.mjs b/components/cloudinary/cloudinary.app.mjs index ce1be88cb1fb9..a519e825a7e61 100644 --- a/components/cloudinary/cloudinary.app.mjs +++ b/components/cloudinary/cloudinary.app.mjs @@ -8,7 +8,7 @@ export default { resourceType: { type: "string", label: "Resource Type", - description: "The type of asset. Defaults to `image` if left blank", + description: "The type of asset. Defaults to `image` if not specified. `Note:` use video for all video and audio assets, such as `.mp3`. ", options: constants.RESOURCE_TYPE_OPTIONS, default: "image", optional: true, @@ -32,7 +32,7 @@ export default { deliveryType: { type: "string", label: "Type", - description: "The delivery type. Defaults to `upload` if left blank", + description: "The delivery type. Defaults to `upload` if not specified.", options: constants.DELIVERY_TYPE_OPTIONS, default: "upload", optional: true, From b474087c3947446d4d859a98f318523509b10e26 Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Thu, 26 Dec 2024 21:24:02 -0300 Subject: [PATCH 04/11] Upload Media reworked and simplified --- .../upload-media-asset/upload-media-asset.mjs | 284 ++---------------- components/cloudinary/cloudinary.app.mjs | 8 +- 2 files changed, 35 insertions(+), 257 deletions(-) diff --git a/components/cloudinary/actions/upload-media-asset/upload-media-asset.mjs b/components/cloudinary/actions/upload-media-asset/upload-media-asset.mjs index c9d8378287e92..cffcfdfeeae5a 100644 --- a/components/cloudinary/actions/upload-media-asset/upload-media-asset.mjs +++ b/components/cloudinary/actions/upload-media-asset/upload-media-asset.mjs @@ -3,20 +3,25 @@ import cloudinary from "../../cloudinary.app.mjs"; export default { key: "cloudinary-upload-media-asset", name: "Upload Media Asset", - description: "Uploads media assets in the cloud such as images or videos, and allows configuration options to be set on the upload. [See the documentation](https://cloudinary.com/documentation/image_upload_api_reference#upload_method)", - version: "0.5.3", + description: "Upload media assets such as images or videos. [See the documentation](https://cloudinary.com/documentation/image_upload_api_reference#upload_method)", + version: "1.0.{{ts}}", type: "action", props: { cloudinary, + infoAlert: { + type: "alert", + alertType: "info", + content: `Cloudinary offers a large amount of options to customize your asset upload. You can set any available options in the \`Additional Options\` prop. [See the Cloudinary documentation for more information.](https://cloudinary.com/documentation/image_upload_api_reference#upload_method)` + }, file: { type: "string", - label: "File", - description: "The file to upload. It can be:\n* a local file path\n* the actual data (byte array buffer).\nFor example, this could be an IO input stream of the data (e.g., File.open(file, \"rb\")).\n* the Data URI (Base64 encoded), max ~60 MB (62,910,000 chars)\n* the remote FTP, HTTP or HTTPS URL address of an existing file\n* a private storage bucket (S3 or Google Storage) URL of a **whitelisted** bucket\nFor details and examples, see: [file source options](https://cloudinary.com/documentation/upload_images#file_source_options).", + label: "File Path or URL", + description: "The file to upload. You can provide a file path from the `/tmp` folder (e.g. `/tmp/myFile.jpg`) or a public file URL, among other options supported by Cloudinary ([see the documentation](https://cloudinary.com/documentation/upload_images#file_source_options) for available options).", }, publicId: { type: "string", label: "Public Id", - description: "The identifier that is used for accessing the uploaded asset. The Public ID may contain a full path including folders separated by a slash (`/`).\nIf not specified, then the Public ID of the asset will either be comprised of random characters or will use the original file's filename, depending whether `use_filename` was set to true.\n\n**Note**: The Public ID value for images and videos should not include a file extension. Include the file extension for `raw` files only.", + description: "The identifier that is used for accessing the uploaded asset. [See the documentation](https://cloudinary.com/documentation/image_upload_api_reference#upload_method) for more information.", optional: true, }, folder: { @@ -25,18 +30,6 @@ export default { description: "An optional folder name where the uploaded asset will be stored. The public ID contains the full path of the uploaded asset, including the folder name.", optional: true, }, - useFilename: { - type: "boolean", - label: "Use Filename", - description: "Whether to use the original file name of the uploaded asset. Relevant only if the `public_id` parameter isn't set.\nWhen false and the `public_id` parameter is also not defined, the Public ID will be comprised of random characters.\n\nWhen true and the `public_id` parameter is not defined, the uploaded file's original filename becomes the Public ID. Random characters are appended to the filename value to ensure Public ID uniqueness if `unique_filename` is true.\n\nDefault: `false`.", - optional: true, - }, - uniqueFilename: { - type: "boolean", - label: "Unique Filename", - description: "When set to false, does not add random characters at the end of the filename that guarantee its uniqueness. In this case, if the `overwrite` parameter is also false, the upload returns an error. This parameter is relevant only if `use_filename` is also set to true. Default: `true`.", - optional: true, - }, resourceType: { propDefinition: [ cloudinary, @@ -49,178 +42,22 @@ export default { "uploadDeliveryType", ], }, - accessControl: { - type: "boolean", - label: "Access Control", - description: "An array of access types for the asset. The asset is accessible as long as one of the access types is valid.\nPossible values for each access type:\n\n- `token` requires either [Token-based authentication](https://cloudinary.com/documentation/control_access_to_media#token_based_authentication_premium_feature) or [Cookie-based authentication](https://cloudinary.com/documentation/control_access_to_media#cookie_based_authentication_premium_feature) for accessing the asset.\nFor example: `access_type: \"token\"`\n- `anonymous` allows public access to the asset. The anonymous access type can optionally include `start` and/or `end` dates (in ISO 8601 format) that define when the asset is publically available. Note that you can only include a single 'anonymous' access type. For example:\n`access_type: \"anonymous\", start: \"2017-12-15T12:00Z\", end: \"2018-01-20T12:00Z\"`", - optional: true, - }, accessMode: { propDefinition: [ cloudinary, "accessMode", ], }, - discardOriginalFilename: { - type: "boolean", - label: "Discard Original Filename", - description: "Whether to discard the name of the original uploaded file. Relevant when delivering assets as attachments (setting the `flag` transformation parameter to `attachment`). Default: `false`.", - optional: true, - }, - overwrite: { - type: "boolean", - label: "Overwrite", - description: "Whether to overwrite existing assets with the same public ID. When set to false, return immediately if an asset with the same Public ID was found. Default: `true` (when using unsigned upload, the default is false and cannot be changed to true).\n**Important**: Depending on the settings for your account, overwriting an asset may clear the tags, contextual, and structured metadata values for that asset. If you prefer these values to always be preserved on overwrite (unless other values are specifically set when uploading the new version), you can [submit a request](https://support.cloudinary.com/hc/en-us/requests/new) to change this behavior for your account.", - optional: true, - }, tags: { - type: "any", + type: "string[]", label: "Tags", description: "An array of tag names to assign to the uploaded asset for later group reference.", optional: true, }, - context: { - type: "object", - label: "Context", - description: "A map of the key-value pairs of general textual context metadata to attach to an uploaded asset. The context values of uploaded files can be retrieved using the Admin API. For example: `alt=My image?caption=Profile image` (the `=` and `?` characters can be supported as values when escaped with a prepended backslash (`\\`)). Note that key values are limited to 1024 characters and an asset can have a maximum of 1000 context key-value pairs.", - optional: true, - }, - colors: { - type: "boolean", - label: "Colors", - description: "Whether to retrieve predominant colors & color histogram of the uploaded image.\n**Note:** If all returned colors are opaque, then 6-digit RGB hex values are returned. If one or more colors contain an alpha channel, then 8-digit RGBA hex quadruplet values are returned.\nDefault: `false`. Relevant for images only.", - optional: true, - }, - faces: { - type: "boolean", - label: "Faces", - description: "Whether to return the coordinates of faces contained in an uploaded image (automatically detected or manually defined). Each face is specified by the X & Y coordinates of the top left corner and the width & height of the face. The coordinates for each face are returned as an array (using the SDKs), and individual faces are separated with a pipe (`?`). For example: `10,20,150,130?213,345,82,61`.\nDefault: `false`. Relevant for images only.", - optional: true, - }, - qualityAnalysis: { - type: "boolean", - label: "Quality Analysis", - description: "Whether to return a quality analysis value for the image between 0 and 1, where 0 means the image is blurry and out of focus and 1 means the image is sharp and in focus. Default: `false`. Relevant for images only.\nPaid customers can [request to take part](https://support.cloudinary.com/hc/en-us/requests/new) in the extended quality analysis Beta trial. When activated, this parameter returns quality scores for various other factors in addition to `focus`, such as `jpeg_quality`, `noise`, `exposure`, `lighting` and `resolution`, together with an overall weighted `quality_score`. The `quality_score`, `color_quality_score` and `pixel_quality_score` fields can be used in the Search API.", - optional: true, - }, - accessibilityAnalysis: { - type: "boolean", - label: "Accessibility Analysis", - description: "Currently available only to paid customers [requesting to take part](https://support.cloudinary.com/hc/en-us/requests/new) in the [accessibility analysis](https://cloudinary.com/documentation/analysis_on_upload#accessibility_analysis) Beta trial. Set to `true` to return accessibility analysis values for the image and to enable the `colorblind_accessibility_score` field to be used in the Search API.\nDefault: `false`. Relevant for images only.", - optional: true, - }, - cinemagraphAnalysis: { - type: "boolean", - label: "Cinemagraph Analysis", - description: "Whether to return a cinemagraph analysis value for the media asset between 0 and 1, where 0 means the asset is **not** a cinemagraph and 1 means the asset **is** a cinemagraph. Default: `false`. Relevant for animated images and video only. A static image will return 0.", - optional: true, - }, - imageMetadata: { - type: "string", - label: "Image Metadata", - description: "Whether to return IPTC, XMP, and detailed Exif metadata of the uploaded asset in the response.\nDefault: `false`. Supported for images, video, and audio.\nReturned metadata for images includes: `PixelsPerUnitX`, `PixelsPerUnitY`, `PixelUnits`, `Colorspace`, and `DPI`.\nReturned metadata for audio and video includes: `audio_codec`, `audio_bit_rate`, `audio_frequency`, `channels`, `channel_layout`.\nAdditional metadata for video includes: `pix_format`, `codec`, `level`, `profile`, `video_bit_rate`, `dar`.", - optional: true, - }, - phash: { - type: "boolean", - label: "pHash", - description: "Whether to return the perceptual hash (pHash) on the uploaded image. The pHash acts as a fingerprint that allows checking image similarity.\nDefault: `false`. Relevant for images only.", - optional: true, - }, - responsiveBreakpoints: { - type: "object", - label: "Responsive Breakpoints", - description: "Requests that Cloudinary automatically find the best breakpoints. The parameter value is an array of breakpoint request settings, where each request setting can include the following parameters:\n* `create_derived`(Boolean - Required) If true, create and keep the derived images of the selected breakpoints during the API call. If false, images * generated during the analysis process are thrown away.\n* `format` (String - Optional) Sets the file extension of the derived resources to the format indicated (as opposed to changing the format as part of a transformation - which would be included as part of the transformation component (e.g., f_jpg)).\n* `transformation` (String - Optional) The base transformation to first apply to the image before finding the best breakpoints. The API accepts a string representation of a chained transformation (same as the regular transformation parameter of the upload API).\n* `max_width` (Integer - Optional) The maximum width needed for this image. If specifying a width bigger than the original image, the width of the original image is used instead. Default: `1000`.\n* `min_width` (Integer - Optional) The minimum width needed for this image. Default: `50`.\n* `bytes_step` (Integer - Optional) The minimum number of bytes between two consecutive breakpoints (images). Default: `20000`.\n* `max_images` (Integer - Optional) The maximum number of breakpoints to find, between 3 and 200. This means that there might be size differences bigger than the given bytes_step value between consecutive images. Default: `20`.\nThe return response will include an array of the selected breakpoints for each breakpoint request, where the following information is given for each breakpoint: `transformation`, `width`, `height`, `bytes`, `url` and `secure_url`.\nRelevant for images only.", - optional: true, - }, - autoTagging: { - type: "integer", - label: "Auto Tagging", - description: "Whether to assign tags to an asset according to detected scene categories with a confidence score higher than the given value (between 0.0 and 1.0). See the [Google Automatic Video Tagging](https://cloudinary.com/documentation/google_automatic_video_tagging_addon), [Google Auto Tagging](https://cloudinary.com/documentation/google_auto_tagging_addon), [Imagga Auto Tagging](https://cloudinary.com/documentation/imagga_auto_tagging_addon), [Amazon Rekognition Auto Tagging](https://cloudinary.com/documentation/aws_rekognition_auto_tagging_addon), and [Amazon Rekognition Celebrity Detection](https://cloudinary.com/documentation/aws_rekognition_celebrity_and_face_detection_addon) add-ons for more details.", - optional: true, - }, - categorization: { - type: "string", - label: "Categorization", - description: "A comma-separated list of the categorization add-ons to run on the asset. Set to `google_tagging`, `google_video_tagging`, `imagga_tagging` and/or `aws_rek_tagging` to automatically classify the scenes of the uploaded asset. See the [Google Automatic Video Tagging](https://cloudinary.com/documentation/google_automatic_video_tagging_addon), [Google Auto Tagging](https://cloudinary.com/documentation/google_auto_tagging_addon), [Imagga Auto Tagging](https://cloudinary.com/documentation/imagga_auto_tagging_addon), and [Amazon Rekognition Auto Tagging](https://cloudinary.com/documentation/aws_rekognition_auto_tagging_addon) add-ons for more details.", - optional: true, - }, - detection: { - type: "string", - label: "Detection", - description: "Set to `adv_face` or `aws_rek_face` to extract an extensive list of face attributes from an image using the [Advanced Facial Attribute Detection](https://cloudinary.com/documentation/advanced_facial_attributes_detection_addon) or [Amazon Rekognition Celebrity Detection](https://cloudinary.com/documentation/aws_rekognition_celebrity_and_face_detection_addon) add-ons.\nRelevant for images only.", - optional: true, - }, - ocr: { - type: "string", - label: "OCR", - description: "Set to `adv_ocr` to extract all text elements in an image as well as the bounding box coordinates of each detected element using the [OCR text detection and extraction add-on](https://cloudinary.com/documentation/ocr_text_detection_and_extraction_addon). Relevant for images only.", - optional: true, - }, - eager: { - type: "any", - label: "Eager", - description: "An array of transformation representations. This generates derived resources in advance, instead of lazily creating each of the derived resources when first accessed by your site's visitors.", - optional: true, - }, - eagerAsync: { - type: "boolean", - label: "Eager Async", - description: "Whether to generate the eager transformations asynchronously in the background after the upload request is completed rather than online as part of the upload call. Default: `false`", - optional: true, - }, - eagerNotificationUrl: { - type: "string", - label: "Eager Notification URL", - description: "An HTTP or HTTPS URL to send a notification to (a webhook) when the generation of eager transformations is completed.", - optional: true, - }, - transformation: { - type: "string", - label: "Transformation", - description: "An incoming transformation to run on the uploaded asset before saving it in the cloud. T his parameter is given as a hash of transformation parameters (or an array of hashes for chained transformations).", - optional: true, - }, format: { type: "string", - label: "Format", - description: "An optional format to convert the uploaded asset to before saving in the cloud. For example: `jpg`.", - optional: true, - }, - customCoordinates: { - type: "any", - label: "Custom Coordinates", - description: "Sets the coordinates of a single region contained in an uploaded image that is subsequently used for cropping uploaded images using the `custom` gravity mode. The region is specified by the X & Y coordinates of the top left corner and the width & height of the region, as an array. For example: `85,120,220,310.`\nRelevant for images only.", - optional: true, - }, - faceCoordinates: { - type: "any", - label: "Face Coordinates", - description: "Sets the coordinates of faces contained in an uploaded image and overrides the automatically detected faces. Each face is specified by the X & Y coordinates of the top left corner and the width & height of the face. The coordinates for each face are given as an array.\nRelevant for images only.", - optional: true, - }, - backgroundRemoval: { - type: "string", - label: "Background Removal", - description: "Automatically remove the background of an image using an add-on.\nSet to `cloudinary_ai` to use the deep-learning based [Cloudinary AI Background Removal](https://cloudinary.com/documentation/cloudinary_ai_background_removal_addon) add-on.\nSet to `pixelz` to use the human-powered [Pizelz Remove-The-Background Editing](https://cloudinary.com/documentation/remove_the_background_image_editing_addon) add-on service.\nRelevant for images only.", - optional: true, - }, - rawConvert: { - type: "string", - label: "Raw Convert", - description: "Asynchronously generates a related file based on the uploaded file.\n* Set to `aspose` to automatically create a PDF or other image format from a `raw` Office document using the [Aspose Document Conversion](https://cloudinary.com/documentation/aspose_document_conversion_addon) add-on.\n* Set to `google_speech` to instruct the [Google AI Video Transcription](https://cloudinary.com/documentation/google_ai_video_transcription_addon) add-on to generate an automatic transcript `raw` file from an uploaded video.\n* Set to `extract_text` to extract all the text from a PDF file and store it in a raw file. The public ID of the generated `raw` file will be in the format: **[pdf_public_id].extract_text.json.**\nSee also: [Converting raw files](https://cloudinary.com/documentation/upload_images#converting_raw_files).", - optional: true, - }, - allowedFormats: { - type: "any", - label: "Allowed Formats", - description: "An array of file formats that are allowed for uploading. Files of other types will be rejected. The formats can be any combination of image types, video formats or raw file extensions. For example: `mp4,ogv,jpg,png,pdf`. Default: any supported format for images and videos, and any kind of raw file (i.e. no restrictions by default).", - optional: true, - }, - async: { - type: "boolean", - label: "Async", - description: "Whether to perform the request in the background (asynchronously). Default: `false`.", + label: "Convert to Format", + description: "An optional format to convert the uploaded asset to before saving in the cloud, e.g. `jpg`.", optional: true, }, backup: { @@ -229,104 +66,45 @@ export default { description: "Tell Cloudinary whether to [back up](https://cloudinary.com/documentation/backups_and_version_management) the uploaded asset. Overrides the default backup settings of your account.", optional: true, }, - eval: { - type: "string", - label: "Eval", - description: "Allows you to modify upload parameters by specifying custom logic with JavaScript. This can be useful for conditionally adding tags, context, metadata or eager transformations depending on specific criteria of the uploaded file. For more details see [Evaluating and modifying upload parameters](https://cloudinary.com/documentation/analysis_on_upload#evaluating_and_modifying_upload_parameters).", - optional: true, - }, - headers: { - type: "string", - label: "Headers", - description: "An HTTP header or a list of headers lines for adding as response HTTP headers when delivering the asset to your users. Supported headers: `Link`, `Authorization`, `X-Robots-Tag`. For example: `X-Robots-Tag: noindex`.", - optional: true, - }, - invalidate: { - type: "boolean", - label: "Invalidate", - description: "Whether to invalidate CDN cached copies of a previously uploaded asset (and all transformed versions that share the same Public ID). Default: `false`.\nIt usually takes between a few seconds and a few minutes for the invalidation to fully propagate through the CDN. There are also a number of other [important considerations](https://cloudinary.com/documentation/managing_assets#invalidating_cached_media_assets_on_the_cdn) when using the invalidate functionality.", - optional: true, - }, - moderation: { - type: "string", - label: "Moderation", - description: "**For all asset types**: Set to `manual` to add the uploaded asset to a queue of pending assets that can be moderated using the Admin API or the [Cloudinary Management Console](https://cloudinary.com/console/media_library), or set to `metascan` to automatically moderate the uploaded asset using the [MetaDefender Anti-Malware Protection](https://cloudinary.com/documentation/metadefender_anti_malware_protection_addon) add-on.\n**For images only**: Set to `webpurify` or `aws_rek` to automatically moderate the uploaded image using the [WebPurify Image Moderation](https://cloudinary.com/documentation/webpurify_image_moderation_addon) add-on or the [Amazon Rekognition AI Moderation](https://cloudinary.com/documentation/aws_rekognition_ai_moderation_addon) add-on respectively.", - optional: true, - }, - notificationUrl: { - type: "string", - label: "Notification URL", - description: "An HTTP or HTTPS URL to receive the upload response (a webhook) when the upload or any requested asynchronous action is completed. If not specified, the response is sent to the global **Notification URL** (if defined) in the **Upload** settings of your account console.", - optional: true, - }, - proxy: { - type: "string", - label: "Proxy", - description: "Tells Cloudinary to upload assets from remote URLs through the given proxy. Format: `https://hostname:port.`", - optional: true, - }, - returnDeleteToken: { - type: "boolean", - label: "Return Deleted Token", - description: "Whether to return a deletion token in the upload response. The token can be used to delete the uploaded asset within 10 minutes using an unauthenticated API request. Default: `false`.", + additionalOptions: { + type: "object", + label: "Additional Options", + description: "Additional parameters and their values to use in the upload. [See the documentation](https://cloudinary.com/documentation/image_upload_api_reference#upload_method) for all available options. Values will be parsed as JSON where applicable. Example: `{ \"use_filename\": true }`", optional: true, }, }, async run({ $ }) { + let file = this.file; + if (typeof file === 'string' && file.match(/^\/?tmp/)) { + file = fs.createReadStream(file); + } + const options = { public_id: this.publicId, folder: this.folder, - use_filename: this.useFilename, - unique_filename: this.uniqueFilename, resource_type: this.resourceType, type: this.type, - access_control: this.accessControl, access_mode: this.accessMode, - discard_original_filename: this.discardOriginalFilename, - overwrite: this.overwrite, tags: this.tags, - context: this.context, - colors: this.colors, - faces: this.faces, - quality_analysis: this.qualityAnalysis, - accessibility_analysis: this.accessibilityAnalysis, - cinemagraph_analysis: this.cinemagraphAnalysis, - image_metadata: this.imageMetadata, - phash: this.phash, - responsive_breakpoints: this.responsiveBreakpoints, - auto_tagging: this.autoTagging, - categorization: this.categorization, - detection: this.detection, - ocr: this.ocr, - eager: this.eager, - eager_async: this.eagerAsync, - eager_notification_url: this.eagerNotificationUrl, - transformation: this.transformation, format: this.format, - custom_coordinates: this.customCoordinates, - face_coordinates: this.faceCoordinates, - background_removal: this.backgroundRemoval, - raw_convert: this.rawConvert, - allowed_formats: this.allowedFormats, - async: this.async, backup: this.backup, - eval: this.eval, - headers: this.headers, - invalidate: this.invalidate, - moderation: this.moderation, - notification_url: this.notification_url, - proxy: this.proxy, - return_delete_token: this.returnDeleteToken, + ...Object.fromEntries(Object.entries(this.additionalOptions ?? {}).map(([key, value]) => { + try { + return [key, JSON.parse(value)] + } catch (err) { + return [key, value] + } + })), }; try { - const response = await this.cloudinary.uploadMedia(this.file, options); + const response = await this.cloudinary.uploadMedia(file, options); if (response) { $.export("$summary", "Successfully uploaded media asset"); } return response; } catch (e) { - throw new Error(`${e.name} - ${e.http_code} - ${e.message}`); + throw new Error(`Cloudinary error response: ${err.error?.message ?? JSON.stringify(err)}`); } }, }; diff --git a/components/cloudinary/cloudinary.app.mjs b/components/cloudinary/cloudinary.app.mjs index a519e825a7e61..8bf76f342e4cd 100644 --- a/components/cloudinary/cloudinary.app.mjs +++ b/components/cloudinary/cloudinary.app.mjs @@ -31,8 +31,8 @@ export default { }, deliveryType: { type: "string", - label: "Type", - description: "The delivery type. Defaults to `upload` if not specified.", + label: "Filter by Type", + description: "Find assets with the specified delivery type (defaults to `upload`).", options: constants.DELIVERY_TYPE_OPTIONS, default: "upload", optional: true, @@ -40,7 +40,7 @@ export default { uploadDeliveryType: { type: "string", label: "Type", - description: "The delivery type. Allows uploading assets as `private` or `authenticated` instead of the default `upload` mode. Valid values: `upload`, `private` and `authenticated`. Default: `upload`.", + description: "The delivery type. Allows uploading assets as `private` or `authenticated` instead of the default `upload` mode.", options: constants.UPLOAD_DELIVERY_TYPE_OPTIONS, default: "upload", optional: true, @@ -48,7 +48,7 @@ export default { accessMode: { type: "string", label: "Access Mode", - description: "Allows the asset to behave as if it's of the authenticated 'type' (see above) while still using the default 'upload' type in delivery URLs. The asset can later be made public by changing its access_mode via the [Admin API](https://cloudinary.com/documentation/admin_api#update_access_mode), without having to update any delivery URLs. Valid values: `public`, and `authenticated`. Default: `public`.", + description: "Allows the asset to behave as if it's of the authenticated 'type'. Default is `public`. The asset can later be made public by changing its Access Mode via the [Admin API](https://cloudinary.com/documentation/admin_api#update_access_mode), without having to update any delivery URLs.", optional: true, options: constants.ACCESS_MODE_OPTIONS, }, From d9a54c595ecf7a06351dc91f7cd17a78af5fbbe0 Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Thu, 26 Dec 2024 21:24:09 -0300 Subject: [PATCH 05/11] File upload improvements --- .../actions/upload-media-asset/upload-media-asset.mjs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/components/cloudinary/actions/upload-media-asset/upload-media-asset.mjs b/components/cloudinary/actions/upload-media-asset/upload-media-asset.mjs index cffcfdfeeae5a..55c468c1942db 100644 --- a/components/cloudinary/actions/upload-media-asset/upload-media-asset.mjs +++ b/components/cloudinary/actions/upload-media-asset/upload-media-asset.mjs @@ -1,4 +1,5 @@ import cloudinary from "../../cloudinary.app.mjs"; +import fs from 'fs'; export default { key: "cloudinary-upload-media-asset", @@ -74,11 +75,6 @@ export default { }, }, async run({ $ }) { - let file = this.file; - if (typeof file === 'string' && file.match(/^\/?tmp/)) { - file = fs.createReadStream(file); - } - const options = { public_id: this.publicId, folder: this.folder, @@ -98,12 +94,12 @@ export default { }; try { - const response = await this.cloudinary.uploadMedia(file, options); + const response = await this.cloudinary.uploadMedia(this.file, options); if (response) { $.export("$summary", "Successfully uploaded media asset"); } return response; - } catch (e) { + } catch (err) { throw new Error(`Cloudinary error response: ${err.error?.message ?? JSON.stringify(err)}`); } }, From abe2c20605674ddc2ac1e0aeb021acff384872fb Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Thu, 26 Dec 2024 22:51:27 -0300 Subject: [PATCH 06/11] Reworking image transformation --- .../image-transformation.mjs | 50 ++++++++++++++++--- components/cloudinary/cloudinary.app.mjs | 2 +- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/components/cloudinary/actions/image-transformation/image-transformation.mjs b/components/cloudinary/actions/image-transformation/image-transformation.mjs index d9df4a4d59760..f7974b27b7110 100644 --- a/components/cloudinary/actions/image-transformation/image-transformation.mjs +++ b/components/cloudinary/actions/image-transformation/image-transformation.mjs @@ -2,30 +2,64 @@ import cloudinary from "../../cloudinary.app.mjs"; export default { key: "cloudinary-image-transformation", - name: "Image Transformation", - description: "Transforms images on-the-fly. It modifies them to any required format, style and dimension, resize and crop the images, etc. [See the documentation](https://cloudinary.com/documentation/image_transformations)", - version: "0.1.2", + name: "Transform Image", + description: "Transform an image on-the-fly with several options. [See the documentation](https://cloudinary.com/documentation/image_transformations)", + version: "0.1.{{ts}}", type: "action", props: { cloudinary, imageSource: { type: "string", label: "Public ID", - description: "The [public ID](https://cloudinary.com/documentation/upload_images#public_id) that references a file you've previously uploaded to Cloudinary, e.g. `folder/filename`.", + description: "The [public ID](https://cloudinary.com/documentation/upload_images#public_id) of the asset , e.g. `folder/filename`.", }, - options: { + width: { + type: "integer", + label: "Width", + description: "The new width of the image, e.g. `300`", + optional: true, + }, + height: { + type: "integer", + label: "Height", + description: "The new height of the image, e.g. `300`", + optional: true, + }, + background: { + type: "string", + label: "Background", + description: "The background color to apply on transparent areas of the image, as a named color or RGB(A) value, e.g. `blue` or `8B0`", + optional: true, + }, + opacity: { + type: "integer", + label: "Opacity", + description: "The opacity level to set for the image, from 0 to 100", + optional: true, + min: 0, + max: 100, + }, + transformations: { type: "object", - label: "Options", - description: "The image transformation options to apply and/or the URL parameters supported by Cloudinary API. For all transformation options, please check [Image transformation API reference](https://cloudinary.com/documentation/image_transformation_reference), for URL parameters, please check [Transforming media assets using dynamic URLs](https://cloudinary.com/documentation/image_transformations#transforming_media_assets_using_dynamic_urls)", + label: "Additional Transformations", + description: "Additional transformations to apply to the image. [See the documentation](https://cloudinary.com/documentation/transformation_reference#co_color) for all available transformations. Example: `{ \"angle\": 90, \"color_space\": \"srgb\"}`", }, }, async run({ $ }) { - const response = await this.cloudinary.transformImage(this.imageSource, this.options); + const { cloudinary, imageSource, transformations, ...options } = this; + try { + const response = await cloudinary.transformImage(imageSource, { + ...options, + ...transformations, + }); if (response) { $.export("$summary", "Successfully transformed image."); } return response; + } catch (err) { + throw new Error(`Cloudinary error response: ${err.error?.message ?? JSON.stringify(err)}`); + } }, }; diff --git a/components/cloudinary/cloudinary.app.mjs b/components/cloudinary/cloudinary.app.mjs index 8bf76f342e4cd..0a7fbcc4ea575 100644 --- a/components/cloudinary/cloudinary.app.mjs +++ b/components/cloudinary/cloudinary.app.mjs @@ -70,7 +70,7 @@ export default { return this._client().api.usage(options); }, async transformImage(imageSource, options) { - return this._client().image(imageSource, options); + return this._client().url(imageSource, options); }, async transformVideo(videoPublicId, options) { return this._client().video(videoPublicId, options); From c482de6f910385d239cfd7379014f40259d63e4e Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Fri, 27 Dec 2024 19:44:35 -0300 Subject: [PATCH 07/11] Video transformation + version bumps --- .../get-account-usage-details.mjs | 2 +- .../actions/get-resources/get-resources.mjs | 2 +- .../image-transformation.mjs | 26 ++++--- .../resource-transformation.mjs | 73 +++++++++++-------- .../upload-media-asset/upload-media-asset.mjs | 2 +- components/cloudinary/cloudinary.app.mjs | 15 +++- 6 files changed, 71 insertions(+), 49 deletions(-) diff --git a/components/cloudinary/actions/get-account-usage-details/get-account-usage-details.mjs b/components/cloudinary/actions/get-account-usage-details/get-account-usage-details.mjs index f5f58dbf7b451..bd26519352103 100644 --- a/components/cloudinary/actions/get-account-usage-details/get-account-usage-details.mjs +++ b/components/cloudinary/actions/get-account-usage-details/get-account-usage-details.mjs @@ -4,7 +4,7 @@ export default { key: "cloudinary-get-account-usage-details", name: "Get Account Usage Details", description: "Gets a report of your Cloudinary account usage details, including storage, credits, bandwidth, requests, number of resources, and add-on usage. [See the documentation](https://cloudinary.com/documentation/admin_api#usage)", - version: "0.2.{{ts}}", + version: "0.2.0", type: "action", props: { cloudinary, diff --git a/components/cloudinary/actions/get-resources/get-resources.mjs b/components/cloudinary/actions/get-resources/get-resources.mjs index ed4dd09d32fe4..fb348fbd58116 100644 --- a/components/cloudinary/actions/get-resources/get-resources.mjs +++ b/components/cloudinary/actions/get-resources/get-resources.mjs @@ -4,7 +4,7 @@ export default { key: "cloudinary-get-resources", name: "Get Resources", description: "Lists resources (assets) uploaded to your product environment. [See the documentation](https://cloudinary.com/documentation/admin_api#get_resources)", - version: "0.1.{{ts}}", + version: "0.1.0", type: "action", props: { cloudinary, diff --git a/components/cloudinary/actions/image-transformation/image-transformation.mjs b/components/cloudinary/actions/image-transformation/image-transformation.mjs index f7974b27b7110..587c5706fef38 100644 --- a/components/cloudinary/actions/image-transformation/image-transformation.mjs +++ b/components/cloudinary/actions/image-transformation/image-transformation.mjs @@ -3,15 +3,16 @@ import cloudinary from "../../cloudinary.app.mjs"; export default { key: "cloudinary-image-transformation", name: "Transform Image", - description: "Transform an image on-the-fly with several options. [See the documentation](https://cloudinary.com/documentation/image_transformations)", - version: "0.1.{{ts}}", + description: "Transform an image asset on-the-fly with several options. [See the documentation](https://cloudinary.com/documentation/image_transformations)", + version: "0.1.0", type: "action", props: { cloudinary, - imageSource: { - type: "string", - label: "Public ID", - description: "The [public ID](https://cloudinary.com/documentation/upload_images#public_id) of the asset , e.g. `folder/filename`.", + assetId: { + propDefinition: [ + cloudinary, + "assetId" + ] }, width: { type: "integer", @@ -40,21 +41,22 @@ export default { max: 100, }, transformations: { - type: "object", - label: "Additional Transformations", - description: "Additional transformations to apply to the image. [See the documentation](https://cloudinary.com/documentation/transformation_reference#co_color) for all available transformations. Example: `{ \"angle\": 90, \"color_space\": \"srgb\"}`", + propDefinition: [ + cloudinary, + "transformations" + ] }, }, async run({ $ }) { - const { cloudinary, imageSource, transformations, ...options } = this; + const { cloudinary, assetId, transformations, ...options } = this; try { - const response = await cloudinary.transformImage(imageSource, { + const response = await cloudinary.transformAsset(assetId, { ...options, ...transformations, }); if (response) { - $.export("$summary", "Successfully transformed image."); + $.export("$summary", "Successfully transformed image"); } return response; diff --git a/components/cloudinary/actions/resource-transformation/resource-transformation.mjs b/components/cloudinary/actions/resource-transformation/resource-transformation.mjs index 827f71e88d8c0..3bfe077eb37bf 100644 --- a/components/cloudinary/actions/resource-transformation/resource-transformation.mjs +++ b/components/cloudinary/actions/resource-transformation/resource-transformation.mjs @@ -2,45 +2,58 @@ import cloudinary from "../../cloudinary.app.mjs"; export default { key: "cloudinary-resource-transformation", - name: "Resource Transformation", - description: "Transforms image or video resources on-the-fly. It allows transformation options for resource optimization (i.e. web viewing), resize and crop the resources, etc. [Image transformation documentation](https://cloudinary.com/documentation/image_transformations). [Video transformation documentation](https://cloudinary.com/documentation/video_transformation_reference)", - version: "0.2.2", + name: "Transform Video or Audio", + description: "Transform a video or audio asset on-the-fly with several options. [See the documentation](https://cloudinary.com/documentation/video_manipulation_and_delivery)", + version: "0.3.0", type: "action", props: { cloudinary, - resourceType: { - propDefinition: [ - cloudinary, - "transformationResourceType", - ], - }, - options: { - type: "string", - label: "Options", - description: "For an image `resourceType`, use this parameter to set the image transformation options to apply and/or the URL parameters supported by Cloudinary API. For all transformation options, please check [Image transformation API reference](https://cloudinary.com/documentation/image_transformation_reference), for URL parameters, please check [Transforming media assets using dynamic URLs](https://cloudinary.com/documentation/image_transformations#transforming_media_assets_using_dynamic_urls).\nFor a video `resourceType`, use this parameter to set video transformation options to apply and/or the URL parameters supported by Cloudinary API. For all transformation options, please check [Video transformation API reference](https://cloudinary.com/documentation/video_transformation_reference), for URL parameters, please check [Transforming media assets using dynamic URLs](https://cloudinary.com/documentation/image_transformations#transforming_media_assets_using_dynamic_urls).", - }, - imageSource: { - type: "string", - label: "Image Source", - description: "If `resourceType` is an image, use this parameter to point to the source of the image to apply transformations on. It can be a local file, the actual image data, a remote FTP, HTTP or HTTPS URL address of an existing image. For details and examples, see: [file source options](https://cloudinary.com/documentation/upload_images#file_source_options).", - optional: true, - }, - videoPublicId: { - type: "string", - label: "Video Public Id", - description: "If `resourceType` is a video, use this parameter to set the public id of the video to apply transformations on. The public id is the unique identifier of the video, and is either specified when uploading the video to your Cloudinary account, or automatically assigned by Cloudinary. For more details on the options for specifying the public id, see [Public ID - the image identifier](https://cloudinary.com/documentation/upload_images#public_id).", - optional: true, - }, + assetId: { + propDefinition: [ + cloudinary, + "assetId" + ] + }, + width: { + type: "integer", + label: "Width", + description: "The new width of the video, e.g. `854`", + optional: true, + }, + height: { + type: "integer", + label: "Height", + description: "The new height of the video, e.g. `480`", + optional: true, + }, + duration: { + type: "integer", + label: "Duration", + description: "The duration to set for the video in seconds, e.g. `30`", + optional: true, + }, + transformations: { + propDefinition: [ + cloudinary, + "transformations" + ] + }, }, async run({ $ }) { - const response = this.resourceType === "image" - ? await this.cloudinary.transformImage(this.imageSource, this.options) - : await this.cloudinary.transformVideo(this.videoPublicId, this.options); + const { cloudinary, assetId, transformations, ...options } = this; + try { + const response = await cloudinary.transformAsset(assetId, { + ...options, + ...transformations, + }); if (response) { - $.export("$summary", `Successfully transformed ${this.resourceType}`); + $.export("$summary", "Successfully transformed video"); } return response; + } catch (err) { + throw new Error(`Cloudinary error response: ${err.error?.message ?? JSON.stringify(err)}`); + } }, }; diff --git a/components/cloudinary/actions/upload-media-asset/upload-media-asset.mjs b/components/cloudinary/actions/upload-media-asset/upload-media-asset.mjs index 55c468c1942db..9b19e61657794 100644 --- a/components/cloudinary/actions/upload-media-asset/upload-media-asset.mjs +++ b/components/cloudinary/actions/upload-media-asset/upload-media-asset.mjs @@ -5,7 +5,7 @@ export default { key: "cloudinary-upload-media-asset", name: "Upload Media Asset", description: "Upload media assets such as images or videos. [See the documentation](https://cloudinary.com/documentation/image_upload_api_reference#upload_method)", - version: "1.0.{{ts}}", + version: "1.0.0", type: "action", props: { cloudinary, diff --git a/components/cloudinary/cloudinary.app.mjs b/components/cloudinary/cloudinary.app.mjs index 0a7fbcc4ea575..40471b1f76f28 100644 --- a/components/cloudinary/cloudinary.app.mjs +++ b/components/cloudinary/cloudinary.app.mjs @@ -52,6 +52,16 @@ export default { optional: true, options: constants.ACCESS_MODE_OPTIONS, }, + assetId: { + type: "string", + label: "Public ID", + description: "The [public ID](https://cloudinary.com/documentation/upload_images#public_id) of the asset , e.g. `folder/filename`.", + }, + transformations: { + type: "object", + label: "Additional Transformations", + description: "Additional transformations to apply to the resource. [See the documentation](https://cloudinary.com/documentation/transformation_reference) for all available transformations. Example: `{ \"angle\": 90, \"color_space\": \"srgb\"}`", + }, }, methods: { _client() { @@ -69,12 +79,9 @@ export default { async getUsage(options) { return this._client().api.usage(options); }, - async transformImage(imageSource, options) { + async transformAsset(imageSource, options) { return this._client().url(imageSource, options); }, - async transformVideo(videoPublicId, options) { - return this._client().video(videoPublicId, options); - }, async uploadMedia(file, options) { return this._client().uploader.upload(file, options); }, From c43afd81e23d1eebc3e9edcdf211b19bfcbfa42c Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Fri, 27 Dec 2024 19:45:26 -0300 Subject: [PATCH 08/11] ESLint fixes --- .../image-transformation.mjs | 34 ++++---- .../resource-transformation.mjs | 86 ++++++++++--------- .../upload-media-asset/upload-media-asset.mjs | 20 +++-- 3 files changed, 76 insertions(+), 64 deletions(-) diff --git a/components/cloudinary/actions/image-transformation/image-transformation.mjs b/components/cloudinary/actions/image-transformation/image-transformation.mjs index 587c5706fef38..fdd80ff384441 100644 --- a/components/cloudinary/actions/image-transformation/image-transformation.mjs +++ b/components/cloudinary/actions/image-transformation/image-transformation.mjs @@ -11,8 +11,8 @@ export default { assetId: { propDefinition: [ cloudinary, - "assetId" - ] + "assetId", + ], }, width: { type: "integer", @@ -43,25 +43,27 @@ export default { transformations: { propDefinition: [ cloudinary, - "transformations" - ] + "transformations", + ], }, }, async run({ $ }) { - const { cloudinary, assetId, transformations, ...options } = this; + const { + cloudinary, assetId, transformations, ...options + } = this; try { - const response = await cloudinary.transformAsset(assetId, { - ...options, - ...transformations, - }); + const response = await cloudinary.transformAsset(assetId, { + ...options, + ...transformations, + }); - if (response) { - $.export("$summary", "Successfully transformed image"); - } + if (response) { + $.export("$summary", "Successfully transformed image"); + } - return response; - } catch (err) { - throw new Error(`Cloudinary error response: ${err.error?.message ?? JSON.stringify(err)}`); - } + return response; + } catch (err) { + throw new Error(`Cloudinary error response: ${err.error?.message ?? JSON.stringify(err)}`); + } }, }; diff --git a/components/cloudinary/actions/resource-transformation/resource-transformation.mjs b/components/cloudinary/actions/resource-transformation/resource-transformation.mjs index 3bfe077eb37bf..70384d1241bc9 100644 --- a/components/cloudinary/actions/resource-transformation/resource-transformation.mjs +++ b/components/cloudinary/actions/resource-transformation/resource-transformation.mjs @@ -8,52 +8,54 @@ export default { type: "action", props: { cloudinary, - assetId: { - propDefinition: [ - cloudinary, - "assetId" - ] - }, - width: { - type: "integer", - label: "Width", - description: "The new width of the video, e.g. `854`", - optional: true, - }, - height: { - type: "integer", - label: "Height", - description: "The new height of the video, e.g. `480`", - optional: true, - }, - duration: { - type: "integer", - label: "Duration", - description: "The duration to set for the video in seconds, e.g. `30`", - optional: true, - }, - transformations: { - propDefinition: [ - cloudinary, - "transformations" - ] - }, + assetId: { + propDefinition: [ + cloudinary, + "assetId", + ], + }, + width: { + type: "integer", + label: "Width", + description: "The new width of the video, e.g. `854`", + optional: true, + }, + height: { + type: "integer", + label: "Height", + description: "The new height of the video, e.g. `480`", + optional: true, + }, + duration: { + type: "integer", + label: "Duration", + description: "The duration to set for the video in seconds, e.g. `30`", + optional: true, + }, + transformations: { + propDefinition: [ + cloudinary, + "transformations", + ], + }, }, async run({ $ }) { - const { cloudinary, assetId, transformations, ...options } = this; + const { + cloudinary, assetId, transformations, ...options + } = this; try { - const response = await cloudinary.transformAsset(assetId, { - ...options, - ...transformations, - }); + const response = await cloudinary.transformAsset(assetId, { + ...options, + ...transformations, + }); - if (response) { - $.export("$summary", "Successfully transformed video"); - } + if (response) { + $.export("$summary", "Successfully transformed video"); + } - return response; - } catch (err) { - throw new Error(`Cloudinary error response: ${err.error?.message ?? JSON.stringify(err)}`); - } + return response; + } catch (err) { + throw new Error(`Cloudinary error response: ${err.error?.message ?? JSON.stringify(err)}`); + } }, }; diff --git a/components/cloudinary/actions/upload-media-asset/upload-media-asset.mjs b/components/cloudinary/actions/upload-media-asset/upload-media-asset.mjs index 9b19e61657794..3129625e29da7 100644 --- a/components/cloudinary/actions/upload-media-asset/upload-media-asset.mjs +++ b/components/cloudinary/actions/upload-media-asset/upload-media-asset.mjs @@ -1,5 +1,4 @@ import cloudinary from "../../cloudinary.app.mjs"; -import fs from 'fs'; export default { key: "cloudinary-upload-media-asset", @@ -12,7 +11,7 @@ export default { infoAlert: { type: "alert", alertType: "info", - content: `Cloudinary offers a large amount of options to customize your asset upload. You can set any available options in the \`Additional Options\` prop. [See the Cloudinary documentation for more information.](https://cloudinary.com/documentation/image_upload_api_reference#upload_method)` + content: "Cloudinary offers a large amount of options to customize your asset upload. You can set any available options in the `Additional Options` prop. [See the Cloudinary documentation for more information.](https://cloudinary.com/documentation/image_upload_api_reference#upload_method)", }, file: { type: "string", @@ -84,13 +83,22 @@ export default { tags: this.tags, format: this.format, backup: this.backup, - ...Object.fromEntries(Object.entries(this.additionalOptions ?? {}).map(([key, value]) => { + ...Object.fromEntries(Object.entries(this.additionalOptions ?? {}).map(([ + key, + value, + ]) => { try { - return [key, JSON.parse(value)] + return [ + key, + JSON.parse(value), + ]; } catch (err) { - return [key, value] + return [ + key, + value, + ]; } - })), + })), }; try { From 57a81eea29874f243d27c57f42fdd27b6eca33ec Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Fri, 3 Jan 2025 17:07:51 -0300 Subject: [PATCH 09/11] pnpm --- pnpm-lock.yaml | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2d53297401286..3ce5fde62c814 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -94,8 +94,8 @@ importers: specifier: ^12.3.4 version: 12.5.0(enquirer@2.4.1) pnpm: - specifier: 9.14.3 - version: 9.14.3 + specifier: 9.14.2 + version: 9.14.2 putout: specifier: '>=36' version: 36.13.1(eslint@8.57.1)(typescript@5.6.3) @@ -216,8 +216,7 @@ importers: components/acelle_mail: {} - components/acronis_cyber_protect_cloud: - specifiers: {} + components/acronis_cyber_protect_cloud: {} components/action_builder: {} @@ -1183,8 +1182,7 @@ importers: specifier: ^0.0.4 version: 0.0.4 - components/bitdefender_gravityzone: - specifiers: {} + components/bitdefender_gravityzone: {} components/bitport: {} @@ -2559,8 +2557,7 @@ importers: specifier: ^2.1.0 version: 2.1.0 - components/demandbase: - specifiers: {} + components/demandbase: {} components/demio: dependencies: @@ -4490,8 +4487,7 @@ importers: specifier: ^1.5.1 version: 1.6.6 - components/goto_meeting: - specifiers: {} + components/goto_meeting: {} components/gotowebinar: dependencies: @@ -8443,8 +8439,7 @@ importers: specifier: ^1.5.1 version: 1.6.6 - components/recruiterflow: - specifiers: {} + components/recruiterflow: {} components/recruitis: dependencies: @@ -11666,8 +11661,7 @@ importers: specifier: ^1.6.5 version: 1.6.6 - components/wolfram_alpha: - specifiers: {} + components/wolfram_alpha: {} components/wonderchat: {} @@ -23209,8 +23203,8 @@ packages: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} engines: {node: '>=4'} - pnpm@9.14.3: - resolution: {integrity: sha512-wPU+6ZR37ZabgrKJrQEaXRa/FiPJV+fynqvo0MALV0wpuMf1T2xn7nEMc/KFyBVNB85EtG/iwO60dqkEQbrDcQ==} + pnpm@9.14.2: + resolution: {integrity: sha512-biuvd9Brk2IpQVLIUcTyeO3jerHro6Vf2jF6SheyCfTbuXP7JQp3q8Rjo0H8sfF/F8+iQJHE6zGc2g2bhCeDhw==} engines: {node: '>=18.12'} hasBin: true @@ -40679,7 +40673,7 @@ snapshots: pluralize@8.0.0: {} - pnpm@9.14.3: {} + pnpm@9.14.2: {} points-on-curve@0.2.0: {} From 7b015661ff428f74b7bfedeb7d38fc5fc3f3c3f0 Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Fri, 3 Jan 2025 22:00:39 -0300 Subject: [PATCH 10/11] Improvements to transformation options --- .../resource-transformation.mjs | 61 ----------------- .../transform-resource/transform-resource.mjs | 65 +++++++++++++++++++ components/cloudinary/cloudinary.app.mjs | 28 ++++++++ 3 files changed, 93 insertions(+), 61 deletions(-) delete mode 100644 components/cloudinary/actions/resource-transformation/resource-transformation.mjs create mode 100644 components/cloudinary/actions/transform-resource/transform-resource.mjs diff --git a/components/cloudinary/actions/resource-transformation/resource-transformation.mjs b/components/cloudinary/actions/resource-transformation/resource-transformation.mjs deleted file mode 100644 index 70384d1241bc9..0000000000000 --- a/components/cloudinary/actions/resource-transformation/resource-transformation.mjs +++ /dev/null @@ -1,61 +0,0 @@ -import cloudinary from "../../cloudinary.app.mjs"; - -export default { - key: "cloudinary-resource-transformation", - name: "Transform Video or Audio", - description: "Transform a video or audio asset on-the-fly with several options. [See the documentation](https://cloudinary.com/documentation/video_manipulation_and_delivery)", - version: "0.3.0", - type: "action", - props: { - cloudinary, - assetId: { - propDefinition: [ - cloudinary, - "assetId", - ], - }, - width: { - type: "integer", - label: "Width", - description: "The new width of the video, e.g. `854`", - optional: true, - }, - height: { - type: "integer", - label: "Height", - description: "The new height of the video, e.g. `480`", - optional: true, - }, - duration: { - type: "integer", - label: "Duration", - description: "The duration to set for the video in seconds, e.g. `30`", - optional: true, - }, - transformations: { - propDefinition: [ - cloudinary, - "transformations", - ], - }, - }, - async run({ $ }) { - const { - cloudinary, assetId, transformations, ...options - } = this; - try { - const response = await cloudinary.transformAsset(assetId, { - ...options, - ...transformations, - }); - - if (response) { - $.export("$summary", "Successfully transformed video"); - } - - return response; - } catch (err) { - throw new Error(`Cloudinary error response: ${err.error?.message ?? JSON.stringify(err)}`); - } - }, -}; diff --git a/components/cloudinary/actions/transform-resource/transform-resource.mjs b/components/cloudinary/actions/transform-resource/transform-resource.mjs new file mode 100644 index 0000000000000..5925e59dc41ee --- /dev/null +++ b/components/cloudinary/actions/transform-resource/transform-resource.mjs @@ -0,0 +1,65 @@ +import { ConfigurationError } from "@pipedream/platform"; +import cloudinary from "../../cloudinary.app.mjs"; + +export default { + key: "cloudinary-transform-resource", + name: "Transform Resource", + description: "Transform an image, video or audio asset on-the-fly with several options. [See the documentation](https://cloudinary.com/documentation/video_manipulation_and_delivery)", + version: "0.0.1", + type: "action", + props: { + cloudinary, + assetId: { + propDefinition: [ + cloudinary, + "assetId", + ], + }, + info: { + type: "alert", + alertType: "info", + content: `You can either select a pre-configured transformation or pass a transformation string. Both can be managed in the [Cloudinary Transformation Builder](https://tx.cloudinary.com/). +\\ +If both are specified, the transformation string will be ignored.`, + }, + namedTransformation: { + propDefinition: [ + cloudinary, + "namedTransformation", + ], + }, + transformationString: { + propDefinition: [ + cloudinary, + "transformationString", + ], + }, + }, + async run({ $ }) { + const { + cloudinary, assetId, namedTransformation, transformationString, + } = this; + + if (!namedTransformation && !transformationString) { + throw new ConfigurationError("Either `Named Transformation` or `Transformation String` are required"); + } + + try { + const response = await cloudinary.transformAsset(assetId, namedTransformation + ? { + transformation: namedTransformation, + } + : { + raw_transformation: transformationString, + }); + + if (response) { + $.export("$summary", "Successfully transformed resource"); + } + + return response; + } catch (err) { + throw new Error(`Cloudinary error response: ${err.error?.message ?? JSON.stringify(err)}`); + } + }, +}; diff --git a/components/cloudinary/cloudinary.app.mjs b/components/cloudinary/cloudinary.app.mjs index 40471b1f76f28..9b22ba9b49d17 100644 --- a/components/cloudinary/cloudinary.app.mjs +++ b/components/cloudinary/cloudinary.app.mjs @@ -62,6 +62,31 @@ export default { label: "Additional Transformations", description: "Additional transformations to apply to the resource. [See the documentation](https://cloudinary.com/documentation/transformation_reference) for all available transformations. Example: `{ \"angle\": 90, \"color_space\": \"srgb\"}`", }, + transformationString: { + type: "string", + label: "Transformation String", + description: "A string representing the transformation to apply to the resource. You can use the [Cloudinary Transformation Builder](https://tx.cloudinary.com/) to create and preview the transformation, then copy the string here. Example: `c_fill,h_500,w_500` is the transformation string in the URL `https://res.cloudinary.com/demo/video/upload/c_fill,h_500,w_500/samples/cld-sample-video.mp4`", + optional: true, + }, + namedTransformation: { + type: "string", + label: "Named Transformation", + description: "Select a pre-configured named transformation to apply to the resource. You can create and manage transformations in the [Cloudinary Transformation Builder](https://tx.cloudinary.com).", + optional: true, + async options({ prevContext: { cursor } }) { + const { + transformations, next_cursor, + } = await this.getTransformations({ + next_cursor: cursor, + }); + return { + options: transformations?.filter?.((t) => t.named).map((t) => t.name.replace(/^t_/, "")), + context: { + cursor: next_cursor, + }, + }; + }, + }, }, methods: { _client() { @@ -85,5 +110,8 @@ export default { async uploadMedia(file, options) { return this._client().uploader.upload(file, options); }, + async getTransformations(args) { + return this._client().api.transformations(args); + }, }, }; From cd1d313f8de7714eb7960a6d2b53c53939a0eea9 Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Fri, 3 Jan 2025 22:04:59 -0300 Subject: [PATCH 11/11] Removing 'transform image' in favor of 'transform resource' --- .../image-transformation.mjs | 69 ------------------- 1 file changed, 69 deletions(-) delete mode 100644 components/cloudinary/actions/image-transformation/image-transformation.mjs diff --git a/components/cloudinary/actions/image-transformation/image-transformation.mjs b/components/cloudinary/actions/image-transformation/image-transformation.mjs deleted file mode 100644 index fdd80ff384441..0000000000000 --- a/components/cloudinary/actions/image-transformation/image-transformation.mjs +++ /dev/null @@ -1,69 +0,0 @@ -import cloudinary from "../../cloudinary.app.mjs"; - -export default { - key: "cloudinary-image-transformation", - name: "Transform Image", - description: "Transform an image asset on-the-fly with several options. [See the documentation](https://cloudinary.com/documentation/image_transformations)", - version: "0.1.0", - type: "action", - props: { - cloudinary, - assetId: { - propDefinition: [ - cloudinary, - "assetId", - ], - }, - width: { - type: "integer", - label: "Width", - description: "The new width of the image, e.g. `300`", - optional: true, - }, - height: { - type: "integer", - label: "Height", - description: "The new height of the image, e.g. `300`", - optional: true, - }, - background: { - type: "string", - label: "Background", - description: "The background color to apply on transparent areas of the image, as a named color or RGB(A) value, e.g. `blue` or `8B0`", - optional: true, - }, - opacity: { - type: "integer", - label: "Opacity", - description: "The opacity level to set for the image, from 0 to 100", - optional: true, - min: 0, - max: 100, - }, - transformations: { - propDefinition: [ - cloudinary, - "transformations", - ], - }, - }, - async run({ $ }) { - const { - cloudinary, assetId, transformations, ...options - } = this; - try { - const response = await cloudinary.transformAsset(assetId, { - ...options, - ...transformations, - }); - - if (response) { - $.export("$summary", "Successfully transformed image"); - } - - return response; - } catch (err) { - throw new Error(`Cloudinary error response: ${err.error?.message ?? JSON.stringify(err)}`); - } - }, -};