@izara_project/izara-core-generate-service-code 1.0.78 → 1.0.80
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 +2 -2
- package/src/compile/flowValidator.js +163 -0
- package/src/compile/loadSchemas.js +15 -5
- package/src/emit/coreFunction/emitCoreFunctionArtifacts.js +137 -7
- package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +137 -17
- package/src/emit/crud/crudActionPlan.js +82 -0
- package/src/emit/crud/emitCrudApplicationArtifacts.js +169 -112
- package/src/emit/crud/emitDynamicCrudFlowSchemas.js +43 -65
- package/src/emit/crud/generateDynamicCrudFlowSchemas.js +4 -1
- package/src/emit/crud/templates/CreateComplete_Main.ejs +8 -3
- package/src/emit/crud/templates/CreateEndpoint_Main.ejs +90 -513
- package/src/emit/crud/templates/CreateLogicalLib.ejs +541 -0
- package/src/emit/crud/templates/DeleteComplete_Main.ejs +8 -3
- package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +93 -203
- package/src/emit/crud/templates/DeleteLogicalLib.ejs +213 -0
- package/src/emit/crud/templates/FlowEndpointRbacCallback_Main.ejs +217 -0
- package/src/emit/crud/templates/GetEndpoint_Main.ejs +1 -1
- package/src/emit/crud/templates/GetRangeEndpoint_Main.ejs +118 -37
- package/src/emit/crud/templates/UpdateComplete_Main.ejs +8 -3
- package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +92 -444
- package/src/emit/crud/templates/UpdateLogicalLib.ejs +477 -0
- package/src/emit/custom/customFlows.js +27 -2
- package/src/emit/custom/emitCustomFlowApplicationArtifacts.js +1 -2
- package/src/emit/custom/templates/FlowEndpoint_Main.ejs +10 -3
- package/src/emit/custom/templates/FlowStep_Main.ejs +1 -1
- package/src/emit/custom/templates/s3/CreateObject_Main.ejs +1 -1
- package/src/emit/custom/templates/triggerCache/CheckTriggerCache_HdrSqs.ejs +2 -2
- package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +3 -9
- package/src/emit/rbac/emitRbacApplicationArtifacts.js +21 -16
- package/src/emit/rbac/rbacFlowTag.js +2 -7
- package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +148 -21
- package/src/emit/relationship/emitDynamicRelationshipFlowSchemas.js +4 -2
- package/src/emit/relationship/templates/ChangeRelationshipComplete_Main.ejs +7 -2
- package/src/emit/relationship/templates/ChangeRelationship_Main.ejs +6 -2
- package/src/emit/relationship/templates/CreateRelationshipComplete_Main.ejs +7 -2
- package/src/emit/relationship/templates/CreateRelationship_Main.ejs +6 -2
- package/src/emit/relationship/templates/DeleteRelationshipComplete_Main.ejs +7 -2
- package/src/emit/relationship/templates/DeleteRelationship_Main.ejs +6 -2
- package/src/emit/relationship/templates/GetRelationship_Main.ejs +1 -1
- package/src/emit/relationship/templates/MoveRelationshipComplete_Main.ejs +7 -2
- package/src/emit/relationship/templates/MoveRelationship_Main.ejs +6 -2
- package/src/emit/relationship/templates/UpdateRelationshipComplete_Main.ejs +7 -2
- package/src/emit/relationship/templates/UpdateRelationship_Main.ejs +6 -2
- package/src/emit/resource/emitResourceArtifacts.js +149 -79
- package/src/emit/resource/templates/DynamoDBTable_Yaml.ejs +4 -4
- package/src/emit/resource/templates/GeneratedLambdaRoleServiceConfig.ejs +31 -5
- package/src/emit/resource/templates/SystemDynamoDB_Yaml.ejs +21 -0
- package/src/emit/resource/templates/WebSocketSubscription_Yaml.ejs +7 -0
- package/src/emit/shared/templates/FlowHandler_HdrApi.ejs +1 -1
- package/src/emit/shared/templates/FlowHandler_HdrDsq.ejs +2 -2
- package/src/emit/shared/templates/FlowHandler_HdrInv.ejs +1 -1
- package/src/emit/shared/templates/FlowHandler_HdrSqs.ejs +2 -2
- package/src/emit/systemText/emitSystemTextSchemas.js +246 -0
- package/src/emit/systemText/templates/SystemTextSchemas.ejs +10 -0
- package/src/generate.js +55 -8
- package/test/crudApplicationArtifacts.test.js +158 -19
- package/test/customFlowApplicationArtifacts.test.js +307 -16
- package/test/dynamicCrudFlowSchemas.test.js +150 -14
- package/test/dynamicRbacFlowSchemas.test.js +2 -2
- package/test/dynamicRelationshipFlowSchemas.test.js +1 -1
- package/test/graphDrivenFlowSchema.test.js +257 -0
- package/test/publicApi.test.js +14 -5
- package/test/resourceArtifacts.test.js +66 -19
- package/test/systemTextSchemas.test.js +154 -0
- package/src/emit/crud/templates/CreateComplete_HdrSqs.ejs +0 -99
- package/src/emit/crud/templates/DeleteComplete_HdrSqs.ejs +0 -99
- package/src/emit/crud/templates/FlowEndpointBeforeLogical_Main.ejs +0 -174
- package/src/emit/crud/templates/FlowEndpointComplete_Main.ejs +0 -187
- package/src/emit/crud/templates/UpdateComplete_HdrSqs.ejs +0 -99
- 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
|
-
|
|
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,
|
|
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}
|
|
58
|
-
`${source}/${action}
|
|
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,22 @@ export function crudApplicationManagedPaths() {
|
|
|
68
75
|
];
|
|
69
76
|
}
|
|
70
77
|
|
|
71
|
-
async function emitAction(action, objects,
|
|
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
|
|
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),
|
|
93
|
+
plan
|
|
90
94
|
};
|
|
91
95
|
const artifacts = [
|
|
92
96
|
{
|
|
@@ -94,6 +98,12 @@ async function emitAction(action, objects, flows, serviceTag) {
|
|
|
94
98
|
content: await render(`${action}Endpoint_Main.ejs`, shared)
|
|
95
99
|
}
|
|
96
100
|
];
|
|
101
|
+
if (action !== 'Get') {
|
|
102
|
+
artifacts.unshift({
|
|
103
|
+
path: `${source}/${action}LogicalLib.js`,
|
|
104
|
+
content: await render(`${action}LogicalLib.ejs`, shared)
|
|
105
|
+
});
|
|
106
|
+
}
|
|
97
107
|
|
|
98
108
|
let targetServiceTag = '${self:custom.iz_serviceName}';
|
|
99
109
|
if (serviceTag) {
|
|
@@ -118,69 +128,75 @@ async function emitAction(action, objects, flows, serviceTag) {
|
|
|
118
128
|
functionName: 'Get',
|
|
119
129
|
queueName: 'GetHdrApi'
|
|
120
130
|
})
|
|
121
|
-
}
|
|
131
|
+
}
|
|
132
|
+
);
|
|
133
|
+
const functions = [
|
|
122
134
|
{
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
135
|
+
type: 'inv',
|
|
136
|
+
functionName: 'GetHdrInv',
|
|
137
|
+
handlerPath: `${handlerRoot}/Get_HdrInv.main`,
|
|
138
|
+
roleName: 'FlowObjectsRole',
|
|
139
|
+
flowTag: action,
|
|
140
|
+
flowStepName: ''
|
|
129
141
|
},
|
|
130
142
|
{
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
143
|
+
type: 'api',
|
|
144
|
+
functionName: 'GetHdrApi',
|
|
145
|
+
handlerPath: `${handlerRoot}/Get_HdrApi.main`,
|
|
146
|
+
roleName: 'FlowObjectsRole',
|
|
147
|
+
flowTag: action,
|
|
148
|
+
flowStepName: '',
|
|
149
|
+
routes: objects.filter(isCrudObject).map((object) => ({
|
|
150
|
+
path: `/${targetServiceTag}/${object.objectType}/get`,
|
|
151
|
+
upperName: upperFirst(object.objectType)
|
|
152
|
+
}))
|
|
138
153
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
154
|
+
];
|
|
155
|
+
|
|
156
|
+
const getRangeRoutes = objects
|
|
157
|
+
.filter(isCrudObject)
|
|
158
|
+
.filter(
|
|
159
|
+
(object) =>
|
|
160
|
+
object.identifiers &&
|
|
161
|
+
object.identifiers.some((i) => i.type === 'sortKey')
|
|
162
|
+
)
|
|
163
|
+
.map((object) => ({
|
|
164
|
+
path: `/${targetServiceTag}/${object.objectType}/getRange`,
|
|
165
|
+
upperName: upperFirst(object.objectType)
|
|
166
|
+
}));
|
|
167
|
+
|
|
168
|
+
if (getRangeRoutes.length > 0) {
|
|
169
|
+
artifacts.push(
|
|
151
170
|
{
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
routes: objects.filter(isCrudObject).map((object) => ({
|
|
159
|
-
path: `/${targetServiceTag}/${object.objectType}/get`,
|
|
160
|
-
upperName: upperFirst(object.objectType)
|
|
161
|
-
}))
|
|
171
|
+
path: `${source}/GetRange_Main.js`,
|
|
172
|
+
content: await render('GetRangeEndpoint_Main.ejs', {
|
|
173
|
+
...shared,
|
|
174
|
+
mainFileName: 'GetRange_Main',
|
|
175
|
+
functionName: 'GetRange'
|
|
176
|
+
})
|
|
162
177
|
},
|
|
163
178
|
{
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
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
|
-
}))
|
|
179
|
+
path: `${source}/GetRange_HdrApi.js`,
|
|
180
|
+
content: await renderShared('FlowHandler_HdrApi.ejs', {
|
|
181
|
+
...shared,
|
|
182
|
+
mainFileName: 'GetRange_Main',
|
|
183
|
+
functionName: 'GetRange',
|
|
184
|
+
queueName: 'GetRangeHdrApi'
|
|
185
|
+
})
|
|
181
186
|
}
|
|
182
|
-
|
|
183
|
-
|
|
187
|
+
);
|
|
188
|
+
functions.push({
|
|
189
|
+
type: 'api',
|
|
190
|
+
functionName: 'GetRangeHdrApi',
|
|
191
|
+
handlerPath: `${handlerRoot}/GetRange_HdrApi.main`,
|
|
192
|
+
roleName: 'FlowObjectsRole',
|
|
193
|
+
flowTag: 'GetRange',
|
|
194
|
+
flowStepName: '',
|
|
195
|
+
routes: getRangeRoutes
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return { artifacts, functions };
|
|
184
200
|
}
|
|
185
201
|
|
|
186
202
|
artifacts.push(
|
|
@@ -230,68 +246,106 @@ async function emitAction(action, objects, flows, serviceTag) {
|
|
|
230
246
|
flowStepName: ''
|
|
231
247
|
}
|
|
232
248
|
];
|
|
233
|
-
|
|
234
|
-
|
|
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`;
|
|
249
|
+
|
|
250
|
+
if (plan.hasRbacCallback) {
|
|
251
|
+
const rbacCallbackMain = `${action}RbacCallback_Main`;
|
|
260
252
|
artifacts.push(
|
|
261
253
|
{
|
|
262
|
-
path: `${source}/${
|
|
263
|
-
content: await render('
|
|
254
|
+
path: `${source}/${rbacCallbackMain}.js`,
|
|
255
|
+
content: await render('FlowEndpointRbacCallback_Main.ejs', shared)
|
|
264
256
|
},
|
|
265
257
|
{
|
|
266
|
-
path: `${source}/${
|
|
258
|
+
path: `${source}/${rbacCallbackMain.replace('_Main', '_HdrSqs')}.js`,
|
|
267
259
|
content: await renderShared('FlowHandler_HdrSqs.ejs', {
|
|
268
260
|
...shared,
|
|
269
|
-
mainFileName:
|
|
270
|
-
functionName: `${action}
|
|
271
|
-
queueName: `${action}
|
|
261
|
+
mainFileName: rbacCallbackMain,
|
|
262
|
+
functionName: `${action}RbacCallbackMain`,
|
|
263
|
+
queueName: `${action}RbacCallbackHdrSqs`
|
|
272
264
|
})
|
|
273
265
|
}
|
|
274
266
|
);
|
|
275
267
|
functions.push({
|
|
276
268
|
type: 'sqs',
|
|
277
|
-
functionName: `${action}
|
|
278
|
-
handlerPath: `${handlerRoot}/${action}
|
|
269
|
+
functionName: `${action}RbacCallbackHdrSqs`,
|
|
270
|
+
handlerPath: `${handlerRoot}/${action}RbacCallback_HdrSqs.main`,
|
|
279
271
|
roleName: 'FlowObjectsRole',
|
|
280
|
-
queueName: `${action}
|
|
272
|
+
queueName: `${action}RbacCallbackHdrSqs`,
|
|
281
273
|
flowTag: action,
|
|
282
|
-
flowStepName: '
|
|
274
|
+
flowStepName: 'RbacCallback'
|
|
283
275
|
});
|
|
284
276
|
}
|
|
277
|
+
|
|
278
|
+
if (plan.hasComplete) {
|
|
279
|
+
const completeMain = `${action}Complete_Main`;
|
|
280
|
+
const templateName =
|
|
281
|
+
plan.hasRbac && !plan.hasGraph
|
|
282
|
+
? 'FlowEndpointRbacCallback_Main.ejs'
|
|
283
|
+
: `${action}Complete_Main.ejs`;
|
|
284
|
+
const templateContext =
|
|
285
|
+
plan.hasRbac && !plan.hasGraph
|
|
286
|
+
? shared
|
|
287
|
+
: { action, ...shared };
|
|
288
|
+
|
|
289
|
+
artifacts.push(
|
|
290
|
+
{
|
|
291
|
+
path: `${source}/${completeMain}.js`,
|
|
292
|
+
content: await render(templateName, templateContext)
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
path: `${source}/${action}Complete_HdrSqs.js`,
|
|
296
|
+
content: await renderShared('FlowHandler_HdrSqs.ejs', {
|
|
297
|
+
...shared,
|
|
298
|
+
mainFileName: completeMain,
|
|
299
|
+
functionName: `${action}CompleteMain`,
|
|
300
|
+
queueName: `${action}CompleteHdrSqs`
|
|
301
|
+
})
|
|
302
|
+
}
|
|
303
|
+
);
|
|
304
|
+
functions.push({
|
|
305
|
+
type: 'sqs',
|
|
306
|
+
functionName: `${action}CompleteHdrSqs`,
|
|
307
|
+
handlerPath: `${handlerRoot}/${action}Complete_HdrSqs.main`,
|
|
308
|
+
roleName: 'FlowObjectsRole',
|
|
309
|
+
queueName: `${action}CompleteHdrSqs`,
|
|
310
|
+
flowTag: action,
|
|
311
|
+
flowStepName: 'Complete'
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
|
|
285
315
|
return { artifacts, functions };
|
|
286
316
|
}
|
|
287
317
|
|
|
288
|
-
function
|
|
318
|
+
function hasSelfRbacAddOn(object) {
|
|
289
319
|
return (
|
|
290
|
-
object?.
|
|
291
|
-
object?.
|
|
320
|
+
Array.isArray(object?.addOnDataStructure) &&
|
|
321
|
+
object.addOnDataStructure.some((addOn) => addOn?.type === 'rbac')
|
|
292
322
|
);
|
|
293
323
|
}
|
|
294
324
|
|
|
325
|
+
function hasRbacAddOn(object, objects = []) {
|
|
326
|
+
const selfHasRbac = hasSelfRbacAddOn(object);
|
|
327
|
+
const belongToTargets = object?.belongTo
|
|
328
|
+
? Array.isArray(object.belongTo)
|
|
329
|
+
? object.belongTo
|
|
330
|
+
: [object.belongTo]
|
|
331
|
+
: [];
|
|
332
|
+
const belongToHasRbac =
|
|
333
|
+
(Array.isArray(object?.belongToSchema?.addOnDataStructure) &&
|
|
334
|
+
object.belongToSchema.addOnDataStructure.some(
|
|
335
|
+
(addOn) => addOn?.type === 'rbac'
|
|
336
|
+
)) ||
|
|
337
|
+
belongToTargets.some((target) => {
|
|
338
|
+
if (target?.serviceTag === 'UserAccount') return true;
|
|
339
|
+
const matched = objects.find(
|
|
340
|
+
(candidate) =>
|
|
341
|
+
candidate?.serviceTag === target?.serviceTag &&
|
|
342
|
+
candidate?.objectType === target?.objectType
|
|
343
|
+
);
|
|
344
|
+
return hasSelfRbacAddOn(matched);
|
|
345
|
+
});
|
|
346
|
+
return selfHasRbac || belongToHasRbac;
|
|
347
|
+
}
|
|
348
|
+
|
|
295
349
|
function upperFirst(value) {
|
|
296
350
|
return value.charAt(0).toUpperCase() + value.slice(1);
|
|
297
351
|
}
|
|
@@ -302,7 +356,10 @@ async function render(templateName, data) {
|
|
|
302
356
|
}
|
|
303
357
|
|
|
304
358
|
async function renderShared(templateName, data) {
|
|
305
|
-
const template = await readFile(
|
|
359
|
+
const template = await readFile(
|
|
360
|
+
new URL(templateName, SHARED_TEMPLATE_URL),
|
|
361
|
+
'utf8'
|
|
362
|
+
);
|
|
306
363
|
return ejsLib.render(template, data);
|
|
307
364
|
}
|
|
308
365
|
|
|
@@ -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 =
|
|
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
|
-
|
|
26
|
-
|
|
22
|
+
const plans = createCrudActionPlans(objects);
|
|
23
|
+
|
|
24
|
+
return CRUD_ACTIONS.map((action, index) => ({
|
|
25
|
+
path: dynamicCrudFlowSchemaPaths[index],
|
|
26
|
+
content: renderDynamicCrudFlowSchema(
|
|
27
27
|
action,
|
|
28
|
-
|
|
29
|
-
)
|
|
30
|
-
|
|
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,
|
|
38
|
-
const outputTopic = action !== 'Get';
|
|
33
|
+
function _createDynamicFlow(action, plan, serviceTag = '') {
|
|
39
34
|
const flowSteps = [
|
|
40
35
|
{
|
|
41
|
-
stepName: '
|
|
42
|
-
...(
|
|
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
|
-
|
|
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 (
|
|
60
|
+
if (plan.hasRbacCallback) {
|
|
73
61
|
flowSteps.push({
|
|
74
|
-
stepName: '
|
|
62
|
+
stepName: 'RbacCallback',
|
|
75
63
|
event: ['extTopic'],
|
|
76
64
|
previousSteps: [
|
|
77
65
|
{
|
|
78
|
-
|
|
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 (
|
|
81
|
+
if (plan.hasComplete) {
|
|
92
82
|
flowSteps.push({
|
|
93
83
|
stepName: 'Complete',
|
|
94
84
|
event: ['extTopic'],
|
|
95
85
|
previousSteps: [
|
|
96
86
|
{
|
|
97
|
-
|
|
87
|
+
sourceType: 'ownTopic',
|
|
88
|
+
stepName: plan.hasRbacCallback ? 'RbacCallback' : 'Start'
|
|
98
89
|
}
|
|
99
90
|
],
|
|
100
|
-
properties:
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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:
|
|
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
|
-
|
|
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(
|
|
15
|
+
emitDynamicCrudFlowSchemas({
|
|
16
|
+
...schemaInputs,
|
|
17
|
+
serviceTag: project.serviceTag
|
|
18
|
+
}),
|
|
16
19
|
{
|
|
17
20
|
managedPaths: dynamicCrudFlowSchemaPaths,
|
|
18
21
|
managedScope: 'crud-flow-schemas'
|
|
@@ -118,8 +118,10 @@ export default async function CreateComplete(
|
|
|
118
118
|
}
|
|
119
119
|
: null;
|
|
120
120
|
if (status === 'complete') {
|
|
121
|
+
const listOfRecords =
|
|
122
|
+
result?.additionalAttributes?.listOfRecords ?? [];
|
|
121
123
|
await Promise.all(
|
|
122
|
-
(
|
|
124
|
+
(listOfRecords ?? []).flatMap((records) =>
|
|
123
125
|
Object.values(records).map(async (record) =>
|
|
124
126
|
dynamodbSharedLib.putItem(
|
|
125
127
|
_izContext,
|
|
@@ -137,9 +139,12 @@ export default async function CreateComplete(
|
|
|
137
139
|
)
|
|
138
140
|
);
|
|
139
141
|
}
|
|
142
|
+
const callingFlowConfig =
|
|
143
|
+
result?.additionalAttributes?.callingFlowConfig ||
|
|
144
|
+
passBackProperties;
|
|
140
145
|
const message =
|
|
141
146
|
callingFlowSharedLib.addParentPassBackPropertiesToSnsResponseMessageObject(
|
|
142
|
-
|
|
147
|
+
callingFlowConfig,
|
|
143
148
|
{
|
|
144
149
|
objType: returnValue.requestParams.objType,
|
|
145
150
|
objInstanceFull: node.objInstanceFull,
|
|
@@ -152,7 +157,7 @@ export default async function CreateComplete(
|
|
|
152
157
|
);
|
|
153
158
|
const messageAttributes =
|
|
154
159
|
callingFlowSharedLib.addParentPassBackCallingFlowToSnsResponseMessageAttributes(
|
|
155
|
-
|
|
160
|
+
callingFlowConfig,
|
|
156
161
|
{}
|
|
157
162
|
);
|
|
158
163
|
const topicArn = snsSharedLib.snsTopicArnByFlowSchema(
|