@izara_project/izara-core-generate-service-code 1.0.91 → 1.0.92

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/package.json +7 -10
  2. package/src/compile/flowValidator.js +6 -0
  3. package/src/compile/loadSchemas.js +177 -69
  4. package/src/emit/crud/generateCrudApplicationArtifacts.js +15 -17
  5. package/src/emit/crud/generateDynamicCrudFlowSchemas.js +16 -21
  6. package/src/emit/crud/loadLocalSchemaArrays.js +4 -8
  7. package/src/emit/custom/customFlowPaths.js +149 -0
  8. package/src/emit/custom/customFlowS3.js +156 -0
  9. package/src/emit/custom/customFlowSteps.js +385 -0
  10. package/src/emit/custom/customFlowTemplates.js +28 -0
  11. package/src/emit/custom/customFlows.js +48 -19
  12. package/src/emit/custom/emitCustomFlowApplicationArtifacts.js +57 -692
  13. package/src/emit/custom/generateCustomFlowApplicationArtifacts.js +27 -25
  14. package/src/emit/rbac/generateCreateTargetRoleHandler.js +11 -13
  15. package/src/emit/rbac/generateDynamicRbacFlowSchemas.js +14 -18
  16. package/src/emit/relationship/generateDynamicRelationshipFlowSchemas.js +16 -19
  17. package/src/emit/relationship/generateRelationshipApplicationArtifacts.js +19 -19
  18. package/src/emit/resource/dynamoResourceArtifacts.js +18 -0
  19. package/src/emit/resource/emitResourceArtifacts.js +13 -1247
  20. package/src/emit/resource/generateResourceArtifacts.js +20 -20
  21. package/src/emit/resource/iamResourceArtifacts.js +612 -0
  22. package/src/emit/resource/resourceState.js +564 -0
  23. package/src/emit/resource/resourceTemplate.js +30 -0
  24. package/src/emit/resource/s3ResourceArtifacts.js +14 -0
  25. package/src/emit/resource/sqsResourceArtifacts.js +113 -0
  26. package/src/emit/shared/runSubsystemGeneration.js +55 -0
  27. package/src/emit/system/emitSystemWebSocketArtifacts.js +2 -1
  28. package/test/crudApplicationArtifacts.test.js +72 -0
  29. package/test/customFlowApplicationArtifacts.test.js +98 -0
  30. package/test/resourceArtifacts.test.js +99 -0
@@ -0,0 +1,149 @@
1
+ import {
2
+ flowDsqSteps,
3
+ flowExtTopicSteps,
4
+ generatedDsqFlows,
5
+ generatedOwnTopicFlows,
6
+ supportedCustomFlows,
7
+ upperFirst,
8
+ flowHasRbac
9
+ } from './customFlows.js';
10
+
11
+ export const YAML_PATH = 'app/sls_yaml/generatedCode/source/flow-schema.yml';
12
+
13
+ export function isS3Only(flow) {
14
+ return flow.event.length === 1 && flow.event[0] === 's3';
15
+ }
16
+
17
+ export function needsProcessMain(flow) {
18
+ const isOwnTopicTransport =
19
+ flow.event.includes('ownTopic') ||
20
+ (flow.event.includes('generateCode') &&
21
+ flow.generatedCodeConfig?.invocationType === 'ownTopic');
22
+ return (
23
+ !isS3Only(flow) &&
24
+ !isOwnTopicTransport &&
25
+ flow.event.some((event) => event !== 'ownTopic' && event !== 's3')
26
+ );
27
+ }
28
+
29
+ export function ownTopicRootPaths(flow, objects = []) {
30
+ const tag = upperFirst(flow.flowTag);
31
+ const source = `app/src/generatedCode/FlowSchemas/${tag}/source`;
32
+ const paths = [
33
+ `${source}/${tag}_Main.js`,
34
+ `${source}/${tag}_HdrSqs.js`,
35
+ `${source}/${tag}_WbsMain.js`,
36
+ `${source}/${tag}_HdrWbs.js`
37
+ ];
38
+ if (flowHasRbac(flow, objects)) {
39
+ paths.push(
40
+ `${source}/${tag}RbacCallback_Main.js`,
41
+ `${source}/${tag}RbacCallback_HdrSqs.js`
42
+ );
43
+ }
44
+ return paths;
45
+ }
46
+
47
+ export function flowPaths(flow, objects = []) {
48
+ const tag = upperFirst(flow.flowTag);
49
+ const process = tag;
50
+ const source = `app/src/generatedCode/FlowSchemas/${tag}/source`;
51
+ const paths = [];
52
+ if (needsProcessMain(flow)) {
53
+ paths.push(`${source}/${process}_Main.js`);
54
+ }
55
+ if (flowHasRbac(flow, objects)) {
56
+ paths.push(
57
+ `${source}/${tag}RbacCallback_Main.js`,
58
+ `${source}/${tag}RbacCallback_HdrSqs.js`
59
+ );
60
+ }
61
+ if (flow.event.includes('extTopic') && !flow.event.includes('ownTopic')) {
62
+ paths.push(`${source}/${process}_HdrSqs.js`);
63
+ }
64
+ if (flow.event.includes('dsq')) {
65
+ paths.push(`${source}/${process}_HdrDsq.js`);
66
+ }
67
+ if (
68
+ flow.event.includes('lambdaSyncInv') ||
69
+ flow.event.includes('eventBridge') ||
70
+ (flow.event.includes('generateCode') &&
71
+ flow.generatedCodeConfig?.invocationType === 'lambdaSyncInv')
72
+ ) {
73
+ paths.push(`${source}/${process}_HdrInv.js`);
74
+ }
75
+ if (flow.event.includes('lambdaSyncApi')) {
76
+ paths.push(`${source}/${process}_HdrApi.js`);
77
+ }
78
+ if (
79
+ flow.event.includes('ownTopic') ||
80
+ (flow.event.includes('generateCode') &&
81
+ flow.generatedCodeConfig?.invocationType === 'ownTopic')
82
+ ) {
83
+ paths.push(...ownTopicRootPaths(flow, objects));
84
+ }
85
+ if (flow.event.includes('s3')) {
86
+ const s3Actions = [
87
+ 'ConfirmAfterUpload',
88
+ 'CreateObject',
89
+ 'CreatePreSignUrl',
90
+ 'ProcessAfterUpload',
91
+ 'ReservedLimit'
92
+ ];
93
+ for (const action of s3Actions) {
94
+ let handler = 'HdrSqs';
95
+ if (action === 'CreateObject') {
96
+ handler = 'HdrWbs';
97
+ } else if (action === 'ProcessAfterUpload') {
98
+ handler = 'HdrS3';
99
+ }
100
+ paths.push(
101
+ `${source}/${tag}${action}_Main.js`,
102
+ `${source}/${tag}${action}_${handler}.js`
103
+ );
104
+ }
105
+ }
106
+ return paths;
107
+ }
108
+
109
+ export function customFlowApplicationManagedPaths(
110
+ flows,
111
+ { objects = [] } = {}
112
+ ) {
113
+ const customFlowList = supportedCustomFlows(flows);
114
+ const generatedRoots = generatedOwnTopicFlows(flows);
115
+ const generatedDsqs = generatedDsqFlows(flows);
116
+ const extSteps = flowExtTopicSteps(flows);
117
+ const dsqSteps = flowDsqSteps(flows);
118
+
119
+ return [
120
+ ...customFlowList.flatMap((flow) => flowPaths(flow, objects)),
121
+ ...generatedRoots.flatMap((flow) => ownTopicRootPaths(flow, objects)),
122
+ ...extSteps.flatMap(({ flowTag, stepName }) => {
123
+ const source = `app/src/generatedCode/FlowSchemas/${flowTag}/source`;
124
+ return [
125
+ `${source}/${flowTag}${stepName}_Main.js`,
126
+ `${source}/${flowTag}${stepName}_HdrSqs.js`
127
+ ];
128
+ }),
129
+ ...dsqSteps.flatMap(({ flowTag, stepName, step }) => {
130
+ const source = `app/src/generatedCode/FlowSchemas/${flowTag}/source`;
131
+ let stepEvents = [];
132
+ if (Array.isArray(step.event)) {
133
+ stepEvents = step.event;
134
+ }
135
+ const files = [`${source}/${flowTag}${stepName}_HdrDsq.js`];
136
+ if (!stepEvents.includes('extTopic')) {
137
+ files.unshift(`${source}/${flowTag}${stepName}_Main.js`);
138
+ }
139
+ return files;
140
+ }),
141
+ ...(customFlowList.length > 0 ||
142
+ generatedRoots.length > 0 ||
143
+ generatedDsqs.length > 0 ||
144
+ extSteps.length > 0 ||
145
+ dsqSteps.length > 0
146
+ ? [YAML_PATH]
147
+ : [])
148
+ ];
149
+ }
@@ -0,0 +1,156 @@
1
+ import { renderCustom } from './customFlowTemplates.js';
2
+ import { customFlowRoleName, upperFirst } from './customFlows.js';
3
+ import {
4
+ renderInvFunctionYaml,
5
+ renderS3FunctionYaml,
6
+ renderSqsFunctionYaml,
7
+ renderWbsFunctionYaml
8
+ } from '../function/functionYamlArtifact.js';
9
+
10
+ export async function emitS3Flow(flow, source, handlerRoot) {
11
+ const tag = upperFirst(flow.flowTag);
12
+ const roleName = customFlowRoleName(flow.flowTag);
13
+ const parts = [
14
+ {
15
+ action: 'CreateObject',
16
+ handler: 'HdrWbs',
17
+ type: 'wbs',
18
+ mainTemplate: 'CreateObject_Main.ejs',
19
+ handlerTemplate: 'CreateObject_HdrWbs.ejs'
20
+ },
21
+ {
22
+ action: 'ReservedLimit',
23
+ handler: 'HdrSqs',
24
+ type: 'sqs',
25
+ mainTemplate: 'ReservedLimit_Main.ejs',
26
+ handlerTemplate: 'ReservedLimit_HdrSqs.ejs'
27
+ },
28
+ {
29
+ action: 'CreatePreSignUrl',
30
+ handler: 'HdrSqs',
31
+ type: 'sqs',
32
+ mainTemplate: 'CreatePreSignUrl_Main.ejs',
33
+ handlerTemplate: 'CreatePreSignUrl_HdrSqs.ejs'
34
+ },
35
+ {
36
+ action: 'ProcessAfterUpload',
37
+ handler: 'HdrS3',
38
+ type: 's3',
39
+ mainTemplate: 'ProcessS3File_Main.ejs',
40
+ handlerTemplate: 'FlowHandler_HdrS3.ejs'
41
+ },
42
+ {
43
+ action: 'ConfirmAfterUpload',
44
+ handler: 'HdrSqs',
45
+ type: 'sqs',
46
+ mainTemplate: 'ConfirmReserved_Main.ejs',
47
+ handlerTemplate: 'ConfirmReserved_HdrSqs.ejs'
48
+ }
49
+ ];
50
+
51
+ const emitted = await Promise.all(
52
+ parts.map(
53
+ async ({ action, handler, type, mainTemplate, handlerTemplate }) => {
54
+ const functionName = `${tag}${action}`;
55
+ const mainFileName = `${functionName}_Main`;
56
+ const handlerFileName = `${functionName}_${handler}`;
57
+ const mainContent = await renderCustom(
58
+ `s3/${mainTemplate}`,
59
+ _s3TemplateData({ action, flow, functionName })
60
+ );
61
+ const handlerContent = await renderCustom(
62
+ `s3/${handlerTemplate}`,
63
+ _s3HandlerData({ action, flow, functionName, mainFileName, handler })
64
+ );
65
+ const descriptor = {
66
+ functionName: `${functionName}${handler}`,
67
+ handlerPath: `${handlerRoot}/${handlerFileName}.main`,
68
+ roleName
69
+ };
70
+ let functionYaml;
71
+ if (type === 'wbs') {
72
+ functionYaml = renderWbsFunctionYaml({
73
+ ...descriptor,
74
+ routeName: tag,
75
+ flowTag: flow.flowTag,
76
+ flowStepName: ''
77
+ });
78
+ } else if (type === 'sqs') {
79
+ let filterPatternFunctionName = descriptor.functionName;
80
+ if (action === 'CreatePreSignUrl') {
81
+ filterPatternFunctionName = 'CreatePresignUrlHdrSqs';
82
+ }
83
+ functionYaml = renderSqsFunctionYaml({
84
+ ...descriptor,
85
+ queueName: descriptor.functionName,
86
+ flowTag: flow.flowTag,
87
+ flowStepName: '',
88
+ filterPatternFunctionName
89
+ });
90
+ } else if (type === 's3') {
91
+ let bucketName = '';
92
+ if (flow.bucketName) {
93
+ bucketName = flow.bucketName;
94
+ }
95
+ functionYaml = renderS3FunctionYaml({
96
+ ...descriptor,
97
+ bucketName,
98
+ flowTag: flow.flowTag,
99
+ flowStepName: ''
100
+ });
101
+ } else {
102
+ functionYaml = renderInvFunctionYaml({
103
+ ...descriptor,
104
+ flowTag: flow.flowTag,
105
+ flowStepName: ''
106
+ });
107
+ }
108
+ return {
109
+ artifacts: [
110
+ { path: `${source}/${mainFileName}.js`, content: mainContent },
111
+ { path: `${source}/${handlerFileName}.js`, content: handlerContent }
112
+ ],
113
+ functionYaml
114
+ };
115
+ }
116
+ )
117
+ );
118
+
119
+ return {
120
+ artifacts: emitted.flatMap((item) => item.artifacts),
121
+ functions: emitted.map((item) => item.functionYaml)
122
+ };
123
+ }
124
+
125
+ function _s3TemplateData({ action, flow, functionName }) {
126
+ if (action === 'CreateObject') {
127
+ return {
128
+ flowTag: flow.flowTag,
129
+ objectType: flow.objType?.objectType,
130
+ functionName
131
+ };
132
+ }
133
+ if (action === 'CreatePreSignUrl') {
134
+ return { flowTag: flow.flowTag };
135
+ }
136
+ return { flowTag: flow.flowTag, functionName };
137
+ }
138
+
139
+ function _s3HandlerData({ action, flow, functionName, mainFileName, handler }) {
140
+ if (action === 'CreateObject') {
141
+ return { functionName, handlerType: handler, route: flow.flowTag };
142
+ }
143
+ if (action === 'ProcessAfterUpload') {
144
+ let bucketName = '';
145
+ if (flow.bucketName) {
146
+ bucketName = flow.bucketName;
147
+ }
148
+ return {
149
+ flowTag: flow.flowTag,
150
+ functionName,
151
+ mainFileName,
152
+ s3Bucket: bucketName
153
+ };
154
+ }
155
+ return { functionName, handlerType: handler };
156
+ }
@@ -0,0 +1,385 @@
1
+ import {
2
+ renderCrudTemplate,
3
+ renderCustom,
4
+ renderDsq,
5
+ renderShared
6
+ } from './customFlowTemplates.js';
7
+ import { customFlowRoleName, upperFirst, flowHasRbac } from './customFlows.js';
8
+ import {
9
+ renderSqsFunctionYaml,
10
+ renderWbsFunctionYaml
11
+ } from '../function/functionYamlArtifact.js';
12
+
13
+ export async function emitExtTopicStep({ flow, step, flowTag, stepName }) {
14
+ const source = `app/src/generatedCode/FlowSchemas/${flowTag}/source`;
15
+ const handlerRoot = `src/generatedCode/FlowSchemas/${flowTag}/source`;
16
+ let functionName = `${flowTag}${stepName}`;
17
+ if (stepName.startsWith(flowTag)) {
18
+ functionName = stepName;
19
+ }
20
+ const mainFileName = `${functionName}_Main`;
21
+ const startConfig = stepConfig(flow, step);
22
+
23
+ const hasTriggerFlowTypes =
24
+ Array.isArray(flow.triggerFlowTypes) && flow.triggerFlowTypes.length > 0;
25
+ const isCheckStep = stepName.toLowerCase().includes('checktrigger');
26
+
27
+ if (isCheckStep && hasTriggerFlowTypes) {
28
+ const queueName = `${functionName}HdrSqs`;
29
+ return {
30
+ artifacts: [
31
+ {
32
+ path: `${source}/${mainFileName}.js`,
33
+ content: await renderCustom(
34
+ 'triggerCache/CheckTriggerCache_Main.ejs',
35
+ { functionName, flowTag }
36
+ )
37
+ },
38
+ {
39
+ path: `${source}/${functionName}_HdrSqs.js`,
40
+ content: await renderCustom(
41
+ 'triggerCache/CheckTriggerCache_HdrSqs.ejs',
42
+ { functionName, queueName, startConfig }
43
+ )
44
+ }
45
+ ],
46
+ functions: [
47
+ renderSqsFunctionYaml({
48
+ functionName: queueName,
49
+ handlerPath: `${handlerRoot}/${functionName}_HdrSqs.main`,
50
+ roleName: customFlowRoleName(flow.flowTag),
51
+ queueName,
52
+ flowTag,
53
+ flowStepName: step.stepName
54
+ })
55
+ ]
56
+ };
57
+ }
58
+
59
+ const artifacts = [
60
+ {
61
+ path: `${source}/${mainFileName}.js`,
62
+ content: await renderStepMain(functionName, _startConfig(flow))
63
+ }
64
+ ];
65
+ const functions = [];
66
+
67
+ let stepEvents = [];
68
+ if (Array.isArray(step.event)) {
69
+ stepEvents = step.event;
70
+ }
71
+ const hasSqs = stepEvents.includes('extTopic') || stepEvents.includes('sqs');
72
+
73
+ if (hasSqs) {
74
+ const queueName = `${functionName}HdrSqs`;
75
+ artifacts.push({
76
+ path: `${source}/${functionName}_HdrSqs.js`,
77
+ content: await renderShared('FlowHandler_HdrSqs.ejs', {
78
+ flowTag: flow.flowTag,
79
+ flowStepName: step.stepName,
80
+ functionName,
81
+ mainFileName,
82
+ startConfig,
83
+ queueName
84
+ })
85
+ });
86
+ functions.push(
87
+ renderSqsFunctionYaml({
88
+ functionName: queueName,
89
+ handlerPath: `${handlerRoot}/${functionName}_HdrSqs.main`,
90
+ roleName: customFlowRoleName(flow.flowTag),
91
+ queueName,
92
+ flowTag,
93
+ flowStepName: step.stepName
94
+ })
95
+ );
96
+ }
97
+
98
+ return { artifacts, functions };
99
+ }
100
+
101
+ export async function emitDsqStep({ flow, step, flowTag, stepName }) {
102
+ const source = `app/src/generatedCode/FlowSchemas/${flowTag}/source`;
103
+ const handlerRoot = `src/generatedCode/FlowSchemas/${flowTag}/source`;
104
+ const functionName = `${flowTag}${stepName}`;
105
+ const mainFileName = `${functionName}_Main`;
106
+ const startConfig = stepConfig(flow, step);
107
+
108
+ let stepEvents = [];
109
+ if (Array.isArray(step.event)) {
110
+ stepEvents = step.event;
111
+ }
112
+ const artifacts = [];
113
+ if (!stepEvents.includes('extTopic')) {
114
+ artifacts.push({
115
+ path: `${source}/${mainFileName}.js`,
116
+ content: await renderStepMain(functionName, startConfig)
117
+ });
118
+ }
119
+ const functions = [];
120
+
121
+ const hasDsq = stepEvents.includes('dsq');
122
+
123
+ if (hasDsq) {
124
+ const queueName = `${functionName}HdrDsq`;
125
+ artifacts.push({
126
+ path: `${source}/${functionName}_HdrDsq.js`,
127
+ content: await renderDsq('FlowHandler_HdrDsq.ejs', {
128
+ flowTag: flow.flowTag,
129
+ flowStepName: step.stepName,
130
+ functionName,
131
+ mainFileName,
132
+ startConfig,
133
+ queueName
134
+ })
135
+ });
136
+ functions.push(
137
+ renderSqsFunctionYaml({
138
+ functionName: queueName,
139
+ handlerPath: `${handlerRoot}/${functionName}_HdrDsq.main`,
140
+ roleName: customFlowRoleName(flow.flowTag),
141
+ queueName,
142
+ flowTag,
143
+ flowStepName: step.stepName
144
+ })
145
+ );
146
+ }
147
+
148
+ return { artifacts, functions };
149
+ }
150
+
151
+ export async function emitOwnTopicRoot(flow, objects) {
152
+ const tag = upperFirst(flow.flowTag);
153
+ const source = `app/src/generatedCode/FlowSchemas/${tag}/source`;
154
+ const handlerRoot = `src/generatedCode/FlowSchemas/${tag}/source`;
155
+ const mainFileName = `${tag}_Main`;
156
+ const wbsMainFileName = `${tag}_WbsMain`;
157
+ const shared = {
158
+ flowTag: flow.flowTag,
159
+ flowStepName: '',
160
+ upperCaseFlowTag: tag,
161
+ startConfig: _startConfig(flow)
162
+ };
163
+ const isRbac = flowHasRbac(flow, objects);
164
+ const ownArtifacts = [
165
+ {
166
+ path: `${source}/${mainFileName}.js`,
167
+ content: await renderEndpointMain(flow, mainFileName, objects)
168
+ },
169
+ {
170
+ path: `${source}/${tag}_HdrSqs.js`,
171
+ content: await renderShared('FlowHandler_HdrSqs.ejs', {
172
+ ...shared,
173
+ functionName: mainFileName,
174
+ mainFileName,
175
+ queueName: `${tag}HdrSqs`
176
+ })
177
+ },
178
+ {
179
+ path: `${source}/${wbsMainFileName}.js`,
180
+ content: await renderCrudTemplate('FlowMain_Wbs.ejs', {
181
+ ...shared,
182
+ functionName: wbsMainFileName
183
+ })
184
+ },
185
+ {
186
+ path: `${source}/${tag}_HdrWbs.js`,
187
+ content: await renderCrudTemplate('FlowEndpoint_HdrWbs.ejs', {
188
+ ...shared,
189
+ functionName: tag,
190
+ mainFileName: wbsMainFileName,
191
+ route: tag
192
+ })
193
+ }
194
+ ];
195
+
196
+ const ownFunctions = [
197
+ renderWbsFunctionYaml({
198
+ functionName: `${tag}HdrWbs`,
199
+ handlerPath: `${handlerRoot}/${tag}_HdrWbs.main`,
200
+ roleName: customFlowRoleName(flow.flowTag),
201
+ routeName: tag,
202
+ flowTag: flow.flowTag,
203
+ flowStepName: ''
204
+ }),
205
+ renderSqsFunctionYaml({
206
+ functionName: `${tag}HdrSqs`,
207
+ handlerPath: `${handlerRoot}/${tag}_HdrSqs.main`,
208
+ roleName: customFlowRoleName(flow.flowTag),
209
+ queueName: `${tag}HdrSqs`,
210
+ flowTag: flow.flowTag,
211
+ flowStepName: ''
212
+ })
213
+ ];
214
+
215
+ if (isRbac) {
216
+ const rbacStep = (flow.flowSteps || []).find(
217
+ (s) =>
218
+ typeof s?.stepName === 'string' &&
219
+ s.stepName.toLowerCase() === 'rbaccallback'
220
+ );
221
+ const rbacConfig = rbacStep ? stepConfig(flow, rbacStep) : null;
222
+ ownArtifacts.push(
223
+ {
224
+ path: `${source}/${tag}RbacCallback_Main.js`,
225
+ content: await renderCustom('FlowEndpointRbacCallback_Main.ejs', {
226
+ flowTag: flow.flowTag,
227
+ upperCaseFlowTag: tag,
228
+ functionName: `${tag}RbacCallbackMain`
229
+ })
230
+ },
231
+ {
232
+ path: `${source}/${tag}RbacCallback_HdrSqs.js`,
233
+ content: await renderShared('FlowHandler_HdrSqs.ejs', {
234
+ flowTag: flow.flowTag,
235
+ flowStepName: 'RbacCallback',
236
+ mainFileName: `${tag}RbacCallback_Main`,
237
+ functionName: `${tag}RbacCallbackMain`,
238
+ queueName: `${tag}RbacCallbackHdrSqs`,
239
+ startConfig: rbacConfig
240
+ })
241
+ }
242
+ );
243
+ ownFunctions.push(
244
+ renderSqsFunctionYaml({
245
+ functionName: `${tag}RbacCallbackHdrSqs`,
246
+ handlerPath: `${handlerRoot}/${tag}RbacCallback_HdrSqs.main`,
247
+ roleName: customFlowRoleName(flow.flowTag),
248
+ queueName: `${tag}RbacCallbackHdrSqs`,
249
+ flowTag: flow.flowTag,
250
+ flowStepName: 'RbacCallback'
251
+ })
252
+ );
253
+ }
254
+
255
+ return {
256
+ artifacts: ownArtifacts,
257
+ functions: ownFunctions
258
+ };
259
+ }
260
+
261
+ export function _startConfig(flow) {
262
+ const steps = flow.flowSteps ?? [];
263
+ const start =
264
+ steps.find(
265
+ (s) =>
266
+ typeof s?.stepName === 'string' &&
267
+ s.stepName.toLowerCase() === 'inprocess'
268
+ ) ??
269
+ steps.find(
270
+ (s) =>
271
+ typeof s?.stepName === 'string' && s.stepName.toLowerCase() === 'start'
272
+ ) ??
273
+ steps[0];
274
+ if (start) {
275
+ return stepConfig(flow, start);
276
+ }
277
+ return null;
278
+ }
279
+
280
+ export function stepConfig(flow, step) {
281
+ return {
282
+ ...step,
283
+ properties: mapFields(step.properties, flow.stepProperties),
284
+ messageAttributes: mapFields(
285
+ step.messageAttributes,
286
+ flow.stepMessageAttributes
287
+ )
288
+ };
289
+ }
290
+
291
+ export function mapFields(items = [], definitions = {}) {
292
+ return items.map((item) => {
293
+ if (typeof item === 'string') {
294
+ const def = definitions?.[item] ?? {};
295
+ return {
296
+ propertyName: item,
297
+ required: def.required ?? false,
298
+ ...def
299
+ };
300
+ }
301
+ if (typeof item === 'object' && item !== null) {
302
+ const name = item.key ?? item.propertyName;
303
+ const def = definitions?.[name] ?? {};
304
+ return {
305
+ propertyName: name,
306
+ required: item.required ?? def.required ?? false,
307
+ ...def,
308
+ ...item
309
+ };
310
+ }
311
+ return item;
312
+ });
313
+ }
314
+
315
+ export async function renderEndpointMain(flow, functionName, objects = []) {
316
+ const isRbac = flowHasRbac(flow, objects);
317
+ const matchedObject = objects.find(
318
+ (o) => o.objectType === flow.objType?.objectType
319
+ );
320
+ let rbacServiceTag = null;
321
+ if (matchedObject) {
322
+ const belongTo = matchedObject.belongTo;
323
+ if (belongTo) {
324
+ if (Array.isArray(belongTo)) {
325
+ rbacServiceTag = belongTo[0]?.serviceTag;
326
+ } else {
327
+ rbacServiceTag = belongTo?.serviceTag;
328
+ }
329
+ }
330
+ }
331
+ if (!rbacServiceTag) {
332
+ rbacServiceTag = flow.objType?.serviceTag || flow.serviceTag || 'Rbac';
333
+ }
334
+
335
+ const enrichedFlow = {
336
+ ...flow,
337
+ isRbac
338
+ };
339
+
340
+ return renderCustom('FlowEndpoint_Main.ejs', {
341
+ flow: enrichedFlow,
342
+ flowTag: flow.flowTag,
343
+ upperCaseFlowTag: upperFirst(flow.flowTag),
344
+ functionName,
345
+ rbacServiceTag,
346
+ tableName: storedCacheTableName(flow, objects),
347
+ startConfig: _startConfig(flow)
348
+ });
349
+ }
350
+
351
+ export function storedCacheTableName(flow, objects) {
352
+ if (flow.statusType !== 'storedCache') {
353
+ return null;
354
+ }
355
+ const candidates = objects.filter(
356
+ (object) => object.objectType === flow.objType?.objectType
357
+ );
358
+ let object;
359
+ if (flow.objType?.serviceTag) {
360
+ object =
361
+ candidates.find(
362
+ (candidate) => candidate.serviceTag === flow.objType.serviceTag
363
+ ) ?? candidates.find((candidate) => candidate.serviceTag === undefined);
364
+ } else {
365
+ object = candidates[0];
366
+ }
367
+ const targetResource = Object.values(object?.storageResources ?? {}).find(
368
+ (resource) =>
369
+ resource?.storageType === 'dynamo' ||
370
+ resource?.storageType === 'dynamoDB' ||
371
+ !resource?.storageType
372
+ );
373
+ if (targetResource?.tableName) {
374
+ return targetResource.tableName;
375
+ }
376
+ return null;
377
+ }
378
+
379
+ export async function renderStepMain(functionName, startConfig = null) {
380
+ return renderCustom('FlowStep_Main.ejs', { functionName, startConfig });
381
+ }
382
+
383
+ export function renderMain(functionName) {
384
+ return `export default async function ${functionName}(_izContext, requestParams, callingFlowConfig = {}) {\n try {\n _izContext?.logger?.debug('${functionName} requestParams', requestParams);\n //(<endpointHook>)\n //(</endpointHook>)\n } catch (error) {\n _izContext?.logger?.error('${functionName} failed', error);\n throw error;\n }\n}\n`;
385
+ }