diff --git a/packages/cli/src/databases/repositories/test.repository.ts b/packages/cli/src/databases/repositories/test.repository.ts new file mode 100644 index 0000000000..c780165c80 --- /dev/null +++ b/packages/cli/src/databases/repositories/test.repository.ts @@ -0,0 +1,11 @@ +import { DataSource, Repository } from '@n8n/typeorm'; +import { Service } from 'typedi'; + +import { TestEntity } from '@/databases/entities/test-entity'; + +@Service() +export class TestRepository extends Repository { + constructor(dataSource: DataSource) { + super(TestEntity, dataSource.manager); + } +} diff --git a/packages/cli/src/evaluation/tests.controller.ts b/packages/cli/src/evaluation/tests.controller.ts new file mode 100644 index 0000000000..db1f148f1f --- /dev/null +++ b/packages/cli/src/evaluation/tests.controller.ts @@ -0,0 +1,75 @@ +// import type { Scope } from '@n8n/permissions'; + +// import type { User } from '@/databases/entities/user'; +import { Get, /*Patch, Post,*/ RestController } from '@/decorators'; + +import { TestsService } from './tests.service'; +import { TestsRequest } from './tests.types'; + +@RestController('/tests') +export class TestsController { + constructor(private readonly testsService: TestsService) {} + + // private async getAccessibleWorkflowIds(user: User, scope: Scope) { + // if (this.license.isSharingEnabled()) { + // return await this.workflowSharingService.getSharedWorkflowIds(user, { scopes: [scope] }); + // } else { + // return await this.workflowSharingService.getSharedWorkflowIds(user, { + // workflowRoles: ['workflow:owner'], + // projectRoles: ['project:personalOwner'], + // }); + // } + // } + + @Get('/') + async getMany(_req: TestsRequest.GetMany) { + return await this.testsService.getMany( + /*req.user, { + listQueryOptions: req.listQueryOptions, + }*/ + ); + } + + // @Get('/:id') + // async getOne(req: ExecutionRequest.GetOne) { + // if (!isPositiveInteger(req.params.id)) { + // throw new BadRequestError('Execution ID is not a number'); + // } + // + // const workflowIds = await this.getAccessibleWorkflowIds(req.user, 'workflow:read'); + // + // if (workflowIds.length === 0) throw new NotFoundError('Execution not found'); + // + // return this.license.isSharingEnabled() + // ? await this.enterpriseExecutionService.findOne(req, workflowIds) + // : await this.executionService.findOne(req, workflowIds); + // } + // + // @Post('/delete') + // async delete(req: ExecutionRequest.Delete) { + // const workflowIds = await this.getAccessibleWorkflowIds(req.user, 'workflow:execute'); + // + // if (workflowIds.length === 0) throw new NotFoundError('Execution not found'); + // + // return await this.executionService.delete(req, workflowIds); + // } + // + // @Patch('/:id') + // async update(req: ExecutionRequest.Update) { + // if (!isPositiveInteger(req.params.id)) { + // throw new BadRequestError('Execution ID is not a number'); + // } + // + // const workflowIds = await this.getAccessibleWorkflowIds(req.user, 'workflow:read'); + // + // // Fail fast if no workflows are accessible + // if (workflowIds.length === 0) throw new NotFoundError('Execution not found'); + // + // const { body: payload } = req; + // const validatedPayload = validateExecutionUpdatePayload(payload); + // + // await this.executionService.annotate(req.params.id, validatedPayload, workflowIds); + // + // return await this.executionService.findOne(req, workflowIds); + // } +} diff --git a/packages/cli/src/evaluation/tests.service.ts b/packages/cli/src/evaluation/tests.service.ts new file mode 100644 index 0000000000..d8aec0255c --- /dev/null +++ b/packages/cli/src/evaluation/tests.service.ts @@ -0,0 +1,36 @@ +import { Service } from 'typedi'; + +import type { TestEntity } from '@/databases/entities/test-entity'; +// import type { User } from '@/databases/entities/user'; +import { TestRepository } from '@/databases/repositories/test.repository'; +import { validateEntity } from '@/generic-helpers'; +// import type { ListQuery } from '@/requests'; + +@Service() +export class TestsService { + constructor(private testRepository: TestRepository) {} + + // toEntity(attrs: { name: string; id?: string }) { + // attrs.name = attrs.name.trim(); + // + // return this.testRepository.create(attrs); + // } + + async save(test: TestEntity) { + await validateEntity(test); + + return await this.testRepository.save(test); + } + + async delete(id: string) { + return await this.testRepository.delete(id); + } + + async getMany(/*user: User, options: ListQuery.Options*/) { + const allTests = await this.testRepository.find({ + select: ['id', 'name', 'createdAt', 'updatedAt'], + }); + + return { allTests, count: allTests.length }; + } +} diff --git a/packages/cli/src/evaluation/tests.types.ts b/packages/cli/src/evaluation/tests.types.ts new file mode 100644 index 0000000000..9d0c18824f --- /dev/null +++ b/packages/cli/src/evaluation/tests.types.ts @@ -0,0 +1,30 @@ +import type { TestEntity } from '@/databases/entities/test-entity'; +import type { AuthenticatedRequest, ListQuery } from '@/requests'; + +// ---------------------------------- +// /tests +// ---------------------------------- + +export declare namespace TestsRequest { + namespace RouteParams { + type TestId = { + id: TestEntity['id']; + }; + } + + type GetOne = AuthenticatedRequest; + + type GetMany = AuthenticatedRequest<{}, {}, {}, ListQuery.Params & { includeScopes?: string }> & { + listQueryOptions: ListQuery.Options; + }; + + type Create = AuthenticatedRequest<{}, {}, { name: string; workflowId: string }>; + + type Update = AuthenticatedRequest< + RouteParams.TestId, + {}, + { name?: string; evaluationWorkflowId?: string; annotationTagId?: string } + >; + + type Delete = AuthenticatedRequest; +}