@izara_project/izara-core-generate-service-code 1.0.90 → 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 (82) 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/emitDynamicCrudFlowSchemas.js +2 -2
  5. package/src/emit/crud/generateCrudApplicationArtifacts.js +15 -17
  6. package/src/emit/crud/generateDynamicCrudFlowSchemas.js +16 -21
  7. package/src/emit/crud/loadLocalSchemaArrays.js +4 -8
  8. package/src/emit/crud/templates/CreateAfterHookCallback_Main.ejs +6 -6
  9. package/src/emit/crud/templates/CreateBeforeHookCallback_Main.ejs +3 -3
  10. package/src/emit/crud/templates/CreateComplete_Main.ejs +22 -22
  11. package/src/emit/crud/templates/CreateEndpoint_Main.ejs +18 -18
  12. package/src/emit/crud/templates/CreateLogicalLib.ejs +47 -47
  13. package/src/emit/crud/templates/CreateNodeCallback_Main.ejs +24 -24
  14. package/src/emit/crud/templates/DeleteAfterHookCallback_Main.ejs +5 -5
  15. package/src/emit/crud/templates/DeleteBeforeHookCallback_Main.ejs +3 -3
  16. package/src/emit/crud/templates/DeleteComplete_Main.ejs +23 -23
  17. package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +15 -15
  18. package/src/emit/crud/templates/DeleteLogicalLib.ejs +19 -19
  19. package/src/emit/crud/templates/FlowEndpointRbacCallback_Main.ejs +3 -3
  20. package/src/emit/crud/templates/UpdateAfterHookCallback_Main.ejs +5 -5
  21. package/src/emit/crud/templates/UpdateBeforeHookCallback_Main.ejs +3 -3
  22. package/src/emit/crud/templates/UpdateComplete_Main.ejs +22 -22
  23. package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +15 -15
  24. package/src/emit/crud/templates/UpdateLogicalLib.ejs +33 -33
  25. package/src/emit/custom/customFlowPaths.js +149 -0
  26. package/src/emit/custom/customFlowS3.js +156 -0
  27. package/src/emit/custom/customFlowSteps.js +385 -0
  28. package/src/emit/custom/customFlowTemplates.js +28 -0
  29. package/src/emit/custom/customFlows.js +48 -19
  30. package/src/emit/custom/emitCustomFlowApplicationArtifacts.js +57 -692
  31. package/src/emit/custom/generateCustomFlowApplicationArtifacts.js +27 -25
  32. package/src/emit/custom/templates/FlowEndpointRbacCallback_Main.ejs +7 -7
  33. package/src/emit/custom/templates/s3/ConfirmReserved_HdrSqs.ejs +3 -3
  34. package/src/emit/custom/templates/s3/ConfirmReserved_Main.ejs +3 -3
  35. package/src/emit/custom/templates/s3/CreatePreSignUrl_HdrSqs.ejs +3 -3
  36. package/src/emit/custom/templates/s3/CreatePreSignUrl_Main.ejs +4 -4
  37. package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +26 -6
  38. package/src/emit/rbac/emitRbacApplicationArtifacts.js +40 -13
  39. package/src/emit/rbac/generateCreateTargetRoleHandler.js +11 -13
  40. package/src/emit/rbac/generateDynamicRbacFlowSchemas.js +14 -18
  41. package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +13 -7
  42. package/src/emit/relationship/emitDynamicRelationshipFlowSchemas.js +1 -1
  43. package/src/emit/relationship/generateDynamicRelationshipFlowSchemas.js +16 -19
  44. package/src/emit/relationship/generateRelationshipApplicationArtifacts.js +19 -19
  45. package/src/emit/relationship/templates/ChangeRelationshipComplete_HdrSqs.ejs +2 -2
  46. package/src/emit/relationship/templates/ChangeRelationshipComplete_Main.ejs +6 -6
  47. package/src/emit/relationship/templates/ChangeRelationship_Main.ejs +17 -17
  48. package/src/emit/relationship/templates/CreateRelationshipComplete_HdrSqs.ejs +2 -2
  49. package/src/emit/relationship/templates/CreateRelationshipComplete_Main.ejs +6 -6
  50. package/src/emit/relationship/templates/CreateRelationship_Main.ejs +14 -14
  51. package/src/emit/relationship/templates/DeleteRelationshipComplete_HdrSqs.ejs +2 -2
  52. package/src/emit/relationship/templates/DeleteRelationshipComplete_Main.ejs +6 -6
  53. package/src/emit/relationship/templates/DeleteRelationship_Main.ejs +10 -10
  54. package/src/emit/relationship/templates/GetRelationshipComplete_HdrSqs.ejs +2 -2
  55. package/src/emit/relationship/templates/GetRelationshipComplete_Main.ejs +5 -5
  56. package/src/emit/relationship/templates/GetRelationship_Main.ejs +9 -9
  57. package/src/emit/relationship/templates/MoveRelationshipComplete_HdrSqs.ejs +2 -2
  58. package/src/emit/relationship/templates/MoveRelationshipComplete_Main.ejs +6 -6
  59. package/src/emit/relationship/templates/MoveRelationship_Main.ejs +15 -15
  60. package/src/emit/relationship/templates/UpdateRelationshipComplete_HdrSqs.ejs +2 -2
  61. package/src/emit/relationship/templates/UpdateRelationshipComplete_Main.ejs +6 -6
  62. package/src/emit/relationship/templates/UpdateRelationship_Main.ejs +11 -11
  63. package/src/emit/resource/dynamoResourceArtifacts.js +18 -0
  64. package/src/emit/resource/emitResourceArtifacts.js +13 -1251
  65. package/src/emit/resource/generateResourceArtifacts.js +20 -20
  66. package/src/emit/resource/iamResourceArtifacts.js +612 -0
  67. package/src/emit/resource/resourceState.js +564 -0
  68. package/src/emit/resource/resourceTemplate.js +30 -0
  69. package/src/emit/resource/s3ResourceArtifacts.js +14 -0
  70. package/src/emit/resource/sqsResourceArtifacts.js +113 -0
  71. package/src/emit/shared/runSubsystemGeneration.js +55 -0
  72. package/src/emit/shared/templates/FindData_Main.ejs +19 -19
  73. package/src/emit/shared/templates/PaginateProcessLogical_Main.ejs +3 -3
  74. package/src/emit/shared/templates/ProcessLogical_Main.ejs +15 -15
  75. package/src/emit/system/emitSystemWebSocketArtifacts.js +2 -1
  76. package/test/createTargetRoleHandler.test.js +62 -4
  77. package/test/crudApplicationArtifacts.test.js +75 -3
  78. package/test/customFlowApplicationArtifacts.test.js +98 -0
  79. package/test/dynamicCrudFlowSchemas.test.js +2 -2
  80. package/test/dynamicRbacFlowSchemas.test.js +32 -4
  81. package/test/relationshipApplicationArtifacts.test.js +1 -1
  82. package/test/resourceArtifacts.test.js +99 -0
@@ -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
+ }
@@ -0,0 +1,28 @@
1
+ import ejsLib from 'ejs';
2
+ import { readFile } from 'node:fs/promises';
3
+
4
+ const SHARED_TEMPLATE_URL = new URL('../shared/templates/', import.meta.url);
5
+ const CRUD_TEMPLATE_URL = new URL('../crud/templates/', import.meta.url);
6
+ const CUSTOM_TEMPLATE_URL = new URL('./templates/', import.meta.url);
7
+
8
+ export async function renderShared(templateName, data) {
9
+ const templatePath = new URL(templateName, SHARED_TEMPLATE_URL);
10
+ const templateContent = await readFile(templatePath, 'utf8');
11
+ return ejsLib.render(templateContent, data);
12
+ }
13
+
14
+ export async function renderCrudTemplate(templateName, data) {
15
+ const templatePath = new URL(templateName, CRUD_TEMPLATE_URL);
16
+ const templateContent = await readFile(templatePath, 'utf8');
17
+ return ejsLib.render(templateContent, data);
18
+ }
19
+
20
+ export async function renderDsq(templateName, data) {
21
+ return renderShared(templateName, data);
22
+ }
23
+
24
+ export async function renderCustom(templateName, data) {
25
+ const templatePath = new URL(templateName, CUSTOM_TEMPLATE_URL);
26
+ const templateContent = await readFile(templatePath, 'utf8');
27
+ return ejsLib.render(templateContent, data).replace(/\n$/, '');
28
+ }
@@ -5,23 +5,51 @@ const SUPPORTED_EVENTS = new Set([
5
5
  'lambdaSyncApi',
6
6
  'ownTopic',
7
7
  's3',
8
- 'dsq'
8
+ 'dsq',
9
+ 'generateCode'
9
10
  ]);
10
11
 
11
12
  export function supportedCustomFlows(flows) {
12
13
  if (!Array.isArray(flows)) {
13
14
  throw new TypeError('flows must be an array');
14
15
  }
15
- return flows.filter(
16
- (flow) =>
17
- typeof flow?.flowTag === 'string' &&
18
- flow.flowTag !== '' &&
19
- (!flow.generatedCodeConfig ||
20
- (flow.generatedCodeConfig.codeHookTag &&
21
- !flow.event.includes('ownTopic'))) &&
22
- Array.isArray(flow.event) &&
23
- flow.event.some((event) => SUPPORTED_EVENTS.has(event))
24
- );
16
+ return flows.filter((flow) => {
17
+ if (typeof flow?.flowTag !== 'string' || flow.flowTag === '') {
18
+ return false;
19
+ }
20
+ if (!Array.isArray(flow.event)) {
21
+ return false;
22
+ }
23
+ const hasSupportedEvent = flow.event.some((e) => SUPPORTED_EVENTS.has(e));
24
+ if (!hasSupportedEvent) {
25
+ return false;
26
+ }
27
+ if (flow.generatedCodeConfig) {
28
+ if (flowHasOwnTopic(flow)) {
29
+ return false;
30
+ }
31
+ if (!flow.generatedCodeConfig.codeHookTag) {
32
+ return false;
33
+ }
34
+ }
35
+ return true;
36
+ });
37
+ }
38
+
39
+ export function flowHasOwnTopic(flow) {
40
+ if (!Array.isArray(flow?.event)) {
41
+ return false;
42
+ }
43
+ if (flow.event.includes('ownTopic')) {
44
+ return true;
45
+ }
46
+ if (
47
+ flow.event.includes('generateCode') &&
48
+ flow?.generatedCodeConfig?.invocationType === 'ownTopic'
49
+ ) {
50
+ return true;
51
+ }
52
+ return false;
25
53
  }
26
54
 
27
55
  export function customFlowRoleName(flowTag) {
@@ -116,14 +144,15 @@ export function generatedOwnTopicFlows(flows) {
116
144
  if (!Array.isArray(flows)) {
117
145
  throw new TypeError('flows must be an array');
118
146
  }
119
- return flows.filter(
120
- (flow) =>
121
- typeof flow?.flowTag === 'string' &&
122
- flow.flowTag !== '' &&
123
- flow.generatedCodeConfig &&
124
- Array.isArray(flow.event) &&
125
- flow.event.includes('ownTopic')
126
- );
147
+ return flows.filter((flow) => {
148
+ if (typeof flow?.flowTag !== 'string' || flow.flowTag === '') {
149
+ return false;
150
+ }
151
+ if (!flow.generatedCodeConfig) {
152
+ return false;
153
+ }
154
+ return flowHasOwnTopic(flow);
155
+ });
127
156
  }
128
157
 
129
158
  export function generatedDsqFlows(flows) {