mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 18:12:04 +00:00
refactor(core): Modularize community packages (#18641)
This commit is contained in:
@@ -22,7 +22,10 @@ describe('eligibleModules', () => {
|
|||||||
|
|
||||||
it('should consider a module ineligible if it was disabled via env var', () => {
|
it('should consider a module ineligible if it was disabled via env var', () => {
|
||||||
process.env.N8N_DISABLED_MODULES = 'insights';
|
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', () => {
|
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([
|
expect(Container.get(ModuleRegistry).eligibleModules).toEqual([
|
||||||
'insights',
|
'insights',
|
||||||
'external-secrets',
|
'external-secrets',
|
||||||
|
'community-packages',
|
||||||
'data-store',
|
'data-store',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -26,7 +26,11 @@ export class ModuleRegistry {
|
|||||||
private readonly modulesConfig: ModulesConfig,
|
private readonly modulesConfig: ModulesConfig,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
private readonly defaultModules: ModuleName[] = ['insights', 'external-secrets'];
|
private readonly defaultModules: ModuleName[] = [
|
||||||
|
'insights',
|
||||||
|
'external-secrets',
|
||||||
|
'community-packages',
|
||||||
|
];
|
||||||
|
|
||||||
private readonly activeModules: string[] = [];
|
private readonly activeModules: string[] = [];
|
||||||
|
|
||||||
@@ -83,7 +87,7 @@ export class ModuleRegistry {
|
|||||||
|
|
||||||
if (entities?.length) this.entities.push(...entities);
|
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);
|
if (loadDir) this.loadDirs.push(loadDir);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,12 @@ import { CommaSeparatedStringArray, Config, Env } from '@n8n/config';
|
|||||||
|
|
||||||
import { UnknownModuleError } from './errors/unknown-module.error';
|
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];
|
export type ModuleName = (typeof MODULE_NAMES)[number];
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,6 @@ import { ExecutionEntity } from './execution-entity';
|
|||||||
import { ExecutionMetadata } from './execution-metadata';
|
import { ExecutionMetadata } from './execution-metadata';
|
||||||
import { Folder } from './folder';
|
import { Folder } from './folder';
|
||||||
import { FolderTagMapping } from './folder-tag-mapping';
|
import { FolderTagMapping } from './folder-tag-mapping';
|
||||||
import { InstalledNodes } from './installed-nodes';
|
|
||||||
import { InstalledPackages } from './installed-packages';
|
|
||||||
import { InvalidAuthToken } from './invalid-auth-token';
|
import { InvalidAuthToken } from './invalid-auth-token';
|
||||||
import { ProcessedData } from './processed-data';
|
import { ProcessedData } from './processed-data';
|
||||||
import { Project } from './project';
|
import { Project } from './project';
|
||||||
@@ -35,8 +33,6 @@ import { WorkflowTagMapping } from './workflow-tag-mapping';
|
|||||||
|
|
||||||
export {
|
export {
|
||||||
EventDestinations,
|
EventDestinations,
|
||||||
InstalledNodes,
|
|
||||||
InstalledPackages,
|
|
||||||
InvalidAuthToken,
|
InvalidAuthToken,
|
||||||
ProcessedData,
|
ProcessedData,
|
||||||
Settings,
|
Settings,
|
||||||
@@ -72,8 +68,6 @@ export {
|
|||||||
|
|
||||||
export const entities = {
|
export const entities = {
|
||||||
EventDestinations,
|
EventDestinations,
|
||||||
InstalledNodes,
|
|
||||||
InstalledPackages,
|
|
||||||
InvalidAuthToken,
|
InvalidAuthToken,
|
||||||
ProcessedData,
|
ProcessedData,
|
||||||
Settings,
|
Settings,
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ export { EventDestinationsRepository } from './event-destinations.repository';
|
|||||||
export { FolderRepository } from './folder.repository';
|
export { FolderRepository } from './folder.repository';
|
||||||
export { FolderTagMappingRepository } from './folder-tag-mapping.repository';
|
export { FolderTagMappingRepository } from './folder-tag-mapping.repository';
|
||||||
export { ScopeRepository } from './scope.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 { InvalidAuthTokenRepository } from './invalid-auth-token.repository';
|
||||||
export { LicenseMetricsRepository } from './license-metrics.repository';
|
export { LicenseMetricsRepository } from './license-metrics.repository';
|
||||||
export { ProjectRelationRepository } from './project-relation.repository';
|
export { ProjectRelationRepository } from './project-relation.repository';
|
||||||
|
|||||||
@@ -33,10 +33,10 @@ export interface ModuleInterface {
|
|||||||
settings?(): Promise<ModuleSettings>;
|
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'
|
* @example '/Users/nathan/.n8n/nodes/node_modules'
|
||||||
*/
|
*/
|
||||||
loadDir?(): string;
|
loadDir?(): Promise<string | null>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ModuleClass = Constructable<ModuleInterface>;
|
export type ModuleClass = Constructable<ModuleInterface>;
|
||||||
|
|||||||
@@ -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 { 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', () => {
|
describe('uninstallCredential', () => {
|
||||||
const userId = '1234';
|
const userId = '1234';
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ import { mock } from 'jest-mock-extended';
|
|||||||
import type { IRun } from 'n8n-workflow';
|
import type { IRun } from 'n8n-workflow';
|
||||||
|
|
||||||
import { ActiveExecutions } from '@/active-executions';
|
import { ActiveExecutions } from '@/active-executions';
|
||||||
import { CommunityPackagesService } from '@/community-packages/community-packages.service';
|
|
||||||
import { DeprecationService } from '@/deprecation/deprecation.service';
|
import { DeprecationService } from '@/deprecation/deprecation.service';
|
||||||
import { MessageEventBus } from '@/eventbus/message-event-bus/message-event-bus';
|
import { MessageEventBus } from '@/eventbus/message-event-bus/message-event-bus';
|
||||||
import { TelemetryEventRelay } from '@/events/relays/telemetry.event-relay';
|
import { TelemetryEventRelay } from '@/events/relays/telemetry.event-relay';
|
||||||
import { ExternalHooks } from '@/external-hooks';
|
import { ExternalHooks } from '@/external-hooks';
|
||||||
import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
|
import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
|
||||||
|
import { CommunityPackagesService } from '@/modules/community-packages/community-packages.service';
|
||||||
import { PostHogClient } from '@/posthog';
|
import { PostHogClient } from '@/posthog';
|
||||||
import { OwnershipService } from '@/services/ownership.service';
|
import { OwnershipService } from '@/services/ownership.service';
|
||||||
import { ShutdownService } from '@/shutdown/shutdown.service';
|
import { ShutdownService } from '@/shutdown/shutdown.service';
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ import { mock } from 'jest-mock-extended';
|
|||||||
import type { IRun } from 'n8n-workflow';
|
import type { IRun } from 'n8n-workflow';
|
||||||
|
|
||||||
import { ActiveExecutions } from '@/active-executions';
|
import { ActiveExecutions } from '@/active-executions';
|
||||||
import { CommunityPackagesService } from '@/community-packages/community-packages.service';
|
|
||||||
import { DeprecationService } from '@/deprecation/deprecation.service';
|
import { DeprecationService } from '@/deprecation/deprecation.service';
|
||||||
import { MessageEventBus } from '@/eventbus/message-event-bus/message-event-bus';
|
import { MessageEventBus } from '@/eventbus/message-event-bus/message-event-bus';
|
||||||
import { TelemetryEventRelay } from '@/events/relays/telemetry.event-relay';
|
import { TelemetryEventRelay } from '@/events/relays/telemetry.event-relay';
|
||||||
import { ExternalHooks } from '@/external-hooks';
|
import { ExternalHooks } from '@/external-hooks';
|
||||||
import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
|
import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
|
||||||
|
import { CommunityPackagesService } from '@/modules/community-packages/community-packages.service';
|
||||||
import { PostHogClient } from '@/posthog';
|
import { PostHogClient } from '@/posthog';
|
||||||
import { OwnershipService } from '@/services/ownership.service';
|
import { OwnershipService } from '@/services/ownership.service';
|
||||||
import { ShutdownService } from '@/shutdown/shutdown.service';
|
import { ShutdownService } from '@/shutdown/shutdown.service';
|
||||||
|
|||||||
@@ -33,11 +33,11 @@ import { TelemetryEventRelay } from '@/events/relays/telemetry.event-relay';
|
|||||||
import { ExternalHooks } from '@/external-hooks';
|
import { ExternalHooks } from '@/external-hooks';
|
||||||
import { License } from '@/license';
|
import { License } from '@/license';
|
||||||
import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
|
import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
|
||||||
|
import { CommunityPackagesConfig } from '@/modules/community-packages/community-packages.config';
|
||||||
import { NodeTypes } from '@/node-types';
|
import { NodeTypes } from '@/node-types';
|
||||||
import { PostHogClient } from '@/posthog';
|
import { PostHogClient } from '@/posthog';
|
||||||
import { ShutdownService } from '@/shutdown/shutdown.service';
|
import { ShutdownService } from '@/shutdown/shutdown.service';
|
||||||
import { WorkflowHistoryManager } from '@/workflows/workflow-history.ee/workflow-history-manager.ee';
|
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> {
|
export abstract class BaseCommand<F = never> {
|
||||||
readonly flags: F;
|
readonly flags: F;
|
||||||
@@ -133,10 +133,11 @@ export abstract class BaseCommand<F = never> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @TODO: Move to community-packages module
|
||||||
const communityPackagesConfig = Container.get(CommunityPackagesConfig);
|
const communityPackagesConfig = Container.get(CommunityPackagesConfig);
|
||||||
if (communityPackagesConfig.enabled && this.needsCommunityPackages) {
|
if (communityPackagesConfig.enabled && this.needsCommunityPackages) {
|
||||||
const { CommunityPackagesService } = await import(
|
const { CommunityPackagesService } = await import(
|
||||||
'@/community-packages/community-packages.service'
|
'@/modules/community-packages/community-packages.service'
|
||||||
);
|
);
|
||||||
await Container.get(CommunityPackagesService).init();
|
await Container.get(CommunityPackagesService).init();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,8 +30,6 @@ import { deepCopy, NodeConnectionTypes, UnexpectedError, UserError } from 'n8n-w
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
import picocolors from 'picocolors';
|
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';
|
import { CUSTOM_API_CALL_KEY, CUSTOM_API_CALL_NAME, CLI_DIR, inE2ETests } from '@/constants';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
@@ -91,14 +89,6 @@ export class LoadNodesAndCredentials {
|
|||||||
await this.loadNodesFromNodeModules(nodeModulesDir, '@n8n/n8n-nodes-langchain');
|
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) {
|
for (const dir of this.moduleRegistry.loadDirs) {
|
||||||
await this.loadNodesFromNodeModules(dir);
|
await this.loadNodesFromNodeModules(dir);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import type { CommunityNodeType } from '@n8n/api-types';
|
import type { CommunityNodeType } from '@n8n/api-types';
|
||||||
import type { InstalledPackages } from '@n8n/db';
|
|
||||||
import { mock } from 'jest-mock-extended';
|
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 { NodeRequest } from '@/requests';
|
||||||
|
|
||||||
import type { EventService } from '../../events/event.service';
|
import type { EventService } from '../../../events/event.service';
|
||||||
import type { Push } from '../../push';
|
import type { Push } from '../../../push';
|
||||||
import type { CommunityNodeTypesService } from '../community-node-types.service';
|
import type { CommunityNodeTypesService } from '../community-node-types.service';
|
||||||
import type { CommunityPackagesService } from '../community-packages.service';
|
import type { CommunityPackagesService } from '../community-packages.service';
|
||||||
|
import type { InstalledPackages } from '../installed-packages.entity';
|
||||||
|
|
||||||
describe('CommunityPackagesController', () => {
|
describe('CommunityPackagesController', () => {
|
||||||
const push = mock<Push>();
|
const push = mock<Push>();
|
||||||
@@ -1,21 +1,30 @@
|
|||||||
import { mockInstance } from '@n8n/backend-test-utils';
|
import { mockInstance } from '@n8n/backend-test-utils';
|
||||||
import type { InstalledNodes, InstalledPackages } from '@n8n/db';
|
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
|
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 { COMMUNITY_PACKAGE_VERSION } from '../../../../test/integration/shared/constants';
|
||||||
import { createOwner } from './shared/db/users';
|
import { createOwner } from '../../../../test/integration/shared/db/users';
|
||||||
import type { SuperAgentTest } from './shared/types';
|
import type { SuperAgentTest } from '../../../../test/integration/shared/types';
|
||||||
import { setupTestServer, mockPackage, mockNode, mockPackageName } from './shared/utils';
|
import {
|
||||||
|
setupTestServer,
|
||||||
|
mockPackage,
|
||||||
|
mockNode,
|
||||||
|
mockPackageName,
|
||||||
|
} from '../../../../test/integration/shared/utils';
|
||||||
|
|
||||||
const communityPackagesService = mockInstance(CommunityPackagesService, {
|
const communityPackagesService = mockInstance(CommunityPackagesService, {
|
||||||
hasMissingPackages: false,
|
hasMissingPackages: false,
|
||||||
});
|
});
|
||||||
mockInstance(LoadNodesAndCredentials);
|
mockInstance(LoadNodesAndCredentials);
|
||||||
|
|
||||||
const testServer = setupTestServer({ endpointGroups: ['community-packages'] });
|
const testServer = setupTestServer({
|
||||||
|
endpointGroups: ['community-packages'],
|
||||||
|
modules: ['community-packages'],
|
||||||
|
});
|
||||||
|
|
||||||
const commonUpdatesProps = {
|
const commonUpdatesProps = {
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
@@ -1,22 +1,15 @@
|
|||||||
import type { Logger } from '@n8n/backend-common';
|
import type { Logger } from '@n8n/backend-common';
|
||||||
import { randomName, mockInstance } from '@n8n/backend-test-utils';
|
import { randomName, mockInstance } from '@n8n/backend-test-utils';
|
||||||
import { LICENSE_FEATURES } from '@n8n/constants';
|
import { LICENSE_FEATURES } from '@n8n/constants';
|
||||||
import {
|
|
||||||
InstalledNodes,
|
|
||||||
InstalledPackages,
|
|
||||||
InstalledNodesRepository,
|
|
||||||
InstalledPackagesRepository,
|
|
||||||
} from '@n8n/db';
|
|
||||||
import axios from 'axios';
|
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 { mocked } from 'jest-mock';
|
||||||
import { mock } from 'jest-mock-extended';
|
import { mock } from 'jest-mock-extended';
|
||||||
import type { InstanceSettings, PackageDirectoryLoader } from 'n8n-core';
|
import type { InstanceSettings, PackageDirectoryLoader } from 'n8n-core';
|
||||||
import type { PublicInstalledPackage } from 'n8n-workflow';
|
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 { join } from 'node:path';
|
||||||
|
|
||||||
import { CommunityPackagesService } from '@/community-packages/community-packages.service';
|
|
||||||
import {
|
import {
|
||||||
NODE_PACKAGE_PREFIX,
|
NODE_PACKAGE_PREFIX,
|
||||||
NPM_COMMAND_TOKENS,
|
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 { mockPackageName, mockPackagePair } from '@test-integration/utils';
|
||||||
|
|
||||||
import type { CommunityPackagesConfig } from '../community-packages.config';
|
import type { CommunityPackagesConfig } from '../community-packages.config';
|
||||||
|
import { CommunityPackagesService } from '../community-packages.service';
|
||||||
import type { CommunityPackages } from '../community-packages.types';
|
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('node:fs/promises');
|
||||||
jest.mock('child_process');
|
jest.mock('node:child_process');
|
||||||
jest.mock('axios');
|
jest.mock('axios');
|
||||||
|
|
||||||
type ExecOptions = NonNullable<Parameters<typeof exec>[1]>;
|
type ExecOptions = NonNullable<Parameters<typeof exec>[1]>;
|
||||||
@@ -2,7 +2,7 @@ import type { CommunityNodeType } from '@n8n/api-types';
|
|||||||
import { Get, RestController } from '@n8n/decorators';
|
import { Get, RestController } from '@n8n/decorators';
|
||||||
import { Request } from 'express';
|
import { Request } from 'express';
|
||||||
|
|
||||||
import { CommunityNodeTypesService } from '@/community-packages/community-node-types.service';
|
import { CommunityNodeTypesService } from './community-node-types.service';
|
||||||
|
|
||||||
@RestController('/community-node-types')
|
@RestController('/community-node-types')
|
||||||
export class CommunityNodeTypesController {
|
export class CommunityNodeTypesController {
|
||||||
@@ -3,9 +3,8 @@ import { Logger, inProduction } from '@n8n/backend-common';
|
|||||||
import { Service } from '@n8n/di';
|
import { Service } from '@n8n/di';
|
||||||
import { ensureError } from 'n8n-workflow';
|
import { ensureError } from 'n8n-workflow';
|
||||||
|
|
||||||
import { CommunityPackagesConfig } from '@/community-packages/community-packages.config';
|
|
||||||
|
|
||||||
import { getCommunityNodeTypes, StrapiCommunityNodeType } from './community-node-types-utils';
|
import { getCommunityNodeTypes, StrapiCommunityNodeType } from './community-node-types-utils';
|
||||||
|
import { CommunityPackagesConfig } from './community-packages.config';
|
||||||
import { CommunityPackagesService } from './community-packages.service';
|
import { CommunityPackagesService } from './community-packages.service';
|
||||||
|
|
||||||
const UPDATE_INTERVAL = 8 * 60 * 60 * 1000;
|
const UPDATE_INTERVAL = 8 * 60 * 60 * 1000;
|
||||||
@@ -1,13 +1,16 @@
|
|||||||
import { type InstalledNodes, type InstalledPackages, type User } from '@n8n/db';
|
import type { User } from '@n8n/db';
|
||||||
import { CredentialsRepository, InstalledNodesRepository, UserRepository } from '@n8n/db';
|
import { CredentialsRepository, UserRepository } from '@n8n/db';
|
||||||
import { Command } from '@n8n/decorators';
|
import { Command } from '@n8n/decorators';
|
||||||
import { Container } from '@n8n/di';
|
import { Container } from '@n8n/di';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
import { BaseCommand } from '@/commands/base-command';
|
||||||
import { CredentialsService } from '@/credentials/credentials.service';
|
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({
|
const flagsSchema = z.object({
|
||||||
uninstall: z.boolean().describe('Uninstalls the node').optional(),
|
uninstall: z.boolean().describe('Uninstalls the node').optional(),
|
||||||
@@ -1,21 +1,21 @@
|
|||||||
|
import { Delete, Get, Patch, Post, RestController, GlobalScope } from '@n8n/decorators';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
RESPONSE_ERROR_MESSAGES,
|
RESPONSE_ERROR_MESSAGES,
|
||||||
STARTER_TEMPLATE_NAME,
|
STARTER_TEMPLATE_NAME,
|
||||||
UNKNOWN_FAILURE_REASON,
|
UNKNOWN_FAILURE_REASON,
|
||||||
} from '@/constants';
|
} 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 { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
import { InternalServerError } from '@/errors/response-errors/internal-server.error';
|
import { InternalServerError } from '@/errors/response-errors/internal-server.error';
|
||||||
import { EventService } from '@/events/event.service';
|
import { EventService } from '@/events/event.service';
|
||||||
import { Push } from '@/push';
|
import { Push } from '@/push';
|
||||||
import { NodeRequest } from '@/requests';
|
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 {
|
const {
|
||||||
PACKAGE_NOT_INSTALLED,
|
PACKAGE_NOT_INSTALLED,
|
||||||
PACKAGE_NAME_NOT_PROVIDED,
|
PACKAGE_NAME_NOT_PROVIDED,
|
||||||
@@ -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');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,17 +1,15 @@
|
|||||||
import { Logger } from '@n8n/backend-common';
|
import { Logger } from '@n8n/backend-common';
|
||||||
import { LICENSE_FEATURES } from '@n8n/constants';
|
import { LICENSE_FEATURES } from '@n8n/constants';
|
||||||
import type { InstalledPackages } from '@n8n/db';
|
|
||||||
import { InstalledPackagesRepository } from '@n8n/db';
|
|
||||||
import { OnPubSubEvent } from '@n8n/decorators';
|
import { OnPubSubEvent } from '@n8n/decorators';
|
||||||
import { Service } from '@n8n/di';
|
import { Service } from '@n8n/di';
|
||||||
import axios from 'axios';
|
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 type { PackageDirectoryLoader } from 'n8n-core';
|
||||||
import { InstanceSettings } from 'n8n-core';
|
import { InstanceSettings } from 'n8n-core';
|
||||||
import { jsonParse, UnexpectedError, UserError, type PublicInstalledPackage } from 'n8n-workflow';
|
import { jsonParse, UnexpectedError, UserError, type PublicInstalledPackage } from 'n8n-workflow';
|
||||||
import { join } from 'path';
|
import { exec } from 'node:child_process';
|
||||||
import { promisify } from 'util';
|
import { access, constants, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import { promisify } from 'node:util';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
NODE_PACKAGE_PREFIX,
|
NODE_PACKAGE_PREFIX,
|
||||||
@@ -28,6 +26,8 @@ import { toError } from '@/utils';
|
|||||||
|
|
||||||
import { CommunityPackagesConfig } from './community-packages.config';
|
import { CommunityPackagesConfig } from './community-packages.config';
|
||||||
import type { CommunityPackages } from './community-packages.types';
|
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';
|
import { isVersionExists, verifyIntegrity } from './npm-utils';
|
||||||
|
|
||||||
const DEFAULT_REGISTRY = 'https://registry.npmjs.org';
|
const DEFAULT_REGISTRY = 'https://registry.npmjs.org';
|
||||||
@@ -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()
|
@Entity()
|
||||||
export class InstalledNodes {
|
export class InstalledNodes extends BaseEntity {
|
||||||
@Column()
|
@Column()
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Service } from '@n8n/di';
|
import { Service } from '@n8n/di';
|
||||||
import { DataSource, Repository } from '@n8n/typeorm';
|
import { DataSource, Repository } from '@n8n/typeorm';
|
||||||
|
|
||||||
import { InstalledNodes } from '../entities';
|
import { InstalledNodes } from './installed-nodes.entity';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class InstalledNodesRepository extends Repository<InstalledNodes> {
|
export class InstalledNodesRepository extends Repository<InstalledNodes> {
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
|
import { WithTimestamps } from '@n8n/db';
|
||||||
import { Column, Entity, JoinColumn, OneToMany, PrimaryColumn } from '@n8n/typeorm';
|
import { Column, Entity, JoinColumn, OneToMany, PrimaryColumn } from '@n8n/typeorm';
|
||||||
|
|
||||||
import { WithTimestamps } from './abstract-entity';
|
import type { InstalledNodes } from './installed-nodes.entity';
|
||||||
import type { InstalledNodes } from './installed-nodes';
|
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class InstalledPackages extends WithTimestamps {
|
export class InstalledPackages extends WithTimestamps {
|
||||||
@@ -3,7 +3,7 @@ import { DataSource, Repository } from '@n8n/typeorm';
|
|||||||
import type { PackageDirectoryLoader } from 'n8n-core';
|
import type { PackageDirectoryLoader } from 'n8n-core';
|
||||||
|
|
||||||
import { InstalledNodesRepository } from './installed-nodes.repository';
|
import { InstalledNodesRepository } from './installed-nodes.repository';
|
||||||
import { InstalledPackages } from '../entities';
|
import { InstalledPackages } from './installed-packages.entity';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class InstalledPackagesRepository extends Repository<InstalledPackages> {
|
export class InstalledPackagesRepository extends Repository<InstalledPackages> {
|
||||||
@@ -7,6 +7,7 @@ import { InstanceSettings } from 'n8n-core';
|
|||||||
import type { IWorkflowBase } from 'n8n-workflow';
|
import type { IWorkflowBase } from 'n8n-workflow';
|
||||||
|
|
||||||
import { N8N_VERSION } from '@/constants';
|
import { N8N_VERSION } from '@/constants';
|
||||||
|
import { CommunityPackagesConfig } from '@/modules/community-packages/community-packages.config';
|
||||||
import { isApiEnabled } from '@/public-api';
|
import { isApiEnabled } from '@/public-api';
|
||||||
import {
|
import {
|
||||||
ENV_VARS_DOCS_URL,
|
ENV_VARS_DOCS_URL,
|
||||||
@@ -16,7 +17,6 @@ import {
|
|||||||
} from '@/security-audit/constants';
|
} from '@/security-audit/constants';
|
||||||
import type { RiskReporter, Risk, n8n } from '@/security-audit/types';
|
import type { RiskReporter, Risk, n8n } from '@/security-audit/types';
|
||||||
import { toFlaggedNode } from '@/security-audit/utils';
|
import { toFlaggedNode } from '@/security-audit/utils';
|
||||||
import { CommunityPackagesConfig } from '@/community-packages/community-packages.config';
|
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class InstanceRiskReporter implements RiskReporter {
|
export class InstanceRiskReporter implements RiskReporter {
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { InstalledPackages } from '@n8n/db';
|
|
||||||
import { Service } from '@n8n/di';
|
import { Service } from '@n8n/di';
|
||||||
// eslint-disable-next-line n8n-local-rules/misplaced-n8n-typeorm-import
|
// eslint-disable-next-line n8n-local-rules/misplaced-n8n-typeorm-import
|
||||||
import { DataSource, Repository } from '@n8n/typeorm';
|
import { DataSource, Repository } from '@n8n/typeorm';
|
||||||
|
|
||||||
|
import { InstalledPackages } from '@/modules/community-packages/installed-packages.entity';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class PackagesRepository extends Repository<InstalledPackages> {
|
export class PackagesRepository extends Repository<InstalledPackages> {
|
||||||
constructor(dataSource: DataSource) {
|
constructor(dataSource: DataSource) {
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ import '@/webhooks/webhooks.controller';
|
|||||||
|
|
||||||
import { ChatServer } from './chat/chat-server';
|
import { ChatServer } from './chat/chat-server';
|
||||||
import { MfaService } from './mfa/mfa.service';
|
import { MfaService } from './mfa/mfa.service';
|
||||||
import { CommunityPackagesConfig } from './community-packages/community-packages.config';
|
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class Server extends AbstractServer {
|
export class Server extends AbstractServer {
|
||||||
@@ -119,11 +118,6 @@ export class Server extends AbstractServer {
|
|||||||
await Container.get(LdapService).init();
|
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) {
|
if (inE2ETests) {
|
||||||
await import('@/controllers/e2e.controller');
|
await import('@/controllers/e2e.controller');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { Logger, LicenseState, ModuleRegistry } from '@n8n/backend-common';
|
import type { Logger, LicenseState, ModuleRegistry } from '@n8n/backend-common';
|
||||||
import type { GlobalConfig, SecurityConfig } from '@n8n/config';
|
import type { GlobalConfig, SecurityConfig } from '@n8n/config';
|
||||||
|
import { Container } from '@n8n/di';
|
||||||
import { mock } from 'jest-mock-extended';
|
import { mock } from 'jest-mock-extended';
|
||||||
import type { InstanceSettings, BinaryDataConfig } from 'n8n-core';
|
import type { InstanceSettings, BinaryDataConfig } from 'n8n-core';
|
||||||
|
|
||||||
@@ -8,12 +9,11 @@ import type { CredentialsOverwrites } from '@/credentials-overwrites';
|
|||||||
import type { License } from '@/license';
|
import type { License } from '@/license';
|
||||||
import type { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
|
import type { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
|
||||||
import type { MfaService } from '@/mfa/mfa.service';
|
import type { MfaService } from '@/mfa/mfa.service';
|
||||||
|
import { CommunityPackagesConfig } from '@/modules/community-packages/community-packages.config';
|
||||||
import type { PushConfig } from '@/push/push.config';
|
import type { PushConfig } from '@/push/push.config';
|
||||||
import { FrontendService } from '@/services/frontend.service';
|
import { FrontendService } from '@/services/frontend.service';
|
||||||
import type { UrlService } from '@/services/url.service';
|
import type { UrlService } from '@/services/url.service';
|
||||||
import type { UserManagementMailer } from '@/user-management/email';
|
import type { UserManagementMailer } from '@/user-management/email';
|
||||||
import { CommunityPackagesConfig } from '@/community-packages/community-packages.config';
|
|
||||||
import { Container } from '@n8n/di';
|
|
||||||
|
|
||||||
describe('FrontendService', () => {
|
describe('FrontendService', () => {
|
||||||
let originalEnv: NodeJS.ProcessEnv;
|
let originalEnv: NodeJS.ProcessEnv;
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ import { BinaryDataConfig, InstanceSettings } from 'n8n-core';
|
|||||||
import type { ICredentialType, INodeTypeBaseDescription } from 'n8n-workflow';
|
import type { ICredentialType, INodeTypeBaseDescription } from 'n8n-workflow';
|
||||||
import path from 'path';
|
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 config from '@/config';
|
||||||
import { inE2ETests, N8N_VERSION } from '@/constants';
|
import { inE2ETests, N8N_VERSION } from '@/constants';
|
||||||
import { CredentialTypes } from '@/credential-types';
|
import { CredentialTypes } from '@/credential-types';
|
||||||
@@ -20,6 +18,8 @@ import { getLdapLoginLabel } from '@/ldap.ee/helpers.ee';
|
|||||||
import { License } from '@/license';
|
import { License } from '@/license';
|
||||||
import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
|
import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
|
||||||
import { MfaService } from '@/mfa/mfa.service';
|
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 { isApiEnabled } from '@/public-api';
|
||||||
import { PushConfig } from '@/push/push.config';
|
import { PushConfig } from '@/push/push.config';
|
||||||
import { getSamlLoginLabel } from '@/sso.ee/saml/saml-helpers';
|
import { getSamlLoginLabel } from '@/sso.ee/saml/saml-helpers';
|
||||||
@@ -60,8 +60,9 @@ export class FrontendService {
|
|||||||
|
|
||||||
this.initSettings();
|
this.initSettings();
|
||||||
|
|
||||||
|
// @TODO: Move to community-packages module
|
||||||
if (Container.get(CommunityPackagesConfig).enabled) {
|
if (Container.get(CommunityPackagesConfig).enabled) {
|
||||||
void import('@/community-packages/community-packages.service').then(
|
void import('@/modules/community-packages/community-packages.service').then(
|
||||||
({ CommunityPackagesService }) => {
|
({ CommunityPackagesService }) => {
|
||||||
this.communityPackagesService = Container.get(CommunityPackagesService);
|
this.communityPackagesService = Container.get(CommunityPackagesService);
|
||||||
},
|
},
|
||||||
@@ -200,8 +201,11 @@ export class FrontendService {
|
|||||||
executionMode: config.getEnv('executions.mode'),
|
executionMode: config.getEnv('executions.mode'),
|
||||||
isMultiMain: this.instanceSettings.isMultiMain,
|
isMultiMain: this.instanceSettings.isMultiMain,
|
||||||
pushBackend: this.pushConfig.backend,
|
pushBackend: this.pushConfig.backend,
|
||||||
|
|
||||||
|
// @TODO: Move to community-packages module
|
||||||
communityNodesEnabled: Container.get(CommunityPackagesConfig).enabled,
|
communityNodesEnabled: Container.get(CommunityPackagesConfig).enabled,
|
||||||
unverifiedCommunityNodesEnabled: Container.get(CommunityPackagesConfig).unverifiedEnabled,
|
unverifiedCommunityNodesEnabled: Container.get(CommunityPackagesConfig).unverifiedEnabled,
|
||||||
|
|
||||||
deployment: {
|
deployment: {
|
||||||
type: this.globalConfig.deployment.type,
|
type: this.globalConfig.deployment.type,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -12,11 +12,11 @@ import { LogStreamingEventRelay } from '@/events/relays/log-streaming.event-rela
|
|||||||
import { ExternalHooks } from '@/external-hooks';
|
import { ExternalHooks } from '@/external-hooks';
|
||||||
import { License } from '@/license';
|
import { License } from '@/license';
|
||||||
import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
|
import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
|
||||||
|
import { CommunityPackagesService } from '@/modules/community-packages/community-packages.service';
|
||||||
import { Push } from '@/push';
|
import { Push } from '@/push';
|
||||||
import { Publisher } from '@/scaling/pubsub/publisher.service';
|
import { Publisher } from '@/scaling/pubsub/publisher.service';
|
||||||
import { Subscriber } from '@/scaling/pubsub/subscriber.service';
|
import { Subscriber } from '@/scaling/pubsub/subscriber.service';
|
||||||
import { ScalingService } from '@/scaling/scaling.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 { TaskBrokerServer } from '@/task-runners/task-broker/task-broker-server';
|
||||||
import { TaskRunnerProcess } from '@/task-runners/task-runner-process';
|
import { TaskRunnerProcess } from '@/task-runners/task-runner-process';
|
||||||
import { Telemetry } from '@/telemetry';
|
import { Telemetry } from '@/telemetry';
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ import { mock } from 'jest-mock-extended';
|
|||||||
import { v4 as uuid } from 'uuid';
|
import { v4 as uuid } from 'uuid';
|
||||||
|
|
||||||
import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
|
import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
|
||||||
|
import { CommunityPackagesService } from '@/modules/community-packages/community-packages.service';
|
||||||
import { NodeTypes } from '@/node-types';
|
import { NodeTypes } from '@/node-types';
|
||||||
import { OFFICIAL_RISKY_NODE_TYPES, NODES_REPORT } from '@/security-audit/constants';
|
import { OFFICIAL_RISKY_NODE_TYPES, NODES_REPORT } from '@/security-audit/constants';
|
||||||
import { PackagesRepository } from '@/security-audit/security-audit.repository';
|
import { PackagesRepository } from '@/security-audit/security-audit.repository';
|
||||||
import { SecurityAuditService } from '@/security-audit/security-audit.service';
|
import { SecurityAuditService } from '@/security-audit/security-audit.service';
|
||||||
import { toReportTitle } from '@/security-audit/utils';
|
import { toReportTitle } from '@/security-audit/utils';
|
||||||
import { CommunityPackagesService } from '@/community-packages/community-packages.service';
|
|
||||||
|
|
||||||
import { getRiskSection, MOCK_PACKAGE, saveManualTriggerWorkflow } from './utils';
|
import { getRiskSection, MOCK_PACKAGE, saveManualTriggerWorkflow } from './utils';
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import { GlobalConfig } from '@n8n/config';
|
import { GlobalConfig } from '@n8n/config';
|
||||||
import type { InstalledNodes, InstalledPackages } from '@n8n/db';
|
|
||||||
import { WorkflowRepository } from '@n8n/db';
|
import { WorkflowRepository } from '@n8n/db';
|
||||||
import { Container } from '@n8n/di';
|
import { Container } from '@n8n/di';
|
||||||
import nock from 'nock';
|
import nock from 'nock';
|
||||||
import { v4 as uuid } from 'uuid';
|
import { v4 as uuid } from 'uuid';
|
||||||
|
|
||||||
import * as constants from '@/constants';
|
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 type { Risk } from '@/security-audit/types';
|
||||||
import { toReportTitle } from '@/security-audit/utils';
|
import { toReportTitle } from '@/security-audit/utils';
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ type EndpointGroup =
|
|||||||
| 'data-store'
|
| 'data-store'
|
||||||
| 'module-settings';
|
| 'module-settings';
|
||||||
|
|
||||||
type ModuleName = 'insights' | 'external-secrets' | 'data-store';
|
type ModuleName = 'insights' | 'external-secrets' | 'community-packages' | 'data-store';
|
||||||
|
|
||||||
export interface SetupProps {
|
export interface SetupProps {
|
||||||
endpointGroups?: EndpointGroup[];
|
endpointGroups?: EndpointGroup[];
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import { randomName } from '@n8n/backend-test-utils';
|
import { randomName } from '@n8n/backend-test-utils';
|
||||||
import { InstalledPackages, InstalledNodesRepository, InstalledPackagesRepository } from '@n8n/db';
|
|
||||||
import { Container } from '@n8n/di';
|
import { Container } from '@n8n/di';
|
||||||
|
|
||||||
import { NODE_PACKAGE_PREFIX } from '@/constants';
|
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';
|
import { COMMUNITY_NODE_VERSION, COMMUNITY_PACKAGE_VERSION } from '../constants';
|
||||||
|
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ export const setupTestServer = ({
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'community-packages':
|
case 'community-packages':
|
||||||
await import('@/community-packages/community-packages.controller');
|
await import('@/modules/community-packages/community-packages.controller');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'me':
|
case 'me':
|
||||||
|
|||||||
Reference in New Issue
Block a user