diff --git a/packages/@n8n/nodes-langchain/nodes/vector_store/shared/createVectorStoreNode.ts b/packages/@n8n/nodes-langchain/nodes/vector_store/shared/createVectorStoreNode.ts index 441126c985..e393d32e55 100644 --- a/packages/@n8n/nodes-langchain/nodes/vector_store/shared/createVectorStoreNode.ts +++ b/packages/@n8n/nodes-langchain/nodes/vector_store/shared/createVectorStoreNode.ts @@ -392,13 +392,9 @@ export const createVectorStoreNode = (args: VectorStoreNodeConstructorArgs) => ); resultData.push(...serializedDocuments); - try { - await args.populateVectorStore(this, embeddings, processedDocuments, itemIndex); + await args.populateVectorStore(this, embeddings, processedDocuments, itemIndex); - logAiEvent(this, 'ai-vector-store-populated'); - } catch (error) { - throw error; - } + logAiEvent(this, 'ai-vector-store-populated'); } return [resultData]; @@ -443,16 +439,12 @@ export const createVectorStoreNode = (args: VectorStoreNodeConstructorArgs) => resultData.push(...serializedDocuments); - try { - // Use ids option to upsert instead of insert - await vectorStore.addDocuments(processedDocuments, { - ids: [documentId], - }); + // Use ids option to upsert instead of insert + await vectorStore.addDocuments(processedDocuments, { + ids: [documentId], + }); - logAiEvent(this, 'ai-vector-store-updated'); - } catch (error) { - throw error; - } + logAiEvent(this, 'ai-vector-store-updated'); } return [resultData]; diff --git a/packages/@n8n_io/eslint-config/base.js b/packages/@n8n_io/eslint-config/base.js index 0864a20a7b..dc4ad37025 100644 --- a/packages/@n8n_io/eslint-config/base.js +++ b/packages/@n8n_io/eslint-config/base.js @@ -369,6 +369,8 @@ const config = (module.exports = { 'n8n-local-rules/no-unused-param-in-catch-clause': 'error', + 'n8n-local-rules/no-useless-catch-throw': 'error', + 'n8n-local-rules/no-plain-errors': 'error', // ****************************************************************** diff --git a/packages/@n8n_io/eslint-config/local-rules.js b/packages/@n8n_io/eslint-config/local-rules.js index 92b0f6669e..d32d72f89c 100644 --- a/packages/@n8n_io/eslint-config/local-rules.js +++ b/packages/@n8n_io/eslint-config/local-rules.js @@ -172,6 +172,49 @@ module.exports = { }, }, + 'no-useless-catch-throw': { + meta: { + type: 'problem', + docs: { + description: 'Disallow `try-catch` blocks where the `catch` only contains a `throw error`.', + recommended: 'error', + }, + messages: { + noUselessCatchThrow: 'Remove useless `catch` block.', + }, + fixable: 'code', + }, + create(context) { + return { + CatchClause(node) { + if ( + node.body.body.length === 1 && + node.body.body[0].type === 'ThrowStatement' && + node.body.body[0].argument.type === 'Identifier' && + node.body.body[0].argument.name === node.param.name + ) { + context.report({ + node, + messageId: 'noUselessCatchThrow', + fix(fixer) { + const tryStatement = node.parent; + const tryBlock = tryStatement.block; + const sourceCode = context.getSourceCode(); + const tryBlockText = sourceCode.getText(tryBlock); + const tryBlockTextWithoutBraces = tryBlockText.slice(1, -1).trim(); + const indentedTryBlockText = tryBlockTextWithoutBraces + .split('\n') + .map((line) => line.replace(/\t/, '')) + .join('\n'); + return fixer.replaceText(tryStatement, indentedTryBlockText); + }, + }); + } + }, + }; + }, + }, + 'no-skipped-tests': { meta: { type: 'problem', diff --git a/packages/@n8n_io/eslint-config/local-rules.test.js b/packages/@n8n_io/eslint-config/local-rules.test.js index 86589ac67f..ca32c37a40 100644 --- a/packages/@n8n_io/eslint-config/local-rules.test.js +++ b/packages/@n8n_io/eslint-config/local-rules.test.js @@ -51,3 +51,33 @@ ruleTester.run('no-json-parse-json-stringify', rules['no-json-parse-json-stringi }, ], }); + +ruleTester.run('no-useless-catch-throw', rules['no-useless-catch-throw'], { + valid: [ + { + code: 'try { foo(); } catch (e) { console.error(e); }', + }, + { + code: 'try { foo(); } catch (e) { throw new Error("Custom error"); }', + }, + ], + invalid: [ + { + code: ` +try { + // Some comment + if (foo) { + bar(); + } +} catch (e) { + throw e; +}`, + errors: [{ messageId: 'noUselessCatchThrow' }], + output: ` +// Some comment +if (foo) { + bar(); +}`, + }, + ], +}); diff --git a/packages/editor-ui/src/components/ButtonParameter/utils.ts b/packages/editor-ui/src/components/ButtonParameter/utils.ts index 1044477bbb..47a4081963 100644 --- a/packages/editor-ui/src/components/ButtonParameter/utils.ts +++ b/packages/editor-ui/src/components/ButtonParameter/utils.ts @@ -161,28 +161,24 @@ export function reducePayloadSizeOrThrow( error: Error, averageTokenLength = 4, ) { - try { - let remainingTokensToReduce = calculateRemainingTokens(error); + let remainingTokensToReduce = calculateRemainingTokens(error); - const [remaining, parentNodesTokenCount] = trimParentNodesSchema( - payload, - remainingTokensToReduce, - averageTokenLength, - ); + const [remaining, parentNodesTokenCount] = trimParentNodesSchema( + payload, + remainingTokensToReduce, + averageTokenLength, + ); - remainingTokensToReduce = remaining; + remainingTokensToReduce = remaining; - remainingTokensToReduce = trimInputSchemaProperties( - payload, - remainingTokensToReduce, - averageTokenLength, - parentNodesTokenCount, - ); + remainingTokensToReduce = trimInputSchemaProperties( + payload, + remainingTokensToReduce, + averageTokenLength, + parentNodesTokenCount, + ); - if (remainingTokensToReduce > 0) throw error; - } catch (e) { - throw e; - } + if (remainingTokensToReduce > 0) throw error; } export async function generateCodeForAiTransform(prompt: string, path: string, retries = 1) { diff --git a/packages/editor-ui/src/components/CanvasChat/CanvasChat.vue b/packages/editor-ui/src/components/CanvasChat/CanvasChat.vue index 085edeaf73..b2212ffda8 100644 --- a/packages/editor-ui/src/components/CanvasChat/CanvasChat.vue +++ b/packages/editor-ui/src/components/CanvasChat/CanvasChat.vue @@ -200,29 +200,25 @@ async function createExecutionPromise() { } async function onRunChatWorkflow(payload: RunWorkflowChatPayload) { - try { - const runWorkflowOptions: Parameters[0] = { - triggerNode: payload.triggerNode, - nodeData: payload.nodeData, - source: payload.source, - }; + const runWorkflowOptions: Parameters[0] = { + triggerNode: payload.triggerNode, + nodeData: payload.nodeData, + source: payload.source, + }; - if (workflowsStore.chatPartialExecutionDestinationNode) { - runWorkflowOptions.destinationNode = workflowsStore.chatPartialExecutionDestinationNode; - workflowsStore.chatPartialExecutionDestinationNode = null; - } - - const response = await runWorkflow(runWorkflowOptions); - - if (response) { - await createExecutionPromise(); - workflowsStore.appendChatMessage(payload.message); - return response; - } - return; - } catch (error) { - throw error; + if (workflowsStore.chatPartialExecutionDestinationNode) { + runWorkflowOptions.destinationNode = workflowsStore.chatPartialExecutionDestinationNode; + workflowsStore.chatPartialExecutionDestinationNode = null; } + + const response = await runWorkflow(runWorkflowOptions); + + if (response) { + await createExecutionPromise(); + workflowsStore.appendChatMessage(payload.message); + return response; + } + return; } // Initialize chat config diff --git a/packages/editor-ui/src/stores/communityNodes.store.ts b/packages/editor-ui/src/stores/communityNodes.store.ts index ef5fa85e82..5e73d0e31a 100644 --- a/packages/editor-ui/src/stores/communityNodes.store.ts +++ b/packages/editor-ui/src/stores/communityNodes.store.ts @@ -55,21 +55,13 @@ export const useCommunityNodesStore = defineStore(STORES.COMMUNITY_NODES, () => }; const installPackage = async (packageName: string): Promise => { - try { - await communityNodesApi.installNewPackage(rootStore.restApiContext, packageName); - await fetchInstalledPackages(); - } catch (error) { - throw error; - } + await communityNodesApi.installNewPackage(rootStore.restApiContext, packageName); + await fetchInstalledPackages(); }; const uninstallPackage = async (packageName: string): Promise => { - try { - await communityNodesApi.uninstallPackage(rootStore.restApiContext, packageName); - removePackageByName(packageName); - } catch (error) { - throw error; - } + await communityNodesApi.uninstallPackage(rootStore.restApiContext, packageName); + removePackageByName(packageName); }; const removePackageByName = (name: string): void => { @@ -82,16 +74,12 @@ export const useCommunityNodesStore = defineStore(STORES.COMMUNITY_NODES, () => }; const updatePackage = async (packageName: string): Promise => { - try { - const packageToUpdate = installedPackages.value[packageName]; - const updatedPackage = await communityNodesApi.updatePackage( - rootStore.restApiContext, - packageToUpdate.packageName, - ); - updatePackageObject(updatedPackage); - } catch (error) { - throw error; - } + const packageToUpdate = installedPackages.value[packageName]; + const updatedPackage = await communityNodesApi.updatePackage( + rootStore.restApiContext, + packageToUpdate.packageName, + ); + updatePackageObject(updatedPackage); }; return { diff --git a/packages/editor-ui/src/stores/executions.store.ts b/packages/editor-ui/src/stores/executions.store.ts index 14711d8198..c9b5810f86 100644 --- a/packages/editor-ui/src/stores/executions.store.ts +++ b/packages/editor-ui/src/stores/executions.store.ts @@ -173,8 +173,6 @@ export const useExecutionsStore = defineStore('executions', () => { executionsCount.value = data.count; executionsCountEstimated.value = data.estimated; return data; - } catch (e) { - throw e; } finally { loading.value = false; } diff --git a/packages/nodes-base/nodes/Disqus/Disqus.node.ts b/packages/nodes-base/nodes/Disqus/Disqus.node.ts index 27dc878560..664383dc74 100644 --- a/packages/nodes-base/nodes/Disqus/Disqus.node.ts +++ b/packages/nodes-base/nodes/Disqus/Disqus.node.ts @@ -601,16 +601,12 @@ export class Disqus implements INodeType { Object.assign(qs, additionalFields); - try { - const responseData = await disqusApiRequest.call(this, requestMethod, qs, endpoint); - const executionData = this.helpers.constructExecutionMetaData( - this.helpers.returnJsonArray(responseData.response as IDataObject[]), - { itemData: { item: i } }, - ); - returnData.push(...executionData); - } catch (error) { - throw error; - } + const responseData = await disqusApiRequest.call(this, requestMethod, qs, endpoint); + const executionData = this.helpers.constructExecutionMetaData( + this.helpers.returnJsonArray(responseData.response as IDataObject[]), + { itemData: { item: i } }, + ); + returnData.push(...executionData); } else if (operation === 'getPosts') { // ---------------------------------- // getPosts @@ -629,28 +625,24 @@ export class Disqus implements INodeType { qs.forum = id; qs.limit = 100; - try { - let responseData: IDataObject = {}; - if (returnAll) { - responseData.response = await disqusApiRequestAllItems.call( - this, - requestMethod, - qs, - endpoint, - ); - } else { - const limit = this.getNodeParameter('limit', i); - qs.limit = limit; - responseData = await disqusApiRequest.call(this, requestMethod, qs, endpoint); - } - const executionData = this.helpers.constructExecutionMetaData( - this.helpers.returnJsonArray(responseData.response as IDataObject), - { itemData: { item: i } }, + let responseData: IDataObject = {}; + if (returnAll) { + responseData.response = await disqusApiRequestAllItems.call( + this, + requestMethod, + qs, + endpoint, ); - returnData.push(...executionData); - } catch (error) { - throw error; + } else { + const limit = this.getNodeParameter('limit', i); + qs.limit = limit; + responseData = await disqusApiRequest.call(this, requestMethod, qs, endpoint); } + const executionData = this.helpers.constructExecutionMetaData( + this.helpers.returnJsonArray(responseData.response as IDataObject), + { itemData: { item: i } }, + ); + returnData.push(...executionData); } else if (operation === 'getCategories') { // ---------------------------------- // getCategories @@ -668,34 +660,30 @@ export class Disqus implements INodeType { qs.forum = id; qs.limit = 100; - try { - let responseData: IDataObject = {}; + let responseData: IDataObject = {}; - if (returnAll) { - responseData.response = await disqusApiRequestAllItems.call( - this, - requestMethod, - qs, - endpoint, - ); - } else { - const limit = this.getNodeParameter('limit', i); - qs.limit = limit; - responseData = (await disqusApiRequest.call( - this, - requestMethod, - qs, - endpoint, - )) as IDataObject; - } - const executionData = this.helpers.constructExecutionMetaData( - this.helpers.returnJsonArray(responseData.response as IDataObject), - { itemData: { item: i } }, + if (returnAll) { + responseData.response = await disqusApiRequestAllItems.call( + this, + requestMethod, + qs, + endpoint, ); - returnData.push(...executionData); - } catch (error) { - throw error; + } else { + const limit = this.getNodeParameter('limit', i); + qs.limit = limit; + responseData = (await disqusApiRequest.call( + this, + requestMethod, + qs, + endpoint, + )) as IDataObject; } + const executionData = this.helpers.constructExecutionMetaData( + this.helpers.returnJsonArray(responseData.response as IDataObject), + { itemData: { item: i } }, + ); + returnData.push(...executionData); } else if (operation === 'getThreads') { // ---------------------------------- // getThreads @@ -715,28 +703,24 @@ export class Disqus implements INodeType { Object.assign(qs, additionalFields); - try { - let responseData: IDataObject = {}; - if (returnAll) { - responseData.response = await disqusApiRequestAllItems.call( - this, - requestMethod, - qs, - endpoint, - ); - } else { - const limit = this.getNodeParameter('limit', i); - qs.limit = limit; - responseData = await disqusApiRequest.call(this, requestMethod, qs, endpoint); - } - const executionData = this.helpers.constructExecutionMetaData( - this.helpers.returnJsonArray(responseData.response as IDataObject), - { itemData: { item: i } }, + let responseData: IDataObject = {}; + if (returnAll) { + responseData.response = await disqusApiRequestAllItems.call( + this, + requestMethod, + qs, + endpoint, ); - returnData.push(...executionData); - } catch (error) { - throw error; + } else { + const limit = this.getNodeParameter('limit', i); + qs.limit = limit; + responseData = await disqusApiRequest.call(this, requestMethod, qs, endpoint); } + const executionData = this.helpers.constructExecutionMetaData( + this.helpers.returnJsonArray(responseData.response as IDataObject), + { itemData: { item: i } }, + ); + returnData.push(...executionData); } else { throw new NodeOperationError( this.getNode(), diff --git a/packages/nodes-base/nodes/Disqus/GenericFunctions.ts b/packages/nodes-base/nodes/Disqus/GenericFunctions.ts index d9c541144f..85141db3c1 100644 --- a/packages/nodes-base/nodes/Disqus/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Disqus/GenericFunctions.ts @@ -66,14 +66,10 @@ export async function disqusApiRequestAllItems( let responseData; - try { - do { - responseData = await disqusApiRequest.call(this, method, qs, uri, body, option); - qs.cursor = responseData.cursor.id; - returnData.push.apply(returnData, responseData.response as IDataObject[]); - } while (responseData.cursor.more === true && responseData.cursor.hasNext === true); - return returnData; - } catch (error) { - throw error; - } + do { + responseData = await disqusApiRequest.call(this, method, qs, uri, body, option); + qs.cursor = responseData.cursor.id; + returnData.push.apply(returnData, responseData.response as IDataObject[]); + } while (responseData.cursor.more === true && responseData.cursor.hasNext === true); + return returnData; } diff --git a/packages/nodes-base/nodes/FileMaker/GenericFunctions.ts b/packages/nodes-base/nodes/FileMaker/GenericFunctions.ts index 3c3100fa62..21b9e2b0a3 100644 --- a/packages/nodes-base/nodes/FileMaker/GenericFunctions.ts +++ b/packages/nodes-base/nodes/FileMaker/GenericFunctions.ts @@ -154,13 +154,8 @@ export async function getFields(this: ILoadOptionsFunctions): Promise { json: true, }; - try { - const responseData = await this.helpers.request(options); - return responseData.response.fieldMetaData; - } catch (error) { - // If that data does not exist for some reason return the actual error - throw error; - } + const responseData = await this.helpers.request(options); + return responseData.response.fieldMetaData; } /** @@ -185,13 +180,8 @@ export async function getPortals(this: ILoadOptionsFunctions): Promise { json: true, }; - try { - const responseData = await this.helpers.request(options); - return responseData.response.portalMetaData; - } catch (error) { - // If that data does not exist for some reason return the actual error - throw error; - } + const responseData = await this.helpers.request(options); + return responseData.response.portalMetaData; } function parseScriptsList(scripts: ScriptObject[]): INodePropertyOptions[] { @@ -230,15 +220,10 @@ export async function getScripts(this: ILoadOptionsFunctions): Promise { json: true, }; - try { - const responseData = await this.helpers.request(options); - const items = parseScriptsList(responseData.response.scripts as ScriptObject[]); - items.sort((a, b) => (a.name > b.name ? 0 : 1)); - return items; - } catch (error) { - // If that data does not exist for some reason return the actual error - throw error; - } + const responseData = await this.helpers.request(options); + const items = parseScriptsList(responseData.response.scripts as ScriptObject[]); + items.sort((a, b) => (a.name > b.name ? 0 : 1)); + return items; } export async function logout( diff --git a/packages/nodes-base/nodes/Flow/FlowTrigger.node.ts b/packages/nodes-base/nodes/Flow/FlowTrigger.node.ts index fc19041f18..ceab6b14bc 100644 --- a/packages/nodes-base/nodes/Flow/FlowTrigger.node.ts +++ b/packages/nodes-base/nodes/Flow/FlowTrigger.node.ts @@ -107,12 +107,8 @@ export class FlowTrigger implements INodeType { } qs.organization_id = credentials.organizationId as number; const endpoint = '/integration_webhooks'; - try { - webhooks = await flowApiRequest.call(this, 'GET', endpoint, {}, qs); - webhooks = webhooks.integration_webhooks; - } catch (error) { - throw error; - } + webhooks = await flowApiRequest.call(this, 'GET', endpoint, {}, qs); + webhooks = webhooks.integration_webhooks; for (const webhook of webhooks) { // @ts-ignore if (webhookData.webhookIds.includes(webhook.id)) { diff --git a/packages/nodes-base/nodes/ItemLists/V3/actions/router.ts b/packages/nodes-base/nodes/ItemLists/V3/actions/router.ts index 6580464c4a..fa39aa55cf 100644 --- a/packages/nodes-base/nodes/ItemLists/V3/actions/router.ts +++ b/packages/nodes-base/nodes/ItemLists/V3/actions/router.ts @@ -16,19 +16,15 @@ export async function router(this: IExecuteFunctions): Promise { - let webhook; const webhookUrl = this.getNodeWebhookUrl('default'); const listId = this.getNodeParameter('list') as string; const events = this.getNodeParameter('events', []) as string[]; @@ -233,11 +232,7 @@ export class MailchimpTrigger implements INodeType { }, {}), }; const endpoint = `/lists/${listId}/webhooks`; - try { - webhook = await mailchimpApiRequest.call(this, endpoint, 'POST', body); - } catch (error) { - throw error; - } + const webhook = await mailchimpApiRequest.call(this, endpoint, 'POST', body); if (webhook.id === undefined) { return false; } diff --git a/packages/nodes-base/nodes/PayPal/PayPalTrigger.node.ts b/packages/nodes-base/nodes/PayPal/PayPalTrigger.node.ts index 7fb8987ef5..d3bf26669f 100644 --- a/packages/nodes-base/nodes/PayPal/PayPalTrigger.node.ts +++ b/packages/nodes-base/nodes/PayPal/PayPalTrigger.node.ts @@ -115,7 +115,6 @@ export class PayPalTrigger implements INodeType { }, async create(this: IHookFunctions): Promise { - let webhook; const webhookUrl = this.getNodeWebhookUrl('default'); const events = this.getNodeParameter('events', []) as string[]; const body = { @@ -125,11 +124,7 @@ export class PayPalTrigger implements INodeType { }), }; const endpoint = '/notifications/webhooks'; - try { - webhook = await payPalApiRequest.call(this, endpoint, 'POST', body); - } catch (error) { - throw error; - } + const webhook = await payPalApiRequest.call(this, endpoint, 'POST', body); if (webhook.id === undefined) { return false; @@ -156,7 +151,6 @@ export class PayPalTrigger implements INodeType { }; async webhook(this: IWebhookFunctions): Promise { - let webhook; const webhookData = this.getWorkflowStaticData('node'); const bodyData = this.getBodyData(); const req = this.getRequestObject(); @@ -188,11 +182,7 @@ export class PayPalTrigger implements INodeType { webhook_id: webhookData.webhookId, webhook_event: bodyData, }; - try { - webhook = await payPalApiRequest.call(this, endpoint, 'POST', body); - } catch (error) { - throw error; - } + const webhook = await payPalApiRequest.call(this, endpoint, 'POST', body); if (webhook.verification_status !== 'SUCCESS') { return {}; } diff --git a/packages/nodes-base/nodes/Stripe/StripeTrigger.node.ts b/packages/nodes-base/nodes/Stripe/StripeTrigger.node.ts index d255550254..7aa8e62ced 100644 --- a/packages/nodes-base/nodes/Stripe/StripeTrigger.node.ts +++ b/packages/nodes-base/nodes/Stripe/StripeTrigger.node.ts @@ -877,12 +877,7 @@ export class StripeTrigger implements INodeType { enabled_events: events, }; - let responseData; - try { - responseData = await stripeApiRequest.call(this, 'POST', endpoint, body); - } catch (error) { - throw error; - } + const responseData = await stripeApiRequest.call(this, 'POST', endpoint, body); if ( responseData.id === undefined || diff --git a/packages/nodes-base/nodes/Webflow/V2/actions/router.ts b/packages/nodes-base/nodes/Webflow/V2/actions/router.ts index 59eb4c552e..d8b5e17e10 100644 --- a/packages/nodes-base/nodes/Webflow/V2/actions/router.ts +++ b/packages/nodes-base/nodes/Webflow/V2/actions/router.ts @@ -16,19 +16,15 @@ export async function router(this: IExecuteFunctions): Promise