From 442cd094eebe27a5349413078a1f8fdcf9535d95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Wed, 30 Apr 2025 13:34:50 +0200 Subject: [PATCH] refactor(core): Separate list query entities from request types (#15015) --- .../cli/src/controllers/folder.controller.ts | 2 +- .../cli/src/controllers/users.controller.ts | 3 +- .../src/credentials/credentials.service.ts | 4 +- .../repositories/credentials.repository.ts | 2 +- .../repositories/folder.repository.ts | 2 +- .../test-definition.repository.ee.ts | 2 +- .../repositories/test-run.repository.ee.ts | 2 +- .../databases/repositories/user.repository.ts | 2 +- .../repositories/workflow.repository.ts | 15 +++--- .../test-definition.service.ee.ts | 2 +- .../test-definitions.types.ee.ts | 3 +- .../list-query/__tests__/list-query.test.ts | 7 +-- .../cli/src/middlewares/list-query/filter.ts | 2 +- .../cli/src/middlewares/list-query/index.ts | 2 +- .../src/middlewares/list-query/pagination.ts | 2 +- .../cli/src/middlewares/list-query/select.ts | 2 +- .../cli/src/middlewares/list-query/sort-by.ts | 2 +- packages/cli/src/requests.ts | 29 +++++++++-- .../src/services/annotation-tag.service.ee.ts | 5 +- packages/cli/src/services/folder.service.ts | 2 +- .../cli/src/services/ownership.service.ts | 20 ++++---- packages/cli/src/services/role.service.ts | 28 +++++------ packages/cli/src/types-db.ts | 50 +------------------ .../cli/src/workflows/workflow.request.ts | 3 +- .../cli/src/workflows/workflow.service.ts | 13 ++--- .../credentials/credentials.api.ee.test.ts | 31 ++++++------ .../credentials/credentials.api.test.ts | 12 +++-- .../workflows/workflows.controller.test.ts | 6 +-- 28 files changed, 120 insertions(+), 135 deletions(-) diff --git a/packages/cli/src/controllers/folder.controller.ts b/packages/cli/src/controllers/folder.controller.ts index 34ff1fc01c..7e00196fd2 100644 --- a/packages/cli/src/controllers/folder.controller.ts +++ b/packages/cli/src/controllers/folder.controller.ts @@ -21,9 +21,9 @@ import { FolderNotFoundError } from '@/errors/folder-not-found.error'; import { BadRequestError } from '@/errors/response-errors/bad-request.error'; import { InternalServerError } from '@/errors/response-errors/internal-server.error'; import { NotFoundError } from '@/errors/response-errors/not-found.error'; +import type { ListQuery } from '@/requests'; import { AuthenticatedRequest } from '@/requests'; import { FolderService } from '@/services/folder.service'; -import type { ListQuery } from '@/types-db'; @RestController('/projects/:projectId/folders') export class ProjectController { diff --git a/packages/cli/src/controllers/users.controller.ts b/packages/cli/src/controllers/users.controller.ts index 3729e0ce89..6a1f19d2cb 100644 --- a/packages/cli/src/controllers/users.controller.ts +++ b/packages/cli/src/controllers/users.controller.ts @@ -27,11 +27,10 @@ import { NotFoundError } from '@/errors/response-errors/not-found.error'; import { EventService } from '@/events/event.service'; import { ExternalHooks } from '@/external-hooks'; import { listQueryMiddleware } from '@/middlewares'; -import { AuthenticatedRequest, UserRequest } from '@/requests'; +import { ListQuery, AuthenticatedRequest, UserRequest } from '@/requests'; import { FolderService } from '@/services/folder.service'; import { ProjectService } from '@/services/project.service.ee'; import { UserService } from '@/services/user.service'; -import { ListQuery } from '@/types-db'; import type { PublicUser } from '@/types-db'; import { WorkflowService } from '@/workflows/workflow.service'; diff --git a/packages/cli/src/credentials/credentials.service.ts b/packages/cli/src/credentials/credentials.service.ts index 64e7e3729a..799b1167da 100644 --- a/packages/cli/src/credentials/credentials.service.ts +++ b/packages/cli/src/credentials/credentials.service.ts @@ -33,12 +33,12 @@ import { NotFoundError } from '@/errors/response-errors/not-found.error'; import { ExternalHooks } from '@/external-hooks'; import { validateEntity } from '@/generic-helpers'; import { userHasScopes } from '@/permissions.ee/check-access'; -import type { CredentialRequest } from '@/requests'; +import type { CredentialRequest, ListQuery } from '@/requests'; import { CredentialsTester } from '@/services/credentials-tester.service'; import { OwnershipService } from '@/services/ownership.service'; import { ProjectService } from '@/services/project.service.ee'; import { RoleService } from '@/services/role.service'; -import type { ICredentialsDb, ListQuery, ScopesField } from '@/types-db'; +import type { ICredentialsDb, ScopesField } from '@/types-db'; import { CredentialsFinderService } from './credentials-finder.service'; diff --git a/packages/cli/src/databases/repositories/credentials.repository.ts b/packages/cli/src/databases/repositories/credentials.repository.ts index 7e9617e550..ccc752ad8f 100644 --- a/packages/cli/src/databases/repositories/credentials.repository.ts +++ b/packages/cli/src/databases/repositories/credentials.repository.ts @@ -2,7 +2,7 @@ import { Service } from '@n8n/di'; import { DataSource, In, Repository, Like } from '@n8n/typeorm'; import type { FindManyOptions } from '@n8n/typeorm'; -import type { ListQuery } from '@/types-db'; +import type { ListQuery } from '@/requests'; import { CredentialsEntity } from '../entities/credentials-entity'; diff --git a/packages/cli/src/databases/repositories/folder.repository.ts b/packages/cli/src/databases/repositories/folder.repository.ts index 625fc571d0..209942082c 100644 --- a/packages/cli/src/databases/repositories/folder.repository.ts +++ b/packages/cli/src/databases/repositories/folder.repository.ts @@ -3,7 +3,7 @@ import type { EntityManager, SelectQueryBuilder } from '@n8n/typeorm'; import { DataSource, Repository } from '@n8n/typeorm'; import { PROJECT_ROOT } from 'n8n-workflow'; -import type { ListQuery } from '@/types-db'; +import type { ListQuery } from '@/requests'; import type { FolderWithWorkflowAndSubFolderCount } from '../entities/folder'; import { Folder } from '../entities/folder'; diff --git a/packages/cli/src/databases/repositories/test-definition.repository.ee.ts b/packages/cli/src/databases/repositories/test-definition.repository.ee.ts index 12d3bba899..0955e6f89d 100644 --- a/packages/cli/src/databases/repositories/test-definition.repository.ee.ts +++ b/packages/cli/src/databases/repositories/test-definition.repository.ee.ts @@ -4,7 +4,7 @@ import { DataSource, In, Repository } from '@n8n/typeorm'; import { TestDefinition } from '@/databases/entities/test-definition.ee'; import { ForbiddenError } from '@/errors/response-errors/forbidden.error'; -import type { ListQuery } from '@/types-db'; +import type { ListQuery } from '@/requests'; @Service() export class TestDefinitionRepository extends Repository { diff --git a/packages/cli/src/databases/repositories/test-run.repository.ee.ts b/packages/cli/src/databases/repositories/test-run.repository.ee.ts index 1d43208094..c86a3b5842 100644 --- a/packages/cli/src/databases/repositories/test-run.repository.ee.ts +++ b/packages/cli/src/databases/repositories/test-run.repository.ee.ts @@ -8,7 +8,7 @@ import { TestRun } from '@/databases/entities/test-run.ee'; import { NotFoundError } from '@/errors/response-errors/not-found.error'; import type { TestRunErrorCode } from '@/evaluation.ee/test-runner/errors.ee'; import { getTestRunFinalResult } from '@/evaluation.ee/test-runner/utils.ee'; -import type { ListQuery } from '@/types-db'; +import type { ListQuery } from '@/requests'; export type TestRunFinalResult = 'success' | 'error' | 'warning'; diff --git a/packages/cli/src/databases/repositories/user.repository.ts b/packages/cli/src/databases/repositories/user.repository.ts index ea5bf916c7..b69946f651 100644 --- a/packages/cli/src/databases/repositories/user.repository.ts +++ b/packages/cli/src/databases/repositories/user.repository.ts @@ -3,7 +3,7 @@ import type { GlobalRole } from '@n8n/permissions'; import type { DeepPartial, EntityManager, FindManyOptions } from '@n8n/typeorm'; import { DataSource, In, IsNull, Not, Repository } from '@n8n/typeorm'; -import type { ListQuery } from '@/types-db'; +import type { ListQuery } from '@/requests'; import { Project } from '../entities/project'; import { ProjectRelation } from '../entities/project-relation'; diff --git a/packages/cli/src/databases/repositories/workflow.repository.ts b/packages/cli/src/databases/repositories/workflow.repository.ts index 70cfcbd20c..26d22e273c 100644 --- a/packages/cli/src/databases/repositories/workflow.repository.ts +++ b/packages/cli/src/databases/repositories/workflow.repository.ts @@ -13,7 +13,8 @@ import type { } from '@n8n/typeorm'; import { PROJECT_ROOT } from 'n8n-workflow'; -import type { ListQuery } from '@/types-db'; +import type { ListQuery } from '@/requests'; +import type { ListQueryDb } from '@/types-db'; import { FolderRepository } from './folder.repository'; import type { Folder, FolderWithWorkflowAndSubFolderCount } from '../entities/folder'; @@ -33,8 +34,8 @@ type WorkflowFolderUnionRow = { }; export type WorkflowFolderUnionFull = ( - | ListQuery.Workflow.Plain - | ListQuery.Workflow.WithSharing + | ListQueryDb.Workflow.Plain + | ListQueryDb.Workflow.WithSharing | FolderWithWorkflowAndSubFolderCount ) & { resource: ResourceType; @@ -320,7 +321,7 @@ export class WorkflowRepository extends Repository { private enrichDataWithExtras( baseData: WorkflowFolderUnionRow[], extraData: { - workflows: ListQuery.Workflow.WithSharing[] | ListQuery.Workflow.Plain[]; + workflows: ListQueryDb.Workflow.WithSharing[] | ListQueryDb.Workflow.Plain[]; folders: Folder[]; }, ): WorkflowFolderUnionFull[] { @@ -343,8 +344,8 @@ export class WorkflowRepository extends Repository { const query = this.getManyQuery(workflowIds, options); const workflows = (await query.getMany()) as - | ListQuery.Workflow.Plain[] - | ListQuery.Workflow.WithSharing[]; + | ListQueryDb.Workflow.Plain[] + | ListQueryDb.Workflow.WithSharing[]; return workflows; } @@ -357,7 +358,7 @@ export class WorkflowRepository extends Repository { const query = this.getManyQuery(sharedWorkflowIds, options); const [workflows, count] = (await query.getManyAndCount()) as [ - ListQuery.Workflow.Plain[] | ListQuery.Workflow.WithSharing[], + ListQueryDb.Workflow.Plain[] | ListQueryDb.Workflow.WithSharing[], number, ]; diff --git a/packages/cli/src/evaluation.ee/test-definition.service.ee.ts b/packages/cli/src/evaluation.ee/test-definition.service.ee.ts index 6d3e69f2de..5129f3b389 100644 --- a/packages/cli/src/evaluation.ee/test-definition.service.ee.ts +++ b/packages/cli/src/evaluation.ee/test-definition.service.ee.ts @@ -6,8 +6,8 @@ import { TestDefinitionRepository } from '@/databases/repositories/test-definiti import { BadRequestError } from '@/errors/response-errors/bad-request.error'; import { NotFoundError } from '@/errors/response-errors/not-found.error'; import { validateEntity } from '@/generic-helpers'; +import type { ListQuery } from '@/requests'; import { Telemetry } from '@/telemetry'; -import type { ListQuery } from '@/types-db'; type TestDefinitionLike = Omit< Partial, diff --git a/packages/cli/src/evaluation.ee/test-definitions.types.ee.ts b/packages/cli/src/evaluation.ee/test-definitions.types.ee.ts index 86a15fa487..eb19f964f7 100644 --- a/packages/cli/src/evaluation.ee/test-definitions.types.ee.ts +++ b/packages/cli/src/evaluation.ee/test-definitions.types.ee.ts @@ -1,6 +1,5 @@ import type { MockedNodeItem } from '@/databases/entities/test-definition.ee'; -import type { AuthenticatedRequest } from '@/requests'; -import type { ListQuery } from '@/types-db'; +import type { AuthenticatedRequest, ListQuery } from '@/requests'; // ---------------------------------- // /test-definitions diff --git a/packages/cli/src/middlewares/list-query/__tests__/list-query.test.ts b/packages/cli/src/middlewares/list-query/__tests__/list-query.test.ts index da55c9c43b..37b8cba5a8 100644 --- a/packages/cli/src/middlewares/list-query/__tests__/list-query.test.ts +++ b/packages/cli/src/middlewares/list-query/__tests__/list-query.test.ts @@ -3,8 +3,9 @@ import type { Response, NextFunction } from 'express'; import { filterListQueryMiddleware } from '@/middlewares/list-query/filter'; import { paginationListQueryMiddleware } from '@/middlewares/list-query/pagination'; import { selectListQueryMiddleware } from '@/middlewares/list-query/select'; +import type { ListQuery } from '@/requests'; import * as ResponseHelper from '@/response-helper'; -import type { ListQuery } from '@/types-db'; +import type { ListQueryDb } from '@/types-db'; import { sortByQueryMiddleware } from '../sort-by'; @@ -177,7 +178,7 @@ describe('List query middleware', () => { }); describe('Query sort by', () => { - const validCases: Array<{ name: string; value: ListQuery.Workflow.SortOrder }> = [ + const validCases: Array<{ name: string; value: ListQueryDb.Workflow.SortOrder }> = [ { name: 'sorting by name asc', value: 'name:asc', @@ -236,7 +237,7 @@ describe('List query middleware', () => { test.each(invalidCases)('should fail validation when $name', async ({ value }) => { mockReq.query = { - sortBy: value as ListQuery.Workflow.SortOrder, + sortBy: value as ListQueryDb.Workflow.SortOrder, }; await sortByQueryMiddleware(...args); diff --git a/packages/cli/src/middlewares/list-query/filter.ts b/packages/cli/src/middlewares/list-query/filter.ts index dbdb4106c0..8443d01747 100644 --- a/packages/cli/src/middlewares/list-query/filter.ts +++ b/packages/cli/src/middlewares/list-query/filter.ts @@ -1,7 +1,7 @@ import type { NextFunction, Response } from 'express'; +import type { ListQuery } from '@/requests'; import * as ResponseHelper from '@/response-helper'; -import type { ListQuery } from '@/types-db'; import { toError } from '@/utils'; import { CredentialsFilter } from './dtos/credentials.filter.dto'; diff --git a/packages/cli/src/middlewares/list-query/index.ts b/packages/cli/src/middlewares/list-query/index.ts index 3ba662614c..81f6215cf9 100644 --- a/packages/cli/src/middlewares/list-query/index.ts +++ b/packages/cli/src/middlewares/list-query/index.ts @@ -1,6 +1,6 @@ import { type NextFunction, type Response } from 'express'; -import type { ListQuery } from '@/types-db'; +import type { ListQuery } from '@/requests'; import { filterListQueryMiddleware } from './filter'; import { paginationListQueryMiddleware } from './pagination'; diff --git a/packages/cli/src/middlewares/list-query/pagination.ts b/packages/cli/src/middlewares/list-query/pagination.ts index 565948ed94..da24db6d5c 100644 --- a/packages/cli/src/middlewares/list-query/pagination.ts +++ b/packages/cli/src/middlewares/list-query/pagination.ts @@ -1,8 +1,8 @@ import type { RequestHandler } from 'express'; import { UnexpectedError } from 'n8n-workflow'; +import type { ListQuery } from '@/requests'; import * as ResponseHelper from '@/response-helper'; -import type { ListQuery } from '@/types-db'; import { toError } from '@/utils'; import { Pagination } from './dtos/pagination.dto'; diff --git a/packages/cli/src/middlewares/list-query/select.ts b/packages/cli/src/middlewares/list-query/select.ts index 946ab6e559..7eb2de0d37 100644 --- a/packages/cli/src/middlewares/list-query/select.ts +++ b/packages/cli/src/middlewares/list-query/select.ts @@ -1,7 +1,7 @@ import type { RequestHandler } from 'express'; +import type { ListQuery } from '@/requests'; import * as ResponseHelper from '@/response-helper'; -import type { ListQuery } from '@/types-db'; import { toError } from '@/utils'; import { CredentialsSelect } from './dtos/credentials.select.dto'; diff --git a/packages/cli/src/middlewares/list-query/sort-by.ts b/packages/cli/src/middlewares/list-query/sort-by.ts index d93f59f5a1..f600b1fdca 100644 --- a/packages/cli/src/middlewares/list-query/sort-by.ts +++ b/packages/cli/src/middlewares/list-query/sort-by.ts @@ -3,8 +3,8 @@ import { validateSync } from 'class-validator'; import type { RequestHandler } from 'express'; import { UnexpectedError } from 'n8n-workflow'; +import type { ListQuery } from '@/requests'; import * as ResponseHelper from '@/response-helper'; -import type { ListQuery } from '@/types-db'; import { toError } from '@/utils'; import { WorkflowSorting } from './dtos/workflow.sort-by.dto'; diff --git a/packages/cli/src/requests.ts b/packages/cli/src/requests.ts index 53f34f0088..727694f53b 100644 --- a/packages/cli/src/requests.ts +++ b/packages/cli/src/requests.ts @@ -11,7 +11,8 @@ import type { import type { Project } from '@/databases/entities/project'; import type { User } from '@/databases/entities/user'; import type { WorkflowHistory } from '@/databases/entities/workflow-history'; -import type { ListQuery } from '@/types-db'; + +import type { ListQueryDb } from './types-db'; export type APIRequest< RouteParams = {}, @@ -42,13 +43,35 @@ export type AuthenticatedRequest< }; }; +export namespace ListQuery { + export type Request = AuthenticatedRequest<{}, {}, {}, Params> & { + listQueryOptions?: Options; + }; + + export type Params = { + filter?: string; + skip?: string; + take?: string; + select?: string; + sortBy?: string; + }; + + export type Options = { + filter?: Record; + select?: Record; + skip?: number; + take?: number; + sortBy?: string; + }; +} + // ---------------------------------- // list query // ---------------------------------- export function hasSharing( - workflows: ListQuery.Workflow.Plain[] | ListQuery.Workflow.WithSharing[], -): workflows is ListQuery.Workflow.WithSharing[] { + workflows: ListQueryDb.Workflow.Plain[] | ListQueryDb.Workflow.WithSharing[], +): workflows is ListQueryDb.Workflow.WithSharing[] { return workflows.some((w) => 'shared' in w); } diff --git a/packages/cli/src/services/annotation-tag.service.ee.ts b/packages/cli/src/services/annotation-tag.service.ee.ts index 33c106f5b3..8163597029 100644 --- a/packages/cli/src/services/annotation-tag.service.ee.ts +++ b/packages/cli/src/services/annotation-tag.service.ee.ts @@ -3,7 +3,10 @@ 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 '@/types-db'; + +type IAnnotationTagDb = Pick; + +type IAnnotationTagWithCountDb = IAnnotationTagDb & { usageCount: number }; type GetAllResult = T extends { withUsageCount: true } ? IAnnotationTagWithCountDb[] diff --git a/packages/cli/src/services/folder.service.ts b/packages/cli/src/services/folder.service.ts index a2cf5c9bd2..fc35452139 100644 --- a/packages/cli/src/services/folder.service.ts +++ b/packages/cli/src/services/folder.service.ts @@ -9,7 +9,7 @@ import { FolderTagMappingRepository } from '@/databases/repositories/folder-tag- import { FolderRepository } from '@/databases/repositories/folder.repository'; import { WorkflowRepository } from '@/databases/repositories/workflow.repository'; import { FolderNotFoundError } from '@/errors/folder-not-found.error'; -import type { ListQuery } from '@/types-db'; +import type { ListQuery } from '@/requests'; export interface SimpleFolderNode { id: string; diff --git a/packages/cli/src/services/ownership.service.ts b/packages/cli/src/services/ownership.service.ts index 2ef2055f07..2f447d66a3 100644 --- a/packages/cli/src/services/ownership.service.ts +++ b/packages/cli/src/services/ownership.service.ts @@ -7,7 +7,7 @@ import { ProjectRepository } from '@/databases/repositories/project.repository'; import { SharedWorkflowRepository } from '@/databases/repositories/shared-workflow.repository'; import { UserRepository } from '@/databases/repositories/user.repository'; import { CacheService } from '@/services/cache/cache.service'; -import type { ListQuery } from '@/types-db'; +import type { ListQueryDb } from '@/types-db'; @Service() export class OwnershipService { @@ -57,18 +57,20 @@ export class OwnershipService { } addOwnedByAndSharedWith( - rawWorkflow: ListQuery.Workflow.WithSharing, - ): ListQuery.Workflow.WithOwnedByAndSharedWith; + rawWorkflow: ListQueryDb.Workflow.WithSharing, + ): ListQueryDb.Workflow.WithOwnedByAndSharedWith; addOwnedByAndSharedWith( - rawCredential: ListQuery.Credentials.WithSharing, - ): ListQuery.Credentials.WithOwnedByAndSharedWith; + rawCredential: ListQueryDb.Credentials.WithSharing, + ): ListQueryDb.Credentials.WithOwnedByAndSharedWith; addOwnedByAndSharedWith( - rawEntity: ListQuery.Workflow.WithSharing | ListQuery.Credentials.WithSharing, - ): ListQuery.Workflow.WithOwnedByAndSharedWith | ListQuery.Credentials.WithOwnedByAndSharedWith { + rawEntity: ListQueryDb.Workflow.WithSharing | ListQueryDb.Credentials.WithSharing, + ): + | ListQueryDb.Workflow.WithOwnedByAndSharedWith + | ListQueryDb.Credentials.WithOwnedByAndSharedWith { const shared = rawEntity.shared; const entity = rawEntity as - | ListQuery.Workflow.WithOwnedByAndSharedWith - | ListQuery.Credentials.WithOwnedByAndSharedWith; + | ListQueryDb.Workflow.WithOwnedByAndSharedWith + | ListQueryDb.Credentials.WithOwnedByAndSharedWith; Object.assign(entity, { homeProject: null, diff --git a/packages/cli/src/services/role.service.ts b/packages/cli/src/services/role.service.ts index c9ac878f92..72f5df3c44 100644 --- a/packages/cli/src/services/role.service.ts +++ b/packages/cli/src/services/role.service.ts @@ -30,7 +30,7 @@ import { WORKFLOW_SHARING_EDITOR_SCOPES, WORKFLOW_SHARING_OWNER_SCOPES, } from '@/permissions.ee/resource-roles'; -import type { ListQuery, ScopesField } from '@/types-db'; +import type { ListQueryDb, ScopesField } from '@/types-db'; export type RoleNamespace = 'global' | 'project' | 'credential' | 'workflow'; @@ -159,10 +159,10 @@ export class RoleService { } addScopes( - rawWorkflow: ListQuery.Workflow.WithSharing | ListQuery.Workflow.WithOwnedByAndSharedWith, + rawWorkflow: ListQueryDb.Workflow.WithSharing | ListQueryDb.Workflow.WithOwnedByAndSharedWith, user: User, userProjectRelations: ProjectRelation[], - ): ListQuery.Workflow.WithScopes; + ): ListQueryDb.Workflow.WithScopes; addScopes( rawCredential: CredentialsEntity, user: User, @@ -170,29 +170,29 @@ export class RoleService { ): CredentialsEntity & ScopesField; addScopes( rawCredential: - | ListQuery.Credentials.WithSharing - | ListQuery.Credentials.WithOwnedByAndSharedWith, + | ListQueryDb.Credentials.WithSharing + | ListQueryDb.Credentials.WithOwnedByAndSharedWith, user: User, userProjectRelations: ProjectRelation[], - ): ListQuery.Credentials.WithScopes; + ): ListQueryDb.Credentials.WithScopes; addScopes( rawEntity: | CredentialsEntity - | ListQuery.Workflow.WithSharing - | ListQuery.Credentials.WithOwnedByAndSharedWith - | ListQuery.Credentials.WithSharing - | ListQuery.Workflow.WithOwnedByAndSharedWith, + | ListQueryDb.Workflow.WithSharing + | ListQueryDb.Credentials.WithOwnedByAndSharedWith + | ListQueryDb.Credentials.WithSharing + | ListQueryDb.Workflow.WithOwnedByAndSharedWith, user: User, userProjectRelations: ProjectRelation[], ): | (CredentialsEntity & ScopesField) - | ListQuery.Workflow.WithScopes - | ListQuery.Credentials.WithScopes { + | ListQueryDb.Workflow.WithScopes + | ListQueryDb.Credentials.WithScopes { const shared = rawEntity.shared; const entity = rawEntity as | (CredentialsEntity & ScopesField) - | ListQuery.Workflow.WithScopes - | ListQuery.Credentials.WithScopes; + | ListQueryDb.Workflow.WithScopes + | ListQueryDb.Credentials.WithScopes; Object.assign(entity, { scopes: [], diff --git a/packages/cli/src/types-db.ts b/packages/cli/src/types-db.ts index 806d0ea7cc..d43eeb80bf 100644 --- a/packages/cli/src/types-db.ts +++ b/packages/cli/src/types-db.ts @@ -1,5 +1,4 @@ import type { GlobalRole, Scope } from '@n8n/permissions'; -import type express from 'express'; import type { ICredentialsEncrypted, IRunExecutionData, @@ -13,7 +12,6 @@ import type { IUser, } from 'n8n-workflow'; -import type { AnnotationTagEntity } from '@/databases/entities/annotation-tag-entity.ee'; import type { AuthProviderType } from '@/databases/entities/auth-identity'; import type { CredentialsEntity } from '@/databases/entities/credentials-entity'; import type { Folder } from '@/databases/entities/folder'; @@ -71,10 +69,6 @@ export type ITagDb = Pick; export type ITagWithCountDb = ITagDb & UsageCount; -export type IAnnotationTagDb = Pick; - -export type IAnnotationTagWithCountDb = IAnnotationTagDb & UsageCount; - // Almost identical to editor-ui.Interfaces.ts export interface IWorkflowDb extends IWorkflowBase { triggerCount: number; @@ -211,49 +205,7 @@ export namespace ExecutionSummaries { export type ExecutionSummaryWithScopes = ExecutionSummary & { scopes: Scope[] }; } -export type APIRequest< - RouteParams = {}, - ResponseBody = {}, - RequestBody = {}, - RequestQuery = {}, -> = express.Request & { - browserId?: string; -}; - -export type AuthenticatedRequest< - RouteParams = {}, - ResponseBody = {}, - RequestBody = {}, - RequestQuery = {}, -> = Omit, 'user' | 'cookies'> & { - user: User; - cookies: Record; - headers: express.Request['headers'] & { - 'push-ref': string; - }; -}; - -export namespace ListQuery { - export type Request = AuthenticatedRequest<{}, {}, {}, Params> & { - listQueryOptions?: Options; - }; - - export type Params = { - filter?: string; - skip?: string; - take?: string; - select?: string; - sortBy?: string; - }; - - export type Options = { - filter?: Record; - select?: Record; - skip?: number; - take?: number; - sortBy?: string; - }; - +export namespace ListQueryDb { /** * Slim workflow returned from a list query operation. */ diff --git a/packages/cli/src/workflows/workflow.request.ts b/packages/cli/src/workflows/workflow.request.ts index 259f25cf17..a9cba76bf5 100644 --- a/packages/cli/src/workflows/workflow.request.ts +++ b/packages/cli/src/workflows/workflow.request.ts @@ -8,8 +8,7 @@ import type { IWorkflowBase, } from 'n8n-workflow'; -import type { AuthenticatedRequest } from '@/requests'; -import type { ListQuery } from '@/types-db'; +import type { AuthenticatedRequest, ListQuery } from '@/requests'; export declare namespace WorkflowRequest { type CreateUpdatePayload = Partial<{ diff --git a/packages/cli/src/workflows/workflow.service.ts b/packages/cli/src/workflows/workflow.service.ts index 153aa47fb3..da931140c7 100644 --- a/packages/cli/src/workflows/workflow.service.ts +++ b/packages/cli/src/workflows/workflow.service.ts @@ -27,6 +27,7 @@ import { NotFoundError } from '@/errors/response-errors/not-found.error'; import { EventService } from '@/events/event.service'; import { ExternalHooks } from '@/external-hooks'; import { validateEntity } from '@/generic-helpers'; +import type { ListQuery } from '@/requests'; import { hasSharing } from '@/requests'; import { FolderService } from '@/services/folder.service'; import { OrchestrationService } from '@/services/orchestration.service'; @@ -34,7 +35,7 @@ import { OwnershipService } from '@/services/ownership.service'; import { ProjectService } from '@/services/project.service.ee'; import { RoleService } from '@/services/role.service'; import { TagService } from '@/services/tag.service'; -import type { ListQuery } from '@/types-db'; +import type { ListQueryDb } from '@/types-db'; import * as WorkflowHelpers from '@/workflow-helpers'; import { WorkflowFinderService } from './workflow-finder.service'; @@ -138,7 +139,7 @@ export class WorkflowService { } private async processSharedWorkflows( - workflows: ListQuery.Workflow.WithSharing[], + workflows: ListQueryDb.Workflow.WithSharing[], options?: ListQuery.Options, ) { const projectId = options?.filter?.projectId; @@ -152,7 +153,7 @@ export class WorkflowService { return workflows.map((workflow) => this.ownershipService.addOwnedByAndSharedWith(workflow)); } - private async addSharedRelation(workflows: ListQuery.Workflow.WithSharing[]): Promise { + private async addSharedRelation(workflows: ListQueryDb.Workflow.WithSharing[]): Promise { const workflowIds = workflows.map((workflow) => workflow.id); const relations = await this.sharedWorkflowRepository.getAllRelationsForWorkflows(workflowIds); @@ -162,7 +163,7 @@ export class WorkflowService { } private async addUserScopes( - workflows: ListQuery.Workflow.Plain[] | ListQuery.Workflow.WithSharing[], + workflows: ListQueryDb.Workflow.Plain[] | ListQueryDb.Workflow.WithSharing[], user: User, ) { const projectRelations = await this.projectService.getProjectRelationsForUser(user); @@ -173,7 +174,7 @@ export class WorkflowService { } private cleanupSharedField( - workflows: ListQuery.Workflow.Plain[] | ListQuery.Workflow.WithSharing[], + workflows: ListQueryDb.Workflow.Plain[] | ListQueryDb.Workflow.WithSharing[], ): void { /* This is to emulate the old behavior of removing the shared field as @@ -187,7 +188,7 @@ export class WorkflowService { private mergeProcessedWorkflows( workflowsAndFolders: WorkflowFolderUnionFull[], - processedWorkflows: ListQuery.Workflow.Plain[] | ListQuery.Workflow.WithSharing[], + processedWorkflows: ListQueryDb.Workflow.Plain[] | ListQueryDb.Workflow.WithSharing[], ) { const workflowMap = new Map(processedWorkflows.map((workflow) => [workflow.id, workflow])); diff --git a/packages/cli/test/integration/credentials/credentials.api.ee.test.ts b/packages/cli/test/integration/credentials/credentials.api.ee.test.ts index 56783c282a..ba3abdae18 100644 --- a/packages/cli/test/integration/credentials/credentials.api.ee.test.ts +++ b/packages/cli/test/integration/credentials/credentials.api.ee.test.ts @@ -9,7 +9,7 @@ import type { User } from '@/databases/entities/user'; import { ProjectRepository } from '@/databases/repositories/project.repository'; import { SharedCredentialsRepository } from '@/databases/repositories/shared-credentials.repository'; import { ProjectService } from '@/services/project.service.ee'; -import type { ListQuery } from '@/types-db'; +import type { ListQueryDb } from '@/types-db'; import { UserManagementMailer } from '@/user-management/email'; import { createWorkflow, shareWorkflowWithUsers } from '@test-integration/db/workflows'; @@ -134,13 +134,14 @@ describe('GET /credentials', () => { expect(response.statusCode).toBe(200); expect(response.body.data).toHaveLength(2); // owner retrieved owner cred and member cred - const ownerCredential: ListQuery.Credentials.WithOwnedByAndSharedWith = response.body.data.find( - (e: ListQuery.Credentials.WithOwnedByAndSharedWith) => - e.homeProject?.id === ownerPersonalProject.id, - ); - const memberCredential: ListQuery.Credentials.WithOwnedByAndSharedWith = + const ownerCredential: ListQueryDb.Credentials.WithOwnedByAndSharedWith = response.body.data.find( - (e: ListQuery.Credentials.WithOwnedByAndSharedWith) => + (e: ListQueryDb.Credentials.WithOwnedByAndSharedWith) => + e.homeProject?.id === ownerPersonalProject.id, + ); + const memberCredential: ListQueryDb.Credentials.WithOwnedByAndSharedWith = + response.body.data.find( + (e: ListQueryDb.Credentials.WithOwnedByAndSharedWith) => e.homeProject?.id === member1PersonalProject.id, ); @@ -205,7 +206,7 @@ describe('GET /credentials', () => { expect(response.statusCode).toBe(200); expect(response.body.data).toHaveLength(1); // member retrieved only member cred - const [member1Credential]: [ListQuery.Credentials.WithOwnedByAndSharedWith] = + const [member1Credential]: [ListQueryDb.Credentials.WithOwnedByAndSharedWith] = response.body.data; validateMainCredentialData(member1Credential); @@ -536,7 +537,8 @@ describe('GET /credentials/:id', () => { expect(firstResponse.statusCode).toBe(200); - const firstCredential: ListQuery.Credentials.WithOwnedByAndSharedWith = firstResponse.body.data; + const firstCredential: ListQueryDb.Credentials.WithOwnedByAndSharedWith = + firstResponse.body.data; validateMainCredentialData(firstCredential); expect(firstCredential.data).toBeUndefined(); @@ -593,7 +595,7 @@ describe('GET /credentials/:id', () => { const response1 = await authOwnerAgent.get(`/credentials/${savedCredential.id}`).expect(200); - const credential: ListQuery.Credentials.WithOwnedByAndSharedWith = response1.body.data; + const credential: ListQueryDb.Credentials.WithOwnedByAndSharedWith = response1.body.data; validateMainCredentialData(credential); expect(credential.data).toBeUndefined(); @@ -617,7 +619,7 @@ describe('GET /credentials/:id', () => { .query({ includeData: true }) .expect(200); - const credential2: ListQuery.Credentials.WithOwnedByAndSharedWith = response2.body.data; + const credential2: ListQueryDb.Credentials.WithOwnedByAndSharedWith = response2.body.data; validateMainCredentialData(credential); expect(credential2.data).toBeDefined(); // Instance owners should be capable of editing all credentials @@ -645,7 +647,8 @@ describe('GET /credentials/:id', () => { .get(`/credentials/${savedCredential.id}`) .expect(200); - const firstCredential: ListQuery.Credentials.WithOwnedByAndSharedWith = firstResponse.body.data; + const firstCredential: ListQueryDb.Credentials.WithOwnedByAndSharedWith = + firstResponse.body.data; validateMainCredentialData(firstCredential); expect(firstCredential.data).toBeUndefined(); expect(firstCredential).toMatchObject({ @@ -676,7 +679,7 @@ describe('GET /credentials/:id', () => { .query({ includeData: true }) .expect(200); - const secondCredential: ListQuery.Credentials.WithOwnedByAndSharedWith = + const secondCredential: ListQueryDb.Credentials.WithOwnedByAndSharedWith = secondResponse.body.data; validateMainCredentialData(secondCredential); expect(secondCredential.data).toBeDefined(); @@ -1359,7 +1362,7 @@ describe('PUT /:credentialId/transfer', () => { ); }); -function validateMainCredentialData(credential: ListQuery.Credentials.WithOwnedByAndSharedWith) { +function validateMainCredentialData(credential: ListQueryDb.Credentials.WithOwnedByAndSharedWith) { expect(typeof credential.name).toBe('string'); expect(typeof credential.type).toBe('string'); expect(credential.homeProject).toBeDefined(); diff --git a/packages/cli/test/integration/credentials/credentials.api.test.ts b/packages/cli/test/integration/credentials/credentials.api.test.ts index 4a6c036d28..1cde6efa8a 100644 --- a/packages/cli/test/integration/credentials/credentials.api.test.ts +++ b/packages/cli/test/integration/credentials/credentials.api.test.ts @@ -15,7 +15,7 @@ import { CredentialsRepository } from '@/databases/repositories/credentials.repo import { ProjectRepository } from '@/databases/repositories/project.repository'; import { SharedCredentialsRepository } from '@/databases/repositories/shared-credentials.repository'; import { CredentialsTester } from '@/services/credentials-tester.service'; -import type { ListQuery } from '@/types-db'; +import type { ListQueryDb } from '@/types-db'; import { decryptCredentialData, @@ -74,7 +74,7 @@ beforeEach(async () => { sharedCredentialsRepository = Container.get(SharedCredentialsRepository); }); -type GetAllResponse = { body: { data: ListQuery.Credentials.WithOwnedByAndSharedWith[] } }; +type GetAllResponse = { body: { data: ListQueryDb.Credentials.WithOwnedByAndSharedWith[] } }; // ---------------------------------------- // GET /credentials - fetch all credentials @@ -92,7 +92,7 @@ describe('GET /credentials', () => { expect(response.body.data.length).toBe(2); // owner retrieved owner cred and member cred const savedCredentialsIds = [savedOwnerCredentialId, savedMemberCredentialId]; - response.body.data.forEach((credential: ListQuery.Credentials.WithOwnedByAndSharedWith) => { + response.body.data.forEach((credential: ListQueryDb.Credentials.WithOwnedByAndSharedWith) => { validateMainCredentialData(credential); expect('data' in credential).toBe(false); expect(savedCredentialsIds).toContain(credential.id); @@ -1502,7 +1502,7 @@ const INVALID_PAYLOADS = [ undefined, ]; -function validateMainCredentialData(credential: ListQuery.Credentials.WithOwnedByAndSharedWith) { +function validateMainCredentialData(credential: ListQueryDb.Credentials.WithOwnedByAndSharedWith) { const { name, type, sharedWithProjects, homeProject, isManaged } = credential; expect(typeof name).toBe('string'); @@ -1522,7 +1522,9 @@ function validateMainCredentialData(credential: ListQuery.Credentials.WithOwnedB } } -function validateCredentialWithNoData(credential: ListQuery.Credentials.WithOwnedByAndSharedWith) { +function validateCredentialWithNoData( + credential: ListQueryDb.Credentials.WithOwnedByAndSharedWith, +) { validateMainCredentialData(credential); expect('data' in credential).toBe(false); diff --git a/packages/cli/test/integration/workflows/workflows.controller.test.ts b/packages/cli/test/integration/workflows/workflows.controller.test.ts index 46a8553b44..be045c1260 100644 --- a/packages/cli/test/integration/workflows/workflows.controller.test.ts +++ b/packages/cli/test/integration/workflows/workflows.controller.test.ts @@ -13,7 +13,7 @@ import type { WorkflowFolderUnionFull } from '@/databases/repositories/workflow. import { WorkflowRepository } from '@/databases/repositories/workflow.repository'; import { License } from '@/license'; import { ProjectService } from '@/services/project.service.ee'; -import type { ListQuery } from '@/types-db'; +import type { ListQueryDb } from '@/types-db'; import { EnterpriseWorkflowService } from '@/workflows/workflow.service.ee'; import { createFolder } from '@test-integration/db/folders'; @@ -641,7 +641,7 @@ describe('GET /workflows', () => { }); const found = response.body.data.find( - (w: ListQuery.Workflow.WithOwnership) => w.name === 'First', + (w: ListQueryDb.Workflow.WithOwnership) => w.name === 'First', ); expect(found.nodes).toBeUndefined(); @@ -1458,7 +1458,7 @@ describe('GET /workflows?includeFolders=true', () => { }); const found = response.body.data.find( - (w: ListQuery.Workflow.WithOwnership) => w.name === 'First', + (w: ListQueryDb.Workflow.WithOwnership) => w.name === 'First', ); expect(found.nodes).toBeUndefined();