index.ts•14.7 kB
import { Static, Type } from '@sinclair/typebox'
import { Nullable } from '../../common'
import { Metadata } from '../../common/metadata'
import { BranchCondition, CodeActionSchema, LoopOnItemsActionSchema, PieceActionSchema, RouterActionSchema } from '../actions/action'
import { FlowStatus } from '../flow'
import { FlowVersion, FlowVersionState } from '../flow-version'
import { SaveSampleDataRequest } from '../sample-data'
import { EmptyTrigger, FlowTrigger, PieceTrigger } from '../triggers/trigger'
import { flowPieceUtil } from '../util/flow-piece-util'
import { flowStructureUtil } from '../util/flow-structure-util'
import { _addAction } from './add-action'
import { _addBranch } from './add-branch'
import { _getActionsForCopy } from './copy-action-operations'
import { _deleteAction } from './delete-action'
import { _deleteBranch } from './delete-branch'
import { _duplicateBranch, _duplicateStep } from './duplicate-step'
import { _importFlow } from './import-flow'
import { flowMigrations } from './migrations'
import { _moveAction } from './move-action'
import { _moveBranch } from './move-branch'
import { _getOperationsForPaste } from './paste-operations'
import { _skipAction } from './skip-action'
import { _updateAction } from './update-action'
import { _updateTrigger } from './update-trigger'
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',
MOVE_ACTION = 'MOVE_ACTION',
IMPORT_FLOW = 'IMPORT_FLOW',
UPDATE_TRIGGER = 'UPDATE_TRIGGER',
ADD_ACTION = 'ADD_ACTION',
UPDATE_ACTION = 'UPDATE_ACTION',
DELETE_ACTION = 'DELETE_ACTION',
DUPLICATE_ACTION = 'DUPLICATE_ACTION',
USE_AS_DRAFT = 'USE_AS_DRAFT',
DELETE_BRANCH = 'DELETE_BRANCH',
ADD_BRANCH = 'ADD_BRANCH',
DUPLICATE_BRANCH = 'DUPLICATE_BRANCH',
SET_SKIP_ACTION = 'SET_SKIP_ACTION',
UPDATE_METADATA = 'UPDATE_METADATA',
MOVE_BRANCH = 'MOVE_BRANCH',
SAVE_SAMPLE_DATA = 'SAVE_SAMPLE_DATA',
}
export const DeleteBranchRequest = Type.Object({
branchIndex: Type.Number(),
stepName: Type.String(),
})
export const AddBranchRequest = Type.Object({
branchIndex: Type.Number(),
stepName: Type.String(),
conditions: Type.Optional(Type.Array(Type.Array(BranchCondition))),
branchName: Type.String(),
})
export const MoveBranchRequest = Type.Object({
sourceBranchIndex: Type.Number(),
targetBranchIndex: Type.Number(),
stepName: Type.String(),
})
export type MoveBranchRequest = Static<typeof MoveBranchRequest>
export const SkipActionRequest = Type.Object({
names: Type.Array(Type.String()),
skip: Type.Boolean(),
})
export type SkipActionRequest = Static<typeof SkipActionRequest>
export const DuplicateBranchRequest = Type.Object({
branchIndex: Type.Number(),
stepName: Type.String(),
})
export type DeleteBranchRequest = Static<typeof DeleteBranchRequest>
export type AddBranchRequest = Static<typeof AddBranchRequest>
export type DuplicateBranchRequest = Static<typeof DuplicateBranchRequest>
export enum StepLocationRelativeToParent {
AFTER = 'AFTER',
INSIDE_LOOP = 'INSIDE_LOOP',
INSIDE_BRANCH = 'INSIDE_BRANCH',
}
export const UseAsDraftRequest = Type.Object({
versionId: Type.String(),
})
export type UseAsDraftRequest = Static<typeof UseAsDraftRequest>
export const LockFlowRequest = Type.Object({})
export type LockFlowRequest = Static<typeof LockFlowRequest>
export const ImportFlowRequest = Type.Object({
displayName: Type.String({}),
trigger: FlowTrigger,
schemaVersion: Nullable(Type.String()),
})
export type ImportFlowRequest = Static<typeof ImportFlowRequest>
export const ChangeFolderRequest = Type.Object({
folderId: Nullable(Type.String({})),
})
export type ChangeFolderRequest = Static<typeof ChangeFolderRequest>
export const ChangeNameRequest = Type.Object({
displayName: Type.String({}),
})
export type ChangeNameRequest = Static<typeof ChangeNameRequest>
export const DeleteActionRequest = Type.Object({
names: Type.Array(Type.String()),
})
export type DeleteActionRequest = Static<typeof DeleteActionRequest>
export const UpdateActionRequest = Type.Union([
CodeActionSchema,
LoopOnItemsActionSchema,
PieceActionSchema,
RouterActionSchema,
])
export type UpdateActionRequest = Static<typeof UpdateActionRequest>
export const DuplicateStepRequest = Type.Object({
stepName: Type.String(),
})
export type DuplicateStepRequest = Static<typeof DuplicateStepRequest>
export const MoveActionRequest = Type.Object({
name: Type.String(),
newParentStep: Type.String(),
stepLocationRelativeToNewParent: Type.Optional(
Type.Enum(StepLocationRelativeToParent),
),
branchIndex: Type.Optional(Type.Number()),
})
export type MoveActionRequest = Static<typeof MoveActionRequest>
export const AddActionRequest = Type.Object({
parentStep: Type.String(),
stepLocationRelativeToParent: Type.Optional(
Type.Enum(StepLocationRelativeToParent),
),
branchIndex: Type.Optional(Type.Number()),
action: UpdateActionRequest,
})
export type AddActionRequest = Static<typeof AddActionRequest>
export const UpdateTriggerRequest = Type.Union([EmptyTrigger, PieceTrigger])
export type UpdateTriggerRequest = Static<typeof UpdateTriggerRequest>
export const UpdateFlowStatusRequest = Type.Object({
status: Type.Enum(FlowStatus),
})
export type UpdateFlowStatusRequest = Static<typeof UpdateFlowStatusRequest>
export const ChangePublishedVersionIdRequest = Type.Object({
status: Type.Optional(Type.Enum(FlowStatus)),
})
export type ChangePublishedVersionIdRequest = Static<
typeof ChangePublishedVersionIdRequest
>
export const UpdateMetadataRequest = Type.Object({
metadata: Nullable(Metadata),
})
export type UpdateMetadataRequest = Static<typeof UpdateMetadataRequest>
export const FlowOperationRequest = Type.Union([
Type.Object(
{
type: Type.Literal(FlowOperationType.MOVE_ACTION),
request: MoveActionRequest,
},
{
title: 'Move Action',
},
),
Type.Object(
{
type: Type.Literal(FlowOperationType.CHANGE_STATUS),
request: UpdateFlowStatusRequest,
},
{
title: 'Change Status',
},
),
Type.Object(
{
type: Type.Literal(FlowOperationType.LOCK_AND_PUBLISH),
request: ChangePublishedVersionIdRequest,
},
{
title: 'Lock and Publish',
},
),
Type.Object(
{
type: Type.Literal(FlowOperationType.USE_AS_DRAFT),
request: UseAsDraftRequest,
},
{
title: 'Copy as Draft',
},
),
Type.Object(
{
type: Type.Literal(FlowOperationType.LOCK_FLOW),
request: LockFlowRequest,
},
{
title: 'Lock Flow',
},
),
Type.Object(
{
type: Type.Literal(FlowOperationType.IMPORT_FLOW),
request: ImportFlowRequest,
},
{
title: 'Import Flow',
},
),
Type.Object(
{
type: Type.Literal(FlowOperationType.CHANGE_NAME),
request: ChangeNameRequest,
},
{
title: 'Change Name',
},
),
Type.Object(
{
type: Type.Literal(FlowOperationType.DELETE_ACTION),
request: DeleteActionRequest,
},
{
title: 'Delete Action',
},
),
Type.Object(
{
type: Type.Literal(FlowOperationType.UPDATE_ACTION),
request: UpdateActionRequest,
},
{
title: 'Update Action',
},
),
Type.Object(
{
type: Type.Literal(FlowOperationType.ADD_ACTION),
request: AddActionRequest,
},
{
title: 'Add Action',
},
),
Type.Object(
{
type: Type.Literal(FlowOperationType.UPDATE_TRIGGER),
request: UpdateTriggerRequest,
},
{
title: 'Update Trigger',
},
),
Type.Object(
{
type: Type.Literal(FlowOperationType.CHANGE_FOLDER),
request: ChangeFolderRequest,
},
{
title: 'Change Folder',
},
),
Type.Object(
{
type: Type.Literal(FlowOperationType.DUPLICATE_ACTION),
request: DuplicateStepRequest,
},
{
title: 'Duplicate Action',
},
),
Type.Object(
{
type: Type.Literal(FlowOperationType.DELETE_BRANCH),
request: DeleteBranchRequest,
},
{
title: 'Delete Branch',
},
),
Type.Object(
{
type: Type.Literal(FlowOperationType.ADD_BRANCH),
request: AddBranchRequest,
},
{
title: 'Add Branch',
},
),
Type.Object(
{
type: Type.Literal(FlowOperationType.DUPLICATE_BRANCH),
request: DuplicateBranchRequest,
},
{
title: 'Duplicate Branch',
},
),
Type.Object(
{
type: Type.Literal(FlowOperationType.SET_SKIP_ACTION),
request: SkipActionRequest,
},
{
title: 'Skip Action',
},
),
Type.Object(
{
type: Type.Literal(FlowOperationType.UPDATE_METADATA),
request: UpdateMetadataRequest,
},
{
title: 'Update Metadata',
},
),
Type.Object(
{
type: Type.Literal(FlowOperationType.MOVE_BRANCH),
request: MoveBranchRequest,
},
),
Type.Object(
{
type: Type.Literal(FlowOperationType.SAVE_SAMPLE_DATA),
request: SaveSampleDataRequest,
},
),
])
export type FlowOperationRequest = Static<typeof FlowOperationRequest>
export const flowOperations = {
getActionsForCopy: _getActionsForCopy,
getOperationsForPaste: _getOperationsForPaste,
apply(flowVersion: FlowVersion, operation: FlowOperationRequest): FlowVersion {
let clonedVersion: FlowVersion = JSON.parse(JSON.stringify(flowVersion))
switch (operation.type) {
case FlowOperationType.MOVE_ACTION: {
const operations: FlowOperationRequest[] = _moveAction(clonedVersion, operation.request)
operations.forEach((operation) => {
clonedVersion = flowOperations.apply(clonedVersion, operation)
})
clonedVersion = flowPieceUtil.makeFlowAutoUpgradable(clonedVersion)
break
}
case FlowOperationType.CHANGE_NAME:
clonedVersion.displayName = operation.request.displayName
break
case FlowOperationType.DUPLICATE_BRANCH: {
const operations = _duplicateBranch(operation.request.stepName, operation.request.branchIndex, clonedVersion)
operations.forEach((operation) => {
clonedVersion = flowOperations.apply(clonedVersion, operation)
})
break
}
case FlowOperationType.DUPLICATE_ACTION: {
const operations = _duplicateStep(operation.request.stepName, clonedVersion)
operations.forEach((operation) => {
clonedVersion = flowOperations.apply(clonedVersion, operation)
})
break
}
case FlowOperationType.LOCK_FLOW:
clonedVersion.state = FlowVersionState.LOCKED
break
case FlowOperationType.ADD_ACTION: {
clonedVersion = _addAction(clonedVersion, operation.request)
clonedVersion = flowPieceUtil.makeFlowAutoUpgradable(clonedVersion)
break
}
case FlowOperationType.DELETE_ACTION: {
clonedVersion = _deleteAction(clonedVersion, operation.request)
clonedVersion = flowPieceUtil.makeFlowAutoUpgradable(clonedVersion)
break
}
case FlowOperationType.UPDATE_TRIGGER: {
clonedVersion = _updateTrigger(clonedVersion, operation.request)
clonedVersion = flowPieceUtil.makeFlowAutoUpgradable(clonedVersion)
break
}
case FlowOperationType.ADD_BRANCH: {
clonedVersion = _addBranch(clonedVersion, operation.request)
clonedVersion = flowPieceUtil.makeFlowAutoUpgradable(clonedVersion)
break
}
case FlowOperationType.DELETE_BRANCH: {
clonedVersion = _deleteBranch(clonedVersion, operation.request)
clonedVersion = flowPieceUtil.makeFlowAutoUpgradable(clonedVersion)
break
}
case FlowOperationType.UPDATE_ACTION: {
clonedVersion = _updateAction(clonedVersion, operation.request)
clonedVersion = flowPieceUtil.makeFlowAutoUpgradable(clonedVersion)
break
}
case FlowOperationType.IMPORT_FLOW: {
const migratedFlow = flowMigrations.apply({
...clonedVersion,
trigger: operation.request.trigger,
displayName: operation.request.displayName,
schemaVersion: operation.request.schemaVersion,
})
const operations = _importFlow(clonedVersion, migratedFlow)
operations.forEach((operation) => {
clonedVersion = flowOperations.apply(clonedVersion, operation)
})
break
}
case FlowOperationType.SET_SKIP_ACTION: {
clonedVersion = _skipAction(clonedVersion, operation.request)
clonedVersion = flowPieceUtil.makeFlowAutoUpgradable(clonedVersion)
break
}
case FlowOperationType.MOVE_BRANCH: {
clonedVersion = _moveBranch(clonedVersion, operation.request)
clonedVersion = flowPieceUtil.makeFlowAutoUpgradable(clonedVersion)
break
}
default:
break
}
clonedVersion.valid = flowStructureUtil.getAllSteps(clonedVersion.trigger).every((step) => step.valid)
return clonedVersion
},
}