-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnewEvolveRequest.ts
More file actions
163 lines (145 loc) · 5.43 KB
/
Copy pathnewEvolveRequest.ts
File metadata and controls
163 lines (145 loc) · 5.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import { ApolloServerErrorCode, GraphQLError } from "@graphql/errors";
import {
FieldAnswerArgs,
FlowType,
MutationNewEvolveRequestArgs,
NewRequestArgs,
SystemFieldType,
} from "@graphql/generated/resolver-types";
import { newRequest } from "./newRequest";
import { prisma } from "../../prisma/client";
import { UserOrIdentityContextInterface } from "../entity/UserOrIdentityContext";
import { fieldSetInclude } from "../fields/fieldPrismaTypes";
import { newFlowVersion } from "../flow/newFlowVersion";
// creates a new request for a flow, starting with the request's first step
// validates/creates request fields and request defined options
export const newEvolveRequest = async ({
args,
entityContext,
}: {
args: MutationNewEvolveRequestArgs;
entityContext: UserOrIdentityContextInterface;
}): Promise<string> => {
const [requestArgs, proposedFlowVersionId] = await prisma.$transaction(async (transaction) => {
let draftEvolveFlowVersionId: string | null = null;
const {
request: { new: proposedFlow, flowId },
} = args;
const flow = await transaction.flow.findUniqueOrThrow({
include: { CurrentFlowVersion: true },
where: { id: flowId },
});
if (!flow.CurrentFlowVersion)
throw new GraphQLError(`Missing current version of flow. FlowId ${flowId}`, {
extensions: { code: ApolloServerErrorCode.INTERNAL_SERVER_ERROR },
});
if (!flow.CurrentFlowVersion.evolveFlowId)
throw new GraphQLError(`Flow does not have an evolve flow. FlowId ${flowId}`, {
extensions: { code: ApolloServerErrorCode.BAD_USER_INPUT },
});
if (!proposedFlow.evolve)
throw new GraphQLError("Missing proposed evolve flow", {
extensions: { code: ApolloServerErrorCode.BAD_USER_INPUT },
});
// currently, we're only allowing evolve requests to be created for non-evolve flow
// in the future, we'll allow evolve flows to evolve themselves independent of whatever flow it evolves
// but this is a simplifying assumption for v1 because allowing this could result in invalid evolve flows
if (flow.type === FlowType.Evolve)
throw new GraphQLError(
`Cannot create evolve request for an evolve flow directly. FlowId ${flowId}`,
{
extensions: { code: ApolloServerErrorCode.BAD_USER_INPUT },
},
);
if (!flow.reusable)
throw new GraphQLError(
`Cannot create evolve request for a non-reusable flow. FlowId ${flowId}`,
{
extensions: { code: ApolloServerErrorCode.BAD_USER_INPUT },
},
);
// find evolve flow and it's fields so they can be referenced in the evolve request
const evolveFlow = await transaction.flow.findUniqueOrThrow({
where: { id: flow.CurrentFlowVersion.evolveFlowId },
include: {
CurrentFlowVersion: {
include: {
TriggerFieldSet: {
include: fieldSetInclude,
},
},
},
},
});
const evoleFlowFields = evolveFlow.CurrentFlowVersion?.TriggerFieldSet?.Fields ?? [];
const proposedFlowField = evoleFlowFields.find((field) => {
return field.systemType === SystemFieldType.EvolveFlowProposed;
});
const currentFlowField = evoleFlowFields.find(
(field) => field.systemType === SystemFieldType.EvolveFlowCurrent,
);
const descriptionField = evoleFlowFields.find(
(field) => field.systemType === SystemFieldType.EvolveFlowDescription,
);
if (!proposedFlowField || !currentFlowField || !descriptionField)
throw new GraphQLError("Cannot find proposed flow and current flow fields of evolve flow", {
extensions: { code: ApolloServerErrorCode.INTERNAL_SERVER_ERROR },
});
// create new evolve flow version
// TODO - don't create this if there are no changes
if (flow.CurrentFlowVersion?.evolveFlowId) {
draftEvolveFlowVersionId = await newFlowVersion({
transaction,
flowId: flow.CurrentFlowVersion.evolveFlowId,
active: false,
draftEvolveFlowVersionId: null,
// evolve flow evolves itself
evolveFlowId: flow.CurrentFlowVersion?.evolveFlowId,
flowArgs: proposedFlow.evolve,
type: FlowType.Evolve,
});
}
// create new custom flow version
const proposedFlowVersionId = await newFlowVersion({
transaction,
flowArgs: proposedFlow.flow,
flowId: flow.id,
evolveFlowId: flow.CurrentFlowVersion?.evolveFlowId ?? null,
active: false,
draftEvolveFlowVersionId,
type: flow.type as FlowType,
});
const requestFields: FieldAnswerArgs[] = [
{
fieldId: currentFlowField.id,
value: JSON.stringify(flow.CurrentFlowVersion.id),
optionSelections: [],
},
{
fieldId: proposedFlowField.id,
value: JSON.stringify(proposedFlowVersionId),
optionSelections: [],
},
];
if (args.request.description) {
requestFields.push({
fieldId: descriptionField.id,
value: JSON.stringify(args.request.description),
optionSelections: [],
});
}
const requestArgs: NewRequestArgs = {
requestId: crypto.randomUUID(),
flowId: flow.CurrentFlowVersion.evolveFlowId,
name: args.request.name,
requestFields,
requestDefinedOptions: [],
};
return [requestArgs, proposedFlowVersionId];
});
return await newRequest({
args: { request: requestArgs },
entityContext,
proposedFlowVersionId,
});
};