mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-20 03:12:15 +00:00
Ensure all errors in `core` and `workflow` inherit from `ApplicationError` so that we start normalizing all the errors we report to Sentry Follow-up to: https://github.com/n8n-io/n8n/pull/7757#discussion_r1404338844 ### `core` package `ApplicationError` - `FileSystemError` (abstract) - `FileNotFoundError` - `DisallowedFilepathError` - `BinaryDataError` (abstract) - `InvalidModeError` - `InvalidManagerError` - `InvalidExecutionMetadataError` ### `workflow` package `ApplicationError` - `ExecutionBaseError` (abstract) - `WorkflowActivationError` - `WorkflowDeactivationError` - `WebhookTakenError` - `WorkflowOperationError` - `SubworkflowOperationError` - `CliWorkflowOperationError` - `ExpressionError` - `ExpressionExtensionError` - `NodeError` (abstract) - `NodeOperationError` - `NodeApiError` - `NodeSSLError` Up next: - Reorganize errors in `cli` - Flatten the hierarchy in `workflow` (do we really need `ExecutionBaseError`?) - Remove `ExecutionError` type - Stop throwing plain `Error`s - Replace `severity` with `level` - Add node and credential types as `tags` - Add workflow IDs and execution IDs as `extras`
162 lines
5.1 KiB
TypeScript
162 lines
5.1 KiB
TypeScript
import { ExpressionExtensionError } from '../errors/expression-extension.error';
|
|
import type { ExtensionMap } from './Extensions';
|
|
|
|
function isEmpty(value: object): boolean {
|
|
return Object.keys(value).length === 0;
|
|
}
|
|
|
|
function isNotEmpty(value: object): boolean {
|
|
return !isEmpty(value);
|
|
}
|
|
|
|
function hasField(value: object, extraArgs: string[]): boolean {
|
|
const [name] = extraArgs;
|
|
return name in value;
|
|
}
|
|
|
|
function removeField(value: object, extraArgs: string[]): object {
|
|
const [name] = extraArgs;
|
|
if (name in value) {
|
|
const newObject = { ...value };
|
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
|
|
delete (newObject as any)[name];
|
|
return newObject;
|
|
}
|
|
return value;
|
|
}
|
|
|
|
function removeFieldsContaining(value: object, extraArgs: string[]): object {
|
|
const [match] = extraArgs;
|
|
if (typeof match !== 'string' || match === '') {
|
|
throw new ExpressionExtensionError('removeFieldsContaining(): expected non-empty string arg');
|
|
}
|
|
const newObject = { ...value };
|
|
for (const [key, val] of Object.entries(value)) {
|
|
if (typeof val === 'string' && val.includes(match)) {
|
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
|
|
delete (newObject as any)[key];
|
|
}
|
|
}
|
|
return newObject;
|
|
}
|
|
|
|
function keepFieldsContaining(value: object, extraArgs: string[]): object {
|
|
const [match] = extraArgs;
|
|
if (typeof match !== 'string' || match === '') {
|
|
throw new ExpressionExtensionError(
|
|
'argument of keepFieldsContaining must be a non-empty string',
|
|
);
|
|
}
|
|
const newObject = { ...value };
|
|
for (const [key, val] of Object.entries(value)) {
|
|
if (typeof val !== 'string' || (typeof val === 'string' && !val.includes(match))) {
|
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
|
|
delete (newObject as any)[key];
|
|
}
|
|
}
|
|
return newObject;
|
|
}
|
|
|
|
export function compact(value: object): object {
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
const newObj: any = {};
|
|
for (const [key, val] of Object.entries(value)) {
|
|
if (val !== null && val !== undefined && val !== 'nil' && val !== '') {
|
|
if (typeof val === 'object') {
|
|
if (Object.keys(val as object).length === 0) continue;
|
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument
|
|
newObj[key] = compact(val);
|
|
} else {
|
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
|
newObj[key] = val;
|
|
}
|
|
}
|
|
}
|
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
return newObj;
|
|
}
|
|
|
|
export function urlEncode(value: object) {
|
|
return new URLSearchParams(value as Record<string, string>).toString();
|
|
}
|
|
|
|
isEmpty.doc = {
|
|
name: 'isEmpty',
|
|
description: 'Checks if the Object has no key-value pairs.',
|
|
returnType: 'boolean',
|
|
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-isEmpty',
|
|
};
|
|
|
|
isNotEmpty.doc = {
|
|
name: 'isNotEmpty',
|
|
description: 'Checks if the Object has key-value pairs.',
|
|
returnType: 'boolean',
|
|
docURL:
|
|
'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-isNotEmpty',
|
|
};
|
|
|
|
compact.doc = {
|
|
name: 'compact',
|
|
description: 'Removes empty values from an Object.',
|
|
returnType: 'boolean',
|
|
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-compact',
|
|
};
|
|
|
|
urlEncode.doc = {
|
|
name: 'urlEncode',
|
|
description: 'Transforms an Object into a URL parameter list. Only top-level keys are supported.',
|
|
returnType: 'string',
|
|
docURL:
|
|
'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-urlEncode',
|
|
};
|
|
|
|
hasField.doc = {
|
|
name: 'hasField',
|
|
description: 'Checks if the Object has a given field. Only top-level keys are supported.',
|
|
returnType: 'boolean',
|
|
args: [{ name: 'fieldName', type: 'string' }],
|
|
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-hasField',
|
|
};
|
|
|
|
removeField.doc = {
|
|
name: 'removeField',
|
|
description: 'Removes a given field from the Object. Only top-level fields are supported.',
|
|
returnType: 'object',
|
|
args: [{ name: 'key', type: 'string' }],
|
|
docURL:
|
|
'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-removeField',
|
|
};
|
|
|
|
removeFieldsContaining.doc = {
|
|
name: 'removeFieldsContaining',
|
|
description:
|
|
'Removes fields with a given value from the Object. Only top-level values are supported.',
|
|
returnType: 'object',
|
|
args: [{ name: 'value', type: 'string' }],
|
|
docURL:
|
|
'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-removeFieldsContaining',
|
|
};
|
|
|
|
keepFieldsContaining.doc = {
|
|
name: 'keepFieldsContaining',
|
|
description: 'Removes fields that do not match the given value from the Object.',
|
|
returnType: 'object',
|
|
args: [{ name: 'value', type: 'string' }],
|
|
docURL:
|
|
'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-keepFieldsContaining',
|
|
};
|
|
|
|
export const objectExtensions: ExtensionMap = {
|
|
typeName: 'Object',
|
|
functions: {
|
|
isEmpty,
|
|
isNotEmpty,
|
|
hasField,
|
|
removeField,
|
|
removeFieldsContaining,
|
|
keepFieldsContaining,
|
|
compact,
|
|
urlEncode,
|
|
},
|
|
};
|