mirror of
https://github.com/n8n-io/n8n.git
synced 2025-02-21 02:56:40 -08:00
fix(core): Only use new resource mapper type validation when it is enabled (#13099)
This commit is contained in:
parent
ef87da4c19
commit
a37c8e8fb8
|
@ -1,4 +1,4 @@
|
||||||
import type { IDataObject, INode, INodeType } from 'n8n-workflow';
|
import { ExpressionError, type IDataObject, type INode, type INodeType } from 'n8n-workflow';
|
||||||
|
|
||||||
import { validateValueAgainstSchema } from '../validate-value-against-schema';
|
import { validateValueAgainstSchema } from '../validate-value-against-schema';
|
||||||
|
|
||||||
|
@ -311,8 +311,86 @@ describe('validateValueAgainstSchema', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when attemptToConvertTypes is not set (=default)', () => {
|
describe('when showTypeConversionOptions is not set (=default)', () => {
|
||||||
test('should correctly validate and convert types', () => {
|
test('should correctly convert types', () => {
|
||||||
|
const nodeType = {
|
||||||
|
description: {
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
displayName: 'Columns',
|
||||||
|
name: 'columns',
|
||||||
|
type: 'resourceMapper',
|
||||||
|
required: true,
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsDependsOn: ['table.value', 'operation'],
|
||||||
|
resourceMapper: {
|
||||||
|
mode: 'upsert',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
} as unknown as INodeType;
|
||||||
|
|
||||||
|
const node: INode = {
|
||||||
|
parameters: {
|
||||||
|
columns: {
|
||||||
|
mappingMode: 'defineBelow',
|
||||||
|
value: {
|
||||||
|
id: 2,
|
||||||
|
count: '={{ $json.count }}',
|
||||||
|
},
|
||||||
|
matchingColumns: ['id'],
|
||||||
|
attemptToConvertTypes: false,
|
||||||
|
convertFieldsToString: true,
|
||||||
|
schema: [
|
||||||
|
{
|
||||||
|
id: 'id',
|
||||||
|
displayName: 'id',
|
||||||
|
required: false,
|
||||||
|
defaultMatch: true,
|
||||||
|
display: true,
|
||||||
|
type: 'number',
|
||||||
|
canBeUsedToMatch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'count',
|
||||||
|
displayName: 'count',
|
||||||
|
required: false,
|
||||||
|
defaultMatch: false,
|
||||||
|
display: true,
|
||||||
|
type: 'number',
|
||||||
|
canBeUsedToMatch: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
options: {},
|
||||||
|
},
|
||||||
|
id: '8d6cec63-8db1-440c-8966-4d6311ee69a9',
|
||||||
|
name: 'add products to DB',
|
||||||
|
type: 'n8n-nodes-base.postgres',
|
||||||
|
typeVersion: 2.3,
|
||||||
|
position: [420, 0],
|
||||||
|
};
|
||||||
|
|
||||||
|
const value = {
|
||||||
|
id: 2,
|
||||||
|
count: '23',
|
||||||
|
};
|
||||||
|
|
||||||
|
const parameterName = 'columns.value';
|
||||||
|
|
||||||
|
const result = validateValueAgainstSchema(node, nodeType, value, parameterName, 0, 0);
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
id: 2,
|
||||||
|
count: 23,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when showTypeConversionOptions is true', () => {
|
||||||
|
test('should throw an error', () => {
|
||||||
const nodeType = {
|
const nodeType = {
|
||||||
description: {
|
description: {
|
||||||
properties: [
|
properties: [
|
||||||
|
@ -321,22 +399,10 @@ describe('validateValueAgainstSchema', () => {
|
||||||
name: 'columns',
|
name: 'columns',
|
||||||
type: 'resourceMapper',
|
type: 'resourceMapper',
|
||||||
noDataExpression: true,
|
noDataExpression: true,
|
||||||
default: {
|
|
||||||
mappingMode: 'defineBelow',
|
|
||||||
value: null,
|
|
||||||
},
|
|
||||||
required: true,
|
|
||||||
typeOptions: {
|
typeOptions: {
|
||||||
loadOptionsDependsOn: ['table.value', 'operation'],
|
|
||||||
resourceMapper: {
|
resourceMapper: {
|
||||||
resourceMapperMethod: 'getMappingColumns',
|
showTypeConversionOptions: true,
|
||||||
mode: 'upsert',
|
mode: 'upsert',
|
||||||
fieldWords: {
|
|
||||||
singular: 'column',
|
|
||||||
plural: 'columns',
|
|
||||||
},
|
|
||||||
addAllFields: true,
|
|
||||||
multiKeyMatch: true,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -390,12 +456,9 @@ describe('validateValueAgainstSchema', () => {
|
||||||
|
|
||||||
const parameterName = 'columns.value';
|
const parameterName = 'columns.value';
|
||||||
|
|
||||||
const result = validateValueAgainstSchema(node, nodeType, value, parameterName, 0, 0);
|
expect(() =>
|
||||||
|
validateValueAgainstSchema(node, nodeType, value, parameterName, 0, 0),
|
||||||
expect(result).toEqual({
|
).toThrow(new ExpressionError("Invalid input for 'count' [item 0]"));
|
||||||
id: 2,
|
|
||||||
count: 23,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,6 +6,7 @@ import type {
|
||||||
INodePropertyCollection,
|
INodePropertyCollection,
|
||||||
INodePropertyOptions,
|
INodePropertyOptions,
|
||||||
INodeType,
|
INodeType,
|
||||||
|
ResourceMapperTypeOptions,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import {
|
import {
|
||||||
ExpressionError,
|
ExpressionError,
|
||||||
|
@ -20,9 +21,11 @@ const validateResourceMapperValue = (
|
||||||
parameterName: string,
|
parameterName: string,
|
||||||
paramValues: { [key: string]: unknown },
|
paramValues: { [key: string]: unknown },
|
||||||
node: INode,
|
node: INode,
|
||||||
skipRequiredCheck = false,
|
resourceMapperTypeOptions?: ResourceMapperTypeOptions,
|
||||||
): ExtendedValidationResult => {
|
): ExtendedValidationResult => {
|
||||||
const result: ExtendedValidationResult = { valid: true, newValue: paramValues };
|
const result: ExtendedValidationResult = { valid: true, newValue: paramValues };
|
||||||
|
const skipRequiredCheck = resourceMapperTypeOptions?.mode !== 'add';
|
||||||
|
const enableTypeValidationOptions = Boolean(resourceMapperTypeOptions?.showTypeConversionOptions);
|
||||||
const paramNameParts = parameterName.split('.');
|
const paramNameParts = parameterName.split('.');
|
||||||
if (paramNameParts.length !== 2) {
|
if (paramNameParts.length !== 2) {
|
||||||
return result;
|
return result;
|
||||||
|
@ -56,8 +59,8 @@ const validateResourceMapperValue = (
|
||||||
if (schemaEntry?.type) {
|
if (schemaEntry?.type) {
|
||||||
const validationResult = validateFieldType(key, resolvedValue, schemaEntry.type, {
|
const validationResult = validateFieldType(key, resolvedValue, schemaEntry.type, {
|
||||||
valueOptions: schemaEntry.options,
|
valueOptions: schemaEntry.options,
|
||||||
strict: resourceMapperField.attemptToConvertTypes === false,
|
strict: enableTypeValidationOptions && !resourceMapperField.attemptToConvertTypes,
|
||||||
parseStrings: Boolean(resourceMapperField.convertFieldsToString),
|
parseStrings: enableTypeValidationOptions && resourceMapperField.convertFieldsToString,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!validationResult.valid) {
|
if (!validationResult.valid) {
|
||||||
|
@ -185,7 +188,7 @@ export const validateValueAgainstSchema = (
|
||||||
parameterName,
|
parameterName,
|
||||||
parameterValue as { [key: string]: unknown },
|
parameterValue as { [key: string]: unknown },
|
||||||
node,
|
node,
|
||||||
propertyDescription.typeOptions?.resourceMapper?.mode !== 'add',
|
propertyDescription.typeOptions?.resourceMapper,
|
||||||
);
|
);
|
||||||
} else if (['fixedCollection', 'collection'].includes(propertyDescription.type)) {
|
} else if (['fixedCollection', 'collection'].includes(propertyDescription.type)) {
|
||||||
validationResult = validateCollection(
|
validationResult = validateCollection(
|
||||||
|
|
|
@ -2723,8 +2723,8 @@ export type ResourceMapperValue = {
|
||||||
value: { [key: string]: string | number | boolean | null } | null;
|
value: { [key: string]: string | number | boolean | null } | null;
|
||||||
matchingColumns: string[];
|
matchingColumns: string[];
|
||||||
schema: ResourceMapperField[];
|
schema: ResourceMapperField[];
|
||||||
attemptToConvertTypes?: boolean;
|
attemptToConvertTypes: boolean;
|
||||||
convertFieldsToString?: boolean;
|
convertFieldsToString: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type FilterOperatorType =
|
export type FilterOperatorType =
|
||||||
|
|
Loading…
Reference in a new issue