mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-09 22:24:05 -08:00
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:
parent
679a443a0c
commit
6e1aaa10e5
|
@ -978,7 +978,11 @@ export interface ISettingsState {
|
|||
}
|
||||
|
||||
export interface INodeTypesState {
|
||||
nodeTypes: { [nodeType: string]: INodeTypeDescription };
|
||||
nodeTypes: {
|
||||
[nodeType: string]: {
|
||||
[version: number]: INodeTypeDescription;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export interface ITemplateState {
|
||||
|
|
|
@ -44,31 +44,16 @@ export default Vue.extend({
|
|||
],
|
||||
data() {
|
||||
return {
|
||||
allNodeTypes: [],
|
||||
allLatestNodeTypes: [] as INodeTypeDescription[],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('users', ['personalizedNodeTypes']),
|
||||
nodeTypes(): INodeTypeDescription[] {
|
||||
return this.$store.getters['nodeTypes/allNodeTypes'];
|
||||
return this.$store.getters['nodeTypes/allLatestNodeTypes'];
|
||||
},
|
||||
visibleNodeTypes(): INodeTypeDescription[] {
|
||||
return this.allNodeTypes
|
||||
.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;
|
||||
}, []);
|
||||
return this.allLatestNodeTypes.filter((nodeType) => !HIDDEN_NODES.includes(nodeType.name));
|
||||
},
|
||||
categoriesWithNodes(): ICategoriesWithNodes {
|
||||
return getCategoriesWithNodes(this.visibleNodeTypes, this.personalizedNodeTypes as string[]);
|
||||
|
@ -125,8 +110,8 @@ export default Vue.extend({
|
|||
},
|
||||
watch: {
|
||||
nodeTypes(newList) {
|
||||
if (newList.length !== this.allNodeTypes.length) {
|
||||
this.allNodeTypes = newList;
|
||||
if (newList.length !== this.allLatestNodeTypes.length) {
|
||||
this.allLatestNodeTypes = newList;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
@ -104,9 +104,9 @@ const module: Module<ICredentialsState, IRootState> = {
|
|||
},
|
||||
getNodesWithAccess (state: ICredentialsState, getters: any, rootState: IRootState, rootGetters: any) { // tslint:disable-line:no-any
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -26,25 +26,53 @@ const module: Module<INodeTypesState, IRootState> = {
|
|||
},
|
||||
getters: {
|
||||
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 => {
|
||||
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: {
|
||||
setNodeTypes(state, nodeTypesArray: INodeTypeDescription[]) {
|
||||
state.nodeTypes = toNodeTypesState(nodeTypesArray);
|
||||
},
|
||||
setNodeTypes(state, newNodeTypes: INodeTypeDescription[]) {
|
||||
newNodeTypes.forEach((newNodeType) => {
|
||||
const newNodeVersions = getNodeVersions(newNodeType);
|
||||
|
||||
updateNodeTypes(state, newNodeTypes: INodeTypeDescription[]) {
|
||||
newNodeTypes.forEach((node) => Vue.set(state.nodeTypes, node.name, node));
|
||||
},
|
||||
if (newNodeVersions.length === 0) {
|
||||
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[]) {
|
||||
state.nodeTypes = nodeTypesToRemove.reduce(
|
||||
(oldNodes, newNodeType) => omit(newNodeType.name, oldNodes),
|
||||
|
@ -64,7 +92,7 @@ const module: Module<INodeTypesState, IRootState> = {
|
|||
nodesToBeFetched,
|
||||
);
|
||||
|
||||
context.commit('updateNodeTypes', nodesInformation);
|
||||
context.commit('setNodeTypes', nodesInformation);
|
||||
},
|
||||
async getNodeTypes(context: ActionContext<INodeTypesState, IRootState>) {
|
||||
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(
|
||||
context: ActionContext<INodeTypesState, IRootState>,
|
||||
|
@ -117,20 +145,8 @@ const module: Module<INodeTypesState, IRootState> = {
|
|||
},
|
||||
};
|
||||
|
||||
function toNodeTypesState(nodeTypes: INodeTypeDescription[]) {
|
||||
return nodeTypes.reduce<INodeTypesState['nodeTypes']>((acc, cur) => {
|
||||
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);
|
||||
function getNodeVersions(nodeType: INodeTypeDescription) {
|
||||
return Array.isArray(nodeType.version) ? nodeType.version : [nodeType.version];
|
||||
}
|
||||
|
||||
export default module;
|
||||
|
|
Loading…
Reference in a new issue