@izara_project/izara-core-generate-service-code 1.0.91 → 1.0.93
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 +7 -10
- package/src/compile/flowValidator.js +6 -0
- package/src/compile/loadSchemas.js +195 -69
- package/src/emit/coreFunction/templates/UploadSchema_Main.ejs +2 -2
- package/src/emit/crud/generateCrudApplicationArtifacts.js +15 -17
- package/src/emit/crud/generateDynamicCrudFlowSchemas.js +16 -21
- package/src/emit/crud/loadLocalSchemaArrays.js +4 -8
- package/src/emit/custom/customFlowPaths.js +149 -0
- package/src/emit/custom/customFlowS3.js +156 -0
- package/src/emit/custom/customFlowSteps.js +385 -0
- package/src/emit/custom/customFlowTemplates.js +28 -0
- package/src/emit/custom/customFlows.js +48 -19
- package/src/emit/custom/emitCustomFlowApplicationArtifacts.js +57 -692
- package/src/emit/custom/generateCustomFlowApplicationArtifacts.js +27 -25
- package/src/emit/error/emitErrorSchemas.js +73 -0
- package/src/emit/error/templates/errorSchema.ejs +8 -0
- package/src/emit/rbac/generateCreateTargetRoleHandler.js +11 -13
- package/src/emit/rbac/generateDynamicRbacFlowSchemas.js +14 -18
- package/src/emit/relationship/generateDynamicRelationshipFlowSchemas.js +16 -19
- package/src/emit/relationship/generateRelationshipApplicationArtifacts.js +19 -19
- package/src/emit/resource/dynamoResourceArtifacts.js +18 -0
- package/src/emit/resource/emitResourceArtifacts.js +13 -1247
- package/src/emit/resource/generateResourceArtifacts.js +20 -20
- package/src/emit/resource/iamResourceArtifacts.js +612 -0
- package/src/emit/resource/resourceState.js +564 -0
- package/src/emit/resource/resourceTemplate.js +30 -0
- package/src/emit/resource/s3ResourceArtifacts.js +14 -0
- package/src/emit/resource/sqsResourceArtifacts.js +113 -0
- package/src/emit/shared/runSubsystemGeneration.js +55 -0
- package/src/emit/system/emitSystemWebSocketArtifacts.js +2 -1
- package/src/generate.js +37 -4
- package/test/crudApplicationArtifacts.test.js +72 -0
- package/test/customFlowApplicationArtifacts.test.js +98 -0
- package/test/errorSchemas.test.js +154 -0
- package/test/publicApi.test.js +1 -1
- package/test/resourceArtifacts.test.js +99 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import {
|
|
2
|
+
flowDsqSteps,
|
|
3
|
+
flowExtTopicSteps,
|
|
4
|
+
generatedDsqFlows,
|
|
5
|
+
generatedOwnTopicFlows,
|
|
6
|
+
supportedCustomFlows,
|
|
7
|
+
upperFirst,
|
|
8
|
+
flowHasRbac
|
|
9
|
+
} from './customFlows.js';
|
|
10
|
+
|
|
11
|
+
export const YAML_PATH = 'app/sls_yaml/generatedCode/source/flow-schema.yml';
|
|
12
|
+
|
|
13
|
+
export function isS3Only(flow) {
|
|
14
|
+
return flow.event.length === 1 && flow.event[0] === 's3';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function needsProcessMain(flow) {
|
|
18
|
+
const isOwnTopicTransport =
|
|
19
|
+
flow.event.includes('ownTopic') ||
|
|
20
|
+
(flow.event.includes('generateCode') &&
|
|
21
|
+
flow.generatedCodeConfig?.invocationType === 'ownTopic');
|
|
22
|
+
return (
|
|
23
|
+
!isS3Only(flow) &&
|
|
24
|
+
!isOwnTopicTransport &&
|
|
25
|
+
flow.event.some((event) => event !== 'ownTopic' && event !== 's3')
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function ownTopicRootPaths(flow, objects = []) {
|
|
30
|
+
const tag = upperFirst(flow.flowTag);
|
|
31
|
+
const source = `app/src/generatedCode/FlowSchemas/${tag}/source`;
|
|
32
|
+
const paths = [
|
|
33
|
+
`${source}/${tag}_Main.js`,
|
|
34
|
+
`${source}/${tag}_HdrSqs.js`,
|
|
35
|
+
`${source}/${tag}_WbsMain.js`,
|
|
36
|
+
`${source}/${tag}_HdrWbs.js`
|
|
37
|
+
];
|
|
38
|
+
if (flowHasRbac(flow, objects)) {
|
|
39
|
+
paths.push(
|
|
40
|
+
`${source}/${tag}RbacCallback_Main.js`,
|
|
41
|
+
`${source}/${tag}RbacCallback_HdrSqs.js`
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
return paths;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function flowPaths(flow, objects = []) {
|
|
48
|
+
const tag = upperFirst(flow.flowTag);
|
|
49
|
+
const process = tag;
|
|
50
|
+
const source = `app/src/generatedCode/FlowSchemas/${tag}/source`;
|
|
51
|
+
const paths = [];
|
|
52
|
+
if (needsProcessMain(flow)) {
|
|
53
|
+
paths.push(`${source}/${process}_Main.js`);
|
|
54
|
+
}
|
|
55
|
+
if (flowHasRbac(flow, objects)) {
|
|
56
|
+
paths.push(
|
|
57
|
+
`${source}/${tag}RbacCallback_Main.js`,
|
|
58
|
+
`${source}/${tag}RbacCallback_HdrSqs.js`
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
if (flow.event.includes('extTopic') && !flow.event.includes('ownTopic')) {
|
|
62
|
+
paths.push(`${source}/${process}_HdrSqs.js`);
|
|
63
|
+
}
|
|
64
|
+
if (flow.event.includes('dsq')) {
|
|
65
|
+
paths.push(`${source}/${process}_HdrDsq.js`);
|
|
66
|
+
}
|
|
67
|
+
if (
|
|
68
|
+
flow.event.includes('lambdaSyncInv') ||
|
|
69
|
+
flow.event.includes('eventBridge') ||
|
|
70
|
+
(flow.event.includes('generateCode') &&
|
|
71
|
+
flow.generatedCodeConfig?.invocationType === 'lambdaSyncInv')
|
|
72
|
+
) {
|
|
73
|
+
paths.push(`${source}/${process}_HdrInv.js`);
|
|
74
|
+
}
|
|
75
|
+
if (flow.event.includes('lambdaSyncApi')) {
|
|
76
|
+
paths.push(`${source}/${process}_HdrApi.js`);
|
|
77
|
+
}
|
|
78
|
+
if (
|
|
79
|
+
flow.event.includes('ownTopic') ||
|
|
80
|
+
(flow.event.includes('generateCode') &&
|
|
81
|
+
flow.generatedCodeConfig?.invocationType === 'ownTopic')
|
|
82
|
+
) {
|
|
83
|
+
paths.push(...ownTopicRootPaths(flow, objects));
|
|
84
|
+
}
|
|
85
|
+
if (flow.event.includes('s3')) {
|
|
86
|
+
const s3Actions = [
|
|
87
|
+
'ConfirmAfterUpload',
|
|
88
|
+
'CreateObject',
|
|
89
|
+
'CreatePreSignUrl',
|
|
90
|
+
'ProcessAfterUpload',
|
|
91
|
+
'ReservedLimit'
|
|
92
|
+
];
|
|
93
|
+
for (const action of s3Actions) {
|
|
94
|
+
let handler = 'HdrSqs';
|
|
95
|
+
if (action === 'CreateObject') {
|
|
96
|
+
handler = 'HdrWbs';
|
|
97
|
+
} else if (action === 'ProcessAfterUpload') {
|
|
98
|
+
handler = 'HdrS3';
|
|
99
|
+
}
|
|
100
|
+
paths.push(
|
|
101
|
+
`${source}/${tag}${action}_Main.js`,
|
|
102
|
+
`${source}/${tag}${action}_${handler}.js`
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return paths;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function customFlowApplicationManagedPaths(
|
|
110
|
+
flows,
|
|
111
|
+
{ objects = [] } = {}
|
|
112
|
+
) {
|
|
113
|
+
const customFlowList = supportedCustomFlows(flows);
|
|
114
|
+
const generatedRoots = generatedOwnTopicFlows(flows);
|
|
115
|
+
const generatedDsqs = generatedDsqFlows(flows);
|
|
116
|
+
const extSteps = flowExtTopicSteps(flows);
|
|
117
|
+
const dsqSteps = flowDsqSteps(flows);
|
|
118
|
+
|
|
119
|
+
return [
|
|
120
|
+
...customFlowList.flatMap((flow) => flowPaths(flow, objects)),
|
|
121
|
+
...generatedRoots.flatMap((flow) => ownTopicRootPaths(flow, objects)),
|
|
122
|
+
...extSteps.flatMap(({ flowTag, stepName }) => {
|
|
123
|
+
const source = `app/src/generatedCode/FlowSchemas/${flowTag}/source`;
|
|
124
|
+
return [
|
|
125
|
+
`${source}/${flowTag}${stepName}_Main.js`,
|
|
126
|
+
`${source}/${flowTag}${stepName}_HdrSqs.js`
|
|
127
|
+
];
|
|
128
|
+
}),
|
|
129
|
+
...dsqSteps.flatMap(({ flowTag, stepName, step }) => {
|
|
130
|
+
const source = `app/src/generatedCode/FlowSchemas/${flowTag}/source`;
|
|
131
|
+
let stepEvents = [];
|
|
132
|
+
if (Array.isArray(step.event)) {
|
|
133
|
+
stepEvents = step.event;
|
|
134
|
+
}
|
|
135
|
+
const files = [`${source}/${flowTag}${stepName}_HdrDsq.js`];
|
|
136
|
+
if (!stepEvents.includes('extTopic')) {
|
|
137
|
+
files.unshift(`${source}/${flowTag}${stepName}_Main.js`);
|
|
138
|
+
}
|
|
139
|
+
return files;
|
|
140
|
+
}),
|
|
141
|
+
...(customFlowList.length > 0 ||
|
|
142
|
+
generatedRoots.length > 0 ||
|
|
143
|
+
generatedDsqs.length > 0 ||
|
|
144
|
+
extSteps.length > 0 ||
|
|
145
|
+
dsqSteps.length > 0
|
|
146
|
+
? [YAML_PATH]
|
|
147
|
+
: [])
|
|
148
|
+
];
|
|
149
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { renderCustom } from './customFlowTemplates.js';
|
|
2
|
+
import { customFlowRoleName, upperFirst } from './customFlows.js';
|
|
3
|
+
import {
|
|
4
|
+
renderInvFunctionYaml,
|
|
5
|
+
renderS3FunctionYaml,
|
|
6
|
+
renderSqsFunctionYaml,
|
|
7
|
+
renderWbsFunctionYaml
|
|
8
|
+
} from '../function/functionYamlArtifact.js';
|
|
9
|
+
|
|
10
|
+
export async function emitS3Flow(flow, source, handlerRoot) {
|
|
11
|
+
const tag = upperFirst(flow.flowTag);
|
|
12
|
+
const roleName = customFlowRoleName(flow.flowTag);
|
|
13
|
+
const parts = [
|
|
14
|
+
{
|
|
15
|
+
action: 'CreateObject',
|
|
16
|
+
handler: 'HdrWbs',
|
|
17
|
+
type: 'wbs',
|
|
18
|
+
mainTemplate: 'CreateObject_Main.ejs',
|
|
19
|
+
handlerTemplate: 'CreateObject_HdrWbs.ejs'
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
action: 'ReservedLimit',
|
|
23
|
+
handler: 'HdrSqs',
|
|
24
|
+
type: 'sqs',
|
|
25
|
+
mainTemplate: 'ReservedLimit_Main.ejs',
|
|
26
|
+
handlerTemplate: 'ReservedLimit_HdrSqs.ejs'
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
action: 'CreatePreSignUrl',
|
|
30
|
+
handler: 'HdrSqs',
|
|
31
|
+
type: 'sqs',
|
|
32
|
+
mainTemplate: 'CreatePreSignUrl_Main.ejs',
|
|
33
|
+
handlerTemplate: 'CreatePreSignUrl_HdrSqs.ejs'
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
action: 'ProcessAfterUpload',
|
|
37
|
+
handler: 'HdrS3',
|
|
38
|
+
type: 's3',
|
|
39
|
+
mainTemplate: 'ProcessS3File_Main.ejs',
|
|
40
|
+
handlerTemplate: 'FlowHandler_HdrS3.ejs'
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
action: 'ConfirmAfterUpload',
|
|
44
|
+
handler: 'HdrSqs',
|
|
45
|
+
type: 'sqs',
|
|
46
|
+
mainTemplate: 'ConfirmReserved_Main.ejs',
|
|
47
|
+
handlerTemplate: 'ConfirmReserved_HdrSqs.ejs'
|
|
48
|
+
}
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
const emitted = await Promise.all(
|
|
52
|
+
parts.map(
|
|
53
|
+
async ({ action, handler, type, mainTemplate, handlerTemplate }) => {
|
|
54
|
+
const functionName = `${tag}${action}`;
|
|
55
|
+
const mainFileName = `${functionName}_Main`;
|
|
56
|
+
const handlerFileName = `${functionName}_${handler}`;
|
|
57
|
+
const mainContent = await renderCustom(
|
|
58
|
+
`s3/${mainTemplate}`,
|
|
59
|
+
_s3TemplateData({ action, flow, functionName })
|
|
60
|
+
);
|
|
61
|
+
const handlerContent = await renderCustom(
|
|
62
|
+
`s3/${handlerTemplate}`,
|
|
63
|
+
_s3HandlerData({ action, flow, functionName, mainFileName, handler })
|
|
64
|
+
);
|
|
65
|
+
const descriptor = {
|
|
66
|
+
functionName: `${functionName}${handler}`,
|
|
67
|
+
handlerPath: `${handlerRoot}/${handlerFileName}.main`,
|
|
68
|
+
roleName
|
|
69
|
+
};
|
|
70
|
+
let functionYaml;
|
|
71
|
+
if (type === 'wbs') {
|
|
72
|
+
functionYaml = renderWbsFunctionYaml({
|
|
73
|
+
...descriptor,
|
|
74
|
+
routeName: tag,
|
|
75
|
+
flowTag: flow.flowTag,
|
|
76
|
+
flowStepName: ''
|
|
77
|
+
});
|
|
78
|
+
} else if (type === 'sqs') {
|
|
79
|
+
let filterPatternFunctionName = descriptor.functionName;
|
|
80
|
+
if (action === 'CreatePreSignUrl') {
|
|
81
|
+
filterPatternFunctionName = 'CreatePresignUrlHdrSqs';
|
|
82
|
+
}
|
|
83
|
+
functionYaml = renderSqsFunctionYaml({
|
|
84
|
+
...descriptor,
|
|
85
|
+
queueName: descriptor.functionName,
|
|
86
|
+
flowTag: flow.flowTag,
|
|
87
|
+
flowStepName: '',
|
|
88
|
+
filterPatternFunctionName
|
|
89
|
+
});
|
|
90
|
+
} else if (type === 's3') {
|
|
91
|
+
let bucketName = '';
|
|
92
|
+
if (flow.bucketName) {
|
|
93
|
+
bucketName = flow.bucketName;
|
|
94
|
+
}
|
|
95
|
+
functionYaml = renderS3FunctionYaml({
|
|
96
|
+
...descriptor,
|
|
97
|
+
bucketName,
|
|
98
|
+
flowTag: flow.flowTag,
|
|
99
|
+
flowStepName: ''
|
|
100
|
+
});
|
|
101
|
+
} else {
|
|
102
|
+
functionYaml = renderInvFunctionYaml({
|
|
103
|
+
...descriptor,
|
|
104
|
+
flowTag: flow.flowTag,
|
|
105
|
+
flowStepName: ''
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
artifacts: [
|
|
110
|
+
{ path: `${source}/${mainFileName}.js`, content: mainContent },
|
|
111
|
+
{ path: `${source}/${handlerFileName}.js`, content: handlerContent }
|
|
112
|
+
],
|
|
113
|
+
functionYaml
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
)
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
artifacts: emitted.flatMap((item) => item.artifacts),
|
|
121
|
+
functions: emitted.map((item) => item.functionYaml)
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function _s3TemplateData({ action, flow, functionName }) {
|
|
126
|
+
if (action === 'CreateObject') {
|
|
127
|
+
return {
|
|
128
|
+
flowTag: flow.flowTag,
|
|
129
|
+
objectType: flow.objType?.objectType,
|
|
130
|
+
functionName
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
if (action === 'CreatePreSignUrl') {
|
|
134
|
+
return { flowTag: flow.flowTag };
|
|
135
|
+
}
|
|
136
|
+
return { flowTag: flow.flowTag, functionName };
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function _s3HandlerData({ action, flow, functionName, mainFileName, handler }) {
|
|
140
|
+
if (action === 'CreateObject') {
|
|
141
|
+
return { functionName, handlerType: handler, route: flow.flowTag };
|
|
142
|
+
}
|
|
143
|
+
if (action === 'ProcessAfterUpload') {
|
|
144
|
+
let bucketName = '';
|
|
145
|
+
if (flow.bucketName) {
|
|
146
|
+
bucketName = flow.bucketName;
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
flowTag: flow.flowTag,
|
|
150
|
+
functionName,
|
|
151
|
+
mainFileName,
|
|
152
|
+
s3Bucket: bucketName
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
return { functionName, handlerType: handler };
|
|
156
|
+
}
|
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
import {
|
|
2
|
+
renderCrudTemplate,
|
|
3
|
+
renderCustom,
|
|
4
|
+
renderDsq,
|
|
5
|
+
renderShared
|
|
6
|
+
} from './customFlowTemplates.js';
|
|
7
|
+
import { customFlowRoleName, upperFirst, flowHasRbac } from './customFlows.js';
|
|
8
|
+
import {
|
|
9
|
+
renderSqsFunctionYaml,
|
|
10
|
+
renderWbsFunctionYaml
|
|
11
|
+
} from '../function/functionYamlArtifact.js';
|
|
12
|
+
|
|
13
|
+
export async function emitExtTopicStep({ flow, step, flowTag, stepName }) {
|
|
14
|
+
const source = `app/src/generatedCode/FlowSchemas/${flowTag}/source`;
|
|
15
|
+
const handlerRoot = `src/generatedCode/FlowSchemas/${flowTag}/source`;
|
|
16
|
+
let functionName = `${flowTag}${stepName}`;
|
|
17
|
+
if (stepName.startsWith(flowTag)) {
|
|
18
|
+
functionName = stepName;
|
|
19
|
+
}
|
|
20
|
+
const mainFileName = `${functionName}_Main`;
|
|
21
|
+
const startConfig = stepConfig(flow, step);
|
|
22
|
+
|
|
23
|
+
const hasTriggerFlowTypes =
|
|
24
|
+
Array.isArray(flow.triggerFlowTypes) && flow.triggerFlowTypes.length > 0;
|
|
25
|
+
const isCheckStep = stepName.toLowerCase().includes('checktrigger');
|
|
26
|
+
|
|
27
|
+
if (isCheckStep && hasTriggerFlowTypes) {
|
|
28
|
+
const queueName = `${functionName}HdrSqs`;
|
|
29
|
+
return {
|
|
30
|
+
artifacts: [
|
|
31
|
+
{
|
|
32
|
+
path: `${source}/${mainFileName}.js`,
|
|
33
|
+
content: await renderCustom(
|
|
34
|
+
'triggerCache/CheckTriggerCache_Main.ejs',
|
|
35
|
+
{ functionName, flowTag }
|
|
36
|
+
)
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
path: `${source}/${functionName}_HdrSqs.js`,
|
|
40
|
+
content: await renderCustom(
|
|
41
|
+
'triggerCache/CheckTriggerCache_HdrSqs.ejs',
|
|
42
|
+
{ functionName, queueName, startConfig }
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
functions: [
|
|
47
|
+
renderSqsFunctionYaml({
|
|
48
|
+
functionName: queueName,
|
|
49
|
+
handlerPath: `${handlerRoot}/${functionName}_HdrSqs.main`,
|
|
50
|
+
roleName: customFlowRoleName(flow.flowTag),
|
|
51
|
+
queueName,
|
|
52
|
+
flowTag,
|
|
53
|
+
flowStepName: step.stepName
|
|
54
|
+
})
|
|
55
|
+
]
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const artifacts = [
|
|
60
|
+
{
|
|
61
|
+
path: `${source}/${mainFileName}.js`,
|
|
62
|
+
content: await renderStepMain(functionName, _startConfig(flow))
|
|
63
|
+
}
|
|
64
|
+
];
|
|
65
|
+
const functions = [];
|
|
66
|
+
|
|
67
|
+
let stepEvents = [];
|
|
68
|
+
if (Array.isArray(step.event)) {
|
|
69
|
+
stepEvents = step.event;
|
|
70
|
+
}
|
|
71
|
+
const hasSqs = stepEvents.includes('extTopic') || stepEvents.includes('sqs');
|
|
72
|
+
|
|
73
|
+
if (hasSqs) {
|
|
74
|
+
const queueName = `${functionName}HdrSqs`;
|
|
75
|
+
artifacts.push({
|
|
76
|
+
path: `${source}/${functionName}_HdrSqs.js`,
|
|
77
|
+
content: await renderShared('FlowHandler_HdrSqs.ejs', {
|
|
78
|
+
flowTag: flow.flowTag,
|
|
79
|
+
flowStepName: step.stepName,
|
|
80
|
+
functionName,
|
|
81
|
+
mainFileName,
|
|
82
|
+
startConfig,
|
|
83
|
+
queueName
|
|
84
|
+
})
|
|
85
|
+
});
|
|
86
|
+
functions.push(
|
|
87
|
+
renderSqsFunctionYaml({
|
|
88
|
+
functionName: queueName,
|
|
89
|
+
handlerPath: `${handlerRoot}/${functionName}_HdrSqs.main`,
|
|
90
|
+
roleName: customFlowRoleName(flow.flowTag),
|
|
91
|
+
queueName,
|
|
92
|
+
flowTag,
|
|
93
|
+
flowStepName: step.stepName
|
|
94
|
+
})
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return { artifacts, functions };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export async function emitDsqStep({ flow, step, flowTag, stepName }) {
|
|
102
|
+
const source = `app/src/generatedCode/FlowSchemas/${flowTag}/source`;
|
|
103
|
+
const handlerRoot = `src/generatedCode/FlowSchemas/${flowTag}/source`;
|
|
104
|
+
const functionName = `${flowTag}${stepName}`;
|
|
105
|
+
const mainFileName = `${functionName}_Main`;
|
|
106
|
+
const startConfig = stepConfig(flow, step);
|
|
107
|
+
|
|
108
|
+
let stepEvents = [];
|
|
109
|
+
if (Array.isArray(step.event)) {
|
|
110
|
+
stepEvents = step.event;
|
|
111
|
+
}
|
|
112
|
+
const artifacts = [];
|
|
113
|
+
if (!stepEvents.includes('extTopic')) {
|
|
114
|
+
artifacts.push({
|
|
115
|
+
path: `${source}/${mainFileName}.js`,
|
|
116
|
+
content: await renderStepMain(functionName, startConfig)
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
const functions = [];
|
|
120
|
+
|
|
121
|
+
const hasDsq = stepEvents.includes('dsq');
|
|
122
|
+
|
|
123
|
+
if (hasDsq) {
|
|
124
|
+
const queueName = `${functionName}HdrDsq`;
|
|
125
|
+
artifacts.push({
|
|
126
|
+
path: `${source}/${functionName}_HdrDsq.js`,
|
|
127
|
+
content: await renderDsq('FlowHandler_HdrDsq.ejs', {
|
|
128
|
+
flowTag: flow.flowTag,
|
|
129
|
+
flowStepName: step.stepName,
|
|
130
|
+
functionName,
|
|
131
|
+
mainFileName,
|
|
132
|
+
startConfig,
|
|
133
|
+
queueName
|
|
134
|
+
})
|
|
135
|
+
});
|
|
136
|
+
functions.push(
|
|
137
|
+
renderSqsFunctionYaml({
|
|
138
|
+
functionName: queueName,
|
|
139
|
+
handlerPath: `${handlerRoot}/${functionName}_HdrDsq.main`,
|
|
140
|
+
roleName: customFlowRoleName(flow.flowTag),
|
|
141
|
+
queueName,
|
|
142
|
+
flowTag,
|
|
143
|
+
flowStepName: step.stepName
|
|
144
|
+
})
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return { artifacts, functions };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export async function emitOwnTopicRoot(flow, objects) {
|
|
152
|
+
const tag = upperFirst(flow.flowTag);
|
|
153
|
+
const source = `app/src/generatedCode/FlowSchemas/${tag}/source`;
|
|
154
|
+
const handlerRoot = `src/generatedCode/FlowSchemas/${tag}/source`;
|
|
155
|
+
const mainFileName = `${tag}_Main`;
|
|
156
|
+
const wbsMainFileName = `${tag}_WbsMain`;
|
|
157
|
+
const shared = {
|
|
158
|
+
flowTag: flow.flowTag,
|
|
159
|
+
flowStepName: '',
|
|
160
|
+
upperCaseFlowTag: tag,
|
|
161
|
+
startConfig: _startConfig(flow)
|
|
162
|
+
};
|
|
163
|
+
const isRbac = flowHasRbac(flow, objects);
|
|
164
|
+
const ownArtifacts = [
|
|
165
|
+
{
|
|
166
|
+
path: `${source}/${mainFileName}.js`,
|
|
167
|
+
content: await renderEndpointMain(flow, mainFileName, objects)
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
path: `${source}/${tag}_HdrSqs.js`,
|
|
171
|
+
content: await renderShared('FlowHandler_HdrSqs.ejs', {
|
|
172
|
+
...shared,
|
|
173
|
+
functionName: mainFileName,
|
|
174
|
+
mainFileName,
|
|
175
|
+
queueName: `${tag}HdrSqs`
|
|
176
|
+
})
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
path: `${source}/${wbsMainFileName}.js`,
|
|
180
|
+
content: await renderCrudTemplate('FlowMain_Wbs.ejs', {
|
|
181
|
+
...shared,
|
|
182
|
+
functionName: wbsMainFileName
|
|
183
|
+
})
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
path: `${source}/${tag}_HdrWbs.js`,
|
|
187
|
+
content: await renderCrudTemplate('FlowEndpoint_HdrWbs.ejs', {
|
|
188
|
+
...shared,
|
|
189
|
+
functionName: tag,
|
|
190
|
+
mainFileName: wbsMainFileName,
|
|
191
|
+
route: tag
|
|
192
|
+
})
|
|
193
|
+
}
|
|
194
|
+
];
|
|
195
|
+
|
|
196
|
+
const ownFunctions = [
|
|
197
|
+
renderWbsFunctionYaml({
|
|
198
|
+
functionName: `${tag}HdrWbs`,
|
|
199
|
+
handlerPath: `${handlerRoot}/${tag}_HdrWbs.main`,
|
|
200
|
+
roleName: customFlowRoleName(flow.flowTag),
|
|
201
|
+
routeName: tag,
|
|
202
|
+
flowTag: flow.flowTag,
|
|
203
|
+
flowStepName: ''
|
|
204
|
+
}),
|
|
205
|
+
renderSqsFunctionYaml({
|
|
206
|
+
functionName: `${tag}HdrSqs`,
|
|
207
|
+
handlerPath: `${handlerRoot}/${tag}_HdrSqs.main`,
|
|
208
|
+
roleName: customFlowRoleName(flow.flowTag),
|
|
209
|
+
queueName: `${tag}HdrSqs`,
|
|
210
|
+
flowTag: flow.flowTag,
|
|
211
|
+
flowStepName: ''
|
|
212
|
+
})
|
|
213
|
+
];
|
|
214
|
+
|
|
215
|
+
if (isRbac) {
|
|
216
|
+
const rbacStep = (flow.flowSteps || []).find(
|
|
217
|
+
(s) =>
|
|
218
|
+
typeof s?.stepName === 'string' &&
|
|
219
|
+
s.stepName.toLowerCase() === 'rbaccallback'
|
|
220
|
+
);
|
|
221
|
+
const rbacConfig = rbacStep ? stepConfig(flow, rbacStep) : null;
|
|
222
|
+
ownArtifacts.push(
|
|
223
|
+
{
|
|
224
|
+
path: `${source}/${tag}RbacCallback_Main.js`,
|
|
225
|
+
content: await renderCustom('FlowEndpointRbacCallback_Main.ejs', {
|
|
226
|
+
flowTag: flow.flowTag,
|
|
227
|
+
upperCaseFlowTag: tag,
|
|
228
|
+
functionName: `${tag}RbacCallbackMain`
|
|
229
|
+
})
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
path: `${source}/${tag}RbacCallback_HdrSqs.js`,
|
|
233
|
+
content: await renderShared('FlowHandler_HdrSqs.ejs', {
|
|
234
|
+
flowTag: flow.flowTag,
|
|
235
|
+
flowStepName: 'RbacCallback',
|
|
236
|
+
mainFileName: `${tag}RbacCallback_Main`,
|
|
237
|
+
functionName: `${tag}RbacCallbackMain`,
|
|
238
|
+
queueName: `${tag}RbacCallbackHdrSqs`,
|
|
239
|
+
startConfig: rbacConfig
|
|
240
|
+
})
|
|
241
|
+
}
|
|
242
|
+
);
|
|
243
|
+
ownFunctions.push(
|
|
244
|
+
renderSqsFunctionYaml({
|
|
245
|
+
functionName: `${tag}RbacCallbackHdrSqs`,
|
|
246
|
+
handlerPath: `${handlerRoot}/${tag}RbacCallback_HdrSqs.main`,
|
|
247
|
+
roleName: customFlowRoleName(flow.flowTag),
|
|
248
|
+
queueName: `${tag}RbacCallbackHdrSqs`,
|
|
249
|
+
flowTag: flow.flowTag,
|
|
250
|
+
flowStepName: 'RbacCallback'
|
|
251
|
+
})
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return {
|
|
256
|
+
artifacts: ownArtifacts,
|
|
257
|
+
functions: ownFunctions
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export function _startConfig(flow) {
|
|
262
|
+
const steps = flow.flowSteps ?? [];
|
|
263
|
+
const start =
|
|
264
|
+
steps.find(
|
|
265
|
+
(s) =>
|
|
266
|
+
typeof s?.stepName === 'string' &&
|
|
267
|
+
s.stepName.toLowerCase() === 'inprocess'
|
|
268
|
+
) ??
|
|
269
|
+
steps.find(
|
|
270
|
+
(s) =>
|
|
271
|
+
typeof s?.stepName === 'string' && s.stepName.toLowerCase() === 'start'
|
|
272
|
+
) ??
|
|
273
|
+
steps[0];
|
|
274
|
+
if (start) {
|
|
275
|
+
return stepConfig(flow, start);
|
|
276
|
+
}
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
export function stepConfig(flow, step) {
|
|
281
|
+
return {
|
|
282
|
+
...step,
|
|
283
|
+
properties: mapFields(step.properties, flow.stepProperties),
|
|
284
|
+
messageAttributes: mapFields(
|
|
285
|
+
step.messageAttributes,
|
|
286
|
+
flow.stepMessageAttributes
|
|
287
|
+
)
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
export function mapFields(items = [], definitions = {}) {
|
|
292
|
+
return items.map((item) => {
|
|
293
|
+
if (typeof item === 'string') {
|
|
294
|
+
const def = definitions?.[item] ?? {};
|
|
295
|
+
return {
|
|
296
|
+
propertyName: item,
|
|
297
|
+
required: def.required ?? false,
|
|
298
|
+
...def
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
if (typeof item === 'object' && item !== null) {
|
|
302
|
+
const name = item.key ?? item.propertyName;
|
|
303
|
+
const def = definitions?.[name] ?? {};
|
|
304
|
+
return {
|
|
305
|
+
propertyName: name,
|
|
306
|
+
required: item.required ?? def.required ?? false,
|
|
307
|
+
...def,
|
|
308
|
+
...item
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
return item;
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
export async function renderEndpointMain(flow, functionName, objects = []) {
|
|
316
|
+
const isRbac = flowHasRbac(flow, objects);
|
|
317
|
+
const matchedObject = objects.find(
|
|
318
|
+
(o) => o.objectType === flow.objType?.objectType
|
|
319
|
+
);
|
|
320
|
+
let rbacServiceTag = null;
|
|
321
|
+
if (matchedObject) {
|
|
322
|
+
const belongTo = matchedObject.belongTo;
|
|
323
|
+
if (belongTo) {
|
|
324
|
+
if (Array.isArray(belongTo)) {
|
|
325
|
+
rbacServiceTag = belongTo[0]?.serviceTag;
|
|
326
|
+
} else {
|
|
327
|
+
rbacServiceTag = belongTo?.serviceTag;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
if (!rbacServiceTag) {
|
|
332
|
+
rbacServiceTag = flow.objType?.serviceTag || flow.serviceTag || 'Rbac';
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
const enrichedFlow = {
|
|
336
|
+
...flow,
|
|
337
|
+
isRbac
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
return renderCustom('FlowEndpoint_Main.ejs', {
|
|
341
|
+
flow: enrichedFlow,
|
|
342
|
+
flowTag: flow.flowTag,
|
|
343
|
+
upperCaseFlowTag: upperFirst(flow.flowTag),
|
|
344
|
+
functionName,
|
|
345
|
+
rbacServiceTag,
|
|
346
|
+
tableName: storedCacheTableName(flow, objects),
|
|
347
|
+
startConfig: _startConfig(flow)
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export function storedCacheTableName(flow, objects) {
|
|
352
|
+
if (flow.statusType !== 'storedCache') {
|
|
353
|
+
return null;
|
|
354
|
+
}
|
|
355
|
+
const candidates = objects.filter(
|
|
356
|
+
(object) => object.objectType === flow.objType?.objectType
|
|
357
|
+
);
|
|
358
|
+
let object;
|
|
359
|
+
if (flow.objType?.serviceTag) {
|
|
360
|
+
object =
|
|
361
|
+
candidates.find(
|
|
362
|
+
(candidate) => candidate.serviceTag === flow.objType.serviceTag
|
|
363
|
+
) ?? candidates.find((candidate) => candidate.serviceTag === undefined);
|
|
364
|
+
} else {
|
|
365
|
+
object = candidates[0];
|
|
366
|
+
}
|
|
367
|
+
const targetResource = Object.values(object?.storageResources ?? {}).find(
|
|
368
|
+
(resource) =>
|
|
369
|
+
resource?.storageType === 'dynamo' ||
|
|
370
|
+
resource?.storageType === 'dynamoDB' ||
|
|
371
|
+
!resource?.storageType
|
|
372
|
+
);
|
|
373
|
+
if (targetResource?.tableName) {
|
|
374
|
+
return targetResource.tableName;
|
|
375
|
+
}
|
|
376
|
+
return null;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
export async function renderStepMain(functionName, startConfig = null) {
|
|
380
|
+
return renderCustom('FlowStep_Main.ejs', { functionName, startConfig });
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
export function renderMain(functionName) {
|
|
384
|
+
return `export default async function ${functionName}(_izContext, requestParams, callingFlowConfig = {}) {\n try {\n _izContext?.logger?.debug('${functionName} requestParams', requestParams);\n //(<endpointHook>)\n //(</endpointHook>)\n } catch (error) {\n _izContext?.logger?.error('${functionName} failed', error);\n throw error;\n }\n}\n`;
|
|
385
|
+
}
|