Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Convert to File Node): Operation to convert a string in a plain text file, option to format JSON when creating file #8620

Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type {

import * as spreadsheet from './actions/spreadsheet.operation';
import * as toBinary from './actions/toBinary.operation';
import * as toText from './actions/toText.operation';
import * as toJson from './actions/toJson.operation';
import * as iCall from './actions/iCall.operation';

Expand All @@ -17,7 +18,7 @@ export class ConvertToFile implements INodeType {
name: 'convertToFile',
icon: 'file:convertToFile.svg',
group: ['input'],
version: 1,
version: [1, 1.1],
description: 'Convert JSON data to binary data',
defaults: {
name: 'Convert to File',
Expand Down Expand Up @@ -67,6 +68,12 @@ export class ConvertToFile implements INodeType {
action: 'Convert to RTF',
description: 'Transform input data into a table in an RTF file',
},
{
name: 'Convert to Text File',
value: 'toText',
action: 'Convert to text file',
description: 'Transform input data string into a file',
},
{
name: 'Convert to XLS',
value: 'xls',
Expand All @@ -90,6 +97,7 @@ export class ConvertToFile implements INodeType {
},
...spreadsheet.description,
...toBinary.description,
...toText.description,
...toJson.description,
...iCall.description,
],
Expand All @@ -112,6 +120,10 @@ export class ConvertToFile implements INodeType {
returnData = await toBinary.execute.call(this, items);
}

if (operation === 'toText') {
returnData = await toText.execute.call(this, items);
}

if (operation === 'iCal') {
returnData = await iCall.execute.call(this, items);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ export const properties: INodeProperties[] = [
type: 'boolean',
default: true,
description: 'Whether the data is already base64 encoded',
displayOptions: {
show: {
'@version': [1],
},
},
},
{
displayName: 'Encoding',
Expand All @@ -65,6 +70,7 @@ export const properties: INodeProperties[] = [
displayOptions: {
hide: {
dataIsBase64: [true],
'@version': [{ _cnd: { gt: 1 } }],
},
},
},
Expand Down Expand Up @@ -100,17 +106,24 @@ export const description = updateDisplayOptions(displayOptions, properties);
export async function execute(this: IExecuteFunctions, items: INodeExecutionData[]) {
const returnData: INodeExecutionData[] = [];

const nodeVersion = this.getNode().typeVersion;

for (let i = 0; i < items.length; i++) {
try {
const options = this.getNodeParameter('options', i, {});
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i, 'data');
const sourceProperty = this.getNodeParameter('sourceProperty', i) as string;

let dataIsBase64 = true;
if (nodeVersion === 1) {
dataIsBase64 = options.dataIsBase64 !== false;
}

const jsonToBinaryOptions: JsonToBinaryOptions = {
sourceKey: sourceProperty,
fileName: options.fileName as string,
mimeType: options.mimeType as string,
dataIsBase64: options.dataIsBase64 !== false,
dataIsBase64,
encoding: options.encoding as string,
addBOM: options.addBOM as boolean,
itemIndex: i,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ export const properties: INodeProperties[] = [
},
},
},
{
displayName: 'Format',
name: 'format',
type: 'boolean',
default: false,
description: 'Whether to format the JSON data for easier reading',
},
{
displayName: 'Encoding',
name: 'encoding',
Expand Down Expand Up @@ -98,6 +105,7 @@ export async function execute(this: IExecuteFunctions, items: INodeExecutionData
mimeType: 'application/json',
encoding: options.encoding as string,
addBOM: options.addBOM as boolean,
format: options.format as boolean,
},
);

Expand Down Expand Up @@ -131,6 +139,7 @@ export async function execute(this: IExecuteFunctions, items: INodeExecutionData
fileName: options.fileName as string,
encoding: options.encoding as string,
addBOM: options.addBOM as boolean,
format: options.format as boolean,
mimeType: 'application/json',
itemIndex: i,
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import type { IExecuteFunctions, INodeExecutionData, INodeProperties } from 'n8n-workflow';

import { NodeOperationError } from 'n8n-workflow';

import type { JsonToBinaryOptions } from '@utils/binary';
import { createBinaryFromJson } from '@utils/binary';
import { encodeDecodeOptions } from '@utils/descriptions';
import { updateDisplayOptions } from '@utils/utilities';

export const properties: INodeProperties[] = [
{
displayName: 'Text Input Field',
name: 'sourceProperty',
type: 'string',
default: '',
required: true,
placeholder: 'e.g data',
requiresDataPath: 'single',
description:
"The name of the input field that contains a string to convert to a file. Use dot-notation for deep fields (e.g. 'level1.level2.currentKey').",
},
{
displayName: 'Put Output File in Field',
name: 'binaryPropertyName',
type: 'string',
default: 'data',
required: true,
placeholder: 'e.g data',
hint: 'The name of the output binary field to put the file in',
},
{
displayName: 'Options',
name: 'options',
type: 'collection',
placeholder: 'Add Option',
default: {},
options: [
{
displayName: 'Add Byte Order Mark (BOM)',
description:
'Whether to add special marker at the start of your text file. This marker helps some programs understand how to read the file correctly.',
name: 'addBOM',
displayOptions: {
show: {
encoding: ['utf8', 'cesu8', 'ucs2'],
},
},
type: 'boolean',
default: false,
},
{
displayName: 'Encoding',
name: 'encoding',
type: 'options',
options: encodeDecodeOptions,
default: 'utf8',
description: 'Choose the character set to use to encode the data',
},
{
displayName: 'File Name',
name: 'fileName',
type: 'string',
default: '',
placeholder: 'e.g. myFile',
description: 'Name of the output file',
},
],
},
];

const displayOptions = {
show: {
operation: ['toText'],
},
};

export const description = updateDisplayOptions(displayOptions, properties);

export async function execute(this: IExecuteFunctions, items: INodeExecutionData[]) {
const returnData: INodeExecutionData[] = [];

for (let i = 0; i < items.length; i++) {
try {
const options = this.getNodeParameter('options', i, {});
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i, 'data');
const sourceProperty = this.getNodeParameter('sourceProperty', i) as string;

const jsonToBinaryOptions: JsonToBinaryOptions = {
sourceKey: sourceProperty,
fileName: (options.fileName as string) || 'file.txt',
mimeType: 'text/plain',
dataIsBase64: false,
encoding: options.encoding as string,
addBOM: options.addBOM as boolean,
itemIndex: i,
};

const binaryData = await createBinaryFromJson.call(this, items[i].json, jsonToBinaryOptions);

const newItem: INodeExecutionData = {
json: {},
binary: {
[binaryPropertyName]: binaryData,
},
pairedItem: { item: i },
};

returnData.push(newItem);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({
json: {
error: error.message,
},
pairedItem: {
item: i,
},
});
continue;
}
throw new NodeOperationError(this.getNode(), error, { itemIndex: i });
}
}

return returnData;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers';

const workflows = getWorkflowFilenames(__dirname);

describe('Test ConvertToFile Node', () => testWorkflows(workflows));
Loading
Loading