n8n
Version:
n8n Workflow Automation Tool
272 lines • 12.7 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.LoadNodesAndCredentials = void 0;
const fast_glob_1 = __importDefault(require("fast-glob"));
const typedi_1 = require("typedi");
const path_1 = __importDefault(require("path"));
const promises_1 = __importDefault(require("fs/promises"));
const n8n_core_1 = require("n8n-core");
const n8n_workflow_1 = require("n8n-workflow");
const constants_1 = require("./constants");
const Logger_1 = require("./Logger");
const config_1 = require("@n8n/config");
let LoadNodesAndCredentials = class LoadNodesAndCredentials {
constructor(logger, instanceSettings, globalConfig) {
this.logger = logger;
this.instanceSettings = instanceSettings;
this.globalConfig = globalConfig;
this.known = { nodes: {}, credentials: {} };
this.loaded = { nodes: {}, credentials: {} };
this.types = { nodes: [], credentials: [] };
this.loaders = {};
this.excludeNodes = this.globalConfig.nodes.exclude;
this.includeNodes = this.globalConfig.nodes.include;
this.postProcessors = [];
}
async init() {
var _a;
if (constants_1.inTest)
throw new n8n_workflow_1.ApplicationError('Not available in tests');
const delimiter = process.platform === 'win32' ? ';' : ':';
process.env.NODE_PATH = module.paths.join(delimiter);
module.constructor._initPaths();
if (!constants_1.inE2ETests) {
this.excludeNodes = (_a = this.excludeNodes) !== null && _a !== void 0 ? _a : [];
this.excludeNodes.push('n8n-nodes-base.e2eTest');
}
const basePathsToScan = [
path_1.default.join(constants_1.CLI_DIR, '..'),
path_1.default.join(constants_1.CLI_DIR, 'node_modules'),
];
for (const nodeModulesDir of basePathsToScan) {
await this.loadNodesFromNodeModules(nodeModulesDir, 'n8n-nodes-base');
await this.loadNodesFromNodeModules(nodeModulesDir, '@n8n/n8n-nodes-langchain');
}
await this.loadNodesFromNodeModules(path_1.default.join(this.instanceSettings.nodesDownloadDir, 'node_modules'));
await this.loadNodesFromCustomDirectories();
await this.postProcessLoaders();
}
addPostProcessor(fn) {
this.postProcessors.push(fn);
}
isKnownNode(type) {
return type in this.known.nodes;
}
get loadedCredentials() {
return this.loaded.credentials;
}
get loadedNodes() {
return this.loaded.nodes;
}
get knownCredentials() {
return this.known.credentials;
}
get knownNodes() {
return this.known.nodes;
}
async loadNodesFromNodeModules(nodeModulesDir, packageName) {
const globOptions = {
cwd: nodeModulesDir,
onlyDirectories: true,
deep: 1,
};
const installedPackagePaths = packageName
? await (0, fast_glob_1.default)(packageName, globOptions)
: [
...(await (0, fast_glob_1.default)('n8n-nodes-*', globOptions)),
...(await (0, fast_glob_1.default)('@*/n8n-nodes-*', { ...globOptions, deep: 2 })),
];
for (const packagePath of installedPackagePaths) {
try {
await this.runDirectoryLoader(n8n_core_1.LazyPackageDirectoryLoader, path_1.default.join(nodeModulesDir, packagePath));
}
catch (error) {
n8n_workflow_1.ErrorReporterProxy.error(error);
}
}
}
resolveIcon(packageName, url) {
const loader = this.loaders[packageName];
if (loader) {
const pathPrefix = `/icons/${packageName}/`;
const filePath = path_1.default.resolve(loader.directory, url.substring(pathPrefix.length));
if (!path_1.default.relative(loader.directory, filePath).includes('..')) {
return filePath;
}
}
return undefined;
}
getCustomDirectories() {
const customDirectories = [this.instanceSettings.customExtensionDir];
if (process.env[n8n_core_1.CUSTOM_EXTENSION_ENV] !== undefined) {
const customExtensionFolders = process.env[n8n_core_1.CUSTOM_EXTENSION_ENV].split(';');
customDirectories.push(...customExtensionFolders);
}
return customDirectories;
}
async loadNodesFromCustomDirectories() {
for (const directory of this.getCustomDirectories()) {
await this.runDirectoryLoader(n8n_core_1.CustomDirectoryLoader, directory);
}
}
async loadPackage(packageName) {
const finalNodeUnpackedPath = path_1.default.join(this.instanceSettings.nodesDownloadDir, 'node_modules', packageName);
return await this.runDirectoryLoader(n8n_core_1.PackageDirectoryLoader, finalNodeUnpackedPath);
}
async unloadPackage(packageName) {
if (packageName in this.loaders) {
this.loaders[packageName].reset();
delete this.loaders[packageName];
}
}
supportsProxyAuth(description) {
if (!description.credentials)
return false;
return description.credentials.some(({ name }) => {
const credType = this.types.credentials.find((t) => t.name === name);
if (!credType) {
this.logger.warn(`Failed to load Custom API options for the node "${description.name}": Unknown credential name "${name}"`);
return false;
}
if (credType.authenticate !== undefined)
return true;
return (Array.isArray(credType.extends) &&
credType.extends.some((parentType) => ['oAuth2Api', 'googleOAuth2Api', 'oAuth1Api'].includes(parentType)));
});
}
injectCustomApiCallOptions() {
this.types.nodes.forEach((node) => {
const isLatestVersion = node.defaultVersion === undefined || node.defaultVersion === node.version;
if (isLatestVersion) {
if (!this.supportsProxyAuth(node))
return;
node.properties.forEach((p) => {
if (['resource', 'operation'].includes(p.name) &&
Array.isArray(p.options) &&
p.options[p.options.length - 1].name !== constants_1.CUSTOM_API_CALL_NAME) {
p.options.push({
name: constants_1.CUSTOM_API_CALL_NAME,
value: constants_1.CUSTOM_API_CALL_KEY,
});
}
});
}
});
}
async runDirectoryLoader(constructor, dir) {
const loader = new constructor(dir, this.excludeNodes, this.includeNodes);
await loader.loadAll();
this.loaders[loader.packageName] = loader;
return loader;
}
async postProcessLoaders() {
this.known = { nodes: {}, credentials: {} };
this.loaded = { nodes: {}, credentials: {} };
this.types = { nodes: [], credentials: [] };
for (const loader of Object.values(this.loaders)) {
const { known, types, directory } = loader;
this.types.nodes = this.types.nodes.concat(types.nodes);
this.types.credentials = this.types.credentials.concat(types.credentials);
for (const nodeTypeName in loader.nodeTypes) {
this.loaded.nodes[nodeTypeName] = loader.nodeTypes[nodeTypeName];
}
for (const credentialTypeName in loader.credentialTypes) {
this.loaded.credentials[credentialTypeName] = loader.credentialTypes[credentialTypeName];
}
for (const type in known.nodes) {
const { className, sourcePath } = known.nodes[type];
this.known.nodes[type] = {
className,
sourcePath: path_1.default.join(directory, sourcePath),
};
}
for (const type in known.credentials) {
const { className, sourcePath, supportedNodes, extends: extendsArr, } = known.credentials[type];
this.known.credentials[type] = {
className,
sourcePath: path_1.default.join(directory, sourcePath),
supportedNodes: loader instanceof n8n_core_1.PackageDirectoryLoader
? supportedNodes === null || supportedNodes === void 0 ? void 0 : supportedNodes.map((nodeName) => `${loader.packageName}.${nodeName}`)
: undefined,
extends: extendsArr,
};
}
}
this.injectCustomApiCallOptions();
for (const postProcessor of this.postProcessors) {
await postProcessor();
}
}
async setupHotReload() {
const { default: debounce } = await Promise.resolve().then(() => __importStar(require('lodash/debounce')));
const { watch } = await Promise.resolve().then(() => __importStar(require('chokidar')));
const { Push } = await Promise.resolve().then(() => __importStar(require('./push')));
const push = typedi_1.Container.get(Push);
Object.values(this.loaders).forEach(async (loader) => {
try {
await promises_1.default.access(loader.directory);
}
catch {
return;
}
const realModulePath = path_1.default.join(await promises_1.default.realpath(loader.directory), path_1.default.sep);
const reloader = debounce(async () => {
const modulesToUnload = Object.keys(require.cache).filter((filePath) => filePath.startsWith(realModulePath));
modulesToUnload.forEach((filePath) => {
delete require.cache[filePath];
});
loader.reset();
await loader.loadAll();
await this.postProcessLoaders();
push.broadcast('nodeDescriptionUpdated');
}, 100);
const toWatch = loader.isLazyLoaded
? ['**/nodes.json', '**/credentials.json']
: ['**/*.js', '**/*.json'];
watch(toWatch, { cwd: realModulePath }).on('change', reloader);
});
}
};
exports.LoadNodesAndCredentials = LoadNodesAndCredentials;
exports.LoadNodesAndCredentials = LoadNodesAndCredentials = __decorate([
(0, typedi_1.Service)(),
__metadata("design:paramtypes", [Logger_1.Logger,
n8n_core_1.InstanceSettings,
config_1.GlobalConfig])
], LoadNodesAndCredentials);
//# sourceMappingURL=LoadNodesAndCredentials.js.map