From 1a82170b37cd4da70c7cfbc9323b5cbd58f31220 Mon Sep 17 00:00:00 2001 From: Mohammad AbuAboud Date: Thu, 11 Jan 2024 19:35:35 +0000 Subject: [PATCH 1/2] chore: clean update flow endpoint --- .../app/ee/git-repos/git-repo.controller.ts | 5 - .../src/app/flows/flow/flow.controller.ts | 32 ------ .../src/app/flows/flow/flow.service.ts | 99 +++++++++---------- .../test/integration/ce/flows/flow.test.ts | 22 +++-- packages/shared/src/index.ts | 1 - .../flows/dto/update-flow-status-request.ts | 6 -- .../shared/src/lib/flows/flow-operations.ts | 23 ++++- .../ui/common/src/lib/service/flow.service.ts | 24 ----- .../src/lib/store/flow/flow.effects.ts | 21 ++-- .../flows-table/flows-table.component.ts | 14 ++- 10 files changed, 107 insertions(+), 140 deletions(-) delete mode 100644 packages/shared/src/lib/flows/dto/update-flow-status-request.ts diff --git a/packages/backend/src/app/ee/git-repos/git-repo.controller.ts b/packages/backend/src/app/ee/git-repos/git-repo.controller.ts index 9144c632bd..48ba4ddb9e 100644 --- a/packages/backend/src/app/ee/git-repos/git-repo.controller.ts +++ b/packages/backend/src/app/ee/git-repos/git-repo.controller.ts @@ -44,7 +44,6 @@ const DeleteRepoRequestSchema = { allowedPrincipals: [PrincipalType.SERVICE, PrincipalType.USER], }, schema: { - tags: ['git-repo'], description: 'Delete a git repository information for a project.', params: Type.Object({ id: Type.String(), @@ -60,7 +59,6 @@ const PullRepoRequestSchema = { allowedPrincipals: [PrincipalType.SERVICE, PrincipalType.USER], }, schema: { - tags: ['git-repo'], description: 'Pull all changes from the git repository and overwrite any conflicting changes in the project.', params: Type.Object({ id: Type.String(), @@ -76,7 +74,6 @@ const PushRepoRequestSchema = { allowedPrincipals: [PrincipalType.SERVICE, PrincipalType.USER], }, schema: { - tags: ['git-repo'], description: 'Push all changes from the project and overwrite any conflicting changes in the git repository.', body: PushGitRepoRequest, params: Type.Object({ @@ -93,7 +90,6 @@ const ConfigureRepoRequestSchema = { allowedPrincipals: [PrincipalType.SERVICE, PrincipalType.USER], }, schema: { - tags: ['git-repo'], description: 'Upsert a git repository information for a project.', body: ConfigureRepoRequest, response: { @@ -107,7 +103,6 @@ const ListRepoRequestSchema = { allowedPrincipals: [PrincipalType.SERVICE, PrincipalType.USER], }, schema: { - tags: ['git-repo'], querystring: Type.Object({ projectId: Type.String(), }), diff --git a/packages/backend/src/app/flows/flow/flow.controller.ts b/packages/backend/src/app/flows/flow/flow.controller.ts index 5d3e56479f..aac81f8d9d 100755 --- a/packages/backend/src/app/flows/flow/flow.controller.ts +++ b/packages/backend/src/app/flows/flow/flow.controller.ts @@ -8,7 +8,6 @@ import { PopulatedFlow, PrincipalType, SeekPage, - UpdateFlowStatusRequest, } from '@activepieces/shared' import { StatusCodes } from 'http-status-codes' import { flowService } from './flow.service' @@ -56,22 +55,6 @@ export const flowController: FastifyPluginAsyncTypebox = async (app) => { }) }) - app.post('/:id/status', UpdateFlowStatusRequestOptions, async (request) => { - return flowService.updateStatus({ - id: request.params.id, - projectId: request.principal.projectId, - newStatus: request.body.status, - }) - }) - - app.post('/:id/published-version-id', UpdateFlowPublishedVersionIdRequestOptions, async (request) => { - return flowService.updatedPublishedVersionId({ - id: request.params.id, - userId: request.principal.id, - projectId: request.principal.projectId, - }) - }) - app.get('/', ListFlowsRequestOptions, async (request) => { return flowService.list({ projectId: request.principal.projectId, @@ -138,22 +121,7 @@ const UpdateFlowRequestOptions = { }, } -const UpdateFlowStatusRequestOptions = { - schema: { - body: UpdateFlowStatusRequest, - params: Type.Object({ - id: ApId, - }), - }, -} -const UpdateFlowPublishedVersionIdRequestOptions = { - schema: { - params: Type.Object({ - id: ApId, - }), - }, -} const ListFlowsRequestOptions = { config: { diff --git a/packages/backend/src/app/flows/flow/flow.service.ts b/packages/backend/src/app/flows/flow/flow.service.ts index 060ea44fff..9139ffae2a 100755 --- a/packages/backend/src/app/flows/flow/flow.service.ts +++ b/packages/backend/src/app/flows/flow/flow.service.ts @@ -155,7 +155,21 @@ export const flowService = { }) : null try { - if (operation.type === FlowOperationType.CHANGE_FOLDER) { + if (operation.type === FlowOperationType.LOCK_AND_PUBLISH) { + await flowService.updatedPublishedVersionId({ + id, + userId, + projectId, + }) + } + else if (operation.type === FlowOperationType.CHANGE_STATUS) { + await flowService.updateStatus({ + id, + projectId, + newStatus: operation.request.status, + }) + } + else if (operation.type === FlowOperationType.CHANGE_FOLDER) { await flowRepo.update(id, { folderId: operation.request.folderId, }) @@ -197,28 +211,18 @@ export const flowService = { }, async updateStatus({ id, projectId, newStatus }: UpdateStatusParams): Promise { - const lock = await acquireLock({ - key: id, - timeout: 10000, - }) + const flowToUpdate = await this.getOneOrThrow({ id, projectId }) - try { - const flowToUpdate = await this.getOneOrThrow({ id, projectId }) - - if (flowToUpdate.status !== newStatus) { - const { scheduleOptions } = await hooks.preUpdateStatus({ - flowToUpdate, - newStatus, - }) + if (flowToUpdate.status !== newStatus) { + const { scheduleOptions } = await hooks.preUpdateStatus({ + flowToUpdate, + newStatus, + }) - flowToUpdate.status = newStatus - flowToUpdate.schedule = scheduleOptions + flowToUpdate.status = newStatus + flowToUpdate.schedule = scheduleOptions - await flowRepo.save(flowToUpdate) - } - } - finally { - await lock.release() + await flowRepo.save(flowToUpdate) } return this.getOnePopulatedOrThrow({ @@ -228,44 +232,37 @@ export const flowService = { }, async updatedPublishedVersionId({ id, userId, projectId }: UpdatePublishedVersionIdParams): Promise { - const lock = await acquireLock({ - key: id, - timeout: 10000, - }) - try { - const flowToUpdate = await this.getOneOrThrow({ id, projectId }) - const flowVersionToPublish = await flowVersionService.getFlowVersionOrThrow({ - flowId: id, - versionId: undefined, - }) + const flowToUpdate = await this.getOneOrThrow({ id, projectId }) - const { scheduleOptions } = await hooks.preUpdatePublishedVersionId({ - flowToUpdate, - flowVersionToPublish, - }) + const flowVersionToPublish = await flowVersionService.getFlowVersionOrThrow({ + flowId: id, + versionId: undefined, + }) - const lockedFlowVersion = await lockFlowVersionIfNotLocked({ - flowVersion: flowVersionToPublish, - userId, - projectId, - }) + const { scheduleOptions } = await hooks.preUpdatePublishedVersionId({ + flowToUpdate, + flowVersionToPublish, + }) - flowToUpdate.publishedVersionId = lockedFlowVersion.id - flowToUpdate.status = FlowStatus.ENABLED - flowToUpdate.schedule = scheduleOptions + const lockedFlowVersion = await lockFlowVersionIfNotLocked({ + flowVersion: flowVersionToPublish, + userId, + projectId, + }) - const updatedFlow = await flowRepo.save(flowToUpdate) + flowToUpdate.publishedVersionId = lockedFlowVersion.id + flowToUpdate.status = FlowStatus.ENABLED + flowToUpdate.schedule = scheduleOptions - return { - ...updatedFlow, - version: lockedFlowVersion, - } - } - finally { - await lock.release() + const updatedFlow = await flowRepo.save(flowToUpdate) + + return { + ...updatedFlow, + version: lockedFlowVersion, } + }, async delete({ id, projectId }: DeleteParams): Promise { @@ -342,7 +339,7 @@ const lockFlowVersionIfNotLocked = async ({ flowVersion, userId, projectId }: Lo }) } -const assertFlowIsNotNull: (flow: T | null) => asserts flow is T = (flow: T | null) => { +const assertFlowIsNotNull: (flow: T | null) => asserts flow is T = (flow: T | null) => { if (isNil(flow)) { throw new ActivepiecesError({ code: ErrorCode.ENTITY_NOT_FOUND, diff --git a/packages/backend/test/integration/ce/flows/flow.test.ts b/packages/backend/test/integration/ce/flows/flow.test.ts index 2baeb5d8ed..af4a5e2a0b 100644 --- a/packages/backend/test/integration/ce/flows/flow.test.ts +++ b/packages/backend/test/integration/ce/flows/flow.test.ts @@ -4,7 +4,7 @@ import { generateMockToken } from '../../../helpers/auth' import { createMockUser, createMockProject, createMockFlow, createMockFlowVersion } from '../../../helpers/mocks' import { StatusCodes } from 'http-status-codes' import { FastifyInstance } from 'fastify' -import { FlowStatus, FlowVersionState, PrincipalType } from '@activepieces/shared' +import { FlowOperationType, FlowStatus, FlowVersionState, PrincipalType } from '@activepieces/shared' let app: FastifyInstance | null = null @@ -103,13 +103,16 @@ describe('Flow API', () => { const mockToken = await generateMockToken({ type: PrincipalType.USER, projectId: mockProject.id }) const mockUpdateFlowStatusRequest = { - status: 'ENABLED', + type: FlowOperationType.CHANGE_STATUS, + request: { + status: 'ENABLED', + }, } // act const response = await app?.inject({ method: 'POST', - url: `/v1/flows/${mockFlow.id}/status`, + url: `/v1/flows/${mockFlow.id}`, headers: { authorization: `Bearer ${mockToken}`, }, @@ -155,13 +158,16 @@ describe('Flow API', () => { const mockToken = await generateMockToken({ type: PrincipalType.USER, projectId: mockProject.id }) const mockUpdateFlowStatusRequest = { - status: 'DISABLED', + type: FlowOperationType.CHANGE_STATUS, + request: { + status: 'DISABLED', + }, } // act const response = await app?.inject({ method: 'POST', - url: `/v1/flows/${mockFlow.id}/status`, + url: `/v1/flows/${mockFlow.id}`, headers: { authorization: `Bearer ${mockToken}`, }, @@ -215,7 +221,11 @@ describe('Flow API', () => { // act const response = await app?.inject({ method: 'POST', - url: `/v1/flows/${mockFlow.id}/published-version-id`, + url: `/v1/flows/${mockFlow.id}`, + body: { + type: FlowOperationType.LOCK_AND_PUBLISH, + request: {}, + }, headers: { authorization: `Bearer ${mockToken}`, }, diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index 7fc51a3c3f..56105a53d8 100755 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -53,7 +53,6 @@ export * from './lib/project/project' import { TypeSystem } from '@sinclair/typebox/system' export { RetryFlowRequestBody } from './lib/flow-run/test-flow-run-request' export * from './lib/flows/dto/flow-template-request' -export * from './lib/flows/dto/update-flow-status-request' // Look at https://github.com/sinclairzx81/typebox/issues/350 TypeSystem.ExactOptionalPropertyTypes = false export * from './lib/support-url' diff --git a/packages/shared/src/lib/flows/dto/update-flow-status-request.ts b/packages/shared/src/lib/flows/dto/update-flow-status-request.ts deleted file mode 100644 index 2df2d64b3f..0000000000 --- a/packages/shared/src/lib/flows/dto/update-flow-status-request.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Static, Type } from '@sinclair/typebox' -import { FlowStatus } from '../flow' -export const UpdateFlowStatusRequest = Type.Object({ - status: Type.Enum(FlowStatus), -}) -export type UpdateFlowStatusRequest = Static \ No newline at end of file diff --git a/packages/shared/src/lib/flows/flow-operations.ts b/packages/shared/src/lib/flows/flow-operations.ts index 4f78808e16..086922e7d4 100755 --- a/packages/shared/src/lib/flows/flow-operations.ts +++ b/packages/shared/src/lib/flows/flow-operations.ts @@ -1,11 +1,14 @@ import { CodeActionSchema, BranchActionSchema, LoopOnItemsActionSchema, PieceActionSchema, Action, } from './actions/action' +import { FlowStatus } from './flow' import { EmptyTrigger, PieceTrigger, WebhookTrigger } from './triggers/trigger' import { Static, Type } from '@sinclair/typebox' export enum FlowOperationType { + LOCK_AND_PUBLISH = 'LOCK_AND_PUBLISH', + CHANGE_STATUS = 'CHANGE_STATUS', LOCK_FLOW = 'LOCK_FLOW', CHANGE_FOLDER = 'CHANGE_FOLDER', CHANGE_NAME = 'CHANGE_NAME', @@ -33,9 +36,7 @@ export const UseAsDraftRequest = Type.Object({ }) export type UseAsDraftRequest = Static -export const LockFlowRequest = Type.Object({ - flowId: Type.String({}), -}) +export const LockFlowRequest = Type.Object({}) export type LockFlowRequest = Static @@ -92,12 +93,28 @@ export type AddActionRequest = Static export const UpdateTriggerRequest = Type.Union([EmptyTrigger, PieceTrigger, WebhookTrigger]) export type UpdateTriggerRequest = Static +export const UpdateFlowStatusRequest = Type.Object({ + status: Type.Enum(FlowStatus), +}) +export type UpdateFlowStatusRequest = Static + +export const ChangePublishedVersionIdRequest = Type.Object({}) +export type ChangePublishedVersionIdRequest = Static + export const FlowOperationRequest = Type.Union([ Type.Object({ type: Type.Literal(FlowOperationType.MOVE_ACTION), request: MoveActionRequest, }), + Type.Object({ + type: Type.Literal(FlowOperationType.CHANGE_STATUS), + request: UpdateFlowStatusRequest, + }), + Type.Object({ + type: Type.Literal(FlowOperationType.LOCK_AND_PUBLISH), + request: ChangePublishedVersionIdRequest, + }), Type.Object({ type: Type.Literal(FlowOperationType.USE_AS_DRAFT), request: UseAsDraftRequest, diff --git a/packages/ui/common/src/lib/service/flow.service.ts b/packages/ui/common/src/lib/service/flow.service.ts index cc727ef668..df642e3adf 100755 --- a/packages/ui/common/src/lib/service/flow.service.ts +++ b/packages/ui/common/src/lib/service/flow.service.ts @@ -3,13 +3,11 @@ import { HttpClient } from '@angular/common/http'; import { environment } from '../environments/environment'; import { map, Observable, of, switchMap, tap } from 'rxjs'; import { - ApId, CountFlowsRequest, CreateFlowRequest, ExecutionOutputStatus, ExecutionState, FileId, - Flow, FlowId, FlowOperationRequest, FlowOperationType, @@ -17,11 +15,9 @@ import { FlowVersion, FlowVersionId, ListFlowsRequest, - MakeKeyNonNullableAndRequired, PopulatedFlow, SeekPage, TestFlowRunRequestBody, - UpdateFlowStatusRequest, } from '@activepieces/shared'; import { AuthenticationService } from './authentication.service'; export const CURRENT_FLOW_IS_NEW_KEY_IN_LOCAL_STORAGE = 'newFlow'; @@ -173,24 +169,4 @@ export class FlowService { params: params, }); } - publish(request: { - id: ApId; - }): Observable> { - return this.http.post< - MakeKeyNonNullableAndRequired - >( - environment.apiUrl + `/flows/${request.id}/published-version-id`, - request - ); - } - - updateStatus( - flowId: ApId, - request: UpdateFlowStatusRequest - ): Observable { - return this.http.post( - environment.apiUrl + `/flows/${flowId}/status`, - request - ); - } } diff --git a/packages/ui/feature-builder-store/src/lib/store/flow/flow.effects.ts b/packages/ui/feature-builder-store/src/lib/store/flow/flow.effects.ts index d202f968f1..acbddc94b6 100755 --- a/packages/ui/feature-builder-store/src/lib/store/flow/flow.effects.ts +++ b/packages/ui/feature-builder-store/src/lib/store/flow/flow.effects.ts @@ -422,15 +422,16 @@ export class FlowsEffects { ), switchMap(([_, flow]) => { return this.flowService - .publish({ - id: flow.id, + .update(flow.id, { + type: FlowOperationType.LOCK_AND_PUBLISH, + request: {}, }) .pipe( map((flow) => { return FlowsActions.publishSuccess({ status: flow.status, showSnackbar: true, - publishedFlowVersionId: flow.publishedVersionId, + publishedFlowVersionId: flow.publishedVersionId!, }); }), catchError((err) => { @@ -450,8 +451,11 @@ export class FlowsEffects { ), switchMap(([_, flow]) => { return this.flowService - .updateStatus(flow.id, { - status: FlowStatus.ENABLED, + .update(flow.id, { + type: FlowOperationType.CHANGE_STATUS, + request: { + status: FlowStatus.ENABLED, + }, }) .pipe( switchMap((flow) => { @@ -478,8 +482,11 @@ export class FlowsEffects { ), switchMap(([_, flow]) => { return this.flowService - .updateStatus(flow.id, { - status: FlowStatus.DISABLED, + .update(flow.id, { + type: FlowOperationType.CHANGE_STATUS, + request: { + status: FlowStatus.DISABLED, + }, }) .pipe( switchMap((flow) => { diff --git a/packages/ui/feature-dashboard/src/lib/pages/flows-table/flows-table.component.ts b/packages/ui/feature-dashboard/src/lib/pages/flows-table/flows-table.component.ts index 1a550ac1f9..1b4f0c7ef9 100755 --- a/packages/ui/feature-dashboard/src/lib/pages/flows-table/flows-table.component.ts +++ b/packages/ui/feature-dashboard/src/lib/pages/flows-table/flows-table.component.ts @@ -8,6 +8,7 @@ import { FlowStatus, FolderId, TriggerType, + FlowOperationType, } from '@activepieces/shared'; import { @@ -142,11 +143,14 @@ export class FlowsTableComponent implements OnInit { if (control.enabled) { control.disable(); this.flowsUpdateStatusRequest$[flow.id] = this.flowService - .updateStatus(flow.id, { - status: - flow.status === FlowStatus.ENABLED - ? FlowStatus.DISABLED - : FlowStatus.ENABLED, + .update(flow.id, { + type: FlowOperationType.CHANGE_STATUS, + request: { + status: + flow.status === FlowStatus.ENABLED + ? FlowStatus.DISABLED + : FlowStatus.ENABLED, + }, }) .pipe( tap((res) => { From ab5ad93549fc9ab799689e9f382e0017fcdc98a5 Mon Sep 17 00:00:00 2001 From: Mohammad AbuAboud Date: Sun, 14 Jan 2024 13:23:57 +0000 Subject: [PATCH 2/2] chore: bump shared package --- packages/shared/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shared/package.json b/packages/shared/package.json index 188a9db363..2fa0fcd0d7 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -1,5 +1,5 @@ { "name": "@activepieces/shared", - "version": "0.10.58", + "version": "0.10.59", "type": "commonjs" }