@izara_project/izara-core-generate-service-code 1.0.87 → 1.0.89

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 (32) hide show
  1. package/package.json +1 -1
  2. package/src/compile/flowValidator.js +25 -0
  3. package/src/compile/loadSchemas.js +199 -10
  4. package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +3 -7
  5. package/src/emit/crud/crudActionPlan.js +105 -6
  6. package/src/emit/crud/emitCrudApplicationArtifacts.js +63 -3
  7. package/src/emit/crud/emitDynamicCrudFlowSchemas.js +15 -32
  8. package/src/emit/crud/templates/CreateAfterHookCallback_Main.ejs +121 -0
  9. package/src/emit/crud/templates/CreateBeforeHookCallback_Main.ejs +108 -0
  10. package/src/emit/crud/templates/CreateEndpoint_Main.ejs +140 -340
  11. package/src/emit/crud/templates/CreateLogicalLib.ejs +338 -82
  12. package/src/emit/crud/templates/CreateNodeCallback_Main.ejs +90 -0
  13. package/src/emit/crud/templates/DeleteAfterHookCallback_Main.ejs +118 -0
  14. package/src/emit/crud/templates/DeleteBeforeHookCallback_Main.ejs +99 -0
  15. package/src/emit/crud/templates/DeleteComplete_Main.ejs +124 -10
  16. package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +151 -179
  17. package/src/emit/crud/templates/DeleteLogicalLib.ejs +244 -27
  18. package/src/emit/crud/templates/UpdateAfterHookCallback_Main.ejs +120 -0
  19. package/src/emit/crud/templates/UpdateBeforeHookCallback_Main.ejs +112 -0
  20. package/src/emit/crud/templates/UpdateComplete_Main.ejs +104 -10
  21. package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +166 -185
  22. package/src/emit/crud/templates/UpdateLogicalLib.ejs +123 -3
  23. package/src/emit/custom/customFlows.js +3 -1
  24. package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +8 -2
  25. package/src/emit/rbac/templates/CancelUsage_Main.ejs +34 -14
  26. package/src/emit/rbac/templates/ConfirmUsage_Main.ejs +34 -14
  27. package/src/emit/resource/emitResourceArtifacts.js +119 -59
  28. package/test/crudApplicationArtifacts.test.js +876 -0
  29. package/test/dynamicCrudFlowSchemas.test.js +10 -5
  30. package/test/dynamicRbacFlowSchemas.test.js +24 -2
  31. package/test/graphDrivenFlowSchema.test.js +36 -0
  32. package/test/resourceArtifacts.test.js +271 -12
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@izara_project/izara-core-generate-service-code",
3
- "version": "1.0.87",
3
+ "version": "1.0.89",
4
4
  "description": "Code for locally generating per service files",
5
5
  "homepage": "https://bitbucket.org/izara-core-support-services/izara-core-support-services-generate-service-code#readme",
6
6
  "repository": {
@@ -32,6 +32,31 @@ export function validateFlowSchema(flowSchema) {
32
32
  );
33
33
  }
34
34
 
35
+ let flowEvents = [];
36
+ if (Array.isArray(flowSchema.event)) {
37
+ flowEvents = flowSchema.event;
38
+ }
39
+ const syncEvents = ['lambdaSyncInv', 'lambdaSyncApi'];
40
+ let hasSyncEvent = false;
41
+ for (const eventName of flowEvents) {
42
+ if (syncEvents.includes(eventName)) {
43
+ hasSyncEvent = true;
44
+ break;
45
+ }
46
+ }
47
+
48
+ if (hasSyncEvent && steps.length > 1) {
49
+ let flowTag = 'unknown';
50
+ if (flowSchema.flowTag) {
51
+ flowTag = flowSchema.flowTag;
52
+ }
53
+ throw new Error(
54
+ `FlowSchema validation error: Flow '${flowTag}' with synchronous ` +
55
+ `events ('lambdaSyncInv' | 'lambdaSyncApi') must only define a ` +
56
+ `single entry step 'Start'`
57
+ );
58
+ }
59
+
35
60
  const entryStep = steps[0];
36
61
  if (
37
62
  !entryStep ||
@@ -22,11 +22,66 @@ const VALID_INITIATE_BY_ENUM = [
22
22
  'systemNoUser'
23
23
  ];
24
24
 
25
+ const VALID_CODE_HOOK_TAG_ENUM = ['before', 'after'];
26
+ const VALID_GENERATE_CODE_TAG_ENUM = ['create', 'update', 'delete'];
27
+
25
28
  if (basicValidatorSchema?.basicFlowSchema?.properties?.initiateBy) {
26
29
  basicValidatorSchema.basicFlowSchema.properties.initiateBy.enum =
27
30
  VALID_INITIATE_BY_ENUM;
28
31
  }
29
32
 
33
+ if (
34
+ basicValidatorSchema?.basicFlowSchema?.properties?.generatedCodeConfig
35
+ ?.properties?.codeHookTag
36
+ ) {
37
+ basicValidatorSchema.basicFlowSchema.properties.generatedCodeConfig.properties.codeHookTag.enum =
38
+ VALID_CODE_HOOK_TAG_ENUM;
39
+ }
40
+
41
+ if (
42
+ basicValidatorSchema?.basicFlowSchema?.properties?.generatedCodeConfig
43
+ ?.properties?.generateCodeTag
44
+ ) {
45
+ basicValidatorSchema.basicFlowSchema.properties.generatedCodeConfig.properties.generateCodeTag = {
46
+ anyOf: [
47
+ {
48
+ type: 'array',
49
+ items: {
50
+ type: 'string',
51
+ enum: VALID_GENERATE_CODE_TAG_ENUM
52
+ }
53
+ },
54
+ {
55
+ type: 'string',
56
+ enum: VALID_GENERATE_CODE_TAG_ENUM
57
+ }
58
+ ]
59
+ };
60
+ }
61
+
62
+ if (
63
+ basicValidatorSchema?.basicFlowSchema?.properties?.generatedCodeConfig
64
+ ?.properties
65
+ ) {
66
+ basicValidatorSchema.basicFlowSchema.properties.generatedCodeConfig.properties.objType = {
67
+ anyOf: [
68
+ { type: 'string' },
69
+ {
70
+ type: 'array',
71
+ items: { type: 'string' }
72
+ },
73
+ {
74
+ type: 'object',
75
+ properties: {
76
+ objectType: { type: 'string' },
77
+ serviceTag: { type: 'string' }
78
+ },
79
+ required: ['objectType']
80
+ }
81
+ ]
82
+ };
83
+ }
84
+
30
85
  const VALID_GENERATED_BY_ENUM = [
31
86
  'user',
32
87
  'systemWithUser',
@@ -113,9 +168,101 @@ export async function loadLocalSchemaDirectory(
113
168
  if (directoryName === 'FlowSchemas') {
114
169
  for (const schema of loadedSchemas) {
115
170
  if (Object.prototype.hasOwnProperty.call(schema?.generatedCodeConfig ?? {}, 'codeHookTag')) {
116
- throw new Error(
117
- `Unsupported FlowHook configuration in ${entry.name}: generatedCodeConfig.codeHookTag is no longer supported`
118
- );
171
+ const hookTag = schema.generatedCodeConfig.codeHookTag;
172
+ if (hookTag === 'beforeLogical') {
173
+ throw new Error(
174
+ `Unsupported FlowHook configuration in ${entry.name}: generatedCodeConfig.codeHookTag is no longer supported`
175
+ );
176
+ }
177
+ if (hookTag !== 'before' && hookTag !== 'after') {
178
+ throw new Error(
179
+ `Unsupported FlowHook configuration in ${entry.name}: generatedCodeConfig.codeHookTag '${hookTag}' is invalid. Must be 'before' or 'after'`
180
+ );
181
+ }
182
+ }
183
+ if (
184
+ Object.prototype.hasOwnProperty.call(
185
+ schema?.generatedCodeConfig ?? {},
186
+ 'generateCodeTag'
187
+ )
188
+ ) {
189
+ const codeTag = schema.generatedCodeConfig.generateCodeTag;
190
+ if (Array.isArray(codeTag)) {
191
+ if (codeTag.length === 0) {
192
+ throw new Error(
193
+ `Unsupported FlowHook configuration in ${entry.name}: ` +
194
+ `generatedCodeConfig.generateCodeTag array must not be empty`
195
+ );
196
+ }
197
+ for (const tag of codeTag) {
198
+ if (
199
+ typeof tag !== 'string' ||
200
+ !VALID_GENERATE_CODE_TAG_ENUM.includes(tag.toLowerCase())
201
+ ) {
202
+ throw new Error(
203
+ `Unsupported FlowHook configuration in ${entry.name}: ` +
204
+ `generatedCodeConfig.generateCodeTag contains invalid ` +
205
+ `tag '${tag}'. Must be 'create', 'update', or 'delete'`
206
+ );
207
+ }
208
+ }
209
+ } else if (typeof codeTag === 'string') {
210
+ if (!VALID_GENERATE_CODE_TAG_ENUM.includes(codeTag.toLowerCase())) {
211
+ throw new Error(
212
+ `Unsupported FlowHook configuration in ${entry.name}: ` +
213
+ `generatedCodeConfig.generateCodeTag '${codeTag}' ` +
214
+ `is invalid. Must be 'create', 'update', or 'delete'`
215
+ );
216
+ }
217
+ } else {
218
+ throw new Error(
219
+ `Unsupported FlowHook configuration in ${entry.name}: ` +
220
+ `generatedCodeConfig.generateCodeTag must be an array or string`
221
+ );
222
+ }
223
+ }
224
+ if (
225
+ Object.prototype.hasOwnProperty.call(
226
+ schema?.generatedCodeConfig ?? {},
227
+ 'objType'
228
+ )
229
+ ) {
230
+ const hookObjType = schema.generatedCodeConfig.objType;
231
+ if (Array.isArray(hookObjType)) {
232
+ if (hookObjType.length === 0) {
233
+ throw new Error(
234
+ `Unsupported FlowHook configuration in ${entry.name}: ` +
235
+ `generatedCodeConfig.objType array must not be empty`
236
+ );
237
+ }
238
+ for (const item of hookObjType) {
239
+ const strVal = typeof item === 'string' ? item : item?.objectType;
240
+ if (!strVal || typeof strVal !== 'string') {
241
+ throw new Error(
242
+ `Unsupported FlowHook configuration in ${entry.name}: ` +
243
+ `generatedCodeConfig.objType array items must be non-empty strings or objects with objectType`
244
+ );
245
+ }
246
+ }
247
+ } else if (typeof hookObjType === 'object' && hookObjType !== null) {
248
+ if (
249
+ !hookObjType.objectType ||
250
+ typeof hookObjType.objectType !== 'string'
251
+ ) {
252
+ throw new Error(
253
+ `Unsupported FlowHook configuration in ${entry.name}: ` +
254
+ `generatedCodeConfig.objType object must have string property objectType`
255
+ );
256
+ }
257
+ } else if (
258
+ typeof hookObjType !== 'string' ||
259
+ hookObjType.trim() === ''
260
+ ) {
261
+ throw new Error(
262
+ `Unsupported FlowHook configuration in ${entry.name}: ` +
263
+ `generatedCodeConfig.objType must be a non-empty string, array, or object`
264
+ );
265
+ }
119
266
  }
120
267
  }
121
268
  }
@@ -177,13 +324,55 @@ export async function loadLocalSchemaDirectory(
177
324
  { logger },
178
325
  schema
179
326
  );
180
- if (!status && Array.isArray(errors) && VALID_INITIATE_BY_ENUM.includes(schema?.initiateBy)) {
181
- errors = errors.filter(
182
- (err) =>
183
- !err.includes('initiateBy') &&
184
- !err.includes('must be equal to one of the allowed values (enum)') &&
185
- !(err.includes('should be one of enum') && err.includes(schema?.initiateBy))
186
- );
327
+ if (!status && Array.isArray(errors)) {
328
+ if (VALID_INITIATE_BY_ENUM.includes(schema?.initiateBy)) {
329
+ errors = errors.filter(
330
+ (err) =>
331
+ !err.includes('initiateBy') &&
332
+ !err.includes('must be equal to one of the allowed values (enum)') &&
333
+ !(err.includes('should be one of enum') && err.includes(schema?.initiateBy))
334
+ );
335
+ }
336
+ if (
337
+ VALID_CODE_HOOK_TAG_ENUM.includes(
338
+ schema?.generatedCodeConfig?.codeHookTag
339
+ )
340
+ ) {
341
+ errors = errors.filter(
342
+ (err) =>
343
+ !err.includes('codeHookTag') &&
344
+ !err.includes('must be equal to one of the allowed values (enum)') &&
345
+ !(
346
+ err.includes('should be one of enum') &&
347
+ err.includes(schema?.generatedCodeConfig?.codeHookTag)
348
+ )
349
+ );
350
+ }
351
+ const generateCodeTag =
352
+ schema?.generatedCodeConfig?.generateCodeTag;
353
+ let isGenerateCodeTagValid = false;
354
+ if (Array.isArray(generateCodeTag)) {
355
+ isGenerateCodeTagValid =
356
+ generateCodeTag.length > 0 &&
357
+ generateCodeTag.every((t) => {
358
+ return (
359
+ typeof t === 'string' &&
360
+ VALID_GENERATE_CODE_TAG_ENUM.includes(t.toLowerCase())
361
+ );
362
+ });
363
+ } else if (typeof generateCodeTag === 'string') {
364
+ isGenerateCodeTagValid = VALID_GENERATE_CODE_TAG_ENUM.includes(
365
+ generateCodeTag.toLowerCase()
366
+ );
367
+ }
368
+ if (isGenerateCodeTagValid) {
369
+ errors = errors.filter((err) => {
370
+ return (
371
+ !err.includes('generateCodeTag') &&
372
+ !err.includes('must match a schema in "anyOf"')
373
+ );
374
+ });
375
+ }
187
376
  if (errors.length === 0) {
188
377
  status = true;
189
378
  }
@@ -181,12 +181,6 @@ const tableConfigs = {
181
181
 
182
182
  const currentServiceTag = (typeof serviceTag !== 'undefined' && serviceTag) ? serviceTag : ((typeof project !== 'undefined' && project?.serviceTag) ? project.serviceTag : '');
183
183
  const rbacSubs = [];
184
- if (crud && rbac) {
185
- if (typeof hasQuotaReservation !== 'undefined' && hasQuotaReservation) {
186
- rbacSubs.push({ serviceTag: 'Rbac', topicName: 'ConfirmUsage_Out', sqsEndpoint: 'CreateCompleteHdrSqs' });
187
- rbacSubs.push({ serviceTag: 'Rbac', topicName: 'CancelUsage_Out', sqsEndpoint: 'CreateCompleteHdrSqs' });
188
- }
189
- }
190
184
 
191
185
  if (typeof customRbacFlowTags !== 'undefined' && customRbacFlowTags && customRbacFlowTags.length > 0) {
192
186
  const allRbacTags = Array.from(new Set([
@@ -309,7 +303,9 @@ function roleConfigs() {
309
303
  Effect: 'Allow',
310
304
  Action: ['lambda:InvokeFunction'],
311
305
  Resource: [
312
- `arn:aws:lambda:${process.env.iz_region}:${process.env.iz_accountId}:function:${lambdaSharedLib.lambdaFunctionName(_izContext, 'ValidatorRbacHdrInv', 'Rbac')}`<% if (rbac) { %>,
306
+ `arn:aws:lambda:${process.env.iz_region}:${process.env.iz_accountId}:function:${lambdaSharedLib.lambdaFunctionName(_izContext, 'ValidatorRbacHdrInv', 'Rbac')}`,
307
+ `arn:aws:lambda:${process.env.iz_region}:${process.env.iz_accountId}:function:${lambdaSharedLib.lambdaFunctionName(_izContext, 'ConfirmUsageHdrInv', 'Rbac')}`,
308
+ `arn:aws:lambda:${process.env.iz_region}:${process.env.iz_accountId}:function:${lambdaSharedLib.lambdaFunctionName(_izContext, 'CancelUsageHdrInv', 'Rbac')}`<% if (rbac) { %>,
313
309
  `arn:aws:lambda:${process.env.iz_region}:${process.env.iz_accountId}:function:${lambdaSharedLib.lambdaFunctionName(_izContext, 'ValidatorRbacHdrInv')}`<% } %><% (rbacValidatorServiceTags || []).forEach(function(tag) { %>,
314
310
  `arn:aws:lambda:${process.env.iz_region}:${process.env.iz_accountId}:function:${lambdaSharedLib.lambdaFunctionName(_izContext, 'ValidatorRbacHdrInv', '<%= tag %>')}`<% }); %>
315
311
  ]
@@ -1,6 +1,32 @@
1
1
  export const CRUD_ACTIONS = ['Create', 'Update', 'Delete', 'Get'];
2
2
 
3
- export function createCrudActionPlans(objects = []) {
3
+ export function findHooksForAction(flows = [], action) {
4
+ if (!Array.isArray(flows)) {
5
+ return [];
6
+ }
7
+ const actionLower = action?.toLowerCase();
8
+ return flows.filter((flow) => {
9
+ const config = flow?.generatedCodeConfig;
10
+ if (!config) {
11
+ return false;
12
+ }
13
+ const tag = config.generateCodeTag || config.generatedCodeTag;
14
+ if (!tag) {
15
+ return false;
16
+ }
17
+ if (Array.isArray(tag)) {
18
+ return tag.some((t) => {
19
+ return typeof t === 'string' && t.toLowerCase() === actionLower;
20
+ });
21
+ }
22
+ if (typeof tag === 'string') {
23
+ return tag.toLowerCase() === actionLower;
24
+ }
25
+ return false;
26
+ });
27
+ }
28
+
29
+ export function createCrudActionPlans(objects = [], flows = []) {
4
30
  const hasGraph = hasGraphStorageResource(objects);
5
31
  const hasRbac = objects.some(
6
32
  (object) => isCrudObject(object) && hasRbacObject(object, objects)
@@ -12,29 +38,102 @@ export function createCrudActionPlans(objects = []) {
12
38
  return Object.fromEntries(
13
39
  CRUD_ACTIONS.map((action) => [
14
40
  action,
15
- createCrudActionPlan(action, { hasGraph, hasRbac, isBillable })
41
+ createCrudActionPlan(action, { hasGraph, hasRbac, isBillable, flows })
16
42
  ])
17
43
  );
18
44
  }
19
45
 
46
+ export function resolveHookTargetObjectTypes(hook) {
47
+ const config = hook?.generatedCodeConfig;
48
+ const targetObjType = config?.objType ?? config?.objectType;
49
+ if (targetObjType) {
50
+ if (typeof targetObjType === 'string') {
51
+ return [targetObjType];
52
+ }
53
+ if (Array.isArray(targetObjType)) {
54
+ const types = targetObjType
55
+ .map((t) => (typeof t === 'string' ? t : t?.objectType))
56
+ .filter(Boolean);
57
+ if (types.length > 0) {
58
+ return types;
59
+ }
60
+ }
61
+ if (typeof targetObjType === 'object' && targetObjType?.objectType) {
62
+ return [targetObjType.objectType];
63
+ }
64
+ }
65
+ if (hook?.objType?.objectType) {
66
+ return [hook.objType.objectType];
67
+ }
68
+ if (typeof hook?.objType === 'string') {
69
+ return [hook.objType];
70
+ }
71
+ return null;
72
+ }
73
+
20
74
  export function createCrudActionPlan(
21
75
  action,
22
- { hasGraph = false, hasRbac = false, isBillable = true } = {}
76
+ { hasGraph = false, hasRbac = false, isBillable = true, flows = [] } = {}
23
77
  ) {
24
78
  const actionHasRbac = action !== 'Get' && hasRbac;
25
79
  const outputTopic = action !== 'Get';
26
80
  const hasQuotaReservation = action === 'Create' && hasRbac && isBillable;
27
81
 
82
+ const actionHooks = findHooksForAction(flows, action).map((h) => ({
83
+ ...h,
84
+ targetObjectTypes: resolveHookTargetObjectTypes(h)
85
+ }));
86
+ const beforeHooks = actionHooks.filter(
87
+ (h) => h?.generatedCodeConfig?.codeHookTag === 'before'
88
+ );
89
+ const afterHooks = actionHooks.filter(
90
+ (h) => h?.generatedCodeConfig?.codeHookTag === 'after'
91
+ );
92
+ const hasBeforeHookSync = beforeHooks.some(
93
+ (h) => h?.generatedCodeConfig?.invocationType === 'lambdaSyncInv'
94
+ );
95
+ const hasBeforeHookAsync = beforeHooks.some(
96
+ (h) => h?.generatedCodeConfig?.invocationType === 'ownTopic'
97
+ );
98
+ const hasBeforeHookCallback = outputTopic && hasBeforeHookAsync;
99
+
100
+ const hasAfterHookSync = afterHooks.some(
101
+ (h) => h?.generatedCodeConfig?.invocationType === 'lambdaSyncInv'
102
+ );
103
+ const hasAfterHookAsync = afterHooks.some(
104
+ (h) => h?.generatedCodeConfig?.invocationType === 'ownTopic'
105
+ );
106
+ const hasAfterHookCallback = outputTopic && hasAfterHookAsync;
107
+
108
+ const hasCreateNodeCallback =
109
+ outputTopic &&
110
+ action === 'Create' &&
111
+ actionHasRbac &&
112
+ hasGraph &&
113
+ hasQuotaReservation;
114
+
115
+ const hasComplete =
116
+ outputTopic &&
117
+ !hasCreateNodeCallback &&
118
+ (actionHasRbac || hasGraph || hasAfterHookCallback);
119
+
28
120
  return {
29
121
  action,
30
122
  outputTopic,
31
123
  hasGraph: outputTopic && hasGraph,
32
124
  hasRbac: actionHasRbac,
33
125
  hasQuotaReservation,
34
- hasComplete: outputTopic && (actionHasRbac || hasGraph),
126
+ hasComplete,
35
127
  hasRbacCallback: false,
36
- hasCreateNodeCallback:
37
- outputTopic && action === 'Create' && actionHasRbac && hasGraph && hasQuotaReservation
128
+ hasCreateNodeCallback,
129
+ hasBeforeHookSync,
130
+ hasBeforeHookAsync,
131
+ hasBeforeHookCallback,
132
+ hasAfterHookSync,
133
+ hasAfterHookAsync,
134
+ hasAfterHookCallback,
135
+ beforeHooks,
136
+ afterHooks
38
137
  };
39
138
  }
40
139
 
@@ -51,7 +51,7 @@ export async function emitCrudApplicationArtifacts({
51
51
  }
52
52
 
53
53
  const handlers = await Promise.all(
54
- ACTIONS.map((action) => emitAction(action, objects, serviceTag))
54
+ ACTIONS.map((action) => emitAction(action, objects, serviceTag, flows))
55
55
  );
56
56
  return [
57
57
  ...handlers.flatMap((handler) => handler.artifacts),
@@ -88,6 +88,10 @@ export function crudApplicationManagedPaths() {
88
88
  `${source}/${action}RbacCallback_HdrSqs.js`,
89
89
  `${source}/${action}NodeCallback_Main.js`,
90
90
  `${source}/${action}NodeCallback_HdrSqs.js`,
91
+ `${source}/${action}BeforeHookCallback_Main.js`,
92
+ `${source}/${action}BeforeHookCallback_HdrSqs.js`,
93
+ `${source}/${action}AfterHookCallback_Main.js`,
94
+ `${source}/${action}AfterHookCallback_HdrSqs.js`,
91
95
  `${source}/${action}Complete_Main.js`,
92
96
  `${source}/${action}Complete_HdrSqs.js`
93
97
  );
@@ -98,10 +102,10 @@ export function crudApplicationManagedPaths() {
98
102
  ];
99
103
  }
100
104
 
101
- async function emitAction(action, objects, serviceTag) {
105
+ async function emitAction(action, objects, serviceTag, flows = []) {
102
106
  const source = `app/src/generatedCode/FlowObjects/${action}/source`;
103
107
  const handlerRoot = `src/generatedCode/FlowObjects/${action}/source`;
104
- const plan = createCrudActionPlans(objects)[action];
108
+ const plan = createCrudActionPlans(objects, flows)[action];
105
109
  const mainFileName = `${action}_Main`;
106
110
  const shared = {
107
111
  flowTag: action,
@@ -326,6 +330,62 @@ async function emitAction(action, objects, serviceTag) {
326
330
  });
327
331
  }
328
332
 
333
+ if (plan.hasBeforeHookCallback) {
334
+ const beforeHookCallbackMain = `${action}BeforeHookCallback_Main`;
335
+ artifacts.push(
336
+ {
337
+ path: `${source}/${beforeHookCallbackMain}.js`,
338
+ content: await render(`${action}BeforeHookCallback_Main.ejs`, shared)
339
+ },
340
+ {
341
+ path: `${source}/${action}BeforeHookCallback_HdrSqs.js`,
342
+ content: await renderShared('FlowHandler_HdrSqs.ejs', {
343
+ ...shared,
344
+ mainFileName: beforeHookCallbackMain,
345
+ functionName: `${action}BeforeHookCallbackMain`,
346
+ queueName: `${action}BeforeHookCallbackHdrSqs`
347
+ })
348
+ }
349
+ );
350
+ functions.push({
351
+ type: 'sqs',
352
+ functionName: `${action}BeforeHookCallbackHdrSqs`,
353
+ handlerPath: `${handlerRoot}/${action}BeforeHookCallback_HdrSqs.main`,
354
+ roleName: 'FlowObjectsRole',
355
+ queueName: `${action}BeforeHookCallbackHdrSqs`,
356
+ flowTag: action,
357
+ flowStepName: 'BeforeHookCallback'
358
+ });
359
+ }
360
+
361
+ if (plan.hasAfterHookCallback) {
362
+ const afterHookCallbackMain = `${action}AfterHookCallback_Main`;
363
+ artifacts.push(
364
+ {
365
+ path: `${source}/${afterHookCallbackMain}.js`,
366
+ content: await render(`${action}AfterHookCallback_Main.ejs`, shared)
367
+ },
368
+ {
369
+ path: `${source}/${action}AfterHookCallback_HdrSqs.js`,
370
+ content: await renderShared('FlowHandler_HdrSqs.ejs', {
371
+ ...shared,
372
+ mainFileName: afterHookCallbackMain,
373
+ functionName: `${action}AfterHookCallbackMain`,
374
+ queueName: `${action}AfterHookCallbackHdrSqs`
375
+ })
376
+ }
377
+ );
378
+ functions.push({
379
+ type: 'sqs',
380
+ functionName: `${action}AfterHookCallbackHdrSqs`,
381
+ handlerPath: `${handlerRoot}/${action}AfterHookCallback_HdrSqs.main`,
382
+ roleName: 'FlowObjectsRole',
383
+ queueName: `${action}AfterHookCallbackHdrSqs`,
384
+ flowTag: action,
385
+ flowStepName: 'AfterHookCallback'
386
+ });
387
+ }
388
+
329
389
  if (plan.hasComplete) {
330
390
  const completeMain = `${action}Complete_Main`;
331
391
  let templateName = `${action}Complete_Main.ejs`;
@@ -72,8 +72,10 @@ function _createDynamicFlow(action, plan, serviceTag = '', initiateBy = 'user')
72
72
  toStepNames: ['RbacCallback']
73
73
  }
74
74
  );
75
- } else if (plan.hasComplete) {
76
- const nextStepName = plan.hasCreateNodeCallback ? 'CreateNodeCallback' : 'Complete';
75
+ } else if (plan.hasComplete || plan.hasCreateNodeCallback) {
76
+ const nextStepName = plan.hasCreateNodeCallback
77
+ ? 'CreateNodeCallback'
78
+ : 'Complete';
77
79
  startNextSteps.push({
78
80
  targetType: 'ownTopic',
79
81
  stepName: nextStepName
@@ -106,7 +108,9 @@ function _createDynamicFlow(action, plan, serviceTag = '', initiateBy = 'user')
106
108
  ];
107
109
 
108
110
  if (plan.hasRbacCallback) {
109
- const nextStepName = plan.hasCreateNodeCallback ? 'CreateNodeCallback' : 'Complete';
111
+ const nextStepName = plan.hasCreateNodeCallback
112
+ ? 'CreateNodeCallback'
113
+ : 'Complete';
110
114
  const rbacNextSteps = [
111
115
  {
112
116
  targetType: 'ownTopic',
@@ -162,14 +166,9 @@ function _createDynamicFlow(action, plan, serviceTag = '', initiateBy = 'user')
162
166
  ],
163
167
  nextSteps: [
164
168
  {
165
- targetType: 'ownTopic',
166
- stepName: 'Complete'
167
- },
168
- {
169
- targetType: 'extTopic',
169
+ targetType: 'lambdaSyncInv',
170
170
  serviceTag: 'Rbac',
171
- topicName: 'ConfirmUsage_In',
172
- toStepNames: ['Complete']
171
+ functionName: 'ConfirmUsageHdrInv'
173
172
  }
174
173
  ],
175
174
  properties: [
@@ -184,9 +183,7 @@ function _createDynamicFlow(action, plan, serviceTag = '', initiateBy = 'user')
184
183
  }
185
184
 
186
185
  if (plan.hasComplete) {
187
- const prevStepName = plan.hasCreateNodeCallback
188
- ? 'CreateNodeCallback'
189
- : (plan.hasRbacCallback ? 'RbacCallback' : 'Start');
186
+ const prevStepName = plan.hasRbacCallback ? 'RbacCallback' : 'Start';
190
187
 
191
188
  const completePrevSteps = [
192
189
  {
@@ -195,14 +192,7 @@ function _createDynamicFlow(action, plan, serviceTag = '', initiateBy = 'user')
195
192
  }
196
193
  ];
197
194
 
198
- if (plan.hasCreateNodeCallback) {
199
- completePrevSteps.push({
200
- sourceType: 'extTopic',
201
- serviceTag: 'Rbac',
202
- topicName: 'ConfirmUsage_Out',
203
- fromStepNames: ['CreateNodeCallback']
204
- });
205
- } else if (plan.hasGraph) {
195
+ if (plan.hasGraph) {
206
196
  completePrevSteps.push({
207
197
  sourceType: 'extTopic',
208
198
  serviceTag: 'GraphHandler',
@@ -215,22 +205,15 @@ function _createDynamicFlow(action, plan, serviceTag = '', initiateBy = 'user')
215
205
  stepName: 'Complete',
216
206
  event: ['extTopic'],
217
207
  previousSteps: completePrevSteps,
218
- properties: plan.hasCreateNodeCallback
208
+ properties: plan.hasGraph
219
209
  ? [
220
210
  'returnValue',
221
211
  'parentFlowId',
222
212
  'status',
223
- 'errorsFound'
213
+ 'errorsFound',
214
+ 'graphServiceTag'
224
215
  ]
225
- : (plan.hasGraph
226
- ? [
227
- 'returnValue',
228
- 'parentFlowId',
229
- 'status',
230
- 'errorsFound',
231
- 'graphServiceTag'
232
- ]
233
- : []),
216
+ : [],
234
217
  messageAttributes: MESSAGE_ATTRIBUTES
235
218
  });
236
219
  }