@izara_project/izara-core-generate-service-code 1.0.83 → 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.
- package/package.json +4 -4
- package/src/compile/flowValidator.js +13 -2
- package/src/compile/loadSchemas.js +116 -7
- package/src/emit/attributeTree/emitAttributeTreeSchemas.js +388 -0
- package/src/emit/coreFunction/emitCoreFunctionArtifacts.js +34 -1
- package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +29 -7
- package/src/emit/crud/crudActionPlan.js +41 -6
- package/src/emit/crud/emitCrudApplicationArtifacts.js +56 -8
- package/src/emit/crud/emitDynamicCrudFlowSchemas.js +153 -27
- package/src/emit/crud/generateCrudApplicationArtifacts.js +3 -2
- package/src/emit/crud/generateDynamicCrudFlowSchemas.js +3 -2
- package/src/emit/crud/loadLocalSchemaArrays.js +3 -3
- package/src/emit/crud/templates/CreateComplete_Main.ejs +1 -1
- package/src/emit/crud/templates/CreateConfirmComplete_Main.ejs +54 -0
- package/src/emit/crud/templates/CreateEndpoint_Main.ejs +252 -154
- package/src/emit/crud/templates/CreateLogicalLib.ejs +1163 -236
- package/src/emit/crud/templates/CreateNodeCallback_Main.ejs +221 -0
- package/src/emit/crud/templates/DeleteComplete_Main.ejs +1 -1
- package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +33 -8
- package/src/emit/crud/templates/DeleteLogicalLib.ejs +6 -3
- package/src/emit/crud/templates/FlowEndpointRbacCallback_Main.ejs +20 -120
- package/src/emit/crud/templates/FlowEndpoint_HdrWbs.ejs +79 -10
- package/src/emit/crud/templates/FlowMain_Wbs.ejs +31 -35
- package/src/emit/crud/templates/GetEndpoint_Main.ejs +13 -0
- package/src/emit/crud/templates/UpdateComplete_Main.ejs +1 -1
- package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +52 -3
- package/src/emit/crud/templates/UpdateLogicalLib.ejs +4 -3
- package/src/emit/custom/customFlows.js +47 -0
- package/src/emit/custom/emitCustomFlowApplicationArtifacts.js +168 -49
- package/src/emit/custom/generateCustomFlowApplicationArtifacts.js +1 -1
- package/src/emit/custom/templates/FlowEndpointRbacCallback_Main.ejs +194 -0
- package/src/emit/custom/templates/FlowEndpoint_Main.ejs +14 -22
- package/src/emit/custom/templates/FlowStep_Main.ejs +1 -1
- package/src/emit/function/templates/WbsFunction_Yaml.ejs +0 -2
- package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +33 -8
- package/src/emit/rbac/emitRbacApplicationArtifacts.js +204 -7
- package/src/emit/rbac/templates/CancelUsage_Main.ejs +163 -0
- package/src/emit/rbac/templates/ConfirmUsage_Main.ejs +187 -0
- package/src/emit/rbac/templates/CreateTargetRole_Main.ejs +68 -6
- package/src/emit/rbac/templates/ListRbac_Main.ejs +9 -3
- package/src/emit/rbac/templates/RbacMutation_Main.ejs +1 -1
- package/src/emit/rbac/templates/ReservedDynamicUsage_Main.ejs +166 -0
- package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +84 -23
- package/src/emit/rbac/templates/UserRoleMutation_Main.ejs +11 -8
- package/src/emit/relationship/emitDynamicRelationshipFlowSchemas.js +1 -1
- package/src/emit/relationship/templates/ChangeRelationship_Main.ejs +4 -4
- package/src/emit/resource/emitResourceArtifacts.js +351 -108
- package/src/emit/resource/templates/GeneratedLambdaRoleServiceConfig.ejs +3 -1
- package/src/emit/resource/templates/SystemDynamoDB_Yaml.ejs +55 -2
- package/src/emit/shared/templates/FlowHandler_HdrSqs.ejs +1 -1
- package/src/emit/system/emitSystemWebSocketArtifacts.js +6 -5
- package/src/emit/system/templates/WebSocketConnect.ejs +71 -12
- package/src/emit/system/templates/WebSocketConnect_Yaml.ejs +6 -0
- package/src/emit/systemText/emitSystemTextSchemas.js +1 -1
- package/src/generate.js +41 -10
- package/test/attributeTreeSchemas.test.js +219 -0
- package/test/createTargetRoleHandler.test.js +59 -4
- package/test/crudApplicationArtifacts.test.js +20 -3
- package/test/customFlowApplicationArtifacts.test.js +5 -5
- package/test/dynamicCrudFlowSchemas.test.js +107 -6
- package/test/dynamicRbacFlowSchemas.test.js +15 -2
- package/test/publicApi.test.js +6 -6
- package/test/resourceArtifacts.test.js +89 -27
|
@@ -70,6 +70,10 @@ const externalServices = {
|
|
|
70
70
|
dynamoTableNames.add('RolePermissions');
|
|
71
71
|
dynamoTableNames.add('RoleUsers');
|
|
72
72
|
dynamoTableNames.add('UserRoles');
|
|
73
|
+
dynamoTableNames.add('RbacPermissionCaches');
|
|
74
|
+
dynamoTableNames.add('RoleLimit');
|
|
75
|
+
dynamoTableNames.add('RunningTotalUsage');
|
|
76
|
+
dynamoTableNames.add('RunningTotalReservedUsage');
|
|
73
77
|
}
|
|
74
78
|
if (typeof s3Flows !== 'undefined' && (s3Flows || []).length > 0) {
|
|
75
79
|
dynamoTableNames.add('ReservedDataMain');
|
|
@@ -127,7 +131,10 @@ const tableConfigs = {
|
|
|
127
131
|
const nodeSubs = [];
|
|
128
132
|
(objectGraphServiceTags || []).forEach(function(tag) {
|
|
129
133
|
nodeSubs.push({ serviceTag: tag, topicName: 'UpdateNode_Out', sqsEndpoint: 'UpdateCompleteHdrSqs' });
|
|
130
|
-
|
|
134
|
+
const createNodeEndpoint = (typeof hasQuotaReservation !== 'undefined' && hasQuotaReservation)
|
|
135
|
+
? 'CreateNodeCallbackHdrSqs'
|
|
136
|
+
: 'CreateCompleteHdrSqs';
|
|
137
|
+
nodeSubs.push({ serviceTag: tag, topicName: 'CreateNode_Out', sqsEndpoint: createNodeEndpoint });
|
|
131
138
|
});
|
|
132
139
|
|
|
133
140
|
const customSubs = [];
|
|
@@ -173,18 +180,31 @@ const tableConfigs = {
|
|
|
173
180
|
});
|
|
174
181
|
|
|
175
182
|
const rbacSubs = [];
|
|
176
|
-
if (crud &&
|
|
177
|
-
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 : [])]));
|
|
178
185
|
const hasGraph = typeof objectGraphServiceTags !== 'undefined' && objectGraphServiceTags && objectGraphServiceTags.length > 0;
|
|
186
|
+
const createEndpoint = hasGraph ? 'CreateRbacCallbackHdrSqs' : 'CreateCompleteHdrSqs';
|
|
179
187
|
const updateEndpoint = hasGraph ? 'UpdateRbacCallbackHdrSqs' : 'UpdateCompleteHdrSqs';
|
|
180
188
|
const deleteEndpoint = hasGraph ? 'DeleteRbacCallbackHdrSqs' : 'DeleteCompleteHdrSqs';
|
|
181
189
|
allRbacTags.forEach(function(tag) {
|
|
182
|
-
|
|
183
|
-
rbacSubs.push({ serviceTag: tag, topicName: 'ValidatorRbac_Out', sqsEndpoint: 'CreateCompleteHdrSqs' });
|
|
184
|
-
}
|
|
190
|
+
rbacSubs.push({ serviceTag: tag, topicName: 'ValidatorRbac_Out', sqsEndpoint: createEndpoint });
|
|
185
191
|
rbacSubs.push({ serviceTag: tag, topicName: 'ValidatorRbac_Out', sqsEndpoint: updateEndpoint });
|
|
186
192
|
rbacSubs.push({ serviceTag: tag, topicName: 'ValidatorRbac_Out', sqsEndpoint: deleteEndpoint });
|
|
187
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
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (typeof customRbacFlowTags !== 'undefined' && customRbacFlowTags && customRbacFlowTags.length > 0) {
|
|
201
|
+
const allRbacTags = Array.from(new Set(['Rbac', ...(typeof rbacValidatorServiceTags !== 'undefined' ? rbacValidatorServiceTags : [])]));
|
|
202
|
+
customRbacFlowTags.forEach(function(flowTag) {
|
|
203
|
+
const tagUpper = flowTag[0].toUpperCase() + flowTag.slice(1);
|
|
204
|
+
allRbacTags.forEach(function(tag) {
|
|
205
|
+
rbacSubs.push({ serviceTag: tag, topicName: 'ValidatorRbac_Out', sqsEndpoint: `${tagUpper}RbacCallbackHdrSqs` });
|
|
206
|
+
});
|
|
207
|
+
});
|
|
188
208
|
}
|
|
189
209
|
-%>
|
|
190
210
|
const snsTopicSubscriptions = [
|
|
@@ -294,7 +314,9 @@ function roleConfigs() {
|
|
|
294
314
|
Effect: 'Allow',
|
|
295
315
|
Action: ['sns:Publish'],
|
|
296
316
|
Resource: [
|
|
297
|
-
`arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'ValidatorRbac_In', 'Rbac')}
|
|
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) { %>,
|
|
298
320
|
`arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'ValidatorRbac_In', '<%= tag %>')}`<% }); %>
|
|
299
321
|
]
|
|
300
322
|
},
|
|
@@ -5,36 +5,43 @@ export function createCrudActionPlans(objects = []) {
|
|
|
5
5
|
const hasRbac = objects.some(
|
|
6
6
|
(object) => isCrudObject(object) && hasRbacObject(object, objects)
|
|
7
7
|
);
|
|
8
|
+
const isBillable = objects.some(
|
|
9
|
+
(object) => isCrudObject(object) && isBillableObject(object, objects)
|
|
10
|
+
);
|
|
8
11
|
|
|
9
12
|
return Object.fromEntries(
|
|
10
13
|
CRUD_ACTIONS.map((action) => [
|
|
11
14
|
action,
|
|
12
|
-
createCrudActionPlan(action, { hasGraph, hasRbac })
|
|
15
|
+
createCrudActionPlan(action, { hasGraph, hasRbac, isBillable })
|
|
13
16
|
])
|
|
14
17
|
);
|
|
15
18
|
}
|
|
16
19
|
|
|
17
20
|
export function createCrudActionPlan(
|
|
18
21
|
action,
|
|
19
|
-
{ hasGraph = false, hasRbac = false } = {}
|
|
22
|
+
{ hasGraph = false, hasRbac = false, isBillable = true } = {}
|
|
20
23
|
) {
|
|
21
|
-
const actionHasRbac = action !== '
|
|
24
|
+
const actionHasRbac = action !== 'Get' && hasRbac;
|
|
22
25
|
const outputTopic = action !== 'Get';
|
|
26
|
+
const hasQuotaReservation = action === 'Create' && hasRbac && isBillable;
|
|
23
27
|
|
|
24
28
|
return {
|
|
25
29
|
action,
|
|
26
30
|
outputTopic,
|
|
27
31
|
hasGraph: outputTopic && hasGraph,
|
|
28
32
|
hasRbac: actionHasRbac,
|
|
33
|
+
hasQuotaReservation,
|
|
29
34
|
hasComplete: outputTopic && (actionHasRbac || hasGraph),
|
|
30
|
-
hasRbacCallback: outputTopic && actionHasRbac && hasGraph
|
|
35
|
+
hasRbacCallback: outputTopic && actionHasRbac && hasGraph,
|
|
36
|
+
hasCreateNodeCallback:
|
|
37
|
+
outputTopic && action === 'Create' && actionHasRbac && hasGraph && hasQuotaReservation
|
|
31
38
|
};
|
|
32
39
|
}
|
|
33
40
|
|
|
34
|
-
const VALID_CRUD_GENERATED_BY = new Set([
|
|
41
|
+
export const VALID_CRUD_GENERATED_BY = new Set([
|
|
35
42
|
'user',
|
|
36
43
|
'systemWithUser',
|
|
37
|
-
'
|
|
44
|
+
'systemNoUser'
|
|
38
45
|
]);
|
|
39
46
|
|
|
40
47
|
export function isCrudObject(object) {
|
|
@@ -83,3 +90,31 @@ function normalizeBelongTo(object) {
|
|
|
83
90
|
if (!object?.belongTo) return [];
|
|
84
91
|
return Array.isArray(object.belongTo) ? object.belongTo : [object.belongTo];
|
|
85
92
|
}
|
|
93
|
+
|
|
94
|
+
export function isBillableObject(object, objects = []) {
|
|
95
|
+
if (!isCrudObject(object)) return false;
|
|
96
|
+
|
|
97
|
+
const targets = normalizeBelongTo(object);
|
|
98
|
+
if (targets.length > 0) {
|
|
99
|
+
for (const target of targets) {
|
|
100
|
+
if (typeof target?.billable === 'boolean') {
|
|
101
|
+
return target.billable;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (Array.isArray(object?.addOnDataStructure)) {
|
|
107
|
+
const rbacAddOn = object.addOnDataStructure.find(
|
|
108
|
+
(addOn) => addOn?.type === 'rbac'
|
|
109
|
+
);
|
|
110
|
+
if (typeof rbacAddOn?.billable === 'boolean') {
|
|
111
|
+
return rbacAddOn.billable;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (typeof object?.billable === 'boolean') {
|
|
116
|
+
return object.billable;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
@@ -11,7 +11,8 @@ import {
|
|
|
11
11
|
import {
|
|
12
12
|
CRUD_ACTIONS,
|
|
13
13
|
createCrudActionPlans,
|
|
14
|
-
isCrudObject
|
|
14
|
+
isCrudObject,
|
|
15
|
+
VALID_CRUD_GENERATED_BY
|
|
15
16
|
} from './crudActionPlan.js';
|
|
16
17
|
|
|
17
18
|
const ACTIONS = CRUD_ACTIONS;
|
|
@@ -22,12 +23,26 @@ const SHARED_TEMPLATE_URL = new URL('../shared/templates/', import.meta.url);
|
|
|
22
23
|
export async function emitCrudApplicationArtifacts({
|
|
23
24
|
objects,
|
|
24
25
|
flows = [],
|
|
25
|
-
serviceTag
|
|
26
|
+
serviceTag,
|
|
27
|
+
logger
|
|
26
28
|
}) {
|
|
27
29
|
if (!Array.isArray(objects) || !Array.isArray(flows)) {
|
|
28
30
|
throw new TypeError('objects and flows must be arrays');
|
|
29
31
|
}
|
|
30
|
-
if (!objects.some(isCrudObject))
|
|
32
|
+
if (!objects.some(isCrudObject)) {
|
|
33
|
+
if (objects.length > 0) {
|
|
34
|
+
const summary = objects.map((obj) => ({
|
|
35
|
+
objectType: obj?.objectType ?? '(undefined)',
|
|
36
|
+
generatedBy: obj?.generatedBy ?? '(missing)'
|
|
37
|
+
}));
|
|
38
|
+
logger?.warn?.(
|
|
39
|
+
`[WARN] [CRUD Application] Skipped FlowObjects application artifacts generation: No valid CRUD ObjectSchema found. ` +
|
|
40
|
+
`Checked ${objects.length} object(s): ${JSON.stringify(summary)}. ` +
|
|
41
|
+
`Expected "generatedBy" to be one of: ${Array.from(VALID_CRUD_GENERATED_BY).join(', ')}`
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
31
46
|
|
|
32
47
|
const handlers = await Promise.all(
|
|
33
48
|
ACTIONS.map((action) => emitAction(action, objects, serviceTag))
|
|
@@ -65,6 +80,8 @@ export function crudApplicationManagedPaths() {
|
|
|
65
80
|
`${source}/${action}_HdrWbs.js`,
|
|
66
81
|
`${source}/${action}RbacCallback_Main.js`,
|
|
67
82
|
`${source}/${action}RbacCallback_HdrSqs.js`,
|
|
83
|
+
`${source}/${action}NodeCallback_Main.js`,
|
|
84
|
+
`${source}/${action}NodeCallback_HdrSqs.js`,
|
|
68
85
|
`${source}/${action}Complete_Main.js`,
|
|
69
86
|
`${source}/${action}Complete_HdrSqs.js`
|
|
70
87
|
);
|
|
@@ -87,7 +104,7 @@ async function emitAction(action, objects, serviceTag) {
|
|
|
87
104
|
flow: null,
|
|
88
105
|
flowStepName: '',
|
|
89
106
|
startConfig: null,
|
|
90
|
-
objects:
|
|
107
|
+
objects: objects,
|
|
91
108
|
isCrudObject,
|
|
92
109
|
hasRbacAddOn: (object) => hasRbacAddOn(object, objects),
|
|
93
110
|
plan
|
|
@@ -275,12 +292,43 @@ async function emitAction(action, objects, serviceTag) {
|
|
|
275
292
|
});
|
|
276
293
|
}
|
|
277
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
|
+
|
|
278
323
|
if (plan.hasComplete) {
|
|
279
324
|
const completeMain = `${action}Complete_Main`;
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
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
|
+
|
|
284
332
|
const templateContext =
|
|
285
333
|
plan.hasRbac && !plan.hasGraph
|
|
286
334
|
? shared
|
|
@@ -3,7 +3,8 @@ import {
|
|
|
3
3
|
CRUD_ACTIONS,
|
|
4
4
|
createCrudActionPlans,
|
|
5
5
|
hasGraphStorageResource,
|
|
6
|
-
isCrudObject
|
|
6
|
+
isCrudObject,
|
|
7
|
+
VALID_CRUD_GENERATED_BY
|
|
7
8
|
} from './crudActionPlan.js';
|
|
8
9
|
|
|
9
10
|
const MESSAGE_ATTRIBUTES = ['userId', 'correlationId'];
|
|
@@ -13,37 +14,77 @@ export const dynamicCrudFlowSchemaPaths = CRUD_ACTIONS.map(
|
|
|
13
14
|
`app/src/schemas/FlowSchemas/generateCode/FlowObjects/${action}.js`
|
|
14
15
|
);
|
|
15
16
|
|
|
16
|
-
export function emitDynamicCrudFlowSchemas({
|
|
17
|
+
export function emitDynamicCrudFlowSchemas({
|
|
18
|
+
objects,
|
|
19
|
+
flows = [],
|
|
20
|
+
serviceTag,
|
|
21
|
+
logger
|
|
22
|
+
}) {
|
|
17
23
|
if (!Array.isArray(objects) || !Array.isArray(flows)) {
|
|
18
24
|
throw new TypeError('objects and flows must be arrays');
|
|
19
25
|
}
|
|
20
|
-
if (!objects.some(isCrudObject))
|
|
26
|
+
if (!objects.some(isCrudObject)) {
|
|
27
|
+
if (objects.length > 0) {
|
|
28
|
+
const summary = objects.map((obj) => ({
|
|
29
|
+
objectType: obj?.objectType ?? '(undefined)',
|
|
30
|
+
generatedBy: obj?.generatedBy ?? '(missing)'
|
|
31
|
+
}));
|
|
32
|
+
logger?.warn?.(
|
|
33
|
+
`[WARN] [CRUD FlowSchemas] Skipped FlowObjects FlowSchemas generation: No valid CRUD ObjectSchema found. ` +
|
|
34
|
+
`Checked ${objects.length} object(s): ${JSON.stringify(summary)}. ` +
|
|
35
|
+
`Expected "generatedBy" to be one of: ${Array.from(VALID_CRUD_GENERATED_BY).join(', ')}`
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
21
40
|
|
|
22
41
|
const plans = createCrudActionPlans(objects);
|
|
42
|
+
const primaryObject = objects.find(isCrudObject);
|
|
43
|
+
const initiateBy = primaryObject?.generatedBy || 'user';
|
|
23
44
|
|
|
24
45
|
return CRUD_ACTIONS.map((action, index) => ({
|
|
25
46
|
path: dynamicCrudFlowSchemaPaths[index],
|
|
26
47
|
content: renderDynamicCrudFlowSchema(
|
|
27
48
|
action,
|
|
28
|
-
_createDynamicFlow(action, plans[action], serviceTag)
|
|
49
|
+
_createDynamicFlow(action, plans[action], serviceTag, initiateBy)
|
|
29
50
|
)
|
|
30
51
|
}));
|
|
31
52
|
}
|
|
32
53
|
|
|
33
|
-
function _createDynamicFlow(action, plan, serviceTag = '') {
|
|
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
|
+
|
|
34
84
|
const flowSteps = [
|
|
35
85
|
{
|
|
36
86
|
stepName: 'Start',
|
|
37
|
-
...(
|
|
38
|
-
? {
|
|
39
|
-
nextSteps: [
|
|
40
|
-
{
|
|
41
|
-
targetType: 'ownTopic',
|
|
42
|
-
stepName: plan.hasRbacCallback ? 'RbacCallback' : 'Complete'
|
|
43
|
-
}
|
|
44
|
-
]
|
|
45
|
-
}
|
|
46
|
-
: {}),
|
|
87
|
+
...(startNextSteps.length > 0 ? { nextSteps: startNextSteps } : {}),
|
|
47
88
|
properties: [],
|
|
48
89
|
messageAttributes: MESSAGE_ATTRIBUTES,
|
|
49
90
|
...(plan.outputTopic
|
|
@@ -58,6 +99,22 @@ function _createDynamicFlow(action, plan, serviceTag = '') {
|
|
|
58
99
|
];
|
|
59
100
|
|
|
60
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
|
+
|
|
61
118
|
flowSteps.push({
|
|
62
119
|
stepName: 'RbacCallback',
|
|
63
120
|
event: ['extTopic'],
|
|
@@ -65,45 +122,114 @@ function _createDynamicFlow(action, plan, serviceTag = '') {
|
|
|
65
122
|
{
|
|
66
123
|
sourceType: 'ownTopic',
|
|
67
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']
|
|
68
153
|
}
|
|
69
154
|
],
|
|
70
155
|
nextSteps: [
|
|
71
156
|
{
|
|
72
157
|
targetType: 'ownTopic',
|
|
73
158
|
stepName: 'Complete'
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
targetType: 'extTopic',
|
|
162
|
+
serviceTag: 'Rbac',
|
|
163
|
+
topicName: 'ConfirmUsage_In',
|
|
164
|
+
toStepNames: ['Complete']
|
|
74
165
|
}
|
|
75
166
|
],
|
|
76
|
-
properties: [
|
|
167
|
+
properties: [
|
|
168
|
+
'returnValue',
|
|
169
|
+
'parentFlowId',
|
|
170
|
+
'status',
|
|
171
|
+
'errorsFound',
|
|
172
|
+
'graphServiceTag'
|
|
173
|
+
],
|
|
77
174
|
messageAttributes: MESSAGE_ATTRIBUTES
|
|
78
175
|
});
|
|
79
176
|
}
|
|
80
177
|
|
|
81
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
|
+
|
|
82
206
|
flowSteps.push({
|
|
83
207
|
stepName: 'Complete',
|
|
84
208
|
event: ['extTopic'],
|
|
85
|
-
previousSteps:
|
|
86
|
-
|
|
87
|
-
sourceType: 'ownTopic',
|
|
88
|
-
stepName: plan.hasRbacCallback ? 'RbacCallback' : 'Start'
|
|
89
|
-
}
|
|
90
|
-
],
|
|
91
|
-
properties: plan.hasGraph
|
|
209
|
+
previousSteps: completePrevSteps,
|
|
210
|
+
properties: plan.hasCreateNodeCallback
|
|
92
211
|
? [
|
|
93
212
|
'returnValue',
|
|
94
213
|
'parentFlowId',
|
|
95
214
|
'status',
|
|
96
|
-
'errorsFound'
|
|
97
|
-
'graphServiceTag'
|
|
215
|
+
'errorsFound'
|
|
98
216
|
]
|
|
99
|
-
:
|
|
217
|
+
: (plan.hasGraph
|
|
218
|
+
? [
|
|
219
|
+
'returnValue',
|
|
220
|
+
'parentFlowId',
|
|
221
|
+
'status',
|
|
222
|
+
'errorsFound',
|
|
223
|
+
'graphServiceTag'
|
|
224
|
+
]
|
|
225
|
+
: []),
|
|
100
226
|
messageAttributes: MESSAGE_ATTRIBUTES
|
|
101
227
|
});
|
|
102
228
|
}
|
|
103
229
|
|
|
104
230
|
return {
|
|
105
231
|
flowTag: action,
|
|
106
|
-
initiateBy
|
|
232
|
+
initiateBy,
|
|
107
233
|
handleObj: 'one',
|
|
108
234
|
statusType: 'none',
|
|
109
235
|
event: plan.outputTopic ? ['ownTopic'] : ['lambdaSyncInv', 'lambdaSyncApi'],
|
|
@@ -9,10 +9,11 @@ import {
|
|
|
9
9
|
|
|
10
10
|
export async function generateCrudApplicationArtifacts(rootPath, options = {}) {
|
|
11
11
|
const project = compileProject({ ...options, rootPath });
|
|
12
|
-
const schemas = await loadLocalSchemaArrays(project);
|
|
12
|
+
const schemas = await loadLocalSchemaArrays(project, options);
|
|
13
13
|
const artifacts = await emitCrudApplicationArtifacts({
|
|
14
14
|
...schemas,
|
|
15
|
-
serviceTag: project.serviceTag
|
|
15
|
+
serviceTag: project.serviceTag,
|
|
16
|
+
logger: options.logger
|
|
16
17
|
});
|
|
17
18
|
const files = await commitArtifacts(
|
|
18
19
|
buildGenerationPlan(project, artifacts, {
|
|
@@ -9,12 +9,13 @@ import { loadLocalSchemaArrays } from './loadLocalSchemaArrays.js';
|
|
|
9
9
|
|
|
10
10
|
export async function generateDynamicCrudFlowSchemas(rootPath, options = {}) {
|
|
11
11
|
const project = compileProject({ ...options, rootPath });
|
|
12
|
-
const schemaInputs = await loadLocalSchemaArrays(project);
|
|
12
|
+
const schemaInputs = await loadLocalSchemaArrays(project, options);
|
|
13
13
|
const plan = buildGenerationPlan(
|
|
14
14
|
project,
|
|
15
15
|
emitDynamicCrudFlowSchemas({
|
|
16
16
|
...schemaInputs,
|
|
17
|
-
serviceTag: project.serviceTag
|
|
17
|
+
serviceTag: project.serviceTag,
|
|
18
|
+
logger: options.logger
|
|
18
19
|
}),
|
|
19
20
|
{
|
|
20
21
|
managedPaths: dynamicCrudFlowSchemaPaths,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { loadLocalSchemaDirectory } from '../../compile/loadSchemas.js';
|
|
2
2
|
|
|
3
|
-
export async function loadLocalSchemaArrays(project) {
|
|
3
|
+
export async function loadLocalSchemaArrays(project, options = {}) {
|
|
4
4
|
return {
|
|
5
|
-
objects: await loadLocalSchemaDirectory(project, 'ObjectSchemas'),
|
|
6
|
-
flows: await loadLocalSchemaDirectory(project, 'FlowSchemas')
|
|
5
|
+
objects: await loadLocalSchemaDirectory(project, 'ObjectSchemas', options),
|
|
6
|
+
flows: await loadLocalSchemaDirectory(project, 'FlowSchemas', options)
|
|
7
7
|
};
|
|
8
8
|
}
|
|
@@ -52,7 +52,7 @@ export default async function CreateComplete(
|
|
|
52
52
|
//(</additionalParams>)
|
|
53
53
|
) {
|
|
54
54
|
try {
|
|
55
|
-
_izContext.logger.debug(
|
|
55
|
+
_izContext.logger.debug(`[${process.env.iz_serviceTag}:CreateComplete] started`, {
|
|
56
56
|
requestParams
|
|
57
57
|
});
|
|
58
58
|
const {
|
|
@@ -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
|
+
}
|