refactor(core): fixes n8n-local-rules/no-json-parse-json-stringify warnings (#4407)

* 🔨 fixes

* 🔨 set rule to error
This commit is contained in:
Michael Kret 2022-10-21 18:24:58 +03:00 committed by GitHub
parent e10128cbea
commit 9d6a2c32d7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 75 additions and 50 deletions

View file

@ -323,8 +323,7 @@ const config = (module.exports = {
// TODO: set to `error` and fix offenses
'n8n-local-rules/no-uncaught-json-parse': 'warn',
// TODO: set to `error` and fix offenses
'n8n-local-rules/no-json-parse-json-stringify': 'warn',
'n8n-local-rules/no-json-parse-json-stringify': 'error',
// ******************************************************************
// overrides to base ruleset

View file

@ -2,6 +2,7 @@ import { ContainerOptions, create_container, EventContext, Message, ReceiverOpti
import { ITriggerFunctions } from 'n8n-core';
import {
deepCopy,
IDataObject,
INodeType,
INodeTypeDescription,
@ -172,20 +173,20 @@ export class AmqpTrigger implements INodeType {
if (options.jsonConvertByteArrayToString === true && data.body.content !== undefined) {
// The buffer is not ready... Stringify and parse back to load it.
const cont = JSON.stringify(data.body.content);
data.body = String.fromCharCode.apply(null, JSON.parse(cont).data);
const cont = deepCopy(data.body.content);
data.body = String.fromCharCode.apply(null, cont.data);
}
if (options.jsonConvertByteArrayToString === true && data.body.content !== undefined) {
// The buffer is not ready... Stringify and parse back to load it.
const cont = JSON.stringify(data.body.content);
data.body = String.fromCharCode.apply(null, JSON.parse(cont).data);
const cont = deepCopy(data.body.content);
data.body = String.fromCharCode.apply(null, cont.data);
}
if (options.jsonConvertByteArrayToString === true && data.body.content !== undefined) {
// The buffer is not ready... Stringify and parse back to load it.
const content = JSON.stringify(data.body.content);
data.body = String.fromCharCode.apply(null, JSON.parse(content).data);
const content = deepCopy(data.body.content);
data.body = String.fromCharCode.apply(null, content.data);
}
if (options.jsonParseBody === true) {

View file

@ -6,6 +6,7 @@ import {
} from 'n8n-core';
import {
deepCopy,
ICredentialDataDecryptedObject,
IDataObject,
IHttpRequestOptions,
@ -93,7 +94,7 @@ export function copyInputItem(item: INodeExecutionData, properties: string[]): I
if (item.json[property] === undefined) {
newItem[property] = null;
} else {
newItem[property] = JSON.parse(JSON.stringify(item.json[property]));
newItem[property] = deepCopy(item.json[property]);
}
}
return newItem;

View file

@ -1,4 +1,4 @@
import { IDataObject, INodeExecutionData } from 'n8n-workflow';
import { deepCopy, IDataObject, INodeExecutionData } from 'n8n-workflow';
import {
AdjustedPutItem,
@ -103,7 +103,7 @@ export function copyInputItem(item: INodeExecutionData, properties: string[]): I
if (item.json[property] === undefined) {
newItem[property] = null;
} else {
newItem[property] = JSON.parse(JSON.stringify(item.json[property]));
newItem[property] = deepCopy(item.json[property]);
}
}
return newItem;

View file

@ -3,6 +3,7 @@ import { set } from 'lodash';
import { IExecuteFunctions } from 'n8n-core';
import {
deepCopy,
ILoadOptionsFunctions,
INodeExecutionData,
INodePropertyOptions,
@ -483,7 +484,7 @@ export class Crypto implements INodeType {
if (dataPropertyName.includes('.')) {
// Uses dot notation so copy all data
newItem = {
json: JSON.parse(JSON.stringify(item.json)),
json: deepCopy(item.json),
pairedItem: {
item: i,
},

View file

@ -1,6 +1,7 @@
import { IExecuteFunctions } from 'n8n-core';
import {
deepCopy,
IDataObject,
ILoadOptionsFunctions,
INodeExecutionData,
@ -431,7 +432,7 @@ export class DateTime implements INodeType {
if (dataPropertyName.includes('.')) {
// Uses dot notation so copy all data
newItem = {
json: JSON.parse(JSON.stringify(item.json)),
json: deepCopy(item.json),
pairedItem: {
item: i,
},
@ -475,7 +476,7 @@ export class DateTime implements INodeType {
if (dataPropertyName.includes('.')) {
// Uses dot notation so copy all data
newItem = {
json: JSON.parse(JSON.stringify(item.json)),
json: deepCopy(item.json),
pairedItem: {
item: i,
},

View file

@ -1,5 +1,6 @@
import { BINARY_ENCODING, IExecuteFunctions } from 'n8n-core';
import {
deepCopy,
IDataObject,
ILoadOptionsFunctions,
INodeExecutionData,
@ -1269,8 +1270,8 @@ export class EditImage implements INodeType {
Object.assign(newItem.binary, item.binary);
// Make a deep copy of the binary data we change
if (newItem.binary![dataPropertyName as string]) {
newItem.binary![dataPropertyName as string] = JSON.parse(
JSON.stringify(newItem.binary![dataPropertyName as string]),
newItem.binary![dataPropertyName as string] = deepCopy(
newItem.binary![dataPropertyName as string],
);
}
}

View file

@ -1,5 +1,6 @@
import { IExecuteFunctions } from 'n8n-core';
import {
deepCopy,
IBinaryKeyData,
IDataObject,
INodeExecutionData,
@ -67,7 +68,7 @@ return items;`,
let items = this.getInputData();
// Copy the items as they may get changed in the functions
items = JSON.parse(JSON.stringify(items));
items = deepCopy(items);
// Assign item indexes
for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
@ -82,7 +83,7 @@ return items;`,
inputData[key] = cleanupData(inputData[key] as IDataObject);
} else {
// Is some special object like a Date so stringify
inputData[key] = JSON.parse(JSON.stringify(inputData[key]));
inputData[key] = deepCopy(inputData[key]);
}
}
});

View file

@ -1,5 +1,6 @@
import { IExecuteFunctions } from 'n8n-core';
import {
deepCopy,
IBinaryKeyData,
IDataObject,
INodeExecutionData,
@ -74,7 +75,7 @@ return item;`,
inputData[key] = cleanupData(inputData[key] as IDataObject);
} else {
// Is some special object like a Date so stringify
inputData[key] = JSON.parse(JSON.stringify(inputData[key]));
inputData[key] = deepCopy(inputData[key]);
}
}
});
@ -89,7 +90,7 @@ return item;`,
item.index = itemIndex;
// Copy the items as they may get changed in the functions
item = JSON.parse(JSON.stringify(item));
item = deepCopy(item);
// Define the global objects for the custom function
const sandbox = {

View file

@ -1,6 +1,7 @@
import { IExecuteFunctions } from 'n8n-core';
import {
deepCopy,
IDataObject,
INodeExecutionData,
INodeType,
@ -590,7 +591,7 @@ export class Markdown implements INodeType {
const markdownFromHTML = NodeHtmlMarkdown.translate(html, markdownOptions);
const newItem = JSON.parse(JSON.stringify(items[i].json));
const newItem = deepCopy(items[i].json);
set(newItem, destinationKey, markdownFromHTML);
returnData.push(newItem);
}
@ -605,7 +606,7 @@ export class Markdown implements INodeType {
Object.keys(options).forEach((key) => converter.setOption(key, options[key]));
const htmlFromMarkdown = converter.makeHtml(markdown);
const newItem = JSON.parse(JSON.stringify(items[i].json));
const newItem = deepCopy(items[i].json);
set(newItem, destinationKey, htmlFromMarkdown);
returnData.push(newItem);

View file

@ -4,6 +4,7 @@ import { get } from 'lodash';
import { IExecuteFunctions } from 'n8n-core';
import {
deepCopy,
GenericValue,
INodeExecutionData,
INodeType,
@ -427,7 +428,7 @@ export class MergeV1 implements INodeType {
continue;
} else if (mode === 'mergeByKey') {
// Copy the entry as the data gets changed
entry = JSON.parse(JSON.stringify(entry));
entry = deepCopy(entry);
for (key of Object.keys(copyData[referenceValue as string].json)) {
if (key === propertyName2) {

View file

@ -1,4 +1,4 @@
import { IDataObject, INodeExecutionData } from 'n8n-workflow';
import { deepCopy, IDataObject, INodeExecutionData } from 'n8n-workflow';
import { ITables } from './TableInterface';
/**
@ -15,7 +15,7 @@ export function copyInputItem(item: INodeExecutionData, properties: string[]): I
if (item.json[property] === undefined) {
newItem[property] = null;
} else {
newItem[property] = JSON.parse(JSON.stringify(item.json[property]));
newItem[property] = deepCopy(item.json[property]);
}
}
return newItem;

View file

@ -4,6 +4,7 @@ import { BINARY_ENCODING } from 'n8n-core';
import { IExecuteFunctions } from 'n8n-core';
import {
deepCopy,
IBinaryData,
IDataObject,
INodeExecutionData,
@ -364,7 +365,7 @@ export class MoveBinaryData implements INodeType {
newItem.json = JSON.parse(convertedValue);
} else {
// Does get added to existing data so copy it first
newItem.json = JSON.parse(JSON.stringify(item.json));
newItem.json = deepCopy(item.json);
if (options.keepAsBase64 !== true) {
convertedValue = iconv.decode(buffer, encoding, {
@ -387,7 +388,7 @@ export class MoveBinaryData implements INodeType {
newItem.binary = item.binary;
} else {
// Binary data will change so copy it
newItem.binary = JSON.parse(JSON.stringify(item.binary));
newItem.binary = deepCopy(item.binary);
unset(newItem.binary, sourceKey);
}
} else if (mode === 'jsonToBinary') {
@ -408,7 +409,7 @@ export class MoveBinaryData implements INodeType {
if (item.binary !== undefined) {
// Item already has binary data so copy it
newItem.binary = JSON.parse(JSON.stringify(item.binary));
newItem.binary = deepCopy(item.binary);
} else {
// Item does not have binary data yet so initialize empty
newItem.binary = {};
@ -447,7 +448,7 @@ export class MoveBinaryData implements INodeType {
} else {
// Data should not be kept and only one key has to get removed. So copy all
// data and then remove the not needed one
newItem.json = JSON.parse(JSON.stringify(item.json));
newItem.json = deepCopy(item.json);
const sourceKey = this.getNodeParameter('sourceKey', itemIndex) as string;
unset(newItem.json, sourceKey);

View file

@ -1,4 +1,11 @@
import { ICredentialDataDecryptedObject, IDataObject, ILoadOptionsFunctions, INodeExecutionData, INodeListSearchResult } from 'n8n-workflow';
import {
deepCopy,
ICredentialDataDecryptedObject,
IDataObject,
ILoadOptionsFunctions,
INodeExecutionData,
INodeListSearchResult,
} from 'n8n-workflow';
import mysql2 from 'mysql2/promise';
/**
@ -17,14 +24,16 @@ export function copyInputItems(items: INodeExecutionData[], properties: string[]
if (item.json[property] === undefined) {
newItem[property] = null;
} else {
newItem[property] = JSON.parse(JSON.stringify(item.json[property]));
newItem[property] = deepCopy(item.json[property]);
}
}
return newItem;
});
}
export function createConnection(credentials: ICredentialDataDecryptedObject): Promise<mysql2.Connection> {
export function createConnection(
credentials: ICredentialDataDecryptedObject,
): Promise<mysql2.Connection> {
const { ssl, caCertificate, clientCertificate, clientPrivateKey, ...baseCredentials } =
credentials;
@ -57,7 +66,7 @@ export async function searchTables(
ORDER BY table_name
`;
const [rows] = await connection.query(sql);
const results = (rows as IDataObject[]).map(r => ({
const results = (rows as IDataObject[]).map((r) => ({
name: r.TABLE_NAME as string,
value: r.TABLE_NAME as string,
}));

View file

@ -2,6 +2,7 @@ import { IExecuteFunctions } from 'n8n-core';
import { OptionsWithUri } from 'request';
import {
deepCopy,
ICredentialsDecrypted,
ICredentialTestFunctions,
IDataObject,
@ -297,7 +298,7 @@ export class Odoo implements INodeType {
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
let items = this.getInputData();
items = JSON.parse(JSON.stringify(items));
items = deepCopy(items);
const returnData: IDataObject[] = [];
let responseData;

View file

@ -1,5 +1,11 @@
import { IExecuteFunctions } from 'n8n-core';
import { IDataObject, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
import {
deepCopy,
IDataObject,
INodeExecutionData,
INodeType,
INodeTypeDescription,
} from 'n8n-workflow';
import { get, set, unset } from 'lodash';
import { options } from 'rhea';
@ -165,7 +171,7 @@ export class RenameKeys implements INodeType {
// Copy the whole JSON data as data on any level can be renamed
newItem = {
json: JSON.parse(JSON.stringify(item.json)),
json: deepCopy(item.json),
pairedItem: {
item: itemIndex,
},

View file

@ -1,5 +1,6 @@
import { IExecuteFunctions } from 'n8n-core';
import {
deepCopy,
IDataObject,
INodeExecutionData,
INodeParameters,
@ -162,7 +163,7 @@ export class Set implements INodeType {
Object.assign(newItem.binary, item.binary);
}
newItem.json = JSON.parse(JSON.stringify(item.json));
newItem.json = deepCopy(item.json);
}
// Add boolean values

View file

@ -1,4 +1,4 @@
import { IDataObject, INodeExecutionData } from 'n8n-workflow';
import { deepCopy, IDataObject, INodeExecutionData } from 'n8n-workflow';
import snowflake from 'snowflake-sdk';
@ -53,7 +53,7 @@ export function copyInputItems(items: INodeExecutionData[], properties: string[]
if (item.json[property] === undefined) {
newItem[property] = null;
} else {
newItem[property] = JSON.parse(JSON.stringify(item.json[property]));
newItem[property] = deepCopy(item.json[property]);
}
}
return newItem;

View file

@ -1,6 +1,7 @@
import { IHookFunctions, IWebhookFunctions } from 'n8n-core';
import {
deepCopy,
IDataObject,
ILoadOptionsFunctions,
INodeExecutionData,
@ -707,7 +708,7 @@ export class SurveyMonkeyTrigger implements INodeType {
responseData.questions = {};
// Map the "Map" to JSON
const tuples = JSON.parse(JSON.stringify([...responseQuestions]));
const tuples = deepCopy([...responseQuestions]);
for (const [key, value] of tuples) {
responseData.questions[key] = value;
}

View file

@ -1,4 +1,4 @@
import { IDataObject, INodeProperties } from 'n8n-workflow';
import { deepCopy, IDataObject, INodeProperties } from 'n8n-workflow';
import { groups } from './Json/Groups';
@ -81,7 +81,7 @@ for (const tool of (tools as IDataObject).processors as IDataObject[]) {
tool: [tool.k],
},
},
description: JSON.parse(JSON.stringify(description)),
description: deepCopy(description),
};
let modifiedParam = null;
@ -109,6 +109,7 @@ for (const tool of (tools as IDataObject).processors as IDataObject[]) {
newParameters.push(currentParam);
}
}
// eslint-disable-next-line n8n-local-rules/no-json-parse-json-stringify
parameters = JSON.parse(JSON.stringify(newParameters));
} else {
parameters.push(parameter);

View file

@ -38,6 +38,7 @@ import {
NodeParameterValue,
WebhookHttpMethod,
} from './Interfaces';
import { deepCopy } from './utils';
import type { Workflow } from './Workflow';
@ -660,9 +661,7 @@ export function getNodeParameters(
} else if (returnDefaults) {
// Does not have values defined but defaults should be returned
if (Array.isArray(nodeProperties.default)) {
nodeParameters[nodeProperties.name] = JSON.parse(
JSON.stringify(nodeProperties.default),
);
nodeParameters[nodeProperties.name] = deepCopy(nodeProperties.default);
} else {
// As it is probably wrong for many nodes, do we keep on returning an empty array if
// anything else than an array is set as default
@ -690,7 +689,7 @@ export function getNodeParameters(
}
} else if (returnDefaults) {
// Does not have values defined but defaults should be returned
nodeParameters[nodeProperties.name] = JSON.parse(JSON.stringify(nodeProperties.default));
nodeParameters[nodeProperties.name] = deepCopy(nodeProperties.default);
nodeParametersFull[nodeProperties.name] = nodeParameters[nodeProperties.name];
}
} else if (nodeProperties.type === 'fixedCollection') {
@ -704,7 +703,7 @@ export function getNodeParameters(
let propertyValues = nodeValues[nodeProperties.name];
if (returnDefaults) {
if (propertyValues === undefined) {
propertyValues = JSON.parse(JSON.stringify(nodeProperties.default));
propertyValues = deepCopy(nodeProperties.default);
}
}
@ -819,9 +818,7 @@ export function getNodeParameters(
if (returnDefaults) {
// Set also when it has the default value
if (collectionValues === undefined) {
nodeParameters[nodeProperties.name] = JSON.parse(
JSON.stringify(nodeProperties.default),
);
nodeParameters[nodeProperties.name] = deepCopy(nodeProperties.default);
} else {
nodeParameters[nodeProperties.name] = collectionValues;
}