UNPKG

n8n-nodes-cloudinary

Version:

The official Cloudinary n8n node - upload media, update asset tags and metadata, and more

690 lines 28.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Cloudinary = void 0; const n8n_workflow_1 = require("n8n-workflow"); const cloudinary_utils_1 = require("./cloudinary.utils"); class Cloudinary { constructor() { this.description = { displayName: 'Cloudinary', name: 'cloudinary', icon: 'file:cloudinary.svg', group: ['Cloudinary'], version: 1, subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', description: 'Upload to Cloudinary', defaults: { name: 'Cloudinary', }, inputs: ["main"], outputs: ["main"], credentials: [ { name: 'cloudinaryApi', required: true, }, ], properties: [ { displayName: 'Resource', name: 'resource', type: 'options', noDataExpression: true, options: [ { name: 'Upload', value: 'upload', }, { name: 'Update Asset', value: 'updateAsset', }, { name: 'Admin', value: 'admin', }, ], default: 'upload', }, { displayName: 'Operation', name: 'operation', type: 'options', noDataExpression: true, displayOptions: { show: { resource: ['upload'], }, }, options: [ { name: 'Upload From URL', value: 'uploadUrl', description: 'Upload an asset from URL', action: 'Upload an asset from URL', }, { name: 'Upload File', value: 'uploadFile', description: 'Upload an asset from file data', action: 'Upload an asset from file data', }, ], default: 'uploadUrl', }, { displayName: 'Operation', name: 'operation', type: 'options', noDataExpression: true, displayOptions: { show: { resource: ['updateAsset'], }, }, options: [ { name: 'Update Asset Tags', value: 'updateTags', description: 'Update tags for an existing asset', action: 'Update asset tags', }, { name: 'Update Asset Structured Metadata', value: 'updateMetadata', description: 'Update structured metadata for an existing asset', action: 'Update asset structured metadata', }, ], default: 'updateTags', }, { displayName: 'Operation', name: 'operation', type: 'options', noDataExpression: true, displayOptions: { show: { resource: ['admin'], }, }, options: [ { name: 'Get Tags', value: 'getTags', description: 'Get all tags for a specific resource type', action: 'Get tags for a resource type', }, { name: 'Get Metadata Fields', value: 'getMetadataFields', description: 'Get all metadata fields definitions', action: 'Get metadata fields definitions', }, ], default: 'getTags', }, { displayName: 'URL', name: 'url', type: 'string', default: '', description: 'URL of the image to upload', required: true, displayOptions: { show: { resource: ['upload'], operation: ['uploadUrl'], }, }, }, { displayName: 'Resource Type', name: 'resource_type', type: 'options', options: [ { name: 'Image', value: 'image', }, { name: 'Video', value: 'video', }, { name: 'Raw', value: 'raw', }, ], default: 'image', description: 'The type of asset to upload', displayOptions: { show: { resource: ['upload'], operation: ['uploadUrl'], }, }, }, { displayName: 'Additional Fields', name: 'additionalFields', type: 'collection', placeholder: 'Add Field', displayOptions: { show: { resource: ['upload'], operation: ['uploadUrl'], }, }, default: {}, options: [ { displayName: 'Public ID', name: 'public_id', type: 'string', default: '', description: 'The public ID of the resource', }, { displayName: 'Folder', name: 'folder', type: 'string', default: '', description: 'Folder name where the asset will be stored', }, { displayName: 'Upload Preset', name: 'upload_preset', type: 'string', default: '', description: 'Name of an upload preset that you defined for your Cloudinary account', }, ], }, { displayName: 'Public ID', name: 'publicId', type: 'string', default: '', description: 'The public ID of the asset to update', required: true, displayOptions: { show: { resource: ['updateAsset'], operation: ['updateTags', 'updateMetadata'], }, }, }, { displayName: 'Resource Type', name: 'resourceType', type: 'options', options: [ { name: 'Image', value: 'image', }, { name: 'Video', value: 'video', }, { name: 'Raw', value: 'raw', }, ], default: 'image', description: 'The type of asset to update', displayOptions: { show: { resource: ['updateAsset'], operation: ['updateTags', 'updateMetadata'], }, }, }, { displayName: 'Type', name: 'type', type: 'options', options: [ { name: 'Upload', value: 'upload', }, { name: 'Private', value: 'private', }, { name: 'Authenticated', value: 'authenticated', }, { name: 'Fetch', value: 'fetch', }, ], default: 'upload', description: 'The storage type of the asset', required: true, displayOptions: { show: { resource: ['updateAsset'], operation: ['updateTags', 'updateMetadata'], }, }, }, { displayName: 'Tags', name: 'tags', type: 'string', default: '', description: 'A comma-separated list of tag names to assign to the asset', required: true, displayOptions: { show: { resource: ['updateAsset'], operation: ['updateTags'], }, }, }, { displayName: 'Structured Metadata', name: 'structuredMetadata', type: 'json', default: '{}', description: 'Structured metadata to attach to the asset as JSON. Example: {"field1": "value1", "field2": "value2"}.', required: true, displayOptions: { show: { resource: ['updateAsset'], operation: ['updateMetadata'], }, }, }, { displayName: 'Resource Type', name: 'getTagsResourceType', type: 'options', options: [ { name: 'Image', value: 'image', }, { name: 'Video', value: 'video', }, { name: 'Raw', value: 'raw', }, ], default: 'image', description: 'The type of resource to get tags for', required: true, displayOptions: { show: { resource: ['admin'], operation: ['getTags'], }, }, }, { displayName: 'Prefix', name: 'tagsPrefix', type: 'string', default: '', description: 'Filter tags that start with this prefix', displayOptions: { show: { resource: ['admin'], operation: ['getTags'], }, }, }, { displayName: 'Max Results', name: 'tagsMaxResults', type: 'number', default: 100, description: 'Maximum number of tags to return (1-500)', typeOptions: { minValue: 1, maxValue: 500, }, displayOptions: { show: { resource: ['admin'], operation: ['getTags'], }, }, }, { displayName: 'Update Fields', name: 'updateOptions', type: 'collection', placeholder: 'Add Option', displayOptions: { show: { resource: ['updateAsset'], operation: ['updateTags', 'updateMetadata'], }, }, default: {}, options: [ { displayName: 'Invalidate CDN', name: 'invalidate', type: 'boolean', default: false, description: 'Whether to invalidate CDN cache copies of the asset', }, ], }, { displayName: 'File', name: 'file', type: 'string', typeOptions: { propertyType: 'binary', }, default: 'data', description: 'The file to upload', required: true, displayOptions: { show: { resource: ['upload'], operation: ['uploadFile'], }, }, }, { displayName: 'Resource Type', name: 'resource_type_file', type: 'options', options: [ { name: 'Image', value: 'image', }, { name: 'Video', value: 'video', }, { name: 'Raw', value: 'raw', }, ], default: 'image', description: 'The type of asset to upload', displayOptions: { show: { resource: ['upload'], operation: ['uploadFile'], }, }, }, { displayName: 'Additional Fields', name: 'additionalFieldsFile', type: 'collection', placeholder: 'Add Field', displayOptions: { show: { resource: ['upload'], operation: ['uploadFile'], }, }, default: {}, options: [ { displayName: 'Public ID', name: 'public_id', type: 'string', default: '', description: 'The public ID of the resource', }, { displayName: 'Folder', name: 'folder', type: 'string', default: '', description: 'Folder name where the asset will be stored', }, { displayName: 'Upload Preset', name: 'upload_preset', type: 'string', default: '', description: 'Name of an upload preset that you defined for your Cloudinary account', }, ], }, ], }; } async execute() { const items = this.getInputData(); const returnData = []; const credentials = await this.getCredentials('cloudinaryApi'); const cloudName = credentials.cloudName; const apiKey = credentials.apiKey; const apiSecret = credentials.apiSecret; for (let i = 0; i < items.length; i++) { try { const resource = this.getNodeParameter('resource', i); const operation = this.getNodeParameter('operation', i); if (resource === 'upload' && operation === 'uploadUrl') { const url = this.getNodeParameter('url', i); const resourceType = this.getNodeParameter('resource_type', i); const additionalFields = this.getNodeParameter('additionalFields', i, {}); const timestamp = Math.round(new Date().getTime() / 1000); const params = { timestamp, api_key: apiKey, file: url, ...additionalFields, }; const signature = (0, cloudinary_utils_1.generateCloudinarySignature)(params, apiSecret); params.signature = signature; const uploadUrl = `https://api.cloudinary.com/v1_1/${cloudName}/${resourceType}/upload`; const options = { method: 'POST', url: uploadUrl, body: params, headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': 'n8n/1.0', }, }; const response = await this.helpers.httpRequest(options); returnData.push({ json: response, pairedItem: i, }); } if (resource === 'upload' && operation === 'uploadFile') { const fileData = this.getNodeParameter('file', i); const resourceType = this.getNodeParameter('resource_type_file', i); const additionalFields = this.getNodeParameter('additionalFieldsFile', i, {}); const binaryPropertyName = fileData; const binaryData = this.helpers.assertBinaryData(i, binaryPropertyName); const dataBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName); const timestamp = Math.round(new Date().getTime() / 1000); const params = { timestamp, api_key: apiKey, ...additionalFields, }; const signature = (0, cloudinary_utils_1.generateCloudinarySignature)(params, apiSecret); const uploadUrl = `https://api.cloudinary.com/v1_1/${cloudName}/${resourceType}/upload`; const fields = { api_key: apiKey, timestamp: timestamp.toString(), signature: signature, }; for (const key in additionalFields) { fields[key] = additionalFields[key]; } const { body, boundary } = (0, cloudinary_utils_1.createMultipartBody)(fields, dataBuffer, binaryData.fileName || 'file', binaryData.mimeType || 'application/octet-stream'); const options = { method: 'POST', url: uploadUrl, body: body, headers: { 'Content-Type': `multipart/form-data; boundary=${boundary}`, 'User-Agent': 'n8n/1.0', }, }; const response = await this.helpers.httpRequest(options); returnData.push({ json: response, pairedItem: i, }); } if (resource === 'admin' && operation === 'getTags') { const resourceType = this.getNodeParameter('getTagsResourceType', i); const prefix = this.getNodeParameter('tagsPrefix', i, ''); const maxResults = this.getNodeParameter('tagsMaxResults', i, 100); const tagsUrl = `https://api.cloudinary.com/v1_1/${cloudName}/tags/${resourceType}`; const queryParams = {}; if (prefix) { queryParams.prefix = prefix; } if (maxResults) { queryParams.max_results = maxResults; } const options = { method: 'GET', url: tagsUrl, qs: queryParams, headers: { 'Content-Type': 'application/json', 'User-Agent': 'n8n/1.0', }, auth: { username: apiKey, password: apiSecret, }, }; const response = await this.helpers.httpRequest(options); returnData.push({ json: response, pairedItem: i, }); } if (resource === 'admin' && operation === 'getMetadataFields') { const metadataUrl = `https://api.cloudinary.com/v1_1/${cloudName}/metadata_fields`; const options = { method: 'GET', url: metadataUrl, headers: { 'Content-Type': 'application/json', 'User-Agent': 'n8n/1.0', }, auth: { username: apiKey, password: apiSecret, }, }; const response = await this.helpers.httpRequest(options); returnData.push({ json: response, pairedItem: i, }); } if (resource === 'updateAsset' && operation === 'updateTags') { const publicId = this.getNodeParameter('publicId', i); const resourceType = this.getNodeParameter('resourceType', i); const type = this.getNodeParameter('type', i); const tags = this.getNodeParameter('tags', i); const updateOptions = this.getNodeParameter('updateOptions', i, {}); const body = { tags: tags, ...updateOptions, }; const updateUrl = `https://api.cloudinary.com/v1_1/${cloudName}/resources/${resourceType}/${type}/${publicId}`; const options = { method: 'POST', url: updateUrl, body: body, headers: { 'Content-Type': 'application/json', 'User-Agent': 'n8n/1.0', }, auth: { username: apiKey, password: apiSecret, }, }; const response = await this.helpers.httpRequest(options); returnData.push({ json: response, pairedItem: i, }); } if (resource === 'updateAsset' && operation === 'updateMetadata') { const publicId = this.getNodeParameter('publicId', i); const resourceType = this.getNodeParameter('resourceType', i); const type = this.getNodeParameter('type', i); const structuredMetadata = this.getNodeParameter('structuredMetadata', i); const updateOptions = this.getNodeParameter('updateOptions', i, {}); let metadata; try { metadata = typeof structuredMetadata === 'object' ? structuredMetadata : JSON.parse(structuredMetadata); } catch (error) { throw new n8n_workflow_1.ApplicationError('Invalid JSON for structured metadata'); } const metadataString = Object.keys(metadata) .map((key) => { const value = metadata[key]; const formattedValue = Array.isArray(value) ? JSON.stringify(value) : value; return `${key}=${formattedValue}`; }) .join('|'); const body = { metadata: metadataString, ...updateOptions, }; const updateUrl = `https://api.cloudinary.com/v1_1/${cloudName}/resources/${resourceType}/${type}/${publicId}`; const options = { method: 'POST', url: updateUrl, body: body, headers: { 'Content-Type': 'application/json', 'User-Agent': 'n8n/1.0', }, auth: { username: apiKey, password: apiSecret, }, }; const response = await this.helpers.httpRequest(options); returnData.push({ json: response, pairedItem: i, }); } } catch (error) { if (this.continueOnFail()) { returnData.push({ json: { error: error.message, }, pairedItem: i, }); continue; } throw error; } } return [returnData]; } } exports.Cloudinary = Cloudinary; //# sourceMappingURL=Cloudinary.node.js.map