mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -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 {
|
export interface INodeTypesState {
|
||||||
nodeTypes: { [nodeType: string]: INodeTypeDescription };
|
nodeTypes: {
|
||||||
|
[nodeType: string]: {
|
||||||
|
[version: number]: INodeTypeDescription;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ITemplateState {
|
export interface ITemplateState {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue