Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(editor): Implement Resource Mapper component #6207

Merged
merged 207 commits into from
May 31, 2023
Merged
Show file tree
Hide file tree
Changes from 205 commits
Commits
Show all changes
207 commits
Select commit Hold shift + click to select a range
c72566a
:zap: scaffolding
michael-radency Feb 23, 2023
6446655
:zap: finished scaffolding
michael-radency Feb 23, 2023
5b6da00
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Feb 23, 2023
89fbdc2
:zap: renamed types
michael-radency Feb 23, 2023
f984fd5
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Feb 23, 2023
3fe0aa7
:zap: updated subtitle
michael-radency Feb 23, 2023
105e585
:zap: renamed functions file, UI updates
michael-radency Feb 23, 2023
fafcbb8
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Feb 23, 2023
78c938c
:zap: query parameters fixes, ui updates, refactoring
michael-radency Feb 24, 2023
db35f8c
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Feb 24, 2023
fde1240
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Feb 27, 2023
3d87e7d
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Feb 27, 2023
48065cf
:zap: fixes for credentials test, setup for error parsing
michael-radency Feb 27, 2023
a26c417
:zap: rlc for schema and table, error handling tweaks
michael-radency Feb 27, 2023
189aea6
:zap: delete operation, new options
michael-radency Feb 27, 2023
6884f91
:zap: columns loader
michael-radency Feb 27, 2023
f21ed28
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Feb 27, 2023
cd41966
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Feb 28, 2023
b3df107
:zap: linter fixes
michael-radency Feb 28, 2023
2fa7543
:zap: where clauses setup
michael-radency Feb 28, 2023
7d9c8ff
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Feb 28, 2023
779be26
:zap: logic for processing where clauses
michael-radency Feb 28, 2023
61907b8
:zap: select operation
michael-radency Feb 28, 2023
0ff76e4
:zap: refactoring
michael-radency Feb 28, 2023
7e79e76
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Feb 28, 2023
82be8c9
:zap: data mode for insert and update, wip
michael-radency Feb 28, 2023
8198ec0
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Feb 28, 2023
5c8b79f
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Mar 1, 2023
2ee7d1f
:zap: data mapping, insert update, skip on conflict option
michael-radency Mar 1, 2023
e83fbec
:zap: select columns with spaces fix
michael-radency Mar 1, 2023
cbd7eae
:zap: update operation update, wip
michael-radency Mar 1, 2023
b210c00
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Mar 1, 2023
3ff0c2b
:zap: finished update operation
michael-radency Mar 1, 2023
6544333
:zap: upsert operation
michael-radency Mar 1, 2023
51bf83c
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Mar 1, 2023
7a971c3
:zap: ui fixes
michael-radency Mar 2, 2023
6f49430
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Mar 2, 2023
714bc78
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Mar 2, 2023
27576ce
Copy updates.
gandreini Mar 3, 2023
d1904eb
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Mar 6, 2023
86cc2d5
Copy updates.
gandreini Mar 8, 2023
f82d96c
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Mar 10, 2023
a3c5905
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Mar 10, 2023
512d0da
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Mar 13, 2023
da2962d
:zap: option to convert empty strings to nulls, schema checks
michael-radency Mar 13, 2023
6ca5e32
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Mar 13, 2023
ebed80b
:zap: UI requested updates
michael-radency Mar 13, 2023
96414c8
:zap: ssh setup WIP
michael-radency Mar 13, 2023
4b5887a
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Mar 13, 2023
e9d42d8
:zap: fixes, ssh WIP
michael-radency Mar 13, 2023
7724b2e
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Mar 14, 2023
6d0a9a9
:zap: ssh fixes, credentials
michael-radency Mar 14, 2023
3b00213
:zap: credentials testing update
michael-radency Mar 14, 2023
c12349a
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Mar 14, 2023
1a17fd0
:zap: uncaught error fix
michael-radency Mar 14, 2023
fad9907
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Mar 14, 2023
6fb5202
:zap: clean up
michael-radency Mar 14, 2023
7f49885
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Mar 14, 2023
bde85b9
:zap: address in use fix
michael-radency Mar 15, 2023
3e0f1ff
:zap: improved error message
michael-radency Mar 15, 2023
9161f0f
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Mar 15, 2023
50e6be1
:zap: tests setup
michael-radency Mar 15, 2023
d5c5b73
:zap: unit tests wip
michael-radency Mar 15, 2023
3a21080
:zap: config files clean up
michael-radency Mar 15, 2023
5347bd8
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Mar 15, 2023
ecf806e
:zap: utils unit tests
michael-radency Mar 16, 2023
898347e
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Mar 16, 2023
e91fae3
:zap: refactoring
michael-radency Mar 16, 2023
b13087f
:zap: setup for testing operations, tests for deleteTable operation
michael-radency Mar 16, 2023
ab238be
:zap: executeQuery and insert operations tests
michael-radency Mar 16, 2023
c807221
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Mar 16, 2023
8bd1d15
:zap: select, update, upsert operations tests
michael-radency Mar 16, 2023
8275f0d
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Mar 16, 2023
5bbd0e3
:zap: runQueries tests setup
michael-radency Mar 16, 2023
3c8b5cb
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Mar 16, 2023
3ceb24f
:zap: hint to query
michael-radency Mar 17, 2023
39728d4
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Mar 17, 2023
f1f5a74
Copy updates.
gandreini Mar 21, 2023
a87fc27
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Mar 22, 2023
08affd0
:zap: ui fixes
michael-radency Mar 22, 2023
b0a03fe
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Mar 22, 2023
e40d17c
:zap: clean up
michael-radency Mar 22, 2023
91cdc12
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Mar 23, 2023
02e6f37
:zap: error message update
michael-radency Mar 23, 2023
3b32482
:zap: ui update
michael-radency Mar 23, 2023
a5a10c9
Minor tweaks to query params decription.
gandreini Mar 23, 2023
d5468f3
feat(Google Sheets Node): Implement Resource mapper in Google Sheets …
MiloradFilipovic Mar 23, 2023
8f3cb59
Merge branch 'master' into feature/resource-mapping-component
MiloradFilipovic Mar 23, 2023
f402ce4
Merge branch 'master' of https://github.com/n8n-io/n8n into node-319-…
michael-radency Mar 24, 2023
031a421
:zap: singlton for conections
michael-radency Mar 24, 2023
2f6a726
Merge branch 'node-319-postgres-node-overhaul' of https://github.com/…
michael-radency Mar 24, 2023
59744f4
:zap: credentials test fix, clean up
michael-radency Mar 24, 2023
0f43dc5
feat(Postgres Node): Add resource mapper to new version of Postgres n…
MiloradFilipovic Mar 30, 2023
38c2a21
Merge branch 'node-319-postgres-node-overhaul' into feature/resource-…
MiloradFilipovic Mar 30, 2023
aee8f35
Merge branch 'master' into feature/resource-mapping-component
MiloradFilipovic Apr 4, 2023
8576dcc
Merge branch 'master' into feature/resource-mapping-component
MiloradFilipovic Apr 13, 2023
6246bcb
Merge branch 'master' into feature/resource-mapping-component
MiloradFilipovic Apr 18, 2023
247146e
feat(core): Resource editor componend P0 (#5970)
MiloradFilipovic Apr 24, 2023
ae6929d
Merge branch 'master' into feature/resource-mapping-component
MiloradFilipovic Apr 24, 2023
4e48127
Merge branch 'master' into feature/resource-mapping-component
MiloradFilipovic Apr 24, 2023
e167ed0
Merge branch 'master' into feature/resource-mapping-component
MiloradFilipovic Apr 24, 2023
be34112
✨ Initial mapping field rework
MiloradFilipovic Apr 24, 2023
d30dbaf
Merge branch 'master' into feature/resource-mapping-component
MiloradFilipovic Apr 25, 2023
b35717e
Merge branch 'feature/resource-mapping-component' into NODE-398-resou…
MiloradFilipovic Apr 25, 2023
e11e68b
✨ Added new component for mapping fields, moved bit of logic from roo…
MiloradFilipovic Apr 25, 2023
5dbaaff
✨ Added tooltip for columns that cannot be deleted
MiloradFilipovic Apr 25, 2023
1c7104b
✨ Saving deleted values in parameter value
MiloradFilipovic Apr 25, 2023
41eefa8
✨ Implemented control to add/remove mapping fields
MiloradFilipovic Apr 25, 2023
eed2ba9
✨ Syncing field list with add field dropdown when changing dependent …
MiloradFilipovic Apr 26, 2023
63d12a7
✨ Not showing removed fields in matching columns selector. Updating w…
MiloradFilipovic Apr 26, 2023
0ec89bc
✨ Implementing disabled states for add/remove all fields options
MiloradFilipovic Apr 26, 2023
0b823c7
Merge branch 'master' into feature/resource-mapping-component
MiloradFilipovic Apr 26, 2023
b139a5a
Merge branch 'feature/resource-mapping-component' into NODE-398-resou…
MiloradFilipovic Apr 26, 2023
8608aee
Merge branch 'master' into feature/resource-mapping-component
MiloradFilipovic May 2, 2023
f6d6762
Merge branch 'feature/resource-mapping-component' into NODE-398-resou…
MiloradFilipovic May 2, 2023
f9d4e85
✨ Saving removed columns separately, updating copy
MiloradFilipovic May 2, 2023
edc6f79
✨ Implemented resource mapper values validation
MiloradFilipovic May 2, 2023
8d71806
✨ Updated validation logic and error input styling
MiloradFilipovic May 2, 2023
eff2322
✨ Validating resource mapper fields when new nodes are added
MiloradFilipovic May 3, 2023
79c7b8f
✨ Using node field words in validation, refactoring resource mapper c…
MiloradFilipovic May 3, 2023
ca82636
✨ Implemented schema syncing and add/remove all fields
MiloradFilipovic May 3, 2023
b759822
✨ Implemented custom parameter actions
MiloradFilipovic May 3, 2023
e280754
Merge branch 'master' into feature/resource-mapping-component
MiloradFilipovic May 3, 2023
c313912
Merge branch 'feature/resource-mapping-component' into NODE-398-resou…
MiloradFilipovic May 3, 2023
df68999
✨ Implemented loading indicator in parameter options
MiloradFilipovic May 4, 2023
e76e7a1
🔨 Removing unnecessary constants and vue props
MiloradFilipovic May 4, 2023
d50e79e
✨ Handling default values properly
MiloradFilipovic May 4, 2023
1164849
✨ Fixing validation logic
MiloradFilipovic May 4, 2023
761ec08
👕 Fixing lint errors
MiloradFilipovic May 4, 2023
8517dd2
⚡ Fixing type issues
MiloradFilipovic May 4, 2023
eea0634
⚡ Not showing fields by default if `addAllFields` is set to `false`
MiloradFilipovic May 4, 2023
0067453
✨ Implemented field type validation in resource mapper
MiloradFilipovic May 8, 2023
183d8c0
✨ Updated casing in copy, removed all/remove all option from bottom menu
MiloradFilipovic May 8, 2023
91a442c
✨ Added auto mapping mode notice
MiloradFilipovic May 8, 2023
3743981
✨ Added support for more types in validation
MiloradFilipovic May 8, 2023
589d17a
✨ Added support for enumerated values
MiloradFilipovic May 9, 2023
7ebbb28
Merge branch 'master' into feature/resource-mapping-component
MiloradFilipovic May 9, 2023
34a9423
Merge branch 'feature/resource-mapping-component' into NODE-398-resou…
MiloradFilipovic May 9, 2023
0a3d5d8
✨ Fixing imports after merging
MiloradFilipovic May 9, 2023
ebc39a6
✨ Not showing removed fields in matching columns selector. Refactorin…
MiloradFilipovic May 9, 2023
b5d0c1c
👕 Fixing imports
MiloradFilipovic May 9, 2023
fc6bdb2
✔️ Updating unit tests
MiloradFilipovic May 9, 2023
ae04d40
✅ Added resource mapper schema tests
MiloradFilipovic May 9, 2023
3c3f22c
⚡ Removing `match` from resource mapper field definition, fixing matc…
MiloradFilipovic May 10, 2023
0df2a28
⚡ Fixed schema merging
MiloradFilipovic May 10, 2023
9764469
:zap: update operation return data fix
michael-radency May 10, 2023
bdef214
:zap: review
michael-radency May 11, 2023
67194f8
Merge branch 'master' into feature/resource-mapping-component
MiloradFilipovic May 11, 2023
07fcc32
🐛 Added missing import
MiloradFilipovic May 11, 2023
ea03e85
💄 Updating parameter actions icon based on the ui review
MiloradFilipovic May 12, 2023
415363a
💄 Updating word capitalisation in tooltips
MiloradFilipovic May 12, 2023
e45aabf
💄 Added empty state to mapping fields list
MiloradFilipovic May 12, 2023
1d07972
💄 Removing asterisk from fields, updating tooltips for matching fields
MiloradFilipovic May 12, 2023
319c41e
⚡ Preventing matching fields from being removed by 'Remove All option'
MiloradFilipovic May 12, 2023
11056e8
⚡ Not showing hidden fields in the `Add field` dropdown
MiloradFilipovic May 12, 2023
4b5f5c1
⚡ Added support for custom matching columns labels
MiloradFilipovic May 12, 2023
fead873
:zap: query optimization
michael-radency May 12, 2023
76dc1bb
Merge branch 'feature/resource-mapping-component' of https://github.c…
michael-radency May 12, 2023
0e344e2
:zap: fix
michael-radency May 12, 2023
5e46b2a
⚡ Optimizing Postgres node enumeration logic
MiloradFilipovic May 12, 2023
ff7dccd
⚡ Added empty state for matching columns
MiloradFilipovic May 12, 2023
c38c53d
⚡ Only fully loading fields if there is no schema fetched
MiloradFilipovic May 12, 2023
356e1e3
⚡ Hiding mapping fields if there is no matching columns available in …
MiloradFilipovic May 12, 2023
ef677f2
✔️ Fixing minor issues
MiloradFilipovic May 12, 2023
7c74f24
✨ Implemented runtime type validation
MiloradFilipovic May 15, 2023
1e32ff4
🔨 Refactoring validation logic
MiloradFilipovic May 15, 2023
91fdafa
✨ Implemented required check, added more custom messages
MiloradFilipovic May 15, 2023
33ed43e
✨ Skipping boolean type in required check
MiloradFilipovic May 15, 2023
ed6e8bc
Type check improvements
MiloradFilipovic May 15, 2023
cc65525
✨ Only reloading fields if dependent values actually change
MiloradFilipovic May 16, 2023
723bffc
Merge branch 'master' into feature/resource-mapping-component
MiloradFilipovic May 16, 2023
a019489
✨ Adding item index to validation error title
MiloradFilipovic May 16, 2023
e82ad71
✨ Updating Postgres fetching logic, using resource mapper mode to det…
MiloradFilipovic May 16, 2023
139e14a
✨ Resetting field values when adding them via the addAll option
MiloradFilipovic May 16, 2023
442e9f6
⚡ Using minor version (2.2) for new Postgres node
MiloradFilipovic May 17, 2023
0c38956
⚡ Implemented proper date validation and type casting
MiloradFilipovic May 17, 2023
ac70e02
👕 Consolidating typign
MiloradFilipovic May 17, 2023
edcbdfb
✅ Added unit tests for type validations
MiloradFilipovic May 17, 2023
c5c8155
👌 Addressing front-end review comments
MiloradFilipovic May 17, 2023
5944024
⚡ More refactoring to address review changes
MiloradFilipovic May 18, 2023
0cb1b87
⚡ Updating leftover props
MiloradFilipovic May 18, 2023
3d6194a
⚡ Added fallback for ISO dates with invalid timezones
MiloradFilipovic May 18, 2023
f35c016
Added timestamp to datetime test cases
MiloradFilipovic May 18, 2023
b4ac236
⚡ Reseting matching columns if operation changes
MiloradFilipovic May 19, 2023
c33df40
⚡ Not forcing auto-increment fields to be filled in in Postgres node.…
MiloradFilipovic May 19, 2023
1c9af71
Merge branch 'master' into feature/resource-mapping-component
MiloradFilipovic May 19, 2023
229074d
💄 Added a custom message for invalid dates
MiloradFilipovic May 19, 2023
e5dbde2
⚡ Better handling of JSON values
MiloradFilipovic May 19, 2023
3b5dbe4
⚡ Updating codemirror readonly stauts based on component property, ha…
MiloradFilipovic May 19, 2023
26afefe
Deleting leftover console.log
MiloradFilipovic May 19, 2023
bffc337
⚡ Better time validation
MiloradFilipovic May 19, 2023
c793156
Merge branch 'master' into feature/resource-mapping-component
MiloradFilipovic May 20, 2023
2d0137a
⚡ Fixing build error after merging
MiloradFilipovic May 20, 2023
95d0dbd
👕 Fixing lint error
MiloradFilipovic May 20, 2023
21a5d4a
⚡ Updating node configuration values
MiloradFilipovic May 21, 2023
7fd8b1c
⚡ Handling postgres arrays better
MiloradFilipovic May 22, 2023
5b58617
⚡ Handling SQL array syntax
MiloradFilipovic May 22, 2023
60bed9b
⚡ Updating time validation rules to include timezone
MiloradFilipovic May 23, 2023
4995f12
⚡ Sending expressions that resolve to `null` or `undefined` by the re…
MiloradFilipovic May 23, 2023
e5763c1
⚡ Allowing removed fields to be selected for match
MiloradFilipovic May 23, 2023
ecb86c8
⚡ Updated the query for fetching unique columns and primary keys
MiloradFilipovic May 24, 2023
3ae1822
⚡ Optimizing the unique query
MiloradFilipovic May 24, 2023
00a17b7
⚡ Setting timezone to all parsed dates
MiloradFilipovic May 24, 2023
f01dcc9
⚡ Addressing PR review feedback
MiloradFilipovic May 24, 2023
59af639
⚡ Configuring Sheets node for production, minor vue component update
MiloradFilipovic May 25, 2023
c2911f4
New cases added to the TypeValidation test.
gandreini May 26, 2023
40fd6d1
✅ Tweaking validation rules for arrays/objects and updating test cases
MiloradFilipovic May 31, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions packages/cli/src/Server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import clientOAuth1 from 'oauth-1.0a';
import {
BinaryDataManager,
Credentials,
LoadMappingOptions,
LoadNodeParameterOptions,
LoadNodeListSearch,
UserSettings,
Expand All @@ -49,6 +50,7 @@ import type {
ICredentialTypes,
ExecutionStatus,
IExecutionsSummary,
ResourceMapperFields,
IN8nUISettings,
} from 'n8n-workflow';
import { LoggerProxy, jsonParse } from 'n8n-workflow';
Expand Down Expand Up @@ -79,6 +81,7 @@ import type {
NodeListSearchRequest,
NodeParameterOptionsRequest,
OAuthRequest,
ResourceMapperRequest,
WorkflowRequest,
} from '@/requests';
import { registerController } from '@/decorators';
Expand Down Expand Up @@ -756,6 +759,58 @@ export class Server extends AbstractServer {
),
);

this.app.get(
MiloradFilipovic marked this conversation as resolved.
Show resolved Hide resolved
`/${this.restEndpoint}/get-mapping-fields`,
ResponseHelper.send(
async (
req: ResourceMapperRequest,
res: express.Response,
): Promise<ResourceMapperFields | undefined> => {
const nodeTypeAndVersion = jsonParse(
req.query.nodeTypeAndVersion,
) as INodeTypeNameVersion;

const { path, methodName } = req.query;

if (!req.query.currentNodeParameters) {
throw new ResponseHelper.BadRequestError(
'Parameter currentNodeParameters is required.',
);
}

const currentNodeParameters = jsonParse(
req.query.currentNodeParameters,
) as INodeParameters;

let credentials: INodeCredentials | undefined;

if (req.query.credentials) {
credentials = jsonParse(req.query.credentials);
}

const loadMappingOptionsInstance = new LoadMappingOptions(
nodeTypeAndVersion,
this.nodeTypes,
path,
currentNodeParameters,
credentials,
);

const additionalData = await WorkflowExecuteAdditionalData.getBase(
req.user.id,
currentNodeParameters,
);

const fields = await loadMappingOptionsInstance.getOptionsViaMethodName(
methodName,
additionalData,
);

return fields;
},
),
);

// ----------------------------------------
// Active Workflows
// ----------------------------------------
Expand Down
17 changes: 17 additions & 0 deletions packages/cli/src/requests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,23 @@ export type NodeListSearchRequest = AuthenticatedRequest<
}
>;

// ----------------------------------
// /get-mapping-fields
// ----------------------------------

export type ResourceMapperRequest = AuthenticatedRequest<
{},
{},
{},
{
nodeTypeAndVersion: string;
methodName: string;
path: string;
currentNodeParameters: string;
credentials: string;
}
>;

// ----------------------------------
// /tags
// ----------------------------------
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/Interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type {
ITriggerFunctions as ITriggerFunctionsBase,
IWebhookFunctions as IWebhookFunctionsBase,
BinaryMetadata,
ValidationResult,
} from 'n8n-workflow';

// TODO: remove these after removing `n8n-core` dependency from `nodes-bases`
Expand Down Expand Up @@ -89,3 +90,5 @@ export namespace n8n {
};
}
}

export type ExtendedValidationResult = Partial<ValidationResult> & { fieldName?: string };
34 changes: 34 additions & 0 deletions packages/core/src/LoadMappingOptions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import type { IWorkflowExecuteAdditionalData, ResourceMapperFields } from 'n8n-workflow';

import * as NodeExecuteFunctions from './NodeExecuteFunctions';
import { LoadNodeDetails } from './LoadNodeDetails';

export class LoadMappingOptions extends LoadNodeDetails {
/**
* Returns the available mapping fields for the ResourceMapper component
*/
async getOptionsViaMethodName(
methodName: string,
additionalData: IWorkflowExecuteAdditionalData,
): Promise<ResourceMapperFields> {
const node = this.getTempNode();

const nodeType = this.workflow.nodeTypes.getByNameAndVersion(node.type, node.typeVersion);
const method = nodeType?.methods?.resourceMapping?.[methodName];

if (typeof method !== 'function') {
throw new Error(
`The node-type "${node.type}" does not have the method "${methodName}" defined!`,
);
}

const thisArgs = NodeExecuteFunctions.getLoadOptionsFunctions(
this.workflow,
node,
this.path,
additionalData,
);

return method.call(thisArgs);
}
}
114 changes: 112 additions & 2 deletions packages/core/src/NodeExecuteFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,12 @@ import type {
IWebhookFunctions,
BinaryMetadata,
FileSystemHelperFunctions,
INodeType,
} from 'n8n-workflow';
import {
createDeferredPromise,
isObjectEmpty,
isResourceMapperValue,
NodeApiError,
NodeHelpers,
NodeOperationError,
Expand All @@ -74,6 +76,7 @@ import {
deepCopy,
fileTypeFromMimeType,
ExpressionError,
validateFieldType,
} from 'n8n-workflow';

import pick from 'lodash.pick';
Expand Down Expand Up @@ -114,7 +117,7 @@ import { access as fsAccess } from 'fs/promises';
import { createReadStream } from 'fs';

import { BinaryDataManager } from './BinaryDataManager';
import type { IResponseError, IWorkflowSettings } from './Interfaces';
import type { ExtendedValidationResult, IResponseError, IWorkflowSettings } from './Interfaces';
import { extractValue } from './ExtractValue';
import { getClientCredentialsToken } from './OAuth2Helper';
import { PLACEHOLDER_EMPTY_EXECUTION_ID } from './Constants';
Expand Down Expand Up @@ -1867,7 +1870,7 @@ function cleanupParameterData(inputData: NodeParameterValueType): void {
}

if (Array.isArray(inputData)) {
inputData.forEach((value) => cleanupParameterData(value));
inputData.forEach((value) => cleanupParameterData(value as NodeParameterValueType));
return;
}

Expand All @@ -1886,6 +1889,103 @@ function cleanupParameterData(inputData: NodeParameterValueType): void {
}
}

const validateResourceMapperValue = (
parameterName: string,
paramValues: { [key: string]: unknown },
node: INode,
skipRequiredCheck = false,
): ExtendedValidationResult => {
const result: ExtendedValidationResult = { valid: true, newValue: paramValues };
const paramNameParts = parameterName.split('.');
if (paramNameParts.length !== 2) {
return result;
}
const resourceMapperParamName = paramNameParts[0];
const resourceMapperField = node.parameters[resourceMapperParamName];
if (!resourceMapperField || !isResourceMapperValue(resourceMapperField)) {
return result;
}
const schema = resourceMapperField.schema;
const paramValueNames = Object.keys(paramValues);
for (let i = 0; i < paramValueNames.length; i++) {
const key = paramValueNames[i];
const resolvedValue = paramValues[key];
const schemaEntry = schema.find((s) => s.id === key);

if (
!skipRequiredCheck &&
schemaEntry?.required === true &&
schemaEntry.type !== 'boolean' &&
!resolvedValue
) {
return {
valid: false,
errorMessage: `The value "${String(key)}" is required but not set`,
fieldName: key,
};
}

if (schemaEntry?.type) {
const validationResult = validateFieldType(
key,
resolvedValue,
schemaEntry.type,
schemaEntry.options,
);
if (!validationResult.valid) {
return { ...validationResult, fieldName: key };
} else {
// If it's valid, set the casted value
paramValues[key] = validationResult.newValue;
}
}
}
return result;
};

const validateValueAgainstSchema = (
node: INode,
nodeType: INodeType,
inputValues: string | number | boolean | object | null | undefined,
parameterName: string,
runIndex: number,
itemIndex: number,
) => {
let validationResult: ExtendedValidationResult = { valid: true, newValue: inputValues };
// Currently only validate resource mapper values
const resourceMapperField = nodeType.description.properties.find(
(prop) =>
NodeHelpers.displayParameter(node.parameters, prop, node) &&
prop.type === 'resourceMapper' &&
parameterName === `${prop.name}.value`,
);

if (resourceMapperField && typeof inputValues === 'object') {
validationResult = validateResourceMapperValue(
parameterName,
inputValues as { [key: string]: unknown },
node,
resourceMapperField.typeOptions?.resourceMapper?.mode !== 'add',
);
}

if (!validationResult.valid) {
throw new ExpressionError(
`Invalid input for '${
String(validationResult.fieldName) || parameterName
}' [item ${itemIndex}]`,
{
description: validationResult.errorMessage,
failExecution: true,
runIndex,
itemIndex,
nodeCause: node.name,
},
);
}
return validationResult.newValue;
};

/**
* Returns the requested resolved (all expressions replaced) node parameters.
*
Expand Down Expand Up @@ -1947,6 +2047,16 @@ export function getNodeParameter(
returnData = extractValue(returnData, parameterName, node, nodeType);
}

// Validate parameter value if it has a schema defined
returnData = validateValueAgainstSchema(
node,
nodeType,
returnData,
parameterName,
runIndex,
itemIndex,
);

return returnData;
}

Expand Down
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export * from './Constants';
export * from './Credentials';
export * from './DirectoryLoader';
export * from './Interfaces';
export * from './LoadMappingOptions';
export * from './LoadNodeParameterOptions';
export * from './LoadNodeListSearch';
export * from './NodeExecuteFunctions';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default {
argTypes: {
placement: {
type: 'select',
options: ['top', 'top-start', 'top-end', 'bottom', 'bottom-end'],
options: ['top', 'top-end', 'top-start', 'bottom', 'bottom-end', 'bottom-start'],
},
size: {
type: 'select',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
@visible-change="onVisibleChange"
>
<span :class="{ [$style.button]: true, [$style[theme]]: !!theme }">
<n8n-icon icon="ellipsis-v" :size="iconSize" />
<n8n-icon
:icon="iconOrientation === 'horizontal' ? 'ellipsis-h' : 'ellipsis-v'"
:size="iconSize"
/>
</span>

<template #dropdown>
Expand Down Expand Up @@ -79,6 +82,11 @@ export default defineComponent({
default: 'default',
validator: (value: string): boolean => ['default', 'dark'].includes(value),
},
iconOrientation: {
type: String,
default: 'vertical',
validator: (value: string): boolean => ['horizontal', 'vertical'].includes(value),
},
},
methods: {
onCommand(value: string) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@
v-if="$slots.options && label"
:class="{ [$style.overlay]: true, [$style.visible]: showOptions }"
/>
<div v-if="$slots.options" :class="{ [$style.options]: true, [$style.visible]: showOptions }">
<div
v-if="$slots.options"
:class="{ [$style.options]: true, [$style.visible]: showOptions }"
data-test-id="parameter-input-options-container"
>
<slot name="options" />
</div>
</label>
Expand Down
7 changes: 7 additions & 0 deletions packages/editor-ui/src/Interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1365,6 +1365,13 @@ export type NodeAuthenticationOption = {
displayOptions?: IDisplayOptions;
};

export interface ResourceMapperReqParams {
nodeTypeAndVersion: INodeTypeNameVersion;
path: string;
methodName?: string;
currentNodeParameters: INodeParameters;
credentials?: INodeCredentials;
}
export interface EnvironmentVariable {
id: number;
key: string;
Expand Down
Loading
Loading