refactor: Fix node versioning again (#3819)

* 📘 Update state interface

*  Adjust store module to interface

* 🔥 Remove excess check

* 🐛 Fix filtering

* 🐛 Ensure default to latest version

*  Add `allLatestNodeTypes` getter

* 🔥 Remove excess checks

*  Simplify expression

*  Add check

* 🐛 Account for unknown node type name
This commit is contained in:
Iván Ovejero 2022-08-03 13:11:25 +02:00 committed by GitHub
parent 679a443a0c
commit 6e1aaa10e5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 54 additions and 49 deletions

View file

@ -978,7 +978,11 @@ export interface ISettingsState {
} }
export interface INodeTypesState { export interface INodeTypesState {
nodeTypes: { [nodeType: string]: INodeTypeDescription }; nodeTypes: {
[nodeType: string]: {
[version: number]: INodeTypeDescription;
}
};
} }
export interface ITemplateState { export interface ITemplateState {

View file

@ -44,31 +44,16 @@ export default Vue.extend({
], ],
data() { data() {
return { return {
allNodeTypes: [], allLatestNodeTypes: [] as INodeTypeDescription[],
}; };
}, },
computed: { computed: {
...mapGetters('users', ['personalizedNodeTypes']), ...mapGetters('users', ['personalizedNodeTypes']),
nodeTypes(): INodeTypeDescription[] { nodeTypes(): INodeTypeDescription[] {
return this.$store.getters['nodeTypes/allNodeTypes']; return this.$store.getters['nodeTypes/allLatestNodeTypes'];
}, },
visibleNodeTypes(): INodeTypeDescription[] { visibleNodeTypes(): INodeTypeDescription[] {
return this.allNodeTypes return this.allLatestNodeTypes.filter((nodeType) => !HIDDEN_NODES.includes(nodeType.name));
.filter((nodeType: INodeTypeDescription) => {
return !HIDDEN_NODES.includes(nodeType.name);
}).reduce((accumulator: INodeTypeDescription[], currentValue: INodeTypeDescription) => {
// keep only latest version of the nodes
// accumulator starts as an empty array.
const exists = accumulator.findIndex(nodes => nodes.name === currentValue.name);
if (exists >= 0 && accumulator[exists].version < currentValue.version) {
// This must be a versioned node and we've found a newer version.
// Replace the previous one with this one.
accumulator[exists] = currentValue;
} else {
accumulator.push(currentValue);
}
return accumulator;
}, []);
}, },
categoriesWithNodes(): ICategoriesWithNodes { categoriesWithNodes(): ICategoriesWithNodes {
return getCategoriesWithNodes(this.visibleNodeTypes, this.personalizedNodeTypes as string[]); return getCategoriesWithNodes(this.visibleNodeTypes, this.personalizedNodeTypes as string[]);
@ -125,8 +110,8 @@ export default Vue.extend({
}, },
watch: { watch: {
nodeTypes(newList) { nodeTypes(newList) {
if (newList.length !== this.allNodeTypes.length) { if (newList.length !== this.allLatestNodeTypes.length) {
this.allNodeTypes = newList; this.allLatestNodeTypes = newList;
} }
}, },
}, },

View file

@ -104,9 +104,9 @@ const module: Module<ICredentialsState, IRootState> = {
}, },
getNodesWithAccess (state: ICredentialsState, getters: any, rootState: IRootState, rootGetters: any) { // tslint:disable-line:no-any getNodesWithAccess (state: ICredentialsState, getters: any, rootState: IRootState, rootGetters: any) { // tslint:disable-line:no-any
return (credentialTypeName: string) => { return (credentialTypeName: string) => {
const nodeTypes: INodeTypeDescription[] = rootGetters['nodeTypes/allNodeTypes']; const allLatestNodeTypes: INodeTypeDescription[] = rootGetters['nodeTypes/allLatestNodeTypes'];
return nodeTypes.filter((nodeType: INodeTypeDescription) => { return allLatestNodeTypes.filter((nodeType: INodeTypeDescription) => {
if (!nodeType.credentials) { if (!nodeType.credentials) {
return false; return false;
} }

View file

@ -26,25 +26,53 @@ const module: Module<INodeTypesState, IRootState> = {
}, },
getters: { getters: {
allNodeTypes: (state): INodeTypeDescription[] => { allNodeTypes: (state): INodeTypeDescription[] => {
return Object.values(state.nodeTypes); return Object.values(state.nodeTypes).reduce<INodeTypeDescription[]>((allNodeTypes, nodeType) => {
const versionNumbers = Object.keys(nodeType).map(Number);
const allNodeVersions = versionNumbers.map(version => nodeType[version]);
return [...allNodeTypes, ...allNodeVersions];
}, []);
},
allLatestNodeTypes: (state): INodeTypeDescription[] => {
return Object.values(state.nodeTypes).reduce<INodeTypeDescription[]>((allLatestNodeTypes, nodeVersions) => {
const versionNumbers = Object.keys(nodeVersions).map(Number);
const latestNodeVersion = nodeVersions[Math.max(...versionNumbers)];
if (!latestNodeVersion) return allLatestNodeTypes;
return [...allLatestNodeTypes, latestNodeVersion];
}, []);
}, },
getNodeType: (state) => (nodeTypeName: string, version?: number): INodeTypeDescription | null => { getNodeType: (state) => (nodeTypeName: string, version?: number): INodeTypeDescription | null => {
const nodeType = state.nodeTypes[nodeTypeName]; const nodeVersions = state.nodeTypes[nodeTypeName];
if (!nodeType || !hasValidVersion(nodeType, version)) return null; if (!nodeVersions) return null;
return nodeType; const versionNumbers = Object.keys(nodeVersions).map(Number);
const nodeType = nodeVersions[version || Math.max(...versionNumbers)];
return nodeType || null;
}, },
}, },
mutations: { mutations: {
setNodeTypes(state, nodeTypesArray: INodeTypeDescription[]) { setNodeTypes(state, newNodeTypes: INodeTypeDescription[]) {
state.nodeTypes = toNodeTypesState(nodeTypesArray); newNodeTypes.forEach((newNodeType) => {
}, const newNodeVersions = getNodeVersions(newNodeType);
updateNodeTypes(state, newNodeTypes: INodeTypeDescription[]) { if (newNodeVersions.length === 0) {
newNodeTypes.forEach((node) => Vue.set(state.nodeTypes, node.name, node)); const singleVersion = { [DEFAULT_NODETYPE_VERSION]: newNodeType };
}, Vue.set(state.nodeTypes, newNodeType.name, singleVersion);
return;
}
for (const version of newNodeVersions) {
state.nodeTypes[newNodeType.name]
? Vue.set(state.nodeTypes[newNodeType.name], version, newNodeType)
: Vue.set(state.nodeTypes, newNodeType.name, { [version]: newNodeType });
}
});
},
removeNodeTypes(state, nodeTypesToRemove: INodeTypeDescription[]) { removeNodeTypes(state, nodeTypesToRemove: INodeTypeDescription[]) {
state.nodeTypes = nodeTypesToRemove.reduce( state.nodeTypes = nodeTypesToRemove.reduce(
(oldNodes, newNodeType) => omit(newNodeType.name, oldNodes), (oldNodes, newNodeType) => omit(newNodeType.name, oldNodes),
@ -64,7 +92,7 @@ const module: Module<INodeTypesState, IRootState> = {
nodesToBeFetched, nodesToBeFetched,
); );
context.commit('updateNodeTypes', nodesInformation); context.commit('setNodeTypes', nodesInformation);
}, },
async getNodeTypes(context: ActionContext<INodeTypesState, IRootState>) { async getNodeTypes(context: ActionContext<INodeTypesState, IRootState>) {
const nodeTypes = await getNodeTypes(context.rootGetters.getRestApiContext); const nodeTypes = await getNodeTypes(context.rootGetters.getRestApiContext);
@ -99,7 +127,7 @@ const module: Module<INodeTypesState, IRootState> = {
} }
}); });
context.commit('updateNodeTypes', nodesInformation); context.commit('setNodeTypes', nodesInformation);
}, },
async getNodeParameterOptions( async getNodeParameterOptions(
context: ActionContext<INodeTypesState, IRootState>, context: ActionContext<INodeTypesState, IRootState>,
@ -117,20 +145,8 @@ const module: Module<INodeTypesState, IRootState> = {
}, },
}; };
function toNodeTypesState(nodeTypes: INodeTypeDescription[]) { function getNodeVersions(nodeType: INodeTypeDescription) {
return nodeTypes.reduce<INodeTypesState['nodeTypes']>((acc, cur) => { return Array.isArray(nodeType.version) ? nodeType.version : [nodeType.version];
acc[cur.name] = cur;
return acc;
}, {});
}
function hasValidVersion(nodeType: INodeTypeDescription, version?: number) {
const nodeTypeVersion = Array.isArray(nodeType.version)
? nodeType.version
: [nodeType.version];
return nodeTypeVersion.includes(version || nodeType.defaultVersion || DEFAULT_NODETYPE_VERSION);
} }
export default module; export default module;