fix(workflow): remove a few ts-ignore and eslint-disable (#3958)

fix(workflow): remove a few `ts-ignore` and `eslint-disable`. improve typing
This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™
2022-09-09 16:34:50 +02:00
committed by GitHub
parent 712924cbc3
commit a73ac1d94f
9 changed files with 72 additions and 83 deletions

View File

@@ -1,5 +1,3 @@
/* eslint-disable id-denylist */
// @ts-ignore
import * as tmpl from '@n8n_io/riot-tmpl'; import * as tmpl from '@n8n_io/riot-tmpl';
import { DateTime, Duration, Interval } from 'luxon'; import { DateTime, Duration, Interval } from 'luxon';
@@ -12,20 +10,17 @@ import {
INodeParameters, INodeParameters,
IRunExecutionData, IRunExecutionData,
IWorkflowDataProxyAdditionalKeys, IWorkflowDataProxyAdditionalKeys,
IWorkflowDataProxyData,
NodeParameterValue, NodeParameterValue,
Workflow, Workflow,
WorkflowDataProxy, WorkflowDataProxy,
WorkflowExecuteMode, WorkflowExecuteMode,
} from '.'; } from '.';
// @ts-ignore
// Set it to use double curly brackets instead of single ones // Set it to use double curly brackets instead of single ones
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
tmpl.brackets.set('{{ }}'); tmpl.brackets.set('{{ }}');
// Make sure that error get forwarded // Make sure that error get forwarded
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
tmpl.tmpl.errorHandler = (error: Error) => { tmpl.tmpl.errorHandler = (error: Error) => {
if (error instanceof ExpressionError) { if (error instanceof ExpressionError) {
if (error.context.failExecution) { if (error.context.failExecution) {
@@ -114,7 +109,6 @@ export class Expression {
const data = dataProxy.getDataProxy(); const data = dataProxy.getDataProxy();
// Support only a subset of process properties // Support only a subset of process properties
// @ts-ignore
data.process = { data.process = {
arch: process.arch, arch: process.arch,
env: process.env, env: process.env,
@@ -130,7 +124,6 @@ export class Expression {
* Denylist * Denylist
*/ */
// @ts-ignore
data.document = {}; data.document = {};
data.global = {}; data.global = {};
data.window = {}; data.window = {};
@@ -223,11 +216,13 @@ export class Expression {
data.Intl = typeof Intl !== 'undefined' ? Intl : {}; data.Intl = typeof Intl !== 'undefined' ? Intl : {};
// Text // Text
// eslint-disable-next-line id-denylist
data.String = String; data.String = String;
data.RegExp = RegExp; data.RegExp = RegExp;
// Math // Math
data.Math = Math; data.Math = Math;
// eslint-disable-next-line id-denylist
data.Number = Number; data.Number = Number;
data.BigInt = typeof BigInt !== 'undefined' ? BigInt : {}; data.BigInt = typeof BigInt !== 'undefined' ? BigInt : {};
data.Infinity = Infinity; data.Infinity = Infinity;
@@ -250,15 +245,28 @@ export class Expression {
data.decodeURIComponent = decodeURIComponent; data.decodeURIComponent = decodeURIComponent;
// Other // Other
// eslint-disable-next-line id-denylist
data.Boolean = Boolean; data.Boolean = Boolean;
data.Symbol = Symbol; data.Symbol = Symbol;
// Execute the expression // Execute the expression
// eslint-disable-next-line @typescript-eslint/no-explicit-any const returnValue = this.renderExpression(parameterValue, data);
let returnValue; if (typeof returnValue === 'function') {
throw new Error('Expression resolved to a function. Please add "()"');
} else if (typeof returnValue === 'string') {
return returnValue;
} else if (returnValue !== null && typeof returnValue === 'object') {
if (returnObjectAsString) {
return this.convertObjectValueToString(returnValue);
}
}
return returnValue;
}
private renderExpression(expression: string, data: IWorkflowDataProxyData): tmpl.ReturnValue {
try { try {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call return tmpl.tmpl(expression, data);
returnValue = tmpl.tmpl(parameterValue, data);
} catch (error) { } catch (error) {
if (error instanceof ExpressionError) { if (error instanceof ExpressionError) {
// Ignore all errors except if they are ExpressionErrors and they are supposed // Ignore all errors except if they are ExpressionErrors and they are supposed
@@ -268,18 +276,7 @@ export class Expression {
} }
} }
} }
return null;
if (typeof returnValue === 'function') {
throw new Error('Expression resolved to a function. Please add "()"');
} else if (returnValue !== null && typeof returnValue === 'object') {
if (returnObjectAsString) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
return this.convertObjectValueToString(returnValue);
}
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return returnValue;
} }
/** /**
@@ -495,33 +492,25 @@ export class Expression {
} }
// The parameter value is complex so resolve depending on type // The parameter value is complex so resolve depending on type
if (Array.isArray(parameterValue)) { if (Array.isArray(parameterValue)) {
// Data is an array // Data is an array
const returnData = []; const returnData = parameterValue.map((item) => resolveParameterValue(item, {}));
// eslint-disable-next-line no-restricted-syntax
for (const item of parameterValue) {
returnData.push(resolveParameterValue(item, {}));
}
if (returnObjectAsString && typeof returnData === 'object') {
return this.convertObjectValueToString(returnData);
}
return returnData as NodeParameterValue[] | INodeParameters[]; return returnData as NodeParameterValue[] | INodeParameters[];
} }
if (parameterValue === null || parameterValue === undefined) { if (parameterValue === null || parameterValue === undefined) {
return parameterValue; return parameterValue;
} }
if (typeof parameterValue !== 'object') {
return {};
}
// Data is an object // Data is an object
const returnData: INodeParameters = {}; const returnData: INodeParameters = {};
// eslint-disable-next-line no-restricted-syntax // eslint-disable-next-line no-restricted-syntax
for (const key of Object.keys(parameterValue)) { for (const [key, value] of Object.entries(parameterValue)) {
returnData[key] = resolveParameterValue( returnData[key] = resolveParameterValue(value, parameterValue);
(parameterValue as INodeParameters)[key],
parameterValue as INodeParameters,
);
} }
if (returnObjectAsString && typeof returnData === 'object') { if (returnObjectAsString && typeof returnData === 'object') {

View File

@@ -90,8 +90,7 @@ export abstract class ICredentials {
nodesAccess: ICredentialNodeAccess[], nodesAccess: ICredentialNodeAccess[],
data?: string, data?: string,
) { ) {
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing this.id = nodeCredentials.id ?? undefined;
this.id = nodeCredentials.id || undefined;
this.name = nodeCredentials.name; this.name = nodeCredentials.name;
this.type = type; this.type = type;
this.nodesAccess = nodesAccess; this.nodesAccess = nodesAccess;

View File

@@ -76,9 +76,8 @@ export abstract class ExecutionBaseError extends Error {
this.message = error.message as string; this.message = error.message as string;
} }
if (Object.prototype.hasOwnProperty.call(error, 'context')) { if (error instanceof ExecutionBaseError) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any this.context = error.context;
this.context = (error as any).context;
} }
} }
} }
@@ -130,14 +129,12 @@ abstract class NodeError extends ExecutionBaseError {
): string | null { ): string | null {
// eslint-disable-next-line no-restricted-syntax // eslint-disable-next-line no-restricted-syntax
for (const key of potentialKeys) { for (const key of potentialKeys) {
if (error[key]) { const value = error[key];
if (typeof error[key] === 'string') return error[key] as string; if (value) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion if (typeof value === 'string') return value;
if (typeof error[key] === 'number') return error[key]!.toString(); if (typeof value === 'number') return value.toString();
if (Array.isArray(error[key])) { if (Array.isArray(value)) {
// @ts-ignore const resolvedErrors: string[] = value
const resolvedErrors: string[] = error[key]
// @ts-ignore
.map((error) => { .map((error) => {
if (typeof error === 'string') return error; if (typeof error === 'string') return error;
if (typeof error === 'number') return error.toString(); if (typeof error === 'number') return error.toString();
@@ -146,15 +143,15 @@ abstract class NodeError extends ExecutionBaseError {
} }
return null; return null;
}) })
.filter((errorValue: string | null) => errorValue !== null); .filter((errorValue): errorValue is string => errorValue !== null);
if (resolvedErrors.length === 0) { if (resolvedErrors.length === 0) {
return null; return null;
} }
return resolvedErrors.join(' | '); return resolvedErrors.join(' | ');
} }
if (this.isTraversableObject(error[key])) { if (this.isTraversableObject(value)) {
const property = this.findProperty(error[key] as JsonObject, potentialKeys); const property = this.findProperty(value, potentialKeys);
if (property) { if (property) {
return property; return property;
} }
@@ -164,8 +161,9 @@ abstract class NodeError extends ExecutionBaseError {
// eslint-disable-next-line no-restricted-syntax // eslint-disable-next-line no-restricted-syntax
for (const key of traversalKeys) { for (const key of traversalKeys) {
if (this.isTraversableObject(error[key])) { const value = error[key];
const property = this.findProperty(error[key] as JsonObject, potentialKeys, traversalKeys); if (this.isTraversableObject(value)) {
const property = this.findProperty(value, potentialKeys, traversalKeys);
if (property) { if (property) {
return property; return property;
} }

View File

@@ -427,26 +427,26 @@ export function getParamterDependencies(
): IParameterDependencies { ): IParameterDependencies {
const dependencies: IParameterDependencies = {}; const dependencies: IParameterDependencies = {};
let displayRule: string;
let parameterName: string;
for (const nodeProperties of nodePropertiesArray) { for (const nodeProperties of nodePropertiesArray) {
if (dependencies[nodeProperties.name] === undefined) { const { name, displayOptions } = nodeProperties;
dependencies[nodeProperties.name] = [];
if (!dependencies[name]) {
dependencies[name] = [];
} }
if (nodeProperties.displayOptions === undefined) {
if (!displayOptions) {
// Does not have any dependencies // Does not have any dependencies
continue; continue;
} }
for (displayRule of Object.keys(nodeProperties.displayOptions)) { for (const displayRule of Object.values(displayOptions)) {
// @ts-ignore for (const parameterName of Object.keys(displayRule)) {
for (parameterName of Object.keys(nodeProperties.displayOptions[displayRule])) { if (!dependencies[name].includes(parameterName)) {
if (!dependencies[nodeProperties.name].includes(parameterName)) {
if (parameterName.charAt(0) === '@') { if (parameterName.charAt(0) === '@') {
// Is a special parameter so can be skipped // Is a special parameter so can be skipped
continue; continue;
} }
dependencies[nodeProperties.name].push(parameterName); dependencies[name].push(parameterName);
} }
} }
} }

View File

@@ -352,7 +352,7 @@ export class WorkflowDataProxy {
} }
return new Proxy( return new Proxy(
{}, { binary: undefined, data: undefined, json: undefined },
{ {
get(target, name, receiver) { get(target, name, receiver) {
name = name.toString(); name = name.toString();
@@ -472,8 +472,7 @@ export class WorkflowDataProxy {
throw new Error(`The key "${name.toString()}" is not supported!`); throw new Error(`The key "${name.toString()}" is not supported!`);
} }
// @ts-ignore return that.workflow[name as keyof typeof target];
return that.workflow[name.toString()];
}, },
}, },
); );
@@ -1004,12 +1003,10 @@ export class WorkflowDataProxy {
return new Proxy(base, { return new Proxy(base, {
get(target, name, receiver) { get(target, name, receiver) {
if (['$data', '$json'].includes(name as string)) { if (['$data', '$json'].includes(name as string)) {
// @ts-ignore return that.nodeDataGetter(that.activeNodeName, true)?.json;
return that.nodeDataGetter(that.activeNodeName, true).json;
} }
if (name === '$binary') { if (name === '$binary') {
// @ts-ignore return that.nodeDataGetter(that.activeNodeName, true)?.binary;
return that.nodeDataGetter(that.activeNodeName, true).binary;
} }
return Reflect.get(target, name, receiver); return Reflect.get(target, name, receiver);

14
packages/workflow/src/types.d.ts vendored Normal file
View File

@@ -0,0 +1,14 @@
declare module '@n8n_io/riot-tmpl' {
interface Brackets {
set(token: string): void;
}
type ReturnValue = string | null | (() => unknown);
type TmplFn = (value: string, data: unknown) => ReturnValue;
interface Tmpl extends TmplFn {
errorHandler?(error: Error): void;
}
let brackets: Brackets;
let tmpl: Tmpl;
}

View File

@@ -634,8 +634,6 @@ describe('RoutingNode', () => {
for (const testData of tests) { for (const testData of tests) {
test(testData.description, () => { test(testData.description, () => {
node.parameters = testData.input.nodeParameters; node.parameters = testData.input.nodeParameters;
// @ts-ignore
nodeType.description.properties = [testData.input.nodeTypeProperties]; nodeType.description.properties = [testData.input.nodeTypeProperties];
const workflow = new Workflow({ const workflow = new Workflow({

View File

@@ -1022,7 +1022,6 @@ describe('Workflow', () => {
}, },
{ {
name: 'Node3', name: 'Node3',
// @ts-ignore
parameters: testData.input.hasOwnProperty('Node3') parameters: testData.input.hasOwnProperty('Node3')
? // @ts-ignore ? // @ts-ignore
testData.input.Node3.parameters testData.input.Node3.parameters
@@ -1034,7 +1033,6 @@ describe('Workflow', () => {
}, },
{ {
name: 'Node 4 with spaces', name: 'Node 4 with spaces',
// @ts-ignore
parameters: testData.input.hasOwnProperty('Node4') parameters: testData.input.hasOwnProperty('Node4')
? // @ts-ignore ? // @ts-ignore
testData.input.Node4.parameters testData.input.Node4.parameters
@@ -1080,12 +1078,10 @@ describe('Workflow', () => {
{ {
startTime: 1, startTime: 1,
executionTime: 1, executionTime: 1,
// @ts-ignore
data: { data: {
main: [ main: [
[ [
{ {
// @ts-ignore
json: testData.input.Node1.outputJson || testData.input.Node1.parameters, json: testData.input.Node1.outputJson || testData.input.Node1.parameters,
// @ts-ignore // @ts-ignore
binary: testData.input.Node1.outputBinary, binary: testData.input.Node1.outputBinary,

View File

@@ -75,7 +75,6 @@ describe('WorkflowDataProxy', () => {
{ {
startTime: 1, startTime: 1,
executionTime: 1, executionTime: 1,
// @ts-ignore
data: { data: {
main: [ main: [
[ [
@@ -104,7 +103,6 @@ describe('WorkflowDataProxy', () => {
{ {
startTime: 1, startTime: 1,
executionTime: 1, executionTime: 1,
// @ts-ignore
data: { data: {
main: [ main: [
[ [