@izara_project/izara-core-generate-service-code 1.0.84 → 1.0.85

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 (26) hide show
  1. package/package.json +1 -1
  2. package/src/emit/coreFunction/emitCoreFunctionArtifacts.js +5 -0
  3. package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +13 -4
  4. package/src/emit/crud/crudActionPlan.js +3 -1
  5. package/src/emit/crud/emitCrudApplicationArtifacts.js +37 -4
  6. package/src/emit/crud/emitDynamicCrudFlowSchemas.js +126 -21
  7. package/src/emit/crud/templates/CreateConfirmComplete_Main.ejs +54 -0
  8. package/src/emit/crud/templates/CreateEndpoint_Main.ejs +248 -181
  9. package/src/emit/crud/templates/CreateLogicalLib.ejs +1155 -293
  10. package/src/emit/crud/templates/CreateNodeCallback_Main.ejs +221 -0
  11. package/src/emit/crud/templates/FlowEndpointRbacCallback_Main.ejs +20 -120
  12. package/src/emit/crud/templates/FlowEndpoint_HdrWbs.ejs +76 -14
  13. package/src/emit/crud/templates/FlowMain_Wbs.ejs +31 -35
  14. package/src/emit/rbac/templates/CancelUsage_Main.ejs +82 -22
  15. package/src/emit/rbac/templates/ConfirmUsage_Main.ejs +130 -14
  16. package/src/emit/rbac/templates/CreateTargetRole_Main.ejs +29 -10
  17. package/src/emit/rbac/templates/ReservedDynamicUsage_Main.ejs +30 -11
  18. package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +28 -3
  19. package/src/emit/rbac/templates/UserRoleMutation_Main.ejs +10 -7
  20. package/src/emit/resource/emitResourceArtifacts.js +9 -0
  21. package/src/emit/resource/templates/GeneratedLambdaRoleServiceConfig.ejs +3 -1
  22. package/src/emit/resource/templates/SystemDynamoDB_Yaml.ejs +2 -0
  23. package/src/emit/shared/templates/FlowHandler_HdrSqs.ejs +1 -1
  24. package/src/emit/system/templates/WebSocketConnect_Yaml.ejs +0 -1
  25. package/test/dynamicCrudFlowSchemas.test.js +16 -2
  26. package/test/resourceArtifacts.test.js +21 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@izara_project/izara-core-generate-service-code",
3
- "version": "1.0.84",
3
+ "version": "1.0.85",
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": {
@@ -2,6 +2,7 @@ import ejsLib from 'ejs';
2
2
  import { readFile } from 'node:fs/promises';
3
3
 
4
4
  import { customFlowNextSteps, flowHasRbac, upperFirst } from '../custom/customFlows.js';
5
+ import { createCrudActionPlans } from '../crud/crudActionPlan.js';
5
6
 
6
7
  const TEMPLATE_URL = new URL('./templates/', import.meta.url);
7
8
  const APP_ROOT = 'app/sls_yaml/generatedCode/source';
@@ -239,6 +240,9 @@ export async function emitCoreFunctionArtifacts({ project, objects = [], relatio
239
240
  };
240
241
  });
241
242
 
243
+ const crudPlans = createCrudActionPlans(objects);
244
+ const hasQuotaReservation = crudPlans?.Create?.hasQuotaReservation ?? false;
245
+
242
246
  const state = {
243
247
  project,
244
248
  objects,
@@ -252,6 +256,7 @@ export async function emitCoreFunctionArtifacts({ project, objects = [], relatio
252
256
  crud,
253
257
  hasRelationships,
254
258
  rbac,
259
+ hasQuotaReservation,
255
260
  rbacValidatorServiceTags,
256
261
  s3Flows,
257
262
  hasGenerateGraph: objects.length > 0 || relationships.length > 0
@@ -131,7 +131,10 @@ const tableConfigs = {
131
131
  const nodeSubs = [];
132
132
  (objectGraphServiceTags || []).forEach(function(tag) {
133
133
  nodeSubs.push({ serviceTag: tag, topicName: 'UpdateNode_Out', sqsEndpoint: 'UpdateCompleteHdrSqs' });
134
- nodeSubs.push({ serviceTag: tag, topicName: 'CreateNode_Out', sqsEndpoint: 'CreateCompleteHdrSqs' });
134
+ const createNodeEndpoint = (typeof hasQuotaReservation !== 'undefined' && hasQuotaReservation)
135
+ ? 'CreateNodeCallbackHdrSqs'
136
+ : 'CreateCompleteHdrSqs';
137
+ nodeSubs.push({ serviceTag: tag, topicName: 'CreateNode_Out', sqsEndpoint: createNodeEndpoint });
135
138
  });
136
139
 
137
140
  const customSubs = [];
@@ -177,8 +180,8 @@ const tableConfigs = {
177
180
  });
178
181
 
179
182
  const rbacSubs = [];
180
- if (crud && typeof rbacValidatorServiceTags !== 'undefined' && rbacValidatorServiceTags && rbacValidatorServiceTags.length > 0) {
181
- const allRbacTags = Array.from(new Set(['Rbac', ...rbacValidatorServiceTags]));
183
+ if (crud && rbac) {
184
+ const allRbacTags = Array.from(new Set(['Rbac', ...(typeof rbacValidatorServiceTags !== 'undefined' && rbacValidatorServiceTags ? rbacValidatorServiceTags : [])]));
182
185
  const hasGraph = typeof objectGraphServiceTags !== 'undefined' && objectGraphServiceTags && objectGraphServiceTags.length > 0;
183
186
  const createEndpoint = hasGraph ? 'CreateRbacCallbackHdrSqs' : 'CreateCompleteHdrSqs';
184
187
  const updateEndpoint = hasGraph ? 'UpdateRbacCallbackHdrSqs' : 'UpdateCompleteHdrSqs';
@@ -188,6 +191,10 @@ const tableConfigs = {
188
191
  rbacSubs.push({ serviceTag: tag, topicName: 'ValidatorRbac_Out', sqsEndpoint: updateEndpoint });
189
192
  rbacSubs.push({ serviceTag: tag, topicName: 'ValidatorRbac_Out', sqsEndpoint: deleteEndpoint });
190
193
  });
194
+ if (typeof hasQuotaReservation !== 'undefined' && hasQuotaReservation) {
195
+ rbacSubs.push({ serviceTag: 'Rbac', topicName: 'ConfirmUsage_Out', sqsEndpoint: 'CreateCompleteHdrSqs' });
196
+ rbacSubs.push({ serviceTag: 'Rbac', topicName: 'CancelUsage_Out', sqsEndpoint: 'CreateCompleteHdrSqs' });
197
+ }
191
198
  }
192
199
 
193
200
  if (typeof customRbacFlowTags !== 'undefined' && customRbacFlowTags && customRbacFlowTags.length > 0) {
@@ -307,7 +314,9 @@ function roleConfigs() {
307
314
  Effect: 'Allow',
308
315
  Action: ['sns:Publish'],
309
316
  Resource: [
310
- `arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'ValidatorRbac_In', 'Rbac')}`<% (rbacValidatorServiceTags || []).forEach(function(tag) { %>,
317
+ `arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'ValidatorRbac_In', 'Rbac')}`,
318
+ `arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'ConfirmUsage_In', 'Rbac')}`,
319
+ `arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'CancelUsage_In', 'Rbac')}`<% (rbacValidatorServiceTags || []).forEach(function(tag) { %>,
311
320
  `arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'ValidatorRbac_In', '<%= tag %>')}`<% }); %>
312
321
  ]
313
322
  },
@@ -32,7 +32,9 @@ export function createCrudActionPlan(
32
32
  hasRbac: actionHasRbac,
33
33
  hasQuotaReservation,
34
34
  hasComplete: outputTopic && (actionHasRbac || hasGraph),
35
- hasRbacCallback: outputTopic && actionHasRbac && hasGraph
35
+ hasRbacCallback: outputTopic && actionHasRbac && hasGraph,
36
+ hasCreateNodeCallback:
37
+ outputTopic && action === 'Create' && actionHasRbac && hasGraph && hasQuotaReservation
36
38
  };
37
39
  }
38
40
 
@@ -80,6 +80,8 @@ export function crudApplicationManagedPaths() {
80
80
  `${source}/${action}_HdrWbs.js`,
81
81
  `${source}/${action}RbacCallback_Main.js`,
82
82
  `${source}/${action}RbacCallback_HdrSqs.js`,
83
+ `${source}/${action}NodeCallback_Main.js`,
84
+ `${source}/${action}NodeCallback_HdrSqs.js`,
83
85
  `${source}/${action}Complete_Main.js`,
84
86
  `${source}/${action}Complete_HdrSqs.js`
85
87
  );
@@ -290,12 +292,43 @@ async function emitAction(action, objects, serviceTag) {
290
292
  });
291
293
  }
292
294
 
295
+ if (plan.hasCreateNodeCallback) {
296
+ const nodeCallbackMain = `${action}NodeCallback_Main`;
297
+ artifacts.push(
298
+ {
299
+ path: `${source}/${nodeCallbackMain}.js`,
300
+ content: await render(`${action}NodeCallback_Main.ejs`, shared)
301
+ },
302
+ {
303
+ path: `${source}/${nodeCallbackMain.replace('_Main', '_HdrSqs')}.js`,
304
+ content: await renderShared('FlowHandler_HdrSqs.ejs', {
305
+ ...shared,
306
+ mainFileName: nodeCallbackMain,
307
+ functionName: `${action}NodeCallbackMain`,
308
+ queueName: `${action}NodeCallbackHdrSqs`
309
+ })
310
+ }
311
+ );
312
+ functions.push({
313
+ type: 'sqs',
314
+ functionName: `${action}NodeCallbackHdrSqs`,
315
+ handlerPath: `${handlerRoot}/${action}NodeCallback_HdrSqs.main`,
316
+ roleName: 'FlowObjectsRole',
317
+ queueName: `${action}NodeCallbackHdrSqs`,
318
+ flowTag: action,
319
+ flowStepName: 'CreateNodeCallback'
320
+ });
321
+ }
322
+
293
323
  if (plan.hasComplete) {
294
324
  const completeMain = `${action}Complete_Main`;
295
- const templateName =
296
- plan.hasRbac && !plan.hasGraph
297
- ? 'FlowEndpointRbacCallback_Main.ejs'
298
- : `${action}Complete_Main.ejs`;
325
+ let templateName = `${action}Complete_Main.ejs`;
326
+ if (plan.hasRbac && !plan.hasGraph) {
327
+ templateName = 'FlowEndpointRbacCallback_Main.ejs';
328
+ } else if (plan.hasCreateNodeCallback) {
329
+ templateName = 'CreateConfirmComplete_Main.ejs';
330
+ }
331
+
299
332
  const templateContext =
300
333
  plan.hasRbac && !plan.hasGraph
301
334
  ? shared
@@ -52,19 +52,39 @@ export function emitDynamicCrudFlowSchemas({
52
52
  }
53
53
 
54
54
  function _createDynamicFlow(action, plan, serviceTag = '', initiateBy = 'user') {
55
+ const startNextSteps = [];
56
+ if (plan.hasRbacCallback) {
57
+ startNextSteps.push(
58
+ {
59
+ targetType: 'ownTopic',
60
+ stepName: 'RbacCallback'
61
+ },
62
+ {
63
+ targetType: 'extTopic',
64
+ serviceTag: 'Rbac',
65
+ topicName: 'ValidatorRbac_In',
66
+ toStepNames: ['RbacCallback']
67
+ }
68
+ );
69
+ } else if (plan.hasComplete) {
70
+ startNextSteps.push({
71
+ targetType: 'ownTopic',
72
+ stepName: 'Complete'
73
+ });
74
+ if (plan.hasGraph) {
75
+ startNextSteps.push({
76
+ targetType: 'extTopic',
77
+ serviceTag: 'GraphHandler',
78
+ topicName: `${action}Node_In`,
79
+ toStepNames: ['Complete']
80
+ });
81
+ }
82
+ }
83
+
55
84
  const flowSteps = [
56
85
  {
57
86
  stepName: 'Start',
58
- ...(plan.hasRbacCallback || plan.hasComplete
59
- ? {
60
- nextSteps: [
61
- {
62
- targetType: 'ownTopic',
63
- stepName: plan.hasRbacCallback ? 'RbacCallback' : 'Complete'
64
- }
65
- ]
66
- }
67
- : {}),
87
+ ...(startNextSteps.length > 0 ? { nextSteps: startNextSteps } : {}),
68
88
  properties: [],
69
89
  messageAttributes: MESSAGE_ATTRIBUTES,
70
90
  ...(plan.outputTopic
@@ -79,6 +99,22 @@ function _createDynamicFlow(action, plan, serviceTag = '', initiateBy = 'user')
79
99
  ];
80
100
 
81
101
  if (plan.hasRbacCallback) {
102
+ const nextStepName = plan.hasCreateNodeCallback ? 'CreateNodeCallback' : 'Complete';
103
+ const rbacNextSteps = [
104
+ {
105
+ targetType: 'ownTopic',
106
+ stepName: nextStepName
107
+ }
108
+ ];
109
+ if (plan.hasGraph) {
110
+ rbacNextSteps.push({
111
+ targetType: 'extTopic',
112
+ serviceTag: 'GraphHandler',
113
+ topicName: `${action}Node_In`,
114
+ toStepNames: [nextStepName]
115
+ });
116
+ }
117
+
82
118
  flowSteps.push({
83
119
  stepName: 'RbacCallback',
84
120
  event: ['extTopic'],
@@ -86,38 +122,107 @@ function _createDynamicFlow(action, plan, serviceTag = '', initiateBy = 'user')
86
122
  {
87
123
  sourceType: 'ownTopic',
88
124
  stepName: 'Start'
125
+ },
126
+ {
127
+ sourceType: 'extTopic',
128
+ serviceTag: 'Rbac',
129
+ topicName: 'ValidatorRbac_Out',
130
+ fromStepNames: ['Start']
131
+ }
132
+ ],
133
+ nextSteps: rbacNextSteps,
134
+ properties: [],
135
+ messageAttributes: MESSAGE_ATTRIBUTES
136
+ });
137
+ }
138
+
139
+ if (plan.hasCreateNodeCallback) {
140
+ flowSteps.push({
141
+ stepName: 'CreateNodeCallback',
142
+ event: ['extTopic'],
143
+ previousSteps: [
144
+ {
145
+ sourceType: 'ownTopic',
146
+ stepName: 'RbacCallback'
147
+ },
148
+ {
149
+ sourceType: 'extTopic',
150
+ serviceTag: 'GraphHandler',
151
+ topicName: 'CreateNode_Out',
152
+ fromStepNames: ['RbacCallback']
89
153
  }
90
154
  ],
91
155
  nextSteps: [
92
156
  {
93
157
  targetType: 'ownTopic',
94
158
  stepName: 'Complete'
159
+ },
160
+ {
161
+ targetType: 'extTopic',
162
+ serviceTag: 'Rbac',
163
+ topicName: 'ConfirmUsage_In',
164
+ toStepNames: ['Complete']
95
165
  }
96
166
  ],
97
- properties: [],
167
+ properties: [
168
+ 'returnValue',
169
+ 'parentFlowId',
170
+ 'status',
171
+ 'errorsFound',
172
+ 'graphServiceTag'
173
+ ],
98
174
  messageAttributes: MESSAGE_ATTRIBUTES
99
175
  });
100
176
  }
101
177
 
102
178
  if (plan.hasComplete) {
179
+ const prevStepName = plan.hasCreateNodeCallback
180
+ ? 'CreateNodeCallback'
181
+ : (plan.hasRbacCallback ? 'RbacCallback' : 'Start');
182
+
183
+ const completePrevSteps = [
184
+ {
185
+ sourceType: 'ownTopic',
186
+ stepName: prevStepName
187
+ }
188
+ ];
189
+
190
+ if (plan.hasCreateNodeCallback) {
191
+ completePrevSteps.push({
192
+ sourceType: 'extTopic',
193
+ serviceTag: 'Rbac',
194
+ topicName: 'ConfirmUsage_Out',
195
+ fromStepNames: ['CreateNodeCallback']
196
+ });
197
+ } else if (plan.hasGraph) {
198
+ completePrevSteps.push({
199
+ sourceType: 'extTopic',
200
+ serviceTag: 'GraphHandler',
201
+ topicName: `${action}Node_Out`,
202
+ fromStepNames: [prevStepName]
203
+ });
204
+ }
205
+
103
206
  flowSteps.push({
104
207
  stepName: 'Complete',
105
208
  event: ['extTopic'],
106
- previousSteps: [
107
- {
108
- sourceType: 'ownTopic',
109
- stepName: plan.hasRbacCallback ? 'RbacCallback' : 'Start'
110
- }
111
- ],
112
- properties: plan.hasGraph
209
+ previousSteps: completePrevSteps,
210
+ properties: plan.hasCreateNodeCallback
113
211
  ? [
114
212
  'returnValue',
115
213
  'parentFlowId',
116
214
  'status',
117
- 'errorsFound',
118
- 'graphServiceTag'
215
+ 'errorsFound'
119
216
  ]
120
- : [],
217
+ : (plan.hasGraph
218
+ ? [
219
+ 'returnValue',
220
+ 'parentFlowId',
221
+ 'status',
222
+ 'errorsFound',
223
+ 'graphServiceTag'
224
+ ]
225
+ : []),
121
226
  messageAttributes: MESSAGE_ATTRIBUTES
122
227
  });
123
228
  }
@@ -0,0 +1,54 @@
1
+ import callingFlowSharedLib from '@izara_project/izara-core-library-calling-flow';
2
+ import snsSharedLib from '@izara_project/izara-core-library-sns';
3
+ import { sns } from '@izara_project/izara-core-library-external-request';
4
+ import { consts } from '@izara_project/izara-core-library-service-schemas';
5
+
6
+ import {
7
+ buildCompletionPayload,
8
+ publishCompletionMessage
9
+ } from './CreateLogicalLib.js';
10
+
11
+ const { TOPIC_NAME_GENERATE_CODE } = consts;
12
+
13
+ /**
14
+ * Handles Create flow completion by publishing final response to Calling Flow
15
+ * @param {Object} _izContext - Izara context object
16
+ * @param {Object} requestParams - Final response parameters
17
+ * @param {Object} passBackProperties - Pass-back properties
18
+ * @returns {Promise<Object>} Parent pass-back result
19
+ */
20
+ export default async function CreateComplete(
21
+ _izContext,
22
+ requestParams,
23
+ passBackProperties
24
+ ) {
25
+ try {
26
+ _izContext.logger.debug(`[${process.env.iz_serviceTag}:CreateComplete] started`, {
27
+ requestParams
28
+ });
29
+
30
+ const callingFlowConfig =
31
+ requestParams?.callingFlowProperties ||
32
+ passBackProperties ||
33
+ {};
34
+
35
+ const parentPassBack =
36
+ requestParams?.parentPassBackProperties ||
37
+ requestParams?.returnValue ||
38
+ requestParams;
39
+
40
+ // 1. Build completion response payload and attributes
41
+ const { message, messageAttributes } = buildCompletionPayload(
42
+ callingFlowConfig,
43
+ parentPassBack
44
+ );
45
+
46
+ // 2. Publish completion notification to SNS
47
+ await publishCompletionMessage(_izContext, message, messageAttributes);
48
+
49
+ return parentPassBack;
50
+ } catch (error) {
51
+ _izContext.logger.error('[CreateComplete] error:', error);
52
+ throw error;
53
+ }
54
+ }