n8n
Version:
n8n Workflow Automation Tool
216 lines • 9.49 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.LoadNodesAndCredentials = void 0;
const n8n_core_1 = require("n8n-core");
const n8n_workflow_1 = require("n8n-workflow");
const promises_1 = require("fs/promises");
const glob = require("fast-glob");
const path = require("path");
const Logger_1 = require("./Logger");
const config = require("../config");
const CUSTOM_NODES_CATEGORY = 'Custom Nodes';
class LoadNodesAndCredentialsClass {
constructor() {
this.nodeTypes = {};
this.credentialTypes = {};
this.excludeNodes = undefined;
this.includeNodes = undefined;
this.nodeModulesPath = '';
}
async init() {
this.logger = Logger_1.getLogger();
n8n_workflow_1.LoggerProxy.init(this.logger);
const checkPaths = [
path.join(__dirname, '..', '..', '..', 'n8n-workflow'),
path.join(__dirname, '..', '..', 'node_modules', 'n8n-workflow'),
];
for (const checkPath of checkPaths) {
try {
await promises_1.access(checkPath);
this.nodeModulesPath = path.dirname(checkPath);
break;
}
catch (error) {
continue;
}
}
if (this.nodeModulesPath === '') {
throw new Error('Could not find "node_modules" folder!');
}
this.excludeNodes = config.get('nodes.exclude');
this.includeNodes = config.get('nodes.include');
const packages = await this.getN8nNodePackages();
for (const packageName of packages) {
await this.loadDataFromPackage(packageName);
}
const customDirectories = [];
customDirectories.push(n8n_core_1.UserSettings.getUserN8nFolderCustomExtensionPath());
if (process.env[n8n_core_1.CUSTOM_EXTENSION_ENV] !== undefined) {
const customExtensionFolders = process.env[n8n_core_1.CUSTOM_EXTENSION_ENV].split(';');
customDirectories.push.apply(customDirectories, customExtensionFolders);
}
for (const directory of customDirectories) {
await this.loadDataFromDirectory('CUSTOM', directory);
}
}
async getN8nNodePackages() {
const getN8nNodePackagesRecursive = async (relativePath) => {
const results = [];
const nodeModulesPath = `${this.nodeModulesPath}/${relativePath}`;
for (const file of await promises_1.readdir(nodeModulesPath)) {
const isN8nNodesPackage = file.indexOf('n8n-nodes-') === 0;
const isNpmScopedPackage = file.indexOf('@') === 0;
if (!isN8nNodesPackage && !isNpmScopedPackage) {
continue;
}
if (!(await promises_1.stat(nodeModulesPath)).isDirectory()) {
continue;
}
if (isN8nNodesPackage) {
results.push(`${relativePath}${file}`);
}
if (isNpmScopedPackage) {
results.push(...(await getN8nNodePackagesRecursive(`${relativePath}${file}/`)));
}
}
return results;
};
return getN8nNodePackagesRecursive('');
}
async loadCredentialsFromFile(credentialName, filePath) {
const tempModule = require(filePath);
let tempCredential;
try {
tempCredential = new tempModule[credentialName]();
if (tempCredential.icon && tempCredential.icon.startsWith('file:')) {
tempCredential.icon = `file:${path.join(path.dirname(filePath), tempCredential.icon.substr(5))}`;
}
}
catch (e) {
if (e instanceof TypeError) {
throw new Error(`Class with name "${credentialName}" could not be found. Please check if the class is named correctly!`);
}
else {
throw e;
}
}
this.credentialTypes[tempCredential.name] = tempCredential;
}
async loadNodeFromFile(packageName, nodeName, filePath) {
let tempNode;
let fullNodeName;
const tempModule = require(filePath);
try {
tempNode = new tempModule[nodeName]();
this.addCodex({ node: tempNode, filePath, isCustom: packageName === 'CUSTOM' });
}
catch (error) {
console.error(`Error loading node "${nodeName}" from: "${filePath}"`);
throw error;
}
fullNodeName = `${packageName}.${tempNode.description.name}`;
tempNode.description.name = fullNodeName;
if (tempNode.description.icon !== undefined && tempNode.description.icon.startsWith('file:')) {
tempNode.description.icon = `file:${path.join(path.dirname(filePath), tempNode.description.icon.substr(5))}`;
}
if (tempNode.hasOwnProperty('executeSingle')) {
this.logger.warn(`"executeSingle" will get deprecated soon. Please update the code of node "${packageName}.${nodeName}" to use "execute" instead!`, { filePath });
}
if (tempNode.hasOwnProperty('nodeVersions')) {
const versionedNodeType = tempNode.getNodeType();
this.addCodex({ node: versionedNodeType, filePath, isCustom: packageName === 'CUSTOM' });
if (versionedNodeType.description.icon !== undefined &&
versionedNodeType.description.icon.startsWith('file:')) {
versionedNodeType.description.icon = `file:${path.join(path.dirname(filePath), versionedNodeType.description.icon.substr(5))}`;
}
if (versionedNodeType.hasOwnProperty('executeSingle')) {
this.logger.warn(`"executeSingle" will get deprecated soon. Please update the code of node "${packageName}.${nodeName}" to use "execute" instead!`, { filePath });
}
}
if (this.includeNodes !== undefined && !this.includeNodes.includes(fullNodeName)) {
return;
}
if (this.excludeNodes !== undefined && this.excludeNodes.includes(fullNodeName)) {
return;
}
this.nodeTypes[fullNodeName] = {
type: tempNode,
sourcePath: filePath,
};
}
getCodex(filePath) {
const { categories, subcategories, alias } = require(`${filePath}on`);
return Object.assign(Object.assign(Object.assign({}, (categories && { categories })), (subcategories && { subcategories })), (alias && { alias }));
}
addCodex({ node, filePath, isCustom, }) {
try {
const codex = this.getCodex(filePath);
if (isCustom) {
codex.categories = codex.categories
? codex.categories.concat(CUSTOM_NODES_CATEGORY)
: [CUSTOM_NODES_CATEGORY];
}
node.description.codex = codex;
}
catch (_) {
this.logger.debug(`No codex available for: ${filePath.split('/').pop()}`);
if (isCustom) {
node.description.codex = {
categories: [CUSTOM_NODES_CATEGORY],
};
}
}
}
async loadDataFromDirectory(setPackageName, directory) {
const files = await glob(path.join(directory, '**/*.@(node|credentials).js'));
let fileName;
let type;
const loadPromises = [];
for (const filePath of files) {
[fileName, type] = path.parse(filePath).name.split('.');
if (type === 'node') {
loadPromises.push(this.loadNodeFromFile(setPackageName, fileName, filePath));
}
else if (type === 'credentials') {
loadPromises.push(this.loadCredentialsFromFile(fileName, filePath));
}
}
await Promise.all(loadPromises);
}
async loadDataFromPackage(packageName) {
const packagePath = path.join(this.nodeModulesPath, packageName);
const packageFileString = await promises_1.readFile(path.join(packagePath, 'package.json'), 'utf8');
const packageFile = JSON.parse(packageFileString);
if (!packageFile.hasOwnProperty('n8n')) {
return;
}
let tempPath;
let filePath;
let fileName;
let type;
if (packageFile.n8n.hasOwnProperty('nodes') && Array.isArray(packageFile.n8n.nodes)) {
for (filePath of packageFile.n8n.nodes) {
tempPath = path.join(packagePath, filePath);
[fileName, type] = path.parse(filePath).name.split('.');
await this.loadNodeFromFile(packageName, fileName, tempPath);
}
}
if (packageFile.n8n.hasOwnProperty('credentials') &&
Array.isArray(packageFile.n8n.credentials)) {
for (filePath of packageFile.n8n.credentials) {
tempPath = path.join(packagePath, filePath);
[fileName, type] = path.parse(filePath).name.split('.');
this.loadCredentialsFromFile(fileName, tempPath);
}
}
}
}
let packagesInformationInstance;
function LoadNodesAndCredentials() {
if (packagesInformationInstance === undefined) {
packagesInformationInstance = new LoadNodesAndCredentialsClass();
}
return packagesInformationInstance;
}
exports.LoadNodesAndCredentials = LoadNodesAndCredentials;
//# sourceMappingURL=LoadNodesAndCredentials.js.map
;