@izara_project/izara-core-generate-service-code 1.0.78 → 1.0.79

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 (61) hide show
  1. package/package.json +2 -2
  2. package/src/compile/flowValidator.js +163 -0
  3. package/src/compile/loadSchemas.js +15 -5
  4. package/src/emit/coreFunction/emitCoreFunctionArtifacts.js +137 -7
  5. package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +132 -17
  6. package/src/emit/crud/crudActionPlan.js +82 -0
  7. package/src/emit/crud/emitCrudApplicationArtifacts.js +162 -112
  8. package/src/emit/crud/emitDynamicCrudFlowSchemas.js +43 -65
  9. package/src/emit/crud/generateDynamicCrudFlowSchemas.js +4 -1
  10. package/src/emit/crud/templates/CreateEndpoint_Main.ejs +84 -512
  11. package/src/emit/crud/templates/CreateLogicalLib.ejs +536 -0
  12. package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +87 -202
  13. package/src/emit/crud/templates/DeleteLogicalLib.ejs +213 -0
  14. package/src/emit/crud/templates/FlowEndpointRbacCallback_Main.ejs +217 -0
  15. package/src/emit/crud/templates/GetEndpoint_Main.ejs +1 -1
  16. package/src/emit/crud/templates/GetRangeEndpoint_Main.ejs +9 -2
  17. package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +87 -444
  18. package/src/emit/crud/templates/UpdateLogicalLib.ejs +472 -0
  19. package/src/emit/custom/customFlows.js +27 -2
  20. package/src/emit/custom/emitCustomFlowApplicationArtifacts.js +1 -2
  21. package/src/emit/custom/templates/FlowEndpoint_Main.ejs +10 -3
  22. package/src/emit/custom/templates/FlowStep_Main.ejs +1 -1
  23. package/src/emit/custom/templates/s3/CreateObject_Main.ejs +1 -1
  24. package/src/emit/custom/templates/triggerCache/CheckTriggerCache_HdrSqs.ejs +2 -2
  25. package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +3 -9
  26. package/src/emit/rbac/emitRbacApplicationArtifacts.js +21 -16
  27. package/src/emit/rbac/rbacFlowTag.js +2 -7
  28. package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +148 -21
  29. package/src/emit/relationship/emitDynamicRelationshipFlowSchemas.js +4 -2
  30. package/src/emit/relationship/templates/ChangeRelationship_Main.ejs +1 -1
  31. package/src/emit/relationship/templates/CreateRelationship_Main.ejs +1 -1
  32. package/src/emit/relationship/templates/DeleteRelationship_Main.ejs +1 -1
  33. package/src/emit/relationship/templates/GetRelationship_Main.ejs +1 -1
  34. package/src/emit/relationship/templates/MoveRelationship_Main.ejs +1 -1
  35. package/src/emit/relationship/templates/UpdateRelationship_Main.ejs +1 -1
  36. package/src/emit/resource/emitResourceArtifacts.js +83 -68
  37. package/src/emit/resource/templates/GeneratedLambdaRoleServiceConfig.ejs +31 -5
  38. package/src/emit/resource/templates/SystemDynamoDB_Yaml.ejs +21 -0
  39. package/src/emit/resource/templates/WebSocketSubscription_Yaml.ejs +7 -0
  40. package/src/emit/shared/templates/FlowHandler_HdrApi.ejs +1 -1
  41. package/src/emit/shared/templates/FlowHandler_HdrDsq.ejs +2 -2
  42. package/src/emit/shared/templates/FlowHandler_HdrInv.ejs +1 -1
  43. package/src/emit/shared/templates/FlowHandler_HdrSqs.ejs +2 -2
  44. package/src/emit/systemText/emitSystemTextSchemas.js +246 -0
  45. package/src/emit/systemText/templates/SystemTextSchemas.ejs +10 -0
  46. package/src/generate.js +55 -8
  47. package/test/crudApplicationArtifacts.test.js +147 -19
  48. package/test/customFlowApplicationArtifacts.test.js +308 -16
  49. package/test/dynamicCrudFlowSchemas.test.js +150 -14
  50. package/test/dynamicRbacFlowSchemas.test.js +2 -2
  51. package/test/dynamicRelationshipFlowSchemas.test.js +1 -1
  52. package/test/graphDrivenFlowSchema.test.js +257 -0
  53. package/test/publicApi.test.js +14 -5
  54. package/test/resourceArtifacts.test.js +25 -19
  55. package/test/systemTextSchemas.test.js +154 -0
  56. package/src/emit/crud/templates/CreateComplete_HdrSqs.ejs +0 -99
  57. package/src/emit/crud/templates/DeleteComplete_HdrSqs.ejs +0 -99
  58. package/src/emit/crud/templates/FlowEndpointBeforeLogical_Main.ejs +0 -174
  59. package/src/emit/crud/templates/FlowEndpointComplete_Main.ejs +0 -187
  60. package/src/emit/crud/templates/UpdateComplete_HdrSqs.ejs +0 -99
  61. package/src/emit/resource/templates/ResourceBeforeLogicalYaml.ejs +0 -47
@@ -0,0 +1,82 @@
1
+ export const CRUD_ACTIONS = ['Create', 'Update', 'Delete', 'Get'];
2
+
3
+ export function createCrudActionPlans(objects = []) {
4
+ const hasGraph = hasGraphStorageResource(objects);
5
+ const hasRbac = objects.some(
6
+ (object) => isCrudObject(object) && hasRbacObject(object, objects)
7
+ );
8
+
9
+ return Object.fromEntries(
10
+ CRUD_ACTIONS.map((action) => [
11
+ action,
12
+ createCrudActionPlan(action, { hasGraph, hasRbac })
13
+ ])
14
+ );
15
+ }
16
+
17
+ export function createCrudActionPlan(
18
+ action,
19
+ { hasGraph = false, hasRbac = false } = {}
20
+ ) {
21
+ const actionHasRbac = action !== 'Create' && action !== 'Get' && hasRbac;
22
+ const outputTopic = action !== 'Get';
23
+
24
+ return {
25
+ action,
26
+ outputTopic,
27
+ hasGraph: outputTopic && hasGraph,
28
+ hasRbac: actionHasRbac,
29
+ hasComplete: outputTopic && (actionHasRbac || hasGraph),
30
+ hasRbacCallback: outputTopic && actionHasRbac && hasGraph
31
+ };
32
+ }
33
+
34
+ export function isCrudObject(object) {
35
+ return (
36
+ object?.generatedBy === 'userGenerated' ||
37
+ object?.generatedBy === 'systemGenerated'
38
+ );
39
+ }
40
+
41
+ export function hasGraphStorageResource(objects = []) {
42
+ return objects.some((object) =>
43
+ Object.values(object?.storageResources ?? {}).some(
44
+ (resource) =>
45
+ resource?.storageType === 'graph' ||
46
+ resource?.resourceType === 'graph' ||
47
+ resource?.dbType === 'neo4j' ||
48
+ resource?.storageTag?.toLowerCase().includes('graph')
49
+ )
50
+ );
51
+ }
52
+
53
+ function hasRbacObject(object, objects = []) {
54
+ return (
55
+ hasSelfRbac(object) ||
56
+ Array.isArray(object?.belongToSchema?.addOnDataStructure) &&
57
+ object.belongToSchema.addOnDataStructure.some(
58
+ (addOn) => addOn?.type === 'rbac'
59
+ ) ||
60
+ normalizeBelongTo(object).some((target) => {
61
+ if (target?.serviceTag === 'UserAccount') return true;
62
+ const matched = objects.find(
63
+ (candidate) =>
64
+ candidate?.serviceTag === target?.serviceTag &&
65
+ candidate?.objectType === target?.objectType
66
+ );
67
+ return hasSelfRbac(matched);
68
+ })
69
+ );
70
+ }
71
+
72
+ function hasSelfRbac(object) {
73
+ return (
74
+ Array.isArray(object?.addOnDataStructure) &&
75
+ object.addOnDataStructure.some((addOn) => addOn?.type === 'rbac')
76
+ );
77
+ }
78
+
79
+ function normalizeBelongTo(object) {
80
+ if (!object?.belongTo) return [];
81
+ return Array.isArray(object.belongTo) ? object.belongTo : [object.belongTo];
82
+ }
@@ -8,7 +8,13 @@ import {
8
8
  renderWbsFunctionYaml
9
9
  } from '../function/functionYamlArtifact.js';
10
10
 
11
- const ACTIONS = ['Create', 'Update', 'Delete', 'Get'];
11
+ import {
12
+ CRUD_ACTIONS,
13
+ createCrudActionPlans,
14
+ isCrudObject
15
+ } from './crudActionPlan.js';
16
+
17
+ const ACTIONS = CRUD_ACTIONS;
12
18
  const YAML_PATH = 'app/sls_yaml/generatedCode/source/flow-objects.yml';
13
19
  const TEMPLATE_URL = new URL('./templates/', import.meta.url);
14
20
  const SHARED_TEMPLATE_URL = new URL('../shared/templates/', import.meta.url);
@@ -24,7 +30,7 @@ export async function emitCrudApplicationArtifacts({
24
30
  if (!objects.some(isCrudObject)) return [];
25
31
 
26
32
  const handlers = await Promise.all(
27
- ACTIONS.map((action) => emitAction(action, objects, flows, serviceTag))
33
+ ACTIONS.map((action) => emitAction(action, objects, serviceTag))
28
34
  );
29
35
  return [
30
36
  ...handlers.flatMap((handler) => handler.artifacts),
@@ -43,6 +49,9 @@ export function crudApplicationManagedPaths() {
43
49
  ...ACTIONS.flatMap((action) => {
44
50
  const source = `app/src/generatedCode/FlowObjects/${action}/source`;
45
51
  const paths = [`${source}/${action}_Main.js`];
52
+ if (action !== 'Get') {
53
+ paths.unshift(`${source}/${action}LogicalLib.js`);
54
+ }
46
55
  if (action === 'Get') {
47
56
  paths.push(`${source}/Get_HdrInv.js`, `${source}/Get_HdrApi.js`);
48
57
  paths.push(
@@ -54,10 +63,8 @@ export function crudApplicationManagedPaths() {
54
63
  `${source}/${action}_HdrSqs.js`,
55
64
  `${source}/${action}_WbsMain.js`,
56
65
  `${source}/${action}_HdrWbs.js`,
57
- `${source}/${action}BeforeLogical_Main.js`,
58
- `${source}/${action}BeforeLogical_HdrSqs.js`
59
- );
60
- paths.push(
66
+ `${source}/${action}RbacCallback_Main.js`,
67
+ `${source}/${action}RbacCallback_HdrSqs.js`,
61
68
  `${source}/${action}Complete_Main.js`,
62
69
  `${source}/${action}Complete_HdrSqs.js`
63
70
  );
@@ -68,25 +75,21 @@ export function crudApplicationManagedPaths() {
68
75
  ];
69
76
  }
70
77
 
71
- async function emitAction(action, objects, flows, serviceTag) {
78
+ async function emitAction(action, objects, serviceTag) {
72
79
  const source = `app/src/generatedCode/FlowObjects/${action}/source`;
73
80
  const handlerRoot = `src/generatedCode/FlowObjects/${action}/source`;
74
- const generateCode = flows
75
- .filter(
76
- (flow) =>
77
- flow?.generatedCodeConfig?.generatedCodeTag?.toLowerCase() ===
78
- action.toLowerCase()
79
- )
80
- .map((flow) => ({ ...flow.generatedCodeConfig, flowTag: flow.flowTag }));
81
+ const plan = createCrudActionPlans(objects)[action];
81
82
  const mainFileName = `${action}_Main`;
82
83
  const shared = {
83
84
  flowTag: action,
84
85
  upperCaseFlowTag: action,
85
86
  topicArn: `${action}_In`,
86
- generateCode,
87
87
  flow: null,
88
88
  flowStepName: '',
89
- startConfig: null
89
+ startConfig: null,
90
+ objects: action === 'Create' ? [] : objects,
91
+ isCrudObject,
92
+ hasRbacAddOn: (object) => hasRbacAddOn(object, objects)
90
93
  };
91
94
  const artifacts = [
92
95
  {
@@ -94,6 +97,12 @@ async function emitAction(action, objects, flows, serviceTag) {
94
97
  content: await render(`${action}Endpoint_Main.ejs`, shared)
95
98
  }
96
99
  ];
100
+ if (action !== 'Get') {
101
+ artifacts.unshift({
102
+ path: `${source}/${action}LogicalLib.js`,
103
+ content: await render(`${action}LogicalLib.ejs`, shared)
104
+ });
105
+ }
97
106
 
98
107
  let targetServiceTag = '${self:custom.iz_serviceName}';
99
108
  if (serviceTag) {
@@ -118,69 +127,75 @@ async function emitAction(action, objects, flows, serviceTag) {
118
127
  functionName: 'Get',
119
128
  queueName: 'GetHdrApi'
120
129
  })
121
- },
130
+ }
131
+ );
132
+ const functions = [
122
133
  {
123
- path: `${source}/GetRange_Main.js`,
124
- content: await render('GetRangeEndpoint_Main.ejs', {
125
- ...shared,
126
- mainFileName: 'GetRange_Main',
127
- functionName: 'GetRange'
128
- })
134
+ type: 'inv',
135
+ functionName: 'GetHdrInv',
136
+ handlerPath: `${handlerRoot}/Get_HdrInv.main`,
137
+ roleName: 'FlowObjectsRole',
138
+ flowTag: action,
139
+ flowStepName: ''
129
140
  },
130
141
  {
131
- path: `${source}/GetRange_HdrApi.js`,
132
- content: await renderShared('FlowHandler_HdrApi.ejs', {
133
- ...shared,
134
- mainFileName: 'GetRange_Main',
135
- functionName: 'GetRange',
136
- queueName: 'GetRangeHdrApi'
137
- })
142
+ type: 'api',
143
+ functionName: 'GetHdrApi',
144
+ handlerPath: `${handlerRoot}/Get_HdrApi.main`,
145
+ roleName: 'FlowObjectsRole',
146
+ flowTag: action,
147
+ flowStepName: '',
148
+ routes: objects.filter(isCrudObject).map((object) => ({
149
+ path: `/${targetServiceTag}/${object.objectType}/get`,
150
+ upperName: upperFirst(object.objectType)
151
+ }))
138
152
  }
139
- );
140
- return {
141
- artifacts,
142
- functions: [
143
- {
144
- type: 'inv',
145
- functionName: 'GetHdrInv',
146
- handlerPath: `${handlerRoot}/Get_HdrInv.main`,
147
- roleName: 'FlowObjectsRole',
148
- flowTag: action,
149
- flowStepName: ''
150
- },
153
+ ];
154
+
155
+ const getRangeRoutes = objects
156
+ .filter(isCrudObject)
157
+ .filter(
158
+ (object) =>
159
+ object.identifiers &&
160
+ object.identifiers.some((i) => i.type === 'sortKey')
161
+ )
162
+ .map((object) => ({
163
+ path: `/${targetServiceTag}/${object.objectType}/getRange`,
164
+ upperName: upperFirst(object.objectType)
165
+ }));
166
+
167
+ if (getRangeRoutes.length > 0) {
168
+ artifacts.push(
151
169
  {
152
- type: 'api',
153
- functionName: 'GetHdrApi',
154
- handlerPath: `${handlerRoot}/Get_HdrApi.main`,
155
- roleName: 'FlowObjectsRole',
156
- flowTag: action,
157
- flowStepName: '',
158
- routes: objects.filter(isCrudObject).map((object) => ({
159
- path: `/${targetServiceTag}/${object.objectType}/get`,
160
- upperName: upperFirst(object.objectType)
161
- }))
170
+ path: `${source}/GetRange_Main.js`,
171
+ content: await render('GetRangeEndpoint_Main.ejs', {
172
+ ...shared,
173
+ mainFileName: 'GetRange_Main',
174
+ functionName: 'GetRange'
175
+ })
162
176
  },
163
177
  {
164
- type: 'api',
165
- functionName: 'GetRangeHdrApi',
166
- handlerPath: `${handlerRoot}/GetRange_HdrApi.main`,
167
- roleName: 'FlowObjectsRole',
168
- flowTag: 'GetRange',
169
- flowStepName: '',
170
- routes: objects
171
- .filter(isCrudObject)
172
- .filter(
173
- (object) =>
174
- object.identifiers &&
175
- object.identifiers.some((i) => i.type === 'sortKey')
176
- )
177
- .map((object) => ({
178
- path: `/${targetServiceTag}/${object.objectType}/getRange`,
179
- upperName: upperFirst(object.objectType)
180
- }))
178
+ path: `${source}/GetRange_HdrApi.js`,
179
+ content: await renderShared('FlowHandler_HdrApi.ejs', {
180
+ ...shared,
181
+ mainFileName: 'GetRange_Main',
182
+ functionName: 'GetRange',
183
+ queueName: 'GetRangeHdrApi'
184
+ })
181
185
  }
182
- ]
183
- };
186
+ );
187
+ functions.push({
188
+ type: 'api',
189
+ functionName: 'GetRangeHdrApi',
190
+ handlerPath: `${handlerRoot}/GetRange_HdrApi.main`,
191
+ roleName: 'FlowObjectsRole',
192
+ flowTag: 'GetRange',
193
+ flowStepName: '',
194
+ routes: getRangeRoutes
195
+ });
196
+ }
197
+
198
+ return { artifacts, functions };
184
199
  }
185
200
 
186
201
  artifacts.push(
@@ -230,68 +245,100 @@ async function emitAction(action, objects, flows, serviceTag) {
230
245
  flowStepName: ''
231
246
  }
232
247
  ];
233
- const complete = `${action}Complete`;
234
- artifacts.push(
235
- {
236
- path: `${source}/${complete}_Main.js`,
237
- content: await render(`${action}Complete_Main.ejs`, { action })
238
- },
239
- {
240
- path: `${source}/${complete}_HdrSqs.js`,
241
- content: await render(`${action}Complete_HdrSqs.ejs`, {
242
- ...shared,
243
- mainFileName: `${complete}_Main`,
244
- functionName: complete,
245
- queueName: `${action}CompleteHdrSqs`
246
- })
247
- }
248
- );
249
- functions.push({
250
- type: 'sqs',
251
- functionName: `${action}CompleteHdrSqs`,
252
- handlerPath: `${handlerRoot}/${complete}_HdrSqs.main`,
253
- roleName: 'FlowObjectsRole',
254
- queueName: `${action}CompleteHdrSqs`,
255
- flowTag: action,
256
- flowStepName: 'Complete'
257
- });
258
- if (generateCode.some((config) => config.codeHookTag === 'beforeLogical')) {
259
- const beforeMain = `${action}BeforeLogical_Main`;
248
+
249
+ if (plan.hasRbacCallback) {
250
+ const rbacCallbackMain = `${action}RbacCallback_Main`;
251
+ artifacts.push(
252
+ {
253
+ path: `${source}/${rbacCallbackMain}.js`,
254
+ content: await render('FlowEndpointRbacCallback_Main.ejs', shared)
255
+ },
256
+ {
257
+ path: `${source}/${rbacCallbackMain.replace('_Main', '_HdrSqs')}.js`,
258
+ content: await renderShared('FlowHandler_HdrSqs.ejs', {
259
+ ...shared,
260
+ mainFileName: rbacCallbackMain,
261
+ functionName: `${action}RbacCallbackMain`,
262
+ queueName: `${action}RbacCallbackHdrSqs`
263
+ })
264
+ }
265
+ );
266
+ functions.push({
267
+ type: 'sqs',
268
+ functionName: `${action}RbacCallbackHdrSqs`,
269
+ handlerPath: `${handlerRoot}/${action}RbacCallback_HdrSqs.main`,
270
+ roleName: 'FlowObjectsRole',
271
+ queueName: `${action}RbacCallbackHdrSqs`,
272
+ flowTag: action,
273
+ flowStepName: 'RbacCallback'
274
+ });
275
+ }
276
+
277
+ if (plan.hasComplete) {
278
+ const completeMain = `${action}Complete_Main`;
260
279
  artifacts.push(
261
280
  {
262
- path: `${source}/${beforeMain}.js`,
263
- content: await render('FlowEndpointBeforeLogical_Main.ejs', shared)
281
+ path: `${source}/${completeMain}.js`,
282
+ content: await render(
283
+ plan.hasRbac ? 'FlowEndpointRbacCallback_Main.ejs' : `${action}Complete_Main.ejs`,
284
+ plan.hasRbac ? shared : { action }
285
+ )
264
286
  },
265
287
  {
266
- path: `${source}/${action}BeforeLogical_HdrSqs.js`,
288
+ path: `${source}/${action}Complete_HdrSqs.js`,
267
289
  content: await renderShared('FlowHandler_HdrSqs.ejs', {
268
290
  ...shared,
269
- mainFileName: beforeMain,
270
- functionName: `${action}BeforeLogicalMain`,
271
- queueName: `${action}BeforeLogicalHdrSqs`
291
+ mainFileName: completeMain,
292
+ functionName: `${action}CompleteMain`,
293
+ queueName: `${action}CompleteHdrSqs`
272
294
  })
273
295
  }
274
296
  );
275
297
  functions.push({
276
298
  type: 'sqs',
277
- functionName: `${action}BeforeLogicalHdrSqs`,
278
- handlerPath: `${handlerRoot}/${action}BeforeLogical_HdrSqs.main`,
299
+ functionName: `${action}CompleteHdrSqs`,
300
+ handlerPath: `${handlerRoot}/${action}Complete_HdrSqs.main`,
279
301
  roleName: 'FlowObjectsRole',
280
- queueName: `${action}BeforeLogicalHdrSqs`,
302
+ queueName: `${action}CompleteHdrSqs`,
281
303
  flowTag: action,
282
- flowStepName: 'BeforeLogical'
304
+ flowStepName: 'Complete'
283
305
  });
284
306
  }
307
+
285
308
  return { artifacts, functions };
286
309
  }
287
310
 
288
- function isCrudObject(object) {
311
+ function hasSelfRbacAddOn(object) {
289
312
  return (
290
- object?.generatedBy === 'userGenerated' ||
291
- object?.generatedBy === 'systemGenerated'
313
+ Array.isArray(object?.addOnDataStructure) &&
314
+ object.addOnDataStructure.some((addOn) => addOn?.type === 'rbac')
292
315
  );
293
316
  }
294
317
 
318
+ function hasRbacAddOn(object, objects = []) {
319
+ const selfHasRbac = hasSelfRbacAddOn(object);
320
+ const belongToTargets = object?.belongTo
321
+ ? Array.isArray(object.belongTo)
322
+ ? object.belongTo
323
+ : [object.belongTo]
324
+ : [];
325
+ const belongToHasRbac =
326
+ (Array.isArray(object?.belongToSchema?.addOnDataStructure) &&
327
+ object.belongToSchema.addOnDataStructure.some(
328
+ (addOn) => addOn?.type === 'rbac'
329
+ )) ||
330
+ belongToTargets.some((target) => {
331
+ if (target?.serviceTag === 'UserAccount') return true;
332
+ const matched = objects.find(
333
+ (candidate) =>
334
+ candidate?.serviceTag === target?.serviceTag &&
335
+ candidate?.objectType === target?.objectType
336
+ );
337
+ return hasSelfRbacAddOn(matched);
338
+ });
339
+ return selfHasRbac || belongToHasRbac;
340
+ }
341
+
295
342
  function upperFirst(value) {
296
343
  return value.charAt(0).toUpperCase() + value.slice(1);
297
344
  }
@@ -302,7 +349,10 @@ async function render(templateName, data) {
302
349
  }
303
350
 
304
351
  async function renderShared(templateName, data) {
305
- const template = await readFile(new URL(templateName, SHARED_TEMPLATE_URL), 'utf8');
352
+ const template = await readFile(
353
+ new URL(templateName, SHARED_TEMPLATE_URL),
354
+ 'utf8'
355
+ );
306
356
  return ejsLib.render(template, data);
307
357
  }
308
358
 
@@ -1,64 +1,52 @@
1
1
  import { renderDynamicCrudFlowSchema } from './dynamicCrudFlowSchemaTemplate.js';
2
+ import {
3
+ CRUD_ACTIONS,
4
+ createCrudActionPlans,
5
+ hasGraphStorageResource,
6
+ isCrudObject
7
+ } from './crudActionPlan.js';
2
8
 
3
- const ACTIONS = ['Create', 'Update', 'Delete', 'Get'];
4
9
  const MESSAGE_ATTRIBUTES = ['userId', 'correlationId'];
5
10
 
6
- export const dynamicCrudFlowSchemaPaths = ACTIONS.map(
11
+ export const dynamicCrudFlowSchemaPaths = CRUD_ACTIONS.map(
7
12
  (action) =>
8
13
  `app/src/schemas/FlowSchemas/generateCode/FlowObjects/${action}.js`
9
14
  );
10
15
 
11
- export function emitDynamicCrudFlowSchemas({ objects, flows = [] }) {
16
+ export function emitDynamicCrudFlowSchemas({ objects, flows = [], serviceTag }) {
12
17
  if (!Array.isArray(objects) || !Array.isArray(flows)) {
13
18
  throw new TypeError('objects and flows must be arrays');
14
19
  }
15
- if (
16
- !objects.some(
17
- (object) =>
18
- object?.generatedBy === 'userGenerated' ||
19
- object?.generatedBy === 'systemGenerated'
20
- )
21
- ) {
22
- return [];
23
- }
20
+ if (!objects.some(isCrudObject)) return [];
24
21
 
25
- return ACTIONS.map((action, index) => {
26
- const flow = _createDynamicFlow(
22
+ const plans = createCrudActionPlans(objects);
23
+
24
+ return CRUD_ACTIONS.map((action, index) => ({
25
+ path: dynamicCrudFlowSchemaPaths[index],
26
+ content: renderDynamicCrudFlowSchema(
27
27
  action,
28
- _hasBeforeLogicalStep(flows, action)
29
- );
30
- return {
31
- path: dynamicCrudFlowSchemaPaths[index],
32
- content: renderDynamicCrudFlowSchema(action, flow)
33
- };
34
- });
28
+ _createDynamicFlow(action, plans[action], serviceTag)
29
+ )
30
+ }));
35
31
  }
36
32
 
37
- function _createDynamicFlow(action, hasBeforeLogicalStep) {
38
- const outputTopic = action !== 'Get';
33
+ function _createDynamicFlow(action, plan, serviceTag = '') {
39
34
  const flowSteps = [
40
35
  {
41
- stepName: 'start',
42
- ...(hasBeforeLogicalStep
43
- ? {
44
- nextSteps: [
45
- {
46
- stepName: 'BeforeLogical'
47
- }
48
- ]
49
- }
50
- : outputTopic
36
+ stepName: 'Start',
37
+ ...(plan.hasRbacCallback || plan.hasComplete
51
38
  ? {
52
39
  nextSteps: [
53
40
  {
54
- stepName: 'Complete'
41
+ targetType: 'ownTopic',
42
+ stepName: plan.hasRbacCallback ? 'RbacCallback' : 'Complete'
55
43
  }
56
44
  ]
57
45
  }
58
46
  : {}),
59
47
  properties: [],
60
48
  messageAttributes: MESSAGE_ATTRIBUTES,
61
- ...(outputTopic
49
+ ...(plan.outputTopic
62
50
  ? {
63
51
  returnValues: {
64
52
  properties: [],
@@ -69,17 +57,19 @@ function _createDynamicFlow(action, hasBeforeLogicalStep) {
69
57
  }
70
58
  ];
71
59
 
72
- if (hasBeforeLogicalStep) {
60
+ if (plan.hasRbacCallback) {
73
61
  flowSteps.push({
74
- stepName: 'BeforeLogical',
62
+ stepName: 'RbacCallback',
75
63
  event: ['extTopic'],
76
64
  previousSteps: [
77
65
  {
78
- stepName: 'start'
66
+ sourceType: 'ownTopic',
67
+ stepName: 'Start'
79
68
  }
80
69
  ],
81
70
  nextSteps: [
82
71
  {
72
+ targetType: 'ownTopic',
83
73
  stepName: 'Complete'
84
74
  }
85
75
  ],
@@ -88,38 +78,36 @@ function _createDynamicFlow(action, hasBeforeLogicalStep) {
88
78
  });
89
79
  }
90
80
 
91
- if (action !== 'Get') {
81
+ if (plan.hasComplete) {
92
82
  flowSteps.push({
93
83
  stepName: 'Complete',
94
84
  event: ['extTopic'],
95
85
  previousSteps: [
96
86
  {
97
- stepName: hasBeforeLogicalStep ? 'BeforeLogical' : 'start'
87
+ sourceType: 'ownTopic',
88
+ stepName: plan.hasRbacCallback ? 'RbacCallback' : 'Start'
98
89
  }
99
90
  ],
100
- properties: [
101
- 'returnValue',
102
- 'parentFlowId',
103
- 'status',
104
- 'errorsFound',
105
- 'graphServiceTag'
106
- ],
91
+ properties: plan.hasGraph
92
+ ? [
93
+ 'returnValue',
94
+ 'parentFlowId',
95
+ 'status',
96
+ 'errorsFound',
97
+ 'graphServiceTag'
98
+ ]
99
+ : [],
107
100
  messageAttributes: MESSAGE_ATTRIBUTES
108
101
  });
109
102
  }
110
103
 
111
- let eventTypes = ['lambdaSyncInv', 'lambdaSyncApi'];
112
- if (outputTopic) {
113
- eventTypes = ['ownTopic'];
114
- }
115
-
116
104
  return {
117
105
  flowTag: action,
118
106
  initiateBy: 'system',
119
107
  handleObj: 'one',
120
108
  statusType: 'none',
121
- event: eventTypes,
122
- outputTopic,
109
+ event: plan.outputTopic ? ['ownTopic'] : ['lambdaSyncInv', 'lambdaSyncApi'],
110
+ outputTopic: plan.outputTopic,
123
111
  stepMessageAttributes: {
124
112
  userId: { propertyName: 'x-correlation-base-user-id', type: 'string' },
125
113
  correlationId: { propertyName: 'x-correlation-id', type: 'string' }
@@ -128,14 +116,4 @@ function _createDynamicFlow(action, hasBeforeLogicalStep) {
128
116
  };
129
117
  }
130
118
 
131
- function _hasBeforeLogicalStep(flows, action) {
132
- return flows.some((flow) => {
133
- const config = flow?.generatedCodeConfig;
134
- return (
135
- config?.generatedCodeTag === action.toLowerCase() &&
136
- config.codeHookTag === 'beforeLogical' &&
137
- Array.isArray(flow.event) &&
138
- flow.event.includes(config.invocationType)
139
- );
140
- });
141
- }
119
+ export { hasGraphStorageResource };
@@ -12,7 +12,10 @@ export async function generateDynamicCrudFlowSchemas(rootPath, options = {}) {
12
12
  const schemaInputs = await loadLocalSchemaArrays(project);
13
13
  const plan = buildGenerationPlan(
14
14
  project,
15
- emitDynamicCrudFlowSchemas(schemaInputs),
15
+ emitDynamicCrudFlowSchemas({
16
+ ...schemaInputs,
17
+ serviceTag: project.serviceTag
18
+ }),
16
19
  {
17
20
  managedPaths: dynamicCrudFlowSchemaPaths,
18
21
  managedScope: 'crud-flow-schemas'