Tolerate missing json key in function node output (#2885)

* 🔨 implemented Tolerate missing json key in function node output

* 🔨 clean up

* Small change to code

*  tolerate returning object

*  Rename function

Co-authored-by: Omar Ajoue <krynble@gmail.com>
Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
This commit is contained in:
Michael Kret 2022-03-07 10:54:52 +02:00 committed by GitHub
parent af09bf8e6a
commit 62e05cf0b3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 0 deletions

View file

@ -62,6 +62,7 @@ export interface IExecuteFunctions extends IExecuteFunctionsBase {
requestOptions: OptionsWithUrl | requestPromise.RequestPromiseOptions, requestOptions: OptionsWithUrl | requestPromise.RequestPromiseOptions,
): Promise<any>; // tslint:disable-line:no-any ): Promise<any>; // tslint:disable-line:no-any
returnJsonArray(jsonData: IDataObject | IDataObject[]): INodeExecutionData[]; returnJsonArray(jsonData: IDataObject | IDataObject[]): INodeExecutionData[];
normalizeItemsInArray(items: INodeExecutionData[]): INodeExecutionData[];
httpRequestWithAuthentication( httpRequestWithAuthentication(
this: IAllExecuteFunctions, this: IAllExecuteFunctions,
credentialsType: string, credentialsType: string,

View file

@ -1132,6 +1132,51 @@ export function returnJsonArray(jsonData: IDataObject | IDataObject[]): INodeExe
return returnData; return returnData;
} }
/**
* Automatically put the objects under a 'json' key and don't error,
* if some objects contain json/binary keys and others don't, throws error 'Inconsistent item format'
*
* @export
* @param {INodeExecutionData | INodeExecutionData[]} executionData
* @returns {INodeExecutionData[]}
*/
export function normalizeItems(
executionData: INodeExecutionData | INodeExecutionData[],
): INodeExecutionData[] {
if (typeof executionData === 'object' && !Array.isArray(executionData))
executionData = [{ json: executionData as IDataObject }];
if (executionData.every((item) => typeof item === 'object' && 'json' in item))
return executionData;
if (executionData.some((item) => typeof item === 'object' && 'json' in item)) {
throw new Error('Inconsistent item format');
}
if (executionData.every((item) => typeof item === 'object' && 'binary' in item)) {
const normalizedItems: INodeExecutionData[] = [];
executionData.forEach((item) => {
const json = Object.keys(item).reduce((acc, key) => {
if (key === 'binary') return acc;
return { ...acc, [key]: item[key] };
}, {});
normalizedItems.push({
json,
binary: item.binary,
});
});
return normalizedItems;
}
if (executionData.some((item) => typeof item === 'object' && 'binary' in item)) {
throw new Error('Inconsistent item format');
}
return executionData.map((item) => {
return { json: item };
});
}
// TODO: Move up later // TODO: Move up later
export async function requestWithAuthentication( export async function requestWithAuthentication(
this: IAllExecuteFunctions, this: IAllExecuteFunctions,
@ -2080,6 +2125,7 @@ export function getExecuteFunctions(
); );
}, },
returnJsonArray, returnJsonArray,
normalizeItems,
}, },
}; };
})(workflow, runExecutionData, connectionInputData, inputData, node); })(workflow, runExecutionData, connectionInputData, inputData, node);

View file

@ -119,6 +119,8 @@ return items;`,
try { try {
// Execute the function code // Execute the function code
items = (await vm.run(`module.exports = async function() {${functionCode}\n}()`, __dirname)); items = (await vm.run(`module.exports = async function() {${functionCode}\n}()`, __dirname));
items = this.helpers.normalizeItems(items);
// Do very basic validation of the data // Do very basic validation of the data
if (items === undefined) { if (items === undefined) {
throw new NodeOperationError(this.getNode(), 'No data got returned. Always return an Array of items!'); throw new NodeOperationError(this.getNode(), 'No data got returned. Always return an Array of items!');