mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-25 04:34:06 -08:00
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:
parent
712924cbc3
commit
a73ac1d94f
|
@ -1,5 +1,3 @@
|
|||
/* eslint-disable id-denylist */
|
||||
// @ts-ignore
|
||||
import * as tmpl from '@n8n_io/riot-tmpl';
|
||||
import { DateTime, Duration, Interval } from 'luxon';
|
||||
|
||||
|
@ -12,20 +10,17 @@ import {
|
|||
INodeParameters,
|
||||
IRunExecutionData,
|
||||
IWorkflowDataProxyAdditionalKeys,
|
||||
IWorkflowDataProxyData,
|
||||
NodeParameterValue,
|
||||
Workflow,
|
||||
WorkflowDataProxy,
|
||||
WorkflowExecuteMode,
|
||||
} from '.';
|
||||
|
||||
// @ts-ignore
|
||||
|
||||
// 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('{{ }}');
|
||||
|
||||
// Make sure that error get forwarded
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
tmpl.tmpl.errorHandler = (error: Error) => {
|
||||
if (error instanceof ExpressionError) {
|
||||
if (error.context.failExecution) {
|
||||
|
@ -114,7 +109,6 @@ export class Expression {
|
|||
const data = dataProxy.getDataProxy();
|
||||
|
||||
// Support only a subset of process properties
|
||||
// @ts-ignore
|
||||
data.process = {
|
||||
arch: process.arch,
|
||||
env: process.env,
|
||||
|
@ -130,7 +124,6 @@ export class Expression {
|
|||
* Denylist
|
||||
*/
|
||||
|
||||
// @ts-ignore
|
||||
data.document = {};
|
||||
data.global = {};
|
||||
data.window = {};
|
||||
|
@ -223,11 +216,13 @@ export class Expression {
|
|||
data.Intl = typeof Intl !== 'undefined' ? Intl : {};
|
||||
|
||||
// Text
|
||||
// eslint-disable-next-line id-denylist
|
||||
data.String = String;
|
||||
data.RegExp = RegExp;
|
||||
|
||||
// Math
|
||||
data.Math = Math;
|
||||
// eslint-disable-next-line id-denylist
|
||||
data.Number = Number;
|
||||
data.BigInt = typeof BigInt !== 'undefined' ? BigInt : {};
|
||||
data.Infinity = Infinity;
|
||||
|
@ -250,15 +245,28 @@ export class Expression {
|
|||
data.decodeURIComponent = decodeURIComponent;
|
||||
|
||||
// Other
|
||||
// eslint-disable-next-line id-denylist
|
||||
data.Boolean = Boolean;
|
||||
data.Symbol = Symbol;
|
||||
|
||||
// Execute the expression
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
let returnValue;
|
||||
const returnValue = this.renderExpression(parameterValue, data);
|
||||
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 {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
|
||||
returnValue = tmpl.tmpl(parameterValue, data);
|
||||
return tmpl.tmpl(expression, data);
|
||||
} catch (error) {
|
||||
if (error instanceof ExpressionError) {
|
||||
// Ignore all errors except if they are ExpressionErrors and they are supposed
|
||||
|
@ -268,18 +276,7 @@ export class Expression {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -495,33 +492,25 @@ export class Expression {
|
|||
}
|
||||
|
||||
// The parameter value is complex so resolve depending on type
|
||||
|
||||
if (Array.isArray(parameterValue)) {
|
||||
// Data is an array
|
||||
const returnData = [];
|
||||
// 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);
|
||||
}
|
||||
|
||||
const returnData = parameterValue.map((item) => resolveParameterValue(item, {}));
|
||||
return returnData as NodeParameterValue[] | INodeParameters[];
|
||||
}
|
||||
|
||||
if (parameterValue === null || parameterValue === undefined) {
|
||||
return parameterValue;
|
||||
}
|
||||
|
||||
if (typeof parameterValue !== 'object') {
|
||||
return {};
|
||||
}
|
||||
|
||||
// Data is an object
|
||||
const returnData: INodeParameters = {};
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const key of Object.keys(parameterValue)) {
|
||||
returnData[key] = resolveParameterValue(
|
||||
(parameterValue as INodeParameters)[key],
|
||||
parameterValue as INodeParameters,
|
||||
);
|
||||
for (const [key, value] of Object.entries(parameterValue)) {
|
||||
returnData[key] = resolveParameterValue(value, parameterValue);
|
||||
}
|
||||
|
||||
if (returnObjectAsString && typeof returnData === 'object') {
|
||||
|
|
|
@ -90,8 +90,7 @@ export abstract class ICredentials {
|
|||
nodesAccess: ICredentialNodeAccess[],
|
||||
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.type = type;
|
||||
this.nodesAccess = nodesAccess;
|
||||
|
|
|
@ -76,9 +76,8 @@ export abstract class ExecutionBaseError extends Error {
|
|||
this.message = error.message as string;
|
||||
}
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(error, 'context')) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
this.context = (error as any).context;
|
||||
if (error instanceof ExecutionBaseError) {
|
||||
this.context = error.context;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -130,14 +129,12 @@ abstract class NodeError extends ExecutionBaseError {
|
|||
): string | null {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const key of potentialKeys) {
|
||||
if (error[key]) {
|
||||
if (typeof error[key] === 'string') return error[key] as string;
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
if (typeof error[key] === 'number') return error[key]!.toString();
|
||||
if (Array.isArray(error[key])) {
|
||||
// @ts-ignore
|
||||
const resolvedErrors: string[] = error[key]
|
||||
// @ts-ignore
|
||||
const value = error[key];
|
||||
if (value) {
|
||||
if (typeof value === 'string') return value;
|
||||
if (typeof value === 'number') return value.toString();
|
||||
if (Array.isArray(value)) {
|
||||
const resolvedErrors: string[] = value
|
||||
.map((error) => {
|
||||
if (typeof error === 'string') return error;
|
||||
if (typeof error === 'number') return error.toString();
|
||||
|
@ -146,15 +143,15 @@ abstract class NodeError extends ExecutionBaseError {
|
|||
}
|
||||
return null;
|
||||
})
|
||||
.filter((errorValue: string | null) => errorValue !== null);
|
||||
.filter((errorValue): errorValue is string => errorValue !== null);
|
||||
|
||||
if (resolvedErrors.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return resolvedErrors.join(' | ');
|
||||
}
|
||||
if (this.isTraversableObject(error[key])) {
|
||||
const property = this.findProperty(error[key] as JsonObject, potentialKeys);
|
||||
if (this.isTraversableObject(value)) {
|
||||
const property = this.findProperty(value, potentialKeys);
|
||||
if (property) {
|
||||
return property;
|
||||
}
|
||||
|
@ -164,8 +161,9 @@ abstract class NodeError extends ExecutionBaseError {
|
|||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const key of traversalKeys) {
|
||||
if (this.isTraversableObject(error[key])) {
|
||||
const property = this.findProperty(error[key] as JsonObject, potentialKeys, traversalKeys);
|
||||
const value = error[key];
|
||||
if (this.isTraversableObject(value)) {
|
||||
const property = this.findProperty(value, potentialKeys, traversalKeys);
|
||||
if (property) {
|
||||
return property;
|
||||
}
|
||||
|
|
|
@ -427,26 +427,26 @@ export function getParamterDependencies(
|
|||
): IParameterDependencies {
|
||||
const dependencies: IParameterDependencies = {};
|
||||
|
||||
let displayRule: string;
|
||||
let parameterName: string;
|
||||
for (const nodeProperties of nodePropertiesArray) {
|
||||
if (dependencies[nodeProperties.name] === undefined) {
|
||||
dependencies[nodeProperties.name] = [];
|
||||
const { name, displayOptions } = nodeProperties;
|
||||
|
||||
if (!dependencies[name]) {
|
||||
dependencies[name] = [];
|
||||
}
|
||||
if (nodeProperties.displayOptions === undefined) {
|
||||
|
||||
if (!displayOptions) {
|
||||
// Does not have any dependencies
|
||||
continue;
|
||||
}
|
||||
|
||||
for (displayRule of Object.keys(nodeProperties.displayOptions)) {
|
||||
// @ts-ignore
|
||||
for (parameterName of Object.keys(nodeProperties.displayOptions[displayRule])) {
|
||||
if (!dependencies[nodeProperties.name].includes(parameterName)) {
|
||||
for (const displayRule of Object.values(displayOptions)) {
|
||||
for (const parameterName of Object.keys(displayRule)) {
|
||||
if (!dependencies[name].includes(parameterName)) {
|
||||
if (parameterName.charAt(0) === '@') {
|
||||
// Is a special parameter so can be skipped
|
||||
continue;
|
||||
}
|
||||
dependencies[nodeProperties.name].push(parameterName);
|
||||
dependencies[name].push(parameterName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -352,7 +352,7 @@ export class WorkflowDataProxy {
|
|||
}
|
||||
|
||||
return new Proxy(
|
||||
{},
|
||||
{ binary: undefined, data: undefined, json: undefined },
|
||||
{
|
||||
get(target, name, receiver) {
|
||||
name = name.toString();
|
||||
|
@ -472,8 +472,7 @@ export class WorkflowDataProxy {
|
|||
throw new Error(`The key "${name.toString()}" is not supported!`);
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
return that.workflow[name.toString()];
|
||||
return that.workflow[name as keyof typeof target];
|
||||
},
|
||||
},
|
||||
);
|
||||
|
@ -1004,12 +1003,10 @@ export class WorkflowDataProxy {
|
|||
return new Proxy(base, {
|
||||
get(target, name, receiver) {
|
||||
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') {
|
||||
// @ts-ignore
|
||||
return that.nodeDataGetter(that.activeNodeName, true).binary;
|
||||
return that.nodeDataGetter(that.activeNodeName, true)?.binary;
|
||||
}
|
||||
|
||||
return Reflect.get(target, name, receiver);
|
||||
|
|
14
packages/workflow/src/types.d.ts
vendored
Normal file
14
packages/workflow/src/types.d.ts
vendored
Normal 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;
|
||||
}
|
|
@ -634,8 +634,6 @@ describe('RoutingNode', () => {
|
|||
for (const testData of tests) {
|
||||
test(testData.description, () => {
|
||||
node.parameters = testData.input.nodeParameters;
|
||||
|
||||
// @ts-ignore
|
||||
nodeType.description.properties = [testData.input.nodeTypeProperties];
|
||||
|
||||
const workflow = new Workflow({
|
||||
|
|
|
@ -1022,7 +1022,6 @@ describe('Workflow', () => {
|
|||
},
|
||||
{
|
||||
name: 'Node3',
|
||||
// @ts-ignore
|
||||
parameters: testData.input.hasOwnProperty('Node3')
|
||||
? // @ts-ignore
|
||||
testData.input.Node3.parameters
|
||||
|
@ -1034,7 +1033,6 @@ describe('Workflow', () => {
|
|||
},
|
||||
{
|
||||
name: 'Node 4 with spaces',
|
||||
// @ts-ignore
|
||||
parameters: testData.input.hasOwnProperty('Node4')
|
||||
? // @ts-ignore
|
||||
testData.input.Node4.parameters
|
||||
|
@ -1080,12 +1078,10 @@ describe('Workflow', () => {
|
|||
{
|
||||
startTime: 1,
|
||||
executionTime: 1,
|
||||
// @ts-ignore
|
||||
data: {
|
||||
main: [
|
||||
[
|
||||
{
|
||||
// @ts-ignore
|
||||
json: testData.input.Node1.outputJson || testData.input.Node1.parameters,
|
||||
// @ts-ignore
|
||||
binary: testData.input.Node1.outputBinary,
|
||||
|
|
|
@ -75,7 +75,6 @@ describe('WorkflowDataProxy', () => {
|
|||
{
|
||||
startTime: 1,
|
||||
executionTime: 1,
|
||||
// @ts-ignore
|
||||
data: {
|
||||
main: [
|
||||
[
|
||||
|
@ -104,7 +103,6 @@ describe('WorkflowDataProxy', () => {
|
|||
{
|
||||
startTime: 1,
|
||||
executionTime: 1,
|
||||
// @ts-ignore
|
||||
data: {
|
||||
main: [
|
||||
[
|
||||
|
|
Loading…
Reference in a new issue