first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
import { Service } from '@n8n/di';
|
||||
import type {
|
||||
ICredentialType,
|
||||
INodeType,
|
||||
IVersionedNodeType,
|
||||
KnownNodesAndCredentials,
|
||||
LoadedClass,
|
||||
LoadedNodesAndCredentials,
|
||||
LoadingDetails,
|
||||
} from 'n8n-workflow';
|
||||
import path from 'node:path';
|
||||
|
||||
import { UnrecognizedCredentialTypeError, UnrecognizedNodeTypeError } from '../dist/errors';
|
||||
import { LazyPackageDirectoryLoader } from '../dist/nodes-loader/lazy-package-directory-loader';
|
||||
import { TestDataNode } from './test-data-node';
|
||||
|
||||
/** This rewrites the nodes/credentials source path to load the typescript code instead of the compiled javascript code */
|
||||
const fixSourcePath = (loadInfo: LoadingDetails) => {
|
||||
if (!loadInfo) return;
|
||||
loadInfo.sourcePath = loadInfo.sourcePath.replace(/^dist\//, './').replace(/\.js$/, '.ts');
|
||||
};
|
||||
|
||||
@Service()
|
||||
export class LoadNodesAndCredentials {
|
||||
private loaders: Record<string, LazyPackageDirectoryLoader> = {};
|
||||
|
||||
private directNodes: Record<string, LoadedClass<INodeType>> = {
|
||||
'n8n-nodes-testing.testData': {
|
||||
type: new TestDataNode(),
|
||||
sourcePath: __filename,
|
||||
},
|
||||
};
|
||||
|
||||
readonly known: KnownNodesAndCredentials = {
|
||||
nodes: {
|
||||
'n8n-nodes-testing.testData': {
|
||||
className: 'TestDataNode',
|
||||
sourcePath: __filename,
|
||||
},
|
||||
},
|
||||
credentials: {},
|
||||
};
|
||||
|
||||
readonly loaded: LoadedNodesAndCredentials = { nodes: {}, credentials: {} };
|
||||
|
||||
constructor(packagePaths: string[]) {
|
||||
for (const packagePath of packagePaths) {
|
||||
const loader = new LazyPackageDirectoryLoader(packagePath);
|
||||
this.loaders[loader.packageName] = loader;
|
||||
}
|
||||
}
|
||||
|
||||
async init() {
|
||||
for (const [packageName, loader] of Object.entries(this.loaders)) {
|
||||
await loader.loadAll();
|
||||
const { known, directory } = loader;
|
||||
|
||||
for (const type in known.nodes) {
|
||||
const { className, sourcePath } = known.nodes[type];
|
||||
this.known.nodes[`${packageName}.${type}`] = {
|
||||
className,
|
||||
sourcePath: path.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.join(directory, sourcePath),
|
||||
supportedNodes: supportedNodes?.map((nodeName) => `${loader.packageName}.${nodeName}`),
|
||||
extends: extendsArr,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
recognizesCredential(credentialType: string): boolean {
|
||||
return credentialType in this.known.credentials;
|
||||
}
|
||||
|
||||
getCredential(credentialType: string): LoadedClass<ICredentialType> {
|
||||
for (const loader of Object.values(this.loaders)) {
|
||||
if (credentialType in loader.known.credentials) {
|
||||
const loaded = loader.getCredential(credentialType);
|
||||
this.loaded.credentials[credentialType] = loaded;
|
||||
fixSourcePath(loader.known.credentials[credentialType]);
|
||||
}
|
||||
}
|
||||
|
||||
if (credentialType in this.loaded.credentials) {
|
||||
return this.loaded.credentials[credentialType];
|
||||
}
|
||||
|
||||
throw new UnrecognizedCredentialTypeError(credentialType);
|
||||
}
|
||||
|
||||
getNode(fullNodeType: string): LoadedClass<INodeType | IVersionedNodeType> {
|
||||
const directNode = this.directNodes[fullNodeType];
|
||||
if (directNode) {
|
||||
return directNode;
|
||||
}
|
||||
|
||||
const [packageName, nodeType] = fullNodeType.split('.');
|
||||
const { loaders } = this;
|
||||
const loader = loaders[packageName];
|
||||
if (!loader) {
|
||||
throw new UnrecognizedNodeTypeError(packageName, nodeType);
|
||||
}
|
||||
fixSourcePath(loader.known.nodes[nodeType]);
|
||||
return loader.getNode(nodeType);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user