Support versioned nodes

This commit is contained in:
Iván Ovejero 2021-11-19 12:22:01 +01:00
parent 99963b04a5
commit 9819c25ec5
4 changed files with 89 additions and 16 deletions

View file

@ -40,6 +40,10 @@ class NodeTypesClass implements INodeTypes {
return this.nodeTypes[nodeType].type; return this.nodeTypes[nodeType].type;
} }
/**
* Variant of `getByNameAndVersion` that includes the node's source path,
* to be used for locating the node's `/translations` dir.
*/
getWithPath( getWithPath(
nodeTypeName: string, nodeTypeName: string,
version: number, version: number,

View file

@ -145,7 +145,7 @@ import { InternalHooksManager } from './InternalHooksManager';
import { TagEntity } from './databases/entities/TagEntity'; import { TagEntity } from './databases/entities/TagEntity';
import { WorkflowEntity } from './databases/entities/WorkflowEntity'; import { WorkflowEntity } from './databases/entities/WorkflowEntity';
import { NameRequest } from './WorkflowHelpers'; import { NameRequest } from './WorkflowHelpers';
import { getTranslationPath } from './TranslationHelpers'; import { getExpectedNodeTranslationPath } from './TranslationHelpers';
require('body-parser-xml')(bodyParser); require('body-parser-xml')(bodyParser);
@ -1186,23 +1186,26 @@ class App {
if (language === 'en') { if (language === 'en') {
return nodeInfos.reduce<INodeTypeDescription[]>((acc, { name, version }) => { return nodeInfos.reduce<INodeTypeDescription[]>((acc, { name, version }) => {
const { description } = nodeTypes.getByNameAndVersion(name, version); const { description } = nodeTypes.getByNameAndVersion(name, version);
if (description) acc.push(description); acc.push(description);
return acc; return acc;
}, []); }, []);
} }
// add node translations where available const nodeTypesWithTranslations: INodeTypeDescription[] = [];
return nodeInfos.reduce<INodeTypeDescription[]>((acc, { name, version }) => {
const { description, sourcePath } = nodeTypes.getWithPath(name, version);
const mainTranslationPath = getTranslationPath(sourcePath, language);
if (description && existsSync(mainTranslationPath)) { for (const { name, version } of nodeInfos) {
description.translation = require(mainTranslationPath); const { description, sourcePath } = nodeTypes.getWithPath(name, version);
// eslint-disable-next-line no-await-in-loop
const nodeTranslationPath = await getExpectedNodeTranslationPath(sourcePath, language);
if (existsSync(nodeTranslationPath)) {
description.translation = require(nodeTranslationPath);
} }
if (description) acc.push(description); nodeTypesWithTranslations.push(description);
return acc; }
}, []);
return nodeTypesWithTranslations;
}, },
), ),
); );

View file

@ -1,8 +1,39 @@
import { join, dirname } from 'path'; import { join, dirname } from 'path';
import { readdir } from 'fs/promises';
import { Dirent } from 'fs';
/** const ALLOWED_VERSIONED_DIRNAME_LENGTH = [2, 3]; // v1, v10
* Retrieve the path to the translation file for a node.
*/ function isVersionedDirname(dirent: Dirent) {
export function getTranslationPath(nodeSourcePath: string, language: string): string { if (!dirent.isDirectory()) return false;
return join(dirname(nodeSourcePath), 'translations', `${language}.js`);
return (
ALLOWED_VERSIONED_DIRNAME_LENGTH.includes(dirent.name.length) &&
dirent.name.toLowerCase().startsWith('v')
);
}
async function getMaxVersion(from: string) {
const entries = await readdir(from, { withFileTypes: true });
const dirnames = entries.reduce<string[]>((acc, cur) => {
if (isVersionedDirname(cur)) acc.push(cur.name);
return acc;
}, []);
if (!dirnames.length) return null;
return Math.max(...dirnames.map((d) => parseInt(d.charAt(1), 10)));
}
export async function getExpectedNodeTranslationPath(
nodeSourcePath: string,
language: string,
): Promise<string> {
const nodeDir = dirname(nodeSourcePath);
const maxVersion = await getMaxVersion(nodeDir);
return maxVersion
? join(nodeDir, `v${maxVersion}`, 'translations', `${language}.js`)
: join(nodeDir, 'translations', `${language}.js`);
} }

View file

@ -0,0 +1,35 @@
module.exports = {
mattermost: {
header: {
displayName: '🇩🇪 Mattermost',
description: '🇩🇪 Consume Mattermost API',
},
credentialsModal: {
mattermostApi: {
accessToken: {
displayName: '🇩🇪 Access token',
},
},
},
nodeView: {
resource: {
displayName: '🇩🇪 Resource',
description: '🇩🇪 The resource to operate on.',
options: {
channel: {
displayName: '🇩🇪 Channel',
},
message: {
displayName: '🇩🇪 Message',
},
reaction: {
displayName: '🇩🇪 Reaction',
},
user: {
displayName: '🇩🇪 User',
},
},
},
},
},
};