refactor(core): Modularize community packages (#18641)

This commit is contained in:
Iván Ovejero
2025-08-22 12:19:01 +02:00
committed by GitHub
parent e3772c13d2
commit 9e420d15c1
43 changed files with 144 additions and 98 deletions

View File

@@ -22,7 +22,10 @@ describe('eligibleModules', () => {
it('should consider a module ineligible if it was disabled via env var', () => {
process.env.N8N_DISABLED_MODULES = 'insights';
expect(Container.get(ModuleRegistry).eligibleModules).toEqual(['external-secrets']);
expect(Container.get(ModuleRegistry).eligibleModules).toEqual([
'external-secrets',
'community-packages',
]);
});
it('should consider a module eligible if it was enabled via env var', () => {
@@ -30,6 +33,7 @@ describe('eligibleModules', () => {
expect(Container.get(ModuleRegistry).eligibleModules).toEqual([
'insights',
'external-secrets',
'community-packages',
'data-store',
]);
});

View File

@@ -26,7 +26,11 @@ export class ModuleRegistry {
private readonly modulesConfig: ModulesConfig,
) {}
private readonly defaultModules: ModuleName[] = ['insights', 'external-secrets'];
private readonly defaultModules: ModuleName[] = [
'insights',
'external-secrets',
'community-packages',
];
private readonly activeModules: string[] = [];
@@ -83,7 +87,7 @@ export class ModuleRegistry {
if (entities?.length) this.entities.push(...entities);
const loadDir = Container.get(ModuleClass).loadDir?.();
const loadDir = await Container.get(ModuleClass).loadDir?.();
if (loadDir) this.loadDirs.push(loadDir);
}

View File

@@ -2,7 +2,12 @@ import { CommaSeparatedStringArray, Config, Env } from '@n8n/config';
import { UnknownModuleError } from './errors/unknown-module.error';
export const MODULE_NAMES = ['insights', 'external-secrets', 'data-store'] as const;
export const MODULE_NAMES = [
'insights',
'external-secrets',
'community-packages',
'data-store',
] as const;
export type ModuleName = (typeof MODULE_NAMES)[number];

View File

@@ -11,8 +11,6 @@ import { ExecutionEntity } from './execution-entity';
import { ExecutionMetadata } from './execution-metadata';
import { Folder } from './folder';
import { FolderTagMapping } from './folder-tag-mapping';
import { InstalledNodes } from './installed-nodes';
import { InstalledPackages } from './installed-packages';
import { InvalidAuthToken } from './invalid-auth-token';
import { ProcessedData } from './processed-data';
import { Project } from './project';
@@ -35,8 +33,6 @@ import { WorkflowTagMapping } from './workflow-tag-mapping';
export {
EventDestinations,
InstalledNodes,
InstalledPackages,
InvalidAuthToken,
ProcessedData,
Settings,
@@ -72,8 +68,6 @@ export {
export const entities = {
EventDestinations,
InstalledNodes,
InstalledPackages,
InvalidAuthToken,
ProcessedData,
Settings,

View File

@@ -12,8 +12,6 @@ export { EventDestinationsRepository } from './event-destinations.repository';
export { FolderRepository } from './folder.repository';
export { FolderTagMappingRepository } from './folder-tag-mapping.repository';
export { ScopeRepository } from './scope.repository';
export { InstalledNodesRepository } from './installed-nodes.repository';
export { InstalledPackagesRepository } from './installed-packages.repository';
export { InvalidAuthTokenRepository } from './invalid-auth-token.repository';
export { LicenseMetricsRepository } from './license-metrics.repository';
export { ProjectRelationRepository } from './project-relation.repository';

View File

@@ -33,10 +33,10 @@ export interface ModuleInterface {
settings?(): Promise<ModuleSettings>;
/**
* @returns Path to a dir to load nodes and credentials from.
* @returns Path to a dir to load nodes and credentials from. `null` to skip.
* @example '/Users/nathan/.n8n/nodes/node_modules'
*/
loadDir?(): string;
loadDir?(): Promise<string | null>;
}
export type ModuleClass = Constructable<ModuleInterface>;

View File

@@ -1,7 +1,8 @@
import { type InstalledNodes, type CredentialsEntity, type User } from '@n8n/db';
import type { CredentialsEntity, User } from '@n8n/db';
import { mock } from 'jest-mock-extended';
import { CommunityNode } from '../community-node';
import { CommunityNode } from '@/modules/community-packages/community-node.command';
import type { InstalledNodes } from '@/modules/community-packages/installed-nodes.entity';
describe('uninstallCredential', () => {
const userId = '1234';

View File

@@ -8,12 +8,12 @@ import { mock } from 'jest-mock-extended';
import type { IRun } from 'n8n-workflow';
import { ActiveExecutions } from '@/active-executions';
import { CommunityPackagesService } from '@/community-packages/community-packages.service';
import { DeprecationService } from '@/deprecation/deprecation.service';
import { MessageEventBus } from '@/eventbus/message-event-bus/message-event-bus';
import { TelemetryEventRelay } from '@/events/relays/telemetry.event-relay';
import { ExternalHooks } from '@/external-hooks';
import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
import { CommunityPackagesService } from '@/modules/community-packages/community-packages.service';
import { PostHogClient } from '@/posthog';
import { OwnershipService } from '@/services/ownership.service';
import { ShutdownService } from '@/shutdown/shutdown.service';

View File

@@ -7,12 +7,12 @@ import { mock } from 'jest-mock-extended';
import type { IRun } from 'n8n-workflow';
import { ActiveExecutions } from '@/active-executions';
import { CommunityPackagesService } from '@/community-packages/community-packages.service';
import { DeprecationService } from '@/deprecation/deprecation.service';
import { MessageEventBus } from '@/eventbus/message-event-bus/message-event-bus';
import { TelemetryEventRelay } from '@/events/relays/telemetry.event-relay';
import { ExternalHooks } from '@/external-hooks';
import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
import { CommunityPackagesService } from '@/modules/community-packages/community-packages.service';
import { PostHogClient } from '@/posthog';
import { OwnershipService } from '@/services/ownership.service';
import { ShutdownService } from '@/shutdown/shutdown.service';

View File

@@ -33,11 +33,11 @@ import { TelemetryEventRelay } from '@/events/relays/telemetry.event-relay';
import { ExternalHooks } from '@/external-hooks';
import { License } from '@/license';
import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
import { CommunityPackagesConfig } from '@/modules/community-packages/community-packages.config';
import { NodeTypes } from '@/node-types';
import { PostHogClient } from '@/posthog';
import { ShutdownService } from '@/shutdown/shutdown.service';
import { WorkflowHistoryManager } from '@/workflows/workflow-history.ee/workflow-history-manager.ee';
import { CommunityPackagesConfig } from '@/community-packages/community-packages.config';
export abstract class BaseCommand<F = never> {
readonly flags: F;
@@ -133,10 +133,11 @@ export abstract class BaseCommand<F = never> {
);
}
// @TODO: Move to community-packages module
const communityPackagesConfig = Container.get(CommunityPackagesConfig);
if (communityPackagesConfig.enabled && this.needsCommunityPackages) {
const { CommunityPackagesService } = await import(
'@/community-packages/community-packages.service'
'@/modules/community-packages/community-packages.service'
);
await Container.get(CommunityPackagesService).init();
}

View File

@@ -30,8 +30,6 @@ import { deepCopy, NodeConnectionTypes, UnexpectedError, UserError } from 'n8n-w
import path from 'path';
import picocolors from 'picocolors';
import { CommunityPackagesConfig } from './community-packages/community-packages.config';
import { CUSTOM_API_CALL_KEY, CUSTOM_API_CALL_NAME, CLI_DIR, inE2ETests } from '@/constants';
@Service()
@@ -91,14 +89,6 @@ export class LoadNodesAndCredentials {
await this.loadNodesFromNodeModules(nodeModulesDir, '@n8n/n8n-nodes-langchain');
}
if (!Container.get(CommunityPackagesConfig).preventLoading) {
// Load nodes from any other `n8n-nodes-*` packages in the download directory
// This includes the community nodes
await this.loadNodesFromNodeModules(
path.join(this.instanceSettings.nodesDownloadDir, 'node_modules'),
);
}
for (const dir of this.moduleRegistry.loadDirs) {
await this.loadNodesFromNodeModules(dir);
}

View File

@@ -1,14 +1,14 @@
import type { CommunityNodeType } from '@n8n/api-types';
import type { InstalledPackages } from '@n8n/db';
import { mock } from 'jest-mock-extended';
import { CommunityPackagesController } from '@/community-packages/community-packages.controller';
import { CommunityPackagesController } from '@/modules/community-packages/community-packages.controller';
import type { NodeRequest } from '@/requests';
import type { EventService } from '../../events/event.service';
import type { Push } from '../../push';
import type { EventService } from '../../../events/event.service';
import type { Push } from '../../../push';
import type { CommunityNodeTypesService } from '../community-node-types.service';
import type { CommunityPackagesService } from '../community-packages.service';
import type { InstalledPackages } from '../installed-packages.entity';
describe('CommunityPackagesController', () => {
const push = mock<Push>();

View File

@@ -1,21 +1,30 @@
import { mockInstance } from '@n8n/backend-test-utils';
import type { InstalledNodes, InstalledPackages } from '@n8n/db';
import path from 'path';
import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
import { CommunityPackagesService } from '@/community-packages/community-packages.service';
import { CommunityPackagesService } from '@/modules/community-packages/community-packages.service';
import type { InstalledNodes } from '@/modules/community-packages/installed-nodes.entity';
import type { InstalledPackages } from '@/modules/community-packages/installed-packages.entity';
import { COMMUNITY_PACKAGE_VERSION } from './shared/constants';
import { createOwner } from './shared/db/users';
import type { SuperAgentTest } from './shared/types';
import { setupTestServer, mockPackage, mockNode, mockPackageName } from './shared/utils';
import { COMMUNITY_PACKAGE_VERSION } from '../../../../test/integration/shared/constants';
import { createOwner } from '../../../../test/integration/shared/db/users';
import type { SuperAgentTest } from '../../../../test/integration/shared/types';
import {
setupTestServer,
mockPackage,
mockNode,
mockPackageName,
} from '../../../../test/integration/shared/utils';
const communityPackagesService = mockInstance(CommunityPackagesService, {
hasMissingPackages: false,
});
mockInstance(LoadNodesAndCredentials);
const testServer = setupTestServer({ endpointGroups: ['community-packages'] });
const testServer = setupTestServer({
endpointGroups: ['community-packages'],
modules: ['community-packages'],
});
const commonUpdatesProps = {
createdAt: new Date(),

View File

@@ -1,22 +1,15 @@
import type { Logger } from '@n8n/backend-common';
import { randomName, mockInstance } from '@n8n/backend-test-utils';
import { LICENSE_FEATURES } from '@n8n/constants';
import {
InstalledNodes,
InstalledPackages,
InstalledNodesRepository,
InstalledPackagesRepository,
} from '@n8n/db';
import axios from 'axios';
import { exec } from 'child_process';
import { mkdir, readFile, writeFile, rm, access, constants } from 'fs/promises';
import { mocked } from 'jest-mock';
import { mock } from 'jest-mock-extended';
import type { InstanceSettings, PackageDirectoryLoader } from 'n8n-core';
import type { PublicInstalledPackage } from 'n8n-workflow';
import { exec } from 'node:child_process';
import { mkdir, readFile, writeFile, rm, access, constants } from 'node:fs/promises';
import { join } from 'node:path';
import { CommunityPackagesService } from '@/community-packages/community-packages.service';
import {
NODE_PACKAGE_PREFIX,
NPM_COMMAND_TOKENS,
@@ -31,10 +24,15 @@ import { COMMUNITY_NODE_VERSION, COMMUNITY_PACKAGE_VERSION } from '@test-integra
import { mockPackageName, mockPackagePair } from '@test-integration/utils';
import type { CommunityPackagesConfig } from '../community-packages.config';
import { CommunityPackagesService } from '../community-packages.service';
import type { CommunityPackages } from '../community-packages.types';
import { InstalledNodes } from '../installed-nodes.entity';
import { InstalledNodesRepository } from '../installed-nodes.repository';
import { InstalledPackages } from '../installed-packages.entity';
import { InstalledPackagesRepository } from '../installed-packages.repository';
jest.mock('fs/promises');
jest.mock('child_process');
jest.mock('node:fs/promises');
jest.mock('node:child_process');
jest.mock('axios');
type ExecOptions = NonNullable<Parameters<typeof exec>[1]>;

View File

@@ -2,7 +2,7 @@ import type { CommunityNodeType } from '@n8n/api-types';
import { Get, RestController } from '@n8n/decorators';
import { Request } from 'express';
import { CommunityNodeTypesService } from '@/community-packages/community-node-types.service';
import { CommunityNodeTypesService } from './community-node-types.service';
@RestController('/community-node-types')
export class CommunityNodeTypesController {

View File

@@ -3,9 +3,8 @@ import { Logger, inProduction } from '@n8n/backend-common';
import { Service } from '@n8n/di';
import { ensureError } from 'n8n-workflow';
import { CommunityPackagesConfig } from '@/community-packages/community-packages.config';
import { getCommunityNodeTypes, StrapiCommunityNodeType } from './community-node-types-utils';
import { CommunityPackagesConfig } from './community-packages.config';
import { CommunityPackagesService } from './community-packages.service';
const UPDATE_INTERVAL = 8 * 60 * 60 * 1000;

View File

@@ -1,13 +1,16 @@
import { type InstalledNodes, type InstalledPackages, type User } from '@n8n/db';
import { CredentialsRepository, InstalledNodesRepository, UserRepository } from '@n8n/db';
import type { User } from '@n8n/db';
import { CredentialsRepository, UserRepository } from '@n8n/db';
import { Command } from '@n8n/decorators';
import { Container } from '@n8n/di';
import { z } from 'zod';
import { BaseCommand } from '@/commands/base-command';
import { CredentialsService } from '@/credentials/credentials.service';
import { CommunityPackagesService } from '@/community-packages/community-packages.service';
import { BaseCommand } from './base-command';
import { CommunityPackagesService } from './community-packages.service';
import { InstalledNodes } from './installed-nodes.entity';
import { InstalledNodesRepository } from './installed-nodes.repository';
import { InstalledPackages } from './installed-packages.entity';
const flagsSchema = z.object({
uninstall: z.boolean().describe('Uninstalls the node').optional(),

View File

@@ -1,21 +1,21 @@
import { Delete, Get, Patch, Post, RestController, GlobalScope } from '@n8n/decorators';
import {
RESPONSE_ERROR_MESSAGES,
STARTER_TEMPLATE_NAME,
UNKNOWN_FAILURE_REASON,
} from '@/constants';
import type { InstalledPackages } from '@n8n/db';
import { Delete, Get, Patch, Post, RestController, GlobalScope } from '@n8n/decorators';
import type { CommunityPackages } from './community-packages.types';
import { CommunityNodeTypesService } from './community-node-types.service';
import { CommunityPackagesService } from '@/community-packages/community-packages.service';
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
import { InternalServerError } from '@/errors/response-errors/internal-server.error';
import { EventService } from '@/events/event.service';
import { Push } from '@/push';
import { NodeRequest } from '@/requests';
import { CommunityNodeTypesService } from './community-node-types.service';
import { CommunityPackagesService } from './community-packages.service';
import type { CommunityPackages } from './community-packages.types';
import { InstalledPackages } from './installed-packages.entity';
const {
PACKAGE_NOT_INSTALLED,
PACKAGE_NAME_NOT_PROVIDED,

View File

@@ -0,0 +1,38 @@
import type { EntityClass, ModuleInterface } from '@n8n/decorators';
import { BackendModule } from '@n8n/decorators';
import { Container } from '@n8n/di';
import { InstanceSettings } from 'n8n-core';
import path from 'node:path';
@BackendModule({ name: 'community-packages' })
export class CommunityPackagesModule implements ModuleInterface {
async init() {
await import('./community-packages.controller');
}
async entities() {
const { InstalledNodes } = await import('./installed-nodes.entity');
const { InstalledPackages } = await import('./installed-packages.entity');
return [InstalledNodes, InstalledPackages] as EntityClass[];
}
async settings() {
const { CommunityPackagesConfig } = await import('./community-packages.config');
return {
communityNodesEnabled: Container.get(CommunityPackagesConfig).enabled,
unverifiedCommunityNodesEnabled: Container.get(CommunityPackagesConfig).unverifiedEnabled,
};
}
async loadDir() {
const { CommunityPackagesConfig } = await import('./community-packages.config');
const { preventLoading } = Container.get(CommunityPackagesConfig);
if (preventLoading) return null;
return path.join(Container.get(InstanceSettings).nodesDownloadDir, 'node_modules');
}
}

View File

@@ -1,17 +1,15 @@
import { Logger } from '@n8n/backend-common';
import { LICENSE_FEATURES } from '@n8n/constants';
import type { InstalledPackages } from '@n8n/db';
import { InstalledPackagesRepository } from '@n8n/db';
import { OnPubSubEvent } from '@n8n/decorators';
import { Service } from '@n8n/di';
import axios from 'axios';
import { exec } from 'child_process';
import { access, constants, mkdir, readFile, rm, writeFile } from 'fs/promises';
import type { PackageDirectoryLoader } from 'n8n-core';
import { InstanceSettings } from 'n8n-core';
import { jsonParse, UnexpectedError, UserError, type PublicInstalledPackage } from 'n8n-workflow';
import { join } from 'path';
import { promisify } from 'util';
import { exec } from 'node:child_process';
import { access, constants, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
import { join } from 'node:path';
import { promisify } from 'node:util';
import {
NODE_PACKAGE_PREFIX,
@@ -28,6 +26,8 @@ import { toError } from '@/utils';
import { CommunityPackagesConfig } from './community-packages.config';
import type { CommunityPackages } from './community-packages.types';
import { InstalledPackages } from './installed-packages.entity';
import { InstalledPackagesRepository } from './installed-packages.repository';
import { isVersionExists, verifyIntegrity } from './npm-utils';
const DEFAULT_REGISTRY = 'https://registry.npmjs.org';

View File

@@ -1,9 +1,9 @@
import { Column, Entity, JoinColumn, ManyToOne, PrimaryColumn } from '@n8n/typeorm';
import { BaseEntity, Column, Entity, JoinColumn, ManyToOne, PrimaryColumn } from '@n8n/typeorm';
import { InstalledPackages } from './installed-packages';
import { InstalledPackages } from './installed-packages.entity';
@Entity()
export class InstalledNodes {
export class InstalledNodes extends BaseEntity {
@Column()
name: string;

View File

@@ -1,7 +1,7 @@
import { Service } from '@n8n/di';
import { DataSource, Repository } from '@n8n/typeorm';
import { InstalledNodes } from '../entities';
import { InstalledNodes } from './installed-nodes.entity';
@Service()
export class InstalledNodesRepository extends Repository<InstalledNodes> {

View File

@@ -1,7 +1,7 @@
import { WithTimestamps } from '@n8n/db';
import { Column, Entity, JoinColumn, OneToMany, PrimaryColumn } from '@n8n/typeorm';
import { WithTimestamps } from './abstract-entity';
import type { InstalledNodes } from './installed-nodes';
import type { InstalledNodes } from './installed-nodes.entity';
@Entity()
export class InstalledPackages extends WithTimestamps {

View File

@@ -3,7 +3,7 @@ import { DataSource, Repository } from '@n8n/typeorm';
import type { PackageDirectoryLoader } from 'n8n-core';
import { InstalledNodesRepository } from './installed-nodes.repository';
import { InstalledPackages } from '../entities';
import { InstalledPackages } from './installed-packages.entity';
@Service()
export class InstalledPackagesRepository extends Repository<InstalledPackages> {

View File

@@ -7,6 +7,7 @@ import { InstanceSettings } from 'n8n-core';
import type { IWorkflowBase } from 'n8n-workflow';
import { N8N_VERSION } from '@/constants';
import { CommunityPackagesConfig } from '@/modules/community-packages/community-packages.config';
import { isApiEnabled } from '@/public-api';
import {
ENV_VARS_DOCS_URL,
@@ -16,7 +17,6 @@ import {
} from '@/security-audit/constants';
import type { RiskReporter, Risk, n8n } from '@/security-audit/types';
import { toFlaggedNode } from '@/security-audit/utils';
import { CommunityPackagesConfig } from '@/community-packages/community-packages.config';
@Service()
export class InstanceRiskReporter implements RiskReporter {

View File

@@ -1,8 +1,9 @@
import { InstalledPackages } from '@n8n/db';
import { Service } from '@n8n/di';
// eslint-disable-next-line n8n-local-rules/misplaced-n8n-typeorm-import
import { DataSource, Repository } from '@n8n/typeorm';
import { InstalledPackages } from '@/modules/community-packages/installed-packages.entity';
@Service()
export class PackagesRepository extends Repository<InstalledPackages> {
constructor(dataSource: DataSource) {

View File

@@ -65,7 +65,6 @@ import '@/webhooks/webhooks.controller';
import { ChatServer } from './chat/chat-server';
import { MfaService } from './mfa/mfa.service';
import { CommunityPackagesConfig } from './community-packages/community-packages.config';
@Service()
export class Server extends AbstractServer {
@@ -119,11 +118,6 @@ export class Server extends AbstractServer {
await Container.get(LdapService).init();
}
if (Container.get(CommunityPackagesConfig).enabled) {
await import('@/community-packages/community-packages.controller');
await import('@/community-packages/community-node-types.controller');
}
if (inE2ETests) {
await import('@/controllers/e2e.controller');
}

View File

@@ -1,5 +1,6 @@
import type { Logger, LicenseState, ModuleRegistry } from '@n8n/backend-common';
import type { GlobalConfig, SecurityConfig } from '@n8n/config';
import { Container } from '@n8n/di';
import { mock } from 'jest-mock-extended';
import type { InstanceSettings, BinaryDataConfig } from 'n8n-core';
@@ -8,12 +9,11 @@ import type { CredentialsOverwrites } from '@/credentials-overwrites';
import type { License } from '@/license';
import type { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
import type { MfaService } from '@/mfa/mfa.service';
import { CommunityPackagesConfig } from '@/modules/community-packages/community-packages.config';
import type { PushConfig } from '@/push/push.config';
import { FrontendService } from '@/services/frontend.service';
import type { UrlService } from '@/services/url.service';
import type { UserManagementMailer } from '@/user-management/email';
import { CommunityPackagesConfig } from '@/community-packages/community-packages.config';
import { Container } from '@n8n/di';
describe('FrontendService', () => {
let originalEnv: NodeJS.ProcessEnv;

View File

@@ -10,8 +10,6 @@ import { BinaryDataConfig, InstanceSettings } from 'n8n-core';
import type { ICredentialType, INodeTypeBaseDescription } from 'n8n-workflow';
import path from 'path';
import { CommunityPackagesConfig } from '@/community-packages/community-packages.config';
import type { CommunityPackagesService } from '@/community-packages/community-packages.service';
import config from '@/config';
import { inE2ETests, N8N_VERSION } from '@/constants';
import { CredentialTypes } from '@/credential-types';
@@ -20,6 +18,8 @@ import { getLdapLoginLabel } from '@/ldap.ee/helpers.ee';
import { License } from '@/license';
import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
import { MfaService } from '@/mfa/mfa.service';
import { CommunityPackagesConfig } from '@/modules/community-packages/community-packages.config';
import type { CommunityPackagesService } from '@/modules/community-packages/community-packages.service';
import { isApiEnabled } from '@/public-api';
import { PushConfig } from '@/push/push.config';
import { getSamlLoginLabel } from '@/sso.ee/saml/saml-helpers';
@@ -60,8 +60,9 @@ export class FrontendService {
this.initSettings();
// @TODO: Move to community-packages module
if (Container.get(CommunityPackagesConfig).enabled) {
void import('@/community-packages/community-packages.service').then(
void import('@/modules/community-packages/community-packages.service').then(
({ CommunityPackagesService }) => {
this.communityPackagesService = Container.get(CommunityPackagesService);
},
@@ -200,8 +201,11 @@ export class FrontendService {
executionMode: config.getEnv('executions.mode'),
isMultiMain: this.instanceSettings.isMultiMain,
pushBackend: this.pushConfig.backend,
// @TODO: Move to community-packages module
communityNodesEnabled: Container.get(CommunityPackagesConfig).enabled,
unverifiedCommunityNodesEnabled: Container.get(CommunityPackagesConfig).unverifiedEnabled,
deployment: {
type: this.globalConfig.deployment.type,
},

View File

@@ -12,11 +12,11 @@ import { LogStreamingEventRelay } from '@/events/relays/log-streaming.event-rela
import { ExternalHooks } from '@/external-hooks';
import { License } from '@/license';
import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
import { CommunityPackagesService } from '@/modules/community-packages/community-packages.service';
import { Push } from '@/push';
import { Publisher } from '@/scaling/pubsub/publisher.service';
import { Subscriber } from '@/scaling/pubsub/subscriber.service';
import { ScalingService } from '@/scaling/scaling.service';
import { CommunityPackagesService } from '@/community-packages/community-packages.service';
import { TaskBrokerServer } from '@/task-runners/task-broker/task-broker-server';
import { TaskRunnerProcess } from '@/task-runners/task-runner-process';
import { Telemetry } from '@/telemetry';

View File

@@ -5,12 +5,12 @@ import { mock } from 'jest-mock-extended';
import { v4 as uuid } from 'uuid';
import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
import { CommunityPackagesService } from '@/modules/community-packages/community-packages.service';
import { NodeTypes } from '@/node-types';
import { OFFICIAL_RISKY_NODE_TYPES, NODES_REPORT } from '@/security-audit/constants';
import { PackagesRepository } from '@/security-audit/security-audit.repository';
import { SecurityAuditService } from '@/security-audit/security-audit.service';
import { toReportTitle } from '@/security-audit/utils';
import { CommunityPackagesService } from '@/community-packages/community-packages.service';
import { getRiskSection, MOCK_PACKAGE, saveManualTriggerWorkflow } from './utils';

View File

@@ -1,11 +1,12 @@
import { GlobalConfig } from '@n8n/config';
import type { InstalledNodes, InstalledPackages } from '@n8n/db';
import { WorkflowRepository } from '@n8n/db';
import { Container } from '@n8n/di';
import nock from 'nock';
import { v4 as uuid } from 'uuid';
import * as constants from '@/constants';
import type { InstalledNodes } from '@/modules/community-packages/installed-nodes.entity';
import type { InstalledPackages } from '@/modules/community-packages/installed-packages.entity';
import type { Risk } from '@/security-audit/types';
import { toReportTitle } from '@/security-audit/utils';

View File

@@ -46,7 +46,7 @@ type EndpointGroup =
| 'data-store'
| 'module-settings';
type ModuleName = 'insights' | 'external-secrets' | 'data-store';
type ModuleName = 'insights' | 'external-secrets' | 'community-packages' | 'data-store';
export interface SetupProps {
endpointGroups?: EndpointGroup[];

View File

@@ -1,8 +1,10 @@
import { randomName } from '@n8n/backend-test-utils';
import { InstalledPackages, InstalledNodesRepository, InstalledPackagesRepository } from '@n8n/db';
import { Container } from '@n8n/di';
import { NODE_PACKAGE_PREFIX } from '@/constants';
import { InstalledNodesRepository } from '@/modules/community-packages/installed-nodes.repository';
import { InstalledPackages } from '@/modules/community-packages/installed-packages.entity';
import { InstalledPackagesRepository } from '@/modules/community-packages/installed-packages.repository';
import { COMMUNITY_NODE_VERSION, COMMUNITY_PACKAGE_VERSION } from '../constants';

View File

@@ -232,7 +232,7 @@ export const setupTestServer = ({
break;
case 'community-packages':
await import('@/community-packages/community-packages.controller');
await import('@/modules/community-packages/community-packages.controller');
break;
case 'me':