mirror of
https://github.com/n8n-io/n8n.git
synced 2025-01-11 12:57:29 -08:00
fix(core): Prevent backend from loading duplicate copies of nodes packages (#10979)
Some checks are pending
Test Master / install-and-build (push) Waiting to run
Test Master / Unit tests (18.x) (push) Blocked by required conditions
Test Master / Unit tests (20.x) (push) Blocked by required conditions
Test Master / Unit tests (22.4) (push) Blocked by required conditions
Test Master / Lint (push) Blocked by required conditions
Test Master / Notify Slack on failure (push) Blocked by required conditions
Some checks are pending
Test Master / install-and-build (push) Waiting to run
Test Master / Unit tests (18.x) (push) Blocked by required conditions
Test Master / Unit tests (20.x) (push) Blocked by required conditions
Test Master / Unit tests (22.4) (push) Blocked by required conditions
Test Master / Lint (push) Blocked by required conditions
Test Master / Notify Slack on failure (push) Blocked by required conditions
This commit is contained in:
parent
1944b46fd4
commit
4584f22a9b
|
@ -18,6 +18,7 @@ import type {
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { NodeHelpers, ApplicationError, ErrorReporterProxy as ErrorReporter } from 'n8n-workflow';
|
import { NodeHelpers, ApplicationError, ErrorReporterProxy as ErrorReporter } from 'n8n-workflow';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import picocolors from 'picocolors';
|
||||||
import { Container, Service } from 'typedi';
|
import { Container, Service } from 'typedi';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -146,6 +147,7 @@ export class LoadNodesAndCredentials {
|
||||||
path.join(nodeModulesDir, packagePath),
|
path.join(nodeModulesDir, packagePath),
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
this.logger.error((error as Error).message);
|
||||||
ErrorReporter.error(error);
|
ErrorReporter.error(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -258,6 +260,13 @@ export class LoadNodesAndCredentials {
|
||||||
dir: string,
|
dir: string,
|
||||||
) {
|
) {
|
||||||
const loader = new constructor(dir, this.excludeNodes, this.includeNodes);
|
const loader = new constructor(dir, this.excludeNodes, this.includeNodes);
|
||||||
|
if (loader.packageName in this.loaders) {
|
||||||
|
throw new ApplicationError(
|
||||||
|
picocolors.red(
|
||||||
|
`nodes package ${loader.packageName} is already loaded.\n Please delete this second copy at path ${dir}`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
await loader.loadAll();
|
await loader.loadAll();
|
||||||
this.loaders[loader.packageName] = loader;
|
this.loaders[loader.packageName] = loader;
|
||||||
return loader;
|
return loader;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import glob from 'fast-glob';
|
import glob from 'fast-glob';
|
||||||
import { readFile } from 'fs/promises';
|
import { readFileSync } from 'node:fs';
|
||||||
|
import { readFile } from 'node:fs/promises';
|
||||||
import type {
|
import type {
|
||||||
CodexData,
|
CodexData,
|
||||||
DocumentationLink,
|
DocumentationLink,
|
||||||
|
@ -350,18 +351,11 @@ export class CustomDirectoryLoader extends DirectoryLoader {
|
||||||
* e.g. /nodes-base or community packages.
|
* e.g. /nodes-base or community packages.
|
||||||
*/
|
*/
|
||||||
export class PackageDirectoryLoader extends DirectoryLoader {
|
export class PackageDirectoryLoader extends DirectoryLoader {
|
||||||
packageName = '';
|
packageJson: n8n.PackageJson = this.readJSONSync('package.json');
|
||||||
|
|
||||||
packageJson!: n8n.PackageJson;
|
packageName = this.packageJson.name;
|
||||||
|
|
||||||
async readPackageJson() {
|
|
||||||
this.packageJson = await this.readJSON('package.json');
|
|
||||||
this.packageName = this.packageJson.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
override async loadAll() {
|
override async loadAll() {
|
||||||
await this.readPackageJson();
|
|
||||||
|
|
||||||
const { n8n } = this.packageJson;
|
const { n8n } = this.packageJson;
|
||||||
if (!n8n) return;
|
if (!n8n) return;
|
||||||
|
|
||||||
|
@ -391,6 +385,17 @@ export class PackageDirectoryLoader extends DirectoryLoader {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected readJSONSync<T>(file: string): T {
|
||||||
|
const filePath = this.resolvePath(file);
|
||||||
|
const fileString = readFileSync(filePath, 'utf8');
|
||||||
|
|
||||||
|
try {
|
||||||
|
return jsonParse<T>(fileString);
|
||||||
|
} catch (error) {
|
||||||
|
throw new ApplicationError('Failed to parse JSON', { extra: { filePath } });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected async readJSON<T>(file: string): Promise<T> {
|
protected async readJSON<T>(file: string): Promise<T> {
|
||||||
const filePath = this.resolvePath(file);
|
const filePath = this.resolvePath(file);
|
||||||
const fileString = await readFile(filePath, 'utf8');
|
const fileString = await readFile(filePath, 'utf8');
|
||||||
|
@ -408,8 +413,6 @@ export class PackageDirectoryLoader extends DirectoryLoader {
|
||||||
*/
|
*/
|
||||||
export class LazyPackageDirectoryLoader extends PackageDirectoryLoader {
|
export class LazyPackageDirectoryLoader extends PackageDirectoryLoader {
|
||||||
override async loadAll() {
|
override async loadAll() {
|
||||||
await this.readPackageJson();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const knownNodes: typeof this.known.nodes = await this.readJSON('dist/known/nodes.json');
|
const knownNodes: typeof this.known.nodes = await this.readJSON('dist/known/nodes.json');
|
||||||
for (const nodeName in knownNodes) {
|
for (const nodeName in knownNodes) {
|
||||||
|
|
Loading…
Reference in a new issue