refactor(core): Split out database types (#14942)

This commit is contained in:
Iván Ovejero
2025-04-28 16:15:20 +02:00
committed by GitHub
parent 97055d5714
commit 70b93f2f53
56 changed files with 207 additions and 200 deletions

View File

@@ -6,10 +6,10 @@ import { createDeferredPromise } from 'n8n-workflow';
import type { ActiveExecutions } from '@/active-executions';
import type { Project } from '@/databases/entities/project';
import type { ExecutionRepository } from '@/databases/repositories/execution.repository';
import type { IExecutionResponse } from '@/interfaces';
import type { MultiMainSetup } from '@/scaling/multi-main-setup.ee';
import { OrchestrationService } from '@/services/orchestration.service';
import type { OwnershipService } from '@/services/ownership.service';
import type { IExecutionResponse } from '@/types-db';
import { WaitTracker } from '@/wait-tracker';
import type { WorkflowRunner } from '@/workflow-runner';
import { mockLogger } from '@test/mocking';

View File

@@ -46,11 +46,11 @@ import { WorkflowRepository } from '@/databases/repositories/workflow.repository
import { executeErrorWorkflow } from '@/execution-lifecycle/execute-error-workflow';
import { ExecutionService } from '@/executions/execution.service';
import { ExternalHooks } from '@/external-hooks';
import type { IWorkflowDb } from '@/interfaces';
import { NodeTypes } from '@/node-types';
import { Publisher } from '@/scaling/pubsub/publisher.service';
import { ActiveWorkflowsService } from '@/services/active-workflows.service';
import { OrchestrationService } from '@/services/orchestration.service';
import type { IWorkflowDb } from '@/types-db';
import * as WebhookHelpers from '@/webhooks/webhook-helpers';
import { WebhookService } from '@/webhooks/webhook.service';
import * as WorkflowExecuteAdditionalData from '@/workflow-execute-additional-data';

View File

@@ -6,7 +6,8 @@ import { UserError } from 'n8n-workflow';
import path from 'path';
import { CredentialsRepository } from '@/databases/repositories/credentials.repository';
import type { ICredentialsDb, ICredentialsDecryptedDb } from '@/interfaces';
import type { ICredentialsDecryptedDb } from '@/interfaces';
import type { ICredentialsDb } from '@/types-db';
import { BaseCommand } from '../base-command';

View File

@@ -14,11 +14,11 @@ import { BadRequestError } from '@/errors/response-errors/bad-request.error';
import { InvalidMfaCodeError } from '@/errors/response-errors/invalid-mfa-code.error';
import { EventService } from '@/events/event.service';
import { ExternalHooks } from '@/external-hooks';
import type { PublicUser } from '@/interfaces';
import { License } from '@/license';
import { MfaService } from '@/mfa/mfa.service';
import type { AuthenticatedRequest, MeRequest } from '@/requests';
import { UserService } from '@/services/user.service';
import type { PublicUser } from '@/types-db';
import { mockInstance } from '@test/mocking';
import { badPasswords } from '@test/test-data';

View File

@@ -11,10 +11,10 @@ import type { SettingsRepository } from '@/databases/repositories/settings.repos
import type { UserRepository } from '@/databases/repositories/user.repository';
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
import type { EventService } from '@/events/event.service';
import type { PublicUser } from '@/interfaces';
import type { AuthenticatedRequest } from '@/requests';
import type { PasswordUtility } from '@/services/password.utility';
import type { UserService } from '@/services/user.service';
import type { PublicUser } from '@/types-db';
describe('OwnerController', () => {
const configGetSpy = jest.spyOn(config, 'getEnv');

View File

@@ -13,7 +13,6 @@ import { AuthError } from '@/errors/response-errors/auth.error';
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
import { ForbiddenError } from '@/errors/response-errors/forbidden.error';
import { EventService } from '@/events/event.service';
import type { PublicUser } from '@/interfaces';
import { License } from '@/license';
import { MfaService } from '@/mfa/mfa.service';
import { PostHogClient } from '@/posthog';
@@ -24,6 +23,7 @@ import {
isLdapCurrentAuthenticationMethod,
isSamlCurrentAuthenticationMethod,
} from '@/sso.ee/sso-helpers';
import type { PublicUser } from '@/types-db';
@RestController()
export class AuthController {

View File

@@ -17,12 +17,12 @@ import { InvalidMfaCodeError } from '@/errors/response-errors/invalid-mfa-code.e
import { EventService } from '@/events/event.service';
import { ExternalHooks } from '@/external-hooks';
import { validateEntity } from '@/generic-helpers';
import type { PublicUser } from '@/interfaces';
import { MfaService } from '@/mfa/mfa.service';
import { AuthenticatedRequest, MeRequest } from '@/requests';
import { PasswordUtility } from '@/services/password.utility';
import { UserService } from '@/services/user.service';
import { isSamlLicensedAndEnabled } from '@/sso.ee/saml/saml-helpers';
import type { PublicUser } from '@/types-db';
import { PersonalizationSurveyAnswersV4 } from './survey-answers.dto';
@RestController('/me')

View File

@@ -15,9 +15,9 @@ import { AuthError } from '@/errors/response-errors/auth.error';
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
import { NotFoundError } from '@/errors/response-errors/not-found.error';
import { ExternalHooks } from '@/external-hooks';
import type { ICredentialsDb } from '@/interfaces';
import type { AuthenticatedRequest, OAuthRequest } from '@/requests';
import { UrlService } from '@/services/url.service';
import type { ICredentialsDb } from '@/types-db';
import * as WorkflowExecuteAdditionalData from '@/workflow-execute-additional-data';
type CsrfStateParam = {

View File

@@ -26,12 +26,12 @@ import { ForbiddenError } from '@/errors/response-errors/forbidden.error';
import { NotFoundError } from '@/errors/response-errors/not-found.error';
import { EventService } from '@/events/event.service';
import { ExternalHooks } from '@/external-hooks';
import type { PublicUser } from '@/interfaces';
import { listQueryMiddleware } from '@/middlewares';
import { AuthenticatedRequest, ListQuery, UserRequest } from '@/requests';
import { FolderService } from '@/services/folder.service';
import { ProjectService } from '@/services/project.service.ee';
import { UserService } from '@/services/user.service';
import type { PublicUser } from '@/types-db';
import { WorkflowService } from '@/workflows/workflow.service';
@RestController('/users')

View File

@@ -33,7 +33,7 @@ import { CredentialsOverwrites } from '@/credentials-overwrites';
import type { CredentialsEntity } from '@/databases/entities/credentials-entity';
import { CredentialsRepository } from '@/databases/repositories/credentials.repository';
import { SharedCredentialsRepository } from '@/databases/repositories/shared-credentials.repository';
import type { ICredentialsDb } from '@/interfaces';
import type { ICredentialsDb } from '@/types-db';
import { RESPONSE_ERROR_MESSAGES } from './constants';
import { CredentialNotFoundError } from './errors/credential-not-found.error';

View File

@@ -32,7 +32,6 @@ import { BadRequestError } from '@/errors/response-errors/bad-request.error';
import { NotFoundError } from '@/errors/response-errors/not-found.error';
import { ExternalHooks } from '@/external-hooks';
import { validateEntity } from '@/generic-helpers';
import type { ICredentialsDb } from '@/interfaces';
import { userHasScopes } from '@/permissions.ee/check-access';
import type { CredentialRequest, ListQuery } from '@/requests';
import { CredentialsTester } from '@/services/credentials-tester.service';
@@ -40,6 +39,7 @@ import { OwnershipService } from '@/services/ownership.service';
import { ProjectService } from '@/services/project.service.ee';
import type { ScopesField } from '@/services/role.service';
import { RoleService } from '@/services/role.service';
import type { ICredentialsDb } from '@/types-db';
import { CredentialsFinderService } from './credentials-finder.service';

View File

@@ -1,7 +1,7 @@
import { Column, Entity, Index, OneToMany } from '@n8n/typeorm';
import { IsObject, IsString, Length } from 'class-validator';
import type { ICredentialsDb } from '@/interfaces';
import type { ICredentialsDb } from '@/types-db';
import { WithTimestampsAndStringId } from './abstract-entity';
import type { SharedCredentials } from './shared-credentials';

View File

@@ -13,12 +13,12 @@ import {
import { IsEmail, IsString, Length } from 'class-validator';
import type { IUser, IUserSettings } from 'n8n-workflow';
import type { IPersonalizationSurveyAnswers } from '@/interfaces';
import {
GLOBAL_OWNER_SCOPES,
GLOBAL_MEMBER_SCOPES,
GLOBAL_ADMIN_SCOPES,
} from '@/permissions.ee/global-roles';
import type { IPersonalizationSurveyAnswers } from '@/types-db';
import { NoUrl } from '@/validators/no-url.validator';
import { NoXss } from '@/validators/no-xss.validator';

View File

@@ -12,7 +12,7 @@ import { Length } from 'class-validator';
import { IConnections, IDataObject, IWorkflowSettings, WorkflowFEMeta } from 'n8n-workflow';
import type { IBinaryKeyData, INode, IPairedItemData } from 'n8n-workflow';
import type { IWorkflowDb } from '@/interfaces';
import type { IWorkflowDb } from '@/types-db';
import { WithTimestampsAndStringId, dbType, jsonColumnType } from './abstract-entity';
import { type Folder } from './folder';

View File

@@ -1,5 +1,5 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { UserSettings } from '@/interfaces';
import type { UserSettings } from '@/types-db';
export class AddUserActivatedProperty1681134145996 implements ReversibleMigration {
async up({ queryRunner, tablePrefix }: MigrationContext) {

View File

@@ -1,5 +1,5 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { UserSettings } from '@/interfaces';
import type { UserSettings } from '@/types-db';
export class AddUserActivatedProperty1681134145996 implements ReversibleMigration {
async up({ queryRunner, tablePrefix }: MigrationContext) {

View File

@@ -1,5 +1,5 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { UserSettings } from '@/interfaces';
import type { UserSettings } from '@/types-db';
export class AddUserActivatedProperty1681134145996 implements ReversibleMigration {
async up({ queryRunner, tablePrefix }: MigrationContext) {

View File

@@ -10,7 +10,7 @@ import { nanoid } from 'nanoid';
import { ExecutionEntity } from '@/databases/entities/execution-entity';
import { ExecutionRepository } from '@/databases/repositories/execution.repository';
import type { IExecutionResponse } from '@/interfaces';
import type { IExecutionResponse } from '@/types-db';
import { mockInstance, mockEntityManager } from '@test/mocking';
describe('ExecutionRepository', () => {

View File

@@ -36,12 +36,8 @@ import { AnnotationTagMapping } from '@/databases/entities/annotation-tag-mappin
import { ExecutionAnnotation } from '@/databases/entities/execution-annotation.ee';
import { PostgresLiveRowsRetrievalError } from '@/errors/postgres-live-rows-retrieval.error';
import type { ExecutionSummaries } from '@/executions/execution.types';
import type {
CreateExecutionPayload,
IExecutionBase,
IExecutionFlattedDb,
IExecutionResponse,
} from '@/interfaces';
import type { CreateExecutionPayload, IExecutionFlattedDb } from '@/interfaces';
import type { IExecutionBase, IExecutionResponse } from '@/types-db';
import { separate } from '@/utils';
import { ExecutionDataRepository } from './execution-data.repository';

View File

@@ -3,7 +3,7 @@ import type { EntityManager } from '@n8n/typeorm';
import { DataSource, In, Repository } from '@n8n/typeorm';
import intersection from 'lodash/intersection';
import type { IWorkflowDb } from '@/interfaces';
import type { IWorkflowDb } from '@/types-db';
import { TagEntity } from '../entities/tag-entity';

View File

@@ -14,7 +14,7 @@ import { SharedWorkflowRepository } from '@/databases/repositories/shared-workfl
import { TagRepository } from '@/databases/repositories/tag.repository';
import { WorkflowTagMappingRepository } from '@/databases/repositories/workflow-tag-mapping.repository';
import { WorkflowRepository } from '@/databases/repositories/workflow.repository';
import type { IWorkflowDb } from '@/interfaces';
import type { IWorkflowDb } from '@/types-db';
import { formatWorkflow } from '@/workflows/workflow.formatter';
import {

View File

@@ -1,7 +1,7 @@
import type { IWorkflowBase, JsonObject } from 'n8n-workflow';
import { EventMessageTypeNames } from 'n8n-workflow';
import type { IExecutionBase } from '@/interfaces';
import type { IExecutionBase } from '@/types-db';
import type { EventNamesWorkflowType } from '.';
import { AbstractEventMessage, isEventMessageOptionsWithType } from './abstract-event-message';

View File

@@ -5,7 +5,7 @@ import type { MessageEventBus } from '@/eventbus/message-event-bus/message-event
import { EventService } from '@/events/event.service';
import type { RelayEventMap } from '@/events/maps/relay.event-map';
import { LogStreamingEventRelay } from '@/events/relays/log-streaming.event-relay';
import type { IWorkflowDb } from '@/interfaces';
import type { IWorkflowDb } from '@/types-db';
describe('LogStreamingEventRelay', () => {
const eventBus = mock<MessageEventBus>();

View File

@@ -14,10 +14,10 @@ import type { WorkflowRepository } from '@/databases/repositories/workflow.repos
import { EventService } from '@/events/event.service';
import type { RelayEventMap } from '@/events/maps/relay.event-map';
import { TelemetryEventRelay } from '@/events/relays/telemetry.event-relay';
import type { IWorkflowDb } from '@/interfaces';
import type { License } from '@/license';
import type { NodeTypes } from '@/node-types';
import type { Telemetry } from '@/telemetry';
import type { IWorkflowDb } from '@/types-db';
import { mockInstance } from '@test/mocking';
const flushPromises = async () => await new Promise((resolve) => setImmediate(resolve));

View File

@@ -10,7 +10,7 @@ import type {
import type { ConcurrencyQueueType } from '@/concurrency/concurrency-control.service';
import type { AuthProviderType } from '@/databases/entities/auth-identity';
import type { User } from '@/databases/entities/user';
import type { IWorkflowDb } from '@/interfaces';
import type { IWorkflowDb } from '@/types-db';
import type { AiEventMap } from './ai.event-map';

View File

@@ -4,7 +4,7 @@ import { Logger } from 'n8n-core';
import type { IRunExecutionData, ITaskData } from 'n8n-workflow';
import { ExecutionRepository } from '@/databases/repositories/execution.repository';
import type { IExecutionResponse } from '@/interfaces';
import type { IExecutionResponse } from '@/types-db';
import { mockInstance } from '@test/mocking';
import { saveExecutionProgress } from '../save-execution-progress';

View File

@@ -9,9 +9,9 @@ import { AbortedExecutionRetryError } from '@/errors/aborted-execution-retry.err
import { MissingExecutionStopError } from '@/errors/missing-execution-stop.error';
import { ExecutionService } from '@/executions/execution.service';
import type { ExecutionRequest } from '@/executions/execution.types';
import type { IExecutionResponse } from '@/interfaces';
import { ScalingService } from '@/scaling/scaling.service';
import type { Job } from '@/scaling/scaling.types';
import type { IExecutionResponse } from '@/types-db';
import type { WaitTracker } from '@/wait-tracker';
import { mockInstance } from '@test/mocking';

View File

@@ -9,8 +9,8 @@ import { ExecutionRepository } from '@/databases/repositories/execution.reposito
import { NodeCrashedError } from '@/errors/node-crashed.error';
import { WorkflowCrashedError } from '@/errors/workflow-crashed.error';
import { getLifecycleHooksForRegularMain } from '@/execution-lifecycle/execution-lifecycle-hooks';
import type { IExecutionResponse } from '@/interfaces';
import { Push } from '@/push';
import type { IExecutionResponse } from '@/types-db';
import type { EventMessageTypes } from '../eventbus/event-message-classes';

View File

@@ -1,8 +1,8 @@
import { Service } from '@n8n/di';
import { WorkflowRepository } from '@/databases/repositories/workflow.repository';
import type { IExecutionResponse, IExecutionFlattedResponse } from '@/interfaces';
import type { WorkflowWithSharingsAndCredentials } from '@/workflows/workflows.types';
import type { IExecutionFlattedResponse } from '@/interfaces';
import type { WorkflowWithSharingsAndCredentials, IExecutionResponse } from '@/types-db';
import { ExecutionService } from './execution.service';
import type { ExecutionRequest } from './execution.types';

View File

@@ -33,13 +33,10 @@ import { MissingExecutionStopError } from '@/errors/missing-execution-stop.error
import { QueuedExecutionRetryError } from '@/errors/queued-execution-retry.error';
import { InternalServerError } from '@/errors/response-errors/internal-server.error';
import { NotFoundError } from '@/errors/response-errors/not-found.error';
import type {
CreateExecutionPayload,
IExecutionFlattedResponse,
IExecutionResponse,
} from '@/interfaces';
import type { CreateExecutionPayload, IExecutionFlattedResponse } from '@/interfaces';
import { License } from '@/license';
import { NodeTypes } from '@/node-types';
import type { IExecutionResponse } from '@/types-db';
import { WaitTracker } from '@/wait-tracker';
import { WorkflowRunner } from '@/workflow-runner';
import { WorkflowSharingService } from '@/workflows/workflow-sharing.service';

View File

@@ -15,7 +15,7 @@ import { CredentialsRepository } from '@/databases/repositories/credentials.repo
import { SettingsRepository } from '@/databases/repositories/settings.repository';
import { UserRepository } from '@/databases/repositories/user.repository';
import { WorkflowRepository } from '@/databases/repositories/workflow.repository';
import type { ICredentialsDb, PublicUser } from '@/interfaces';
import type { ICredentialsDb, PublicUser } from '@/types-db';
type Repositories = {
User: UserRepository;

View File

@@ -1,10 +1,9 @@
import type { AssignableRole, GlobalRole, Scope } from '@n8n/permissions';
import type { AssignableRole } from '@n8n/permissions';
import type { Application } from 'express';
import type {
ExecutionError,
ICredentialDataDecryptedObject,
ICredentialsDecrypted,
ICredentialsEncrypted,
IDeferredPromise,
IExecuteResponsePromiseData,
IRun,
@@ -15,8 +14,6 @@ import type {
WorkflowExecuteMode,
ExecutionStatus,
ExecutionSummary,
FeatureFlags,
IUserSettings,
IWorkflowExecutionDataProcess,
DeduplicationMode,
DeduplicationItemTypes,
@@ -24,15 +21,8 @@ import type {
import type PCancelable from 'p-cancelable';
import type { ActiveWorkflowManager } from '@/active-workflow-manager';
import type { AnnotationTagEntity } from '@/databases/entities/annotation-tag-entity.ee';
import type { AuthProviderType } from '@/databases/entities/auth-identity';
import type { SharedCredentials } from '@/databases/entities/shared-credentials';
import type { TagEntity } from '@/databases/entities/tag-entity';
import type { User } from '@/databases/entities/user';
import type { Folder } from './databases/entities/folder';
import type { ExternalHooks } from './external-hooks';
import type { WorkflowWithSharingsAndCredentials } from './workflows/workflows.types';
import type { ExternalHooks } from '@/external-hooks';
import type { ICredentialsBase, IExecutionBase, ITagBase } from '@/types-db';
export interface ICredentialsTypeData {
[key: string]: CredentialLoadingDetails;
@@ -60,39 +50,15 @@ export interface IProcessedDataEntries {
// tags
// ----------------------------------
export interface ITagBase {
id: string;
name: string;
}
export interface ITagToImport extends ITagBase {
createdAt?: string;
updatedAt?: string;
}
export type UsageCount = {
usageCount: number;
};
export type ITagDb = Pick<TagEntity, 'id' | 'name' | 'createdAt' | 'updatedAt'>;
export type ITagWithCountDb = ITagDb & UsageCount;
export type IAnnotationTagDb = Pick<AnnotationTagEntity, 'id' | 'name' | 'createdAt' | 'updatedAt'>;
export type IAnnotationTagWithCountDb = IAnnotationTagDb & UsageCount;
// ----------------------------------
// workflows
// ----------------------------------
// Almost identical to editor-ui.Interfaces.ts
export interface IWorkflowDb extends IWorkflowBase {
triggerCount: number;
tags?: TagEntity[];
parentFolder?: Folder | null;
}
export interface IWorkflowResponse extends IWorkflowBase {
id: string;
}
@@ -110,41 +76,12 @@ export interface IWorkflowToImport
// credentials
// ----------------------------------
export interface ICredentialsBase {
createdAt: Date;
updatedAt: Date;
}
export interface ICredentialsDb extends ICredentialsBase, ICredentialsEncrypted {
id: string;
name: string;
shared?: SharedCredentials[];
}
export type ICredentialsDecryptedDb = ICredentialsBase & ICredentialsDecrypted;
export type ICredentialsDecryptedResponse = ICredentialsDecryptedDb;
export type SaveExecutionDataType = 'all' | 'none';
export interface IExecutionBase {
id: string;
mode: WorkflowExecuteMode;
createdAt: Date; // set by DB
startedAt: Date;
stoppedAt?: Date; // empty value means execution is still running
workflowId: string;
/**
* @deprecated Use `status` instead
*/
finished: boolean;
retryOf?: string; // If it is a retry, the id of the execution it is a retry of.
retrySuccessId?: string; // If it failed and a retry did succeed. The id of the successful retry.
status: ExecutionStatus;
waitTill?: Date | null;
}
// Data in regular format with references
export interface IExecutionDb extends IExecutionBase {
data: IRunExecutionData;
@@ -157,18 +94,6 @@ export type CreateExecutionPayload = Omit<IExecutionDb, 'id' | 'createdAt' | 'st
/** Payload for updating an execution. */
export type UpdateExecutionPayload = Omit<IExecutionDb, 'id' | 'createdAt'>;
export interface IExecutionResponse extends IExecutionBase {
id: string;
data: IRunExecutionData;
retryOf?: string;
retrySuccessId?: string;
workflowData: IWorkflowBase | WorkflowWithSharingsAndCredentials;
customData: Record<string, string>;
annotation: {
tags: ITagBase[];
};
}
// Flatted data to save memory when saving in database or transferring
// via REST API
export interface IExecutionFlatted extends IExecutionBase {
@@ -221,16 +146,6 @@ export interface IExecutingWorkflowData {
status: ExecutionStatus;
}
export interface IPersonalizationSurveyAnswers {
email: string | null;
codingSkill: string | null;
companyIndustry: string[];
companySize: string | null;
otherCompanyIndustry: string | null;
otherWorkArea: string | null;
workArea: string[] | string | null;
}
export interface IActiveDirectorySettings {
enabled: boolean;
}
@@ -323,26 +238,6 @@ export interface ILicensePostResponse extends ILicenseReadResponse {
managementToken: string;
}
export interface PublicUser {
id: string;
email?: string;
firstName?: string;
lastName?: string;
personalizationAnswers?: IPersonalizationSurveyAnswers | null;
password?: string;
passwordResetToken?: string;
createdAt: Date;
isPending: boolean;
role?: GlobalRole;
globalScopes?: Scope[];
signInType: AuthProviderType;
disabled: boolean;
settings?: IUserSettings | null;
inviteAcceptUrl?: string;
isOwner?: boolean;
featureFlags?: FeatureFlags;
}
export interface Invitation {
email: string;
role: AssignableRole;
@@ -354,5 +249,3 @@ export interface N8nApp {
externalHooks: ExternalHooks;
activeWorkflowManager: ActiveWorkflowManager;
}
export type UserSettings = Pick<User, 'id' | 'settings'>;

View File

@@ -14,10 +14,10 @@ import {
import type { Project } from '@/databases/entities/project';
import type { WorkflowEntity } from '@/databases/entities/workflow-entity';
import type { SharedWorkflowRepository } from '@/databases/repositories/shared-workflow.repository';
import type { IWorkflowDb } from '@/interfaces';
import type { TypeUnit } from '@/modules/insights/database/entities/insights-shared';
import { InsightsMetadataRepository } from '@/modules/insights/database/repositories/insights-metadata.repository';
import { InsightsRawRepository } from '@/modules/insights/database/repositories/insights-raw.repository';
import type { IWorkflowDb } from '@/types-db';
import { createTeamProject } from '@test-integration/db/projects';
import { createWorkflow } from '@test-integration/db/workflows';
import * as testDb from '@test-integration/test-db';

View File

@@ -6,8 +6,8 @@ import type { Logger } from 'n8n-core';
import type { Project } from '@/databases/entities/project';
import type { WorkflowEntity } from '@/databases/entities/workflow-entity';
import type { IWorkflowDb } from '@/interfaces';
import type { License } from '@/license';
import type { IWorkflowDb } from '@/types-db';
import { createTeamProject } from '@test-integration/db/projects';
import { createWorkflow } from '@test-integration/db/workflows';
import * as testDb from '@test-integration/test-db';

View File

@@ -8,6 +8,8 @@ import {
} from '@n8n/typeorm';
import { UnexpectedError } from 'n8n-workflow';
import { datetimeColumnType } from '@/databases/entities/abstract-entity';
import { InsightsMetadata } from './insights-metadata';
import type { PeriodUnit } from './insights-shared';
import {
@@ -18,7 +20,6 @@ import {
PeriodUnitToNumber,
TypeToNumber,
} from './insights-shared';
import { datetimeColumnType } from '../../../../databases/entities/abstract-entity';
@Entity()
export class InsightsByPeriod extends BaseEntity {

View File

@@ -3,8 +3,9 @@ import { Container } from '@n8n/di';
import { BaseEntity, Column, Entity, PrimaryGeneratedColumn } from '@n8n/typeorm';
import { UnexpectedError } from 'n8n-workflow';
import { datetimeColumnType } from '@/databases/entities/abstract-entity';
import { isValidTypeNumber, NumberToType, TypeToNumber } from './insights-shared';
import { datetimeColumnType } from '../../../../databases/entities/abstract-entity';
export const { type: dbType } = Container.get(GlobalConfig).database;

View File

@@ -4,7 +4,7 @@ import { InstanceSettings } from 'n8n-core';
import type { FeatureFlags, ITelemetryTrackProperties } from 'n8n-workflow';
import type { PostHog } from 'posthog-node';
import type { PublicUser } from '@/interfaces';
import type { PublicUser } from '@/types-db';
@Service()
export class PostHogClient {

View File

@@ -16,8 +16,8 @@ import { SharedCredentialsRepository } from '@/databases/repositories/shared-cre
import * as Db from '@/db';
import { EventService } from '@/events/event.service';
import { ExternalHooks } from '@/external-hooks';
import type { ICredentialsDb } from '@/interfaces';
import type { CredentialRequest } from '@/requests';
import type { ICredentialsDb } from '@/types-db';
import type { IDependency, IJsonSchema } from '../../../types';

View File

@@ -15,6 +15,7 @@ import type { Variables } from '@/databases/entities/variables';
import type { WorkflowEntity } from '@/databases/entities/workflow-entity';
import type { WorkflowHistory } from '@/databases/entities/workflow-history';
import type { ScopesField } from '@/services/role.service';
import type { SlimProject } from '@/types-db';
export type APIRequest<
RouteParams = {},
@@ -122,7 +123,6 @@ export namespace ListQuery {
}
type SlimUser = Pick<IUser, 'id' | 'email' | 'firstName' | 'lastName'>;
export type SlimProject = Pick<Project, 'id' | 'type' | 'name' | 'icon'>;
export function hasSharing(
workflows: ListQuery.Workflow.Plain[] | ListQuery.Workflow.WithSharing[],

View File

@@ -7,10 +7,10 @@ import { CredentialsHelper } from '@/credentials-helper';
import type { ExecutionRepository } from '@/databases/repositories/execution.repository';
import { VariablesService } from '@/environments.ee/variables/variables.service.ee';
import { ExternalHooks } from '@/external-hooks';
import type { IExecutionResponse } from '@/interfaces';
import type { ManualExecutionService } from '@/manual-execution.service';
import { SecretsHelper } from '@/secrets-helpers.ee';
import { WorkflowStatisticsService } from '@/services/workflow-statistics.service';
import type { IExecutionResponse } from '@/types-db';
import { WorkflowStaticDataService } from '@/workflows/workflow-static-data.service';
import { JobProcessor } from '../job-processor';

View File

@@ -3,7 +3,7 @@ import { Service } from '@n8n/di';
import type { AnnotationTagEntity } from '@/databases/entities/annotation-tag-entity.ee';
import { AnnotationTagRepository } from '@/databases/repositories/annotation-tag.repository.ee';
import { validateEntity } from '@/generic-helpers';
import type { IAnnotationTagDb, IAnnotationTagWithCountDb } from '@/interfaces';
import type { IAnnotationTagDb, IAnnotationTagWithCountDb } from '@/types-db';
type GetAllResult<T> = T extends { withUsageCount: true }
? IAnnotationTagWithCountDb[]

View File

@@ -11,7 +11,7 @@ import { WorkflowTagMapping } from '@/databases/entities/workflow-tag-mapping';
import { CredentialsRepository } from '@/databases/repositories/credentials.repository';
import { TagRepository } from '@/databases/repositories/tag.repository';
import * as Db from '@/db';
import type { ICredentialsDb, IWorkflowDb } from '@/interfaces';
import type { ICredentialsDb, IWorkflowDb } from '@/types-db';
import { replaceInvalidCredentials } from '@/workflow-helpers';
@Service()

View File

@@ -4,7 +4,7 @@ import type { TagEntity } from '@/databases/entities/tag-entity';
import { TagRepository } from '@/databases/repositories/tag.repository';
import { ExternalHooks } from '@/external-hooks';
import { validateEntity } from '@/generic-helpers';
import type { ITagWithCountDb } from '@/interfaces';
import type { ITagWithCountDb } from '@/types-db';
type GetAllResult<T> = T extends { withUsageCount: true } ? ITagWithCountDb[] : TagEntity[];

View File

@@ -9,10 +9,11 @@ import { User } from '@/databases/entities/user';
import { UserRepository } from '@/databases/repositories/user.repository';
import { InternalServerError } from '@/errors/response-errors/internal-server.error';
import { EventService } from '@/events/event.service';
import type { Invitation, PublicUser } from '@/interfaces';
import type { Invitation } from '@/interfaces';
import type { PostHogClient } from '@/posthog';
import type { UserRequest } from '@/requests';
import { UrlService } from '@/services/url.service';
import type { PublicUser } from '@/types-db';
import { UserManagementMailer } from '@/user-management/email';
import { PublicApiKeyService } from './public-api-key.service';

View File

@@ -0,0 +1,142 @@
import type { GlobalRole, Scope } from '@n8n/permissions';
import type {
ICredentialsEncrypted,
IRunExecutionData,
IWorkflowBase,
WorkflowExecuteMode,
ExecutionStatus,
FeatureFlags,
IUserSettings,
} from 'n8n-workflow';
import type { AnnotationTagEntity } from '@/databases/entities/annotation-tag-entity.ee';
import type { AuthProviderType } from '@/databases/entities/auth-identity';
import type { Folder } from '@/databases/entities/folder';
import type { Project } from '@/databases/entities/project';
import type { SharedCredentials } from '@/databases/entities/shared-credentials';
import type { SharedWorkflow } from '@/databases/entities/shared-workflow';
import type { TagEntity } from '@/databases/entities/tag-entity';
import type { User } from '@/databases/entities/user';
import type { WorkflowEntity } from '@/databases/entities/workflow-entity';
export type UsageCount = {
usageCount: number;
};
export interface ITagBase {
id: string;
name: string;
}
export interface ICredentialsBase {
createdAt: Date;
updatedAt: Date;
}
export interface IExecutionBase {
id: string;
mode: WorkflowExecuteMode;
createdAt: Date; // set by DB
startedAt: Date;
stoppedAt?: Date; // empty value means execution is still running
workflowId: string;
/**
* @deprecated Use `status` instead
*/
finished: boolean;
retryOf?: string; // If it is a retry, the id of the execution it is a retry of.
retrySuccessId?: string; // If it failed and a retry did succeed. The id of the successful retry.
status: ExecutionStatus;
waitTill?: Date | null;
}
// Required by PublicUser
export interface IPersonalizationSurveyAnswers {
email: string | null;
codingSkill: string | null;
companyIndustry: string[];
companySize: string | null;
otherCompanyIndustry: string | null;
otherWorkArea: string | null;
workArea: string[] | string | null;
}
export type ITagDb = Pick<TagEntity, 'id' | 'name' | 'createdAt' | 'updatedAt'>;
export type ITagWithCountDb = ITagDb & UsageCount;
export type IAnnotationTagDb = Pick<AnnotationTagEntity, 'id' | 'name' | 'createdAt' | 'updatedAt'>;
export type IAnnotationTagWithCountDb = IAnnotationTagDb & UsageCount;
// Almost identical to editor-ui.Interfaces.ts
export interface IWorkflowDb extends IWorkflowBase {
triggerCount: number;
tags?: TagEntity[];
parentFolder?: Folder | null;
}
export interface ICredentialsDb extends ICredentialsBase, ICredentialsEncrypted {
id: string;
name: string;
shared?: SharedCredentials[];
}
export interface IExecutionResponse extends IExecutionBase {
id: string;
data: IRunExecutionData;
retryOf?: string;
retrySuccessId?: string;
workflowData: IWorkflowBase | WorkflowWithSharingsAndCredentials;
customData: Record<string, string>;
annotation: {
tags: ITagBase[];
};
}
export interface PublicUser {
id: string;
email?: string;
firstName?: string;
lastName?: string;
personalizationAnswers?: IPersonalizationSurveyAnswers | null;
password?: string;
passwordResetToken?: string;
createdAt: Date;
isPending: boolean;
role?: GlobalRole;
globalScopes?: Scope[];
signInType: AuthProviderType;
disabled: boolean;
settings?: IUserSettings | null; // External type from n8n-workflow
inviteAcceptUrl?: string;
isOwner?: boolean;
featureFlags?: FeatureFlags; // External type from n8n-workflow
}
export type UserSettings = Pick<User, 'id' | 'settings'>;
export type SlimProject = Pick<Project, 'id' | 'type' | 'name' | 'icon'>;
export interface CredentialUsedByWorkflow {
id: string;
name: string;
type?: string;
currentUserHasAccess: boolean;
homeProject: SlimProject | null;
sharedWithProjects: SlimProject[];
}
export interface WorkflowWithSharingsAndCredentials extends Omit<WorkflowEntity, 'shared'> {
homeProject?: SlimProject;
sharedWithProjects?: SlimProject[];
usedCredentials?: CredentialUsedByWorkflow[];
shared?: SharedWorkflow[];
}
export interface WorkflowWithSharingsMetaDataAndCredentials extends Omit<WorkflowEntity, 'shared'> {
homeProject?: SlimProject | null;
sharedWithProjects: SlimProject[];
usedCredentials?: CredentialUsedByWorkflow[];
}

View File

@@ -3,9 +3,9 @@ import { mock } from 'jest-mock-extended';
import { FORM_NODE_TYPE, WAITING_FORMS_EXECUTION_STATUS, type Workflow } from 'n8n-workflow';
import type { ExecutionRepository } from '@/databases/repositories/execution.repository';
import type { IExecutionResponse } from '@/types-db';
import { WaitingForms } from '@/webhooks/waiting-forms';
import type { IExecutionResponse } from '../../interfaces';
import type { WaitingWebhookRequest } from '../webhook.types';
describe('WaitingForms', () => {

View File

@@ -4,7 +4,7 @@ import { mock } from 'jest-mock-extended';
import type { ExecutionRepository } from '@/databases/repositories/execution.repository';
import { ConflictError } from '@/errors/response-errors/conflict.error';
import { NotFoundError } from '@/errors/response-errors/not-found.error';
import type { IExecutionResponse } from '@/interfaces';
import type { IExecutionResponse } from '@/types-db';
import { WaitingWebhooks } from '@/webhooks/waiting-webhooks';
import type { IWebhookResponseCallbackData, WaitingWebhookRequest } from '@/webhooks/webhook.types';

View File

@@ -10,7 +10,7 @@ import {
import { ConflictError } from '@/errors/response-errors/conflict.error';
import { NotFoundError } from '@/errors/response-errors/not-found.error';
import type { IExecutionResponse } from '@/interfaces';
import type { IExecutionResponse } from '@/types-db';
import { WaitingWebhooks } from '@/webhooks/waiting-webhooks';
import type { IWebhookResponseCallbackData, WaitingWebhookRequest } from './webhook.types';

View File

@@ -13,8 +13,8 @@ import {
import { ExecutionRepository } from '@/databases/repositories/execution.repository';
import { ConflictError } from '@/errors/response-errors/conflict.error';
import { NotFoundError } from '@/errors/response-errors/not-found.error';
import type { IExecutionResponse } from '@/interfaces';
import { NodeTypes } from '@/node-types';
import type { IExecutionResponse } from '@/types-db';
import * as WebhookHelpers from '@/webhooks/webhook-helpers';
import * as WorkflowExecuteAdditionalData from '@/workflow-execute-additional-data';

View File

@@ -23,12 +23,12 @@ import { TransferWorkflowError } from '@/errors/response-errors/transfer-workflo
import { FolderService } from '@/services/folder.service';
import { OwnershipService } from '@/services/ownership.service';
import { ProjectService } from '@/services/project.service.ee';
import { WorkflowFinderService } from './workflow-finder.service';
import type {
WorkflowWithSharingsAndCredentials,
WorkflowWithSharingsMetaDataAndCredentials,
} from './workflows.types';
} from '@/types-db';
import { WorkflowFinderService } from './workflow-finder.service';
@Service()
export class EnterpriseWorkflowService {

View File

@@ -1,25 +0,0 @@
import type { SharedWorkflow } from '@/databases/entities/shared-workflow';
import type { WorkflowEntity } from '@/databases/entities/workflow-entity';
import type { SlimProject } from '@/requests';
export interface WorkflowWithSharingsAndCredentials extends Omit<WorkflowEntity, 'shared'> {
homeProject?: SlimProject;
sharedWithProjects?: SlimProject[];
usedCredentials?: CredentialUsedByWorkflow[];
shared?: SharedWorkflow[];
}
export interface WorkflowWithSharingsMetaDataAndCredentials extends Omit<WorkflowEntity, 'shared'> {
homeProject?: SlimProject | null;
sharedWithProjects: SlimProject[];
usedCredentials?: CredentialUsedByWorkflow[];
}
export interface CredentialUsedByWorkflow {
id: string;
name: string;
type?: string;
currentUserHasAccess: boolean;
homeProject: SlimProject | null;
sharedWithProjects: SlimProject[];
}

View File

@@ -7,7 +7,7 @@ import type { User } from '@/databases/entities/user';
import { CredentialsRepository } from '@/databases/repositories/credentials.repository';
import { ProjectRepository } from '@/databases/repositories/project.repository';
import { SharedCredentialsRepository } from '@/databases/repositories/shared-credentials.repository';
import type { ICredentialsDb } from '@/interfaces';
import type { ICredentialsDb } from '@/types-db';
import type { CredentialPayload } from '../types';

View File

@@ -10,7 +10,7 @@ import { User } from '@/databases/entities/user';
import { ProjectRepository } from '@/databases/repositories/project.repository';
import { SharedWorkflowRepository } from '@/databases/repositories/shared-workflow.repository';
import { WorkflowRepository } from '@/databases/repositories/workflow.repository';
import type { IWorkflowDb } from '@/interfaces';
import type { IWorkflowDb } from '@/types-db';
export async function createManyWorkflows(
amount: number,

View File

@@ -7,7 +7,7 @@ import type TestAgent from 'supertest/lib/agent';
import type { CredentialsEntity } from '@/databases/entities/credentials-entity';
import type { Project } from '@/databases/entities/project';
import type { User } from '@/databases/entities/user';
import type { ICredentialsDb } from '@/interfaces';
import type { ICredentialsDb } from '@/types-db';
import type { LicenseMocker } from './license';

View File

@@ -1,5 +1,5 @@
import type { User } from '@/databases/entities/user';
import type { PublicUser } from '@/interfaces';
import type { PublicUser } from '@/types-db';
export const validateUser = (user: PublicUser) => {
expect(typeof user.id).toBe('string');

View File

@@ -11,8 +11,8 @@ import { ProjectRepository } from '@/databases/repositories/project.repository';
import { SharedWorkflowRepository } from '@/databases/repositories/shared-workflow.repository';
import { WorkflowHistoryRepository } from '@/databases/repositories/workflow-history.repository';
import { WorkflowRepository } from '@/databases/repositories/workflow.repository';
import type { WorkflowWithSharingsMetaDataAndCredentials } from '@/types-db';
import { UserManagementMailer } from '@/user-management/email';
import type { WorkflowWithSharingsMetaDataAndCredentials } from '@/workflows/workflows.types';
import { mockInstance } from '@test/mocking';
import { createFolder } from '@test-integration/db/folders';