n8n-nodes-cloudinary
Version:
The official Cloudinary n8n node - upload media, update asset tags and metadata, and more
690 lines • 28.8 kB
JavaScript
"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