@izara_project/izara-core-generate-service-code 1.0.61 → 1.0.63
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 +5 -6
- package/src/codeGenerators/app/initial_setup/InitialSetupGenerator.js +100 -150
- package/src/codeGenerators/app/initial_setup/templates/InitialSetup_LambdaRole.ejs +27 -20
- package/src/codeGenerators/app/sls_yaml/FunctionYamlGenerator.js +8 -17
- package/src/codeGenerators/app/sls_yaml/RoleNameConfigGenerator.js +13 -72
- package/src/codeGenerators/app/sls_yaml/_policy/PolicyEmitter.js +3 -2
- package/src/codeGenerators/app/sls_yaml/_policy/__tests__/PolicyEmitter.test.js +3 -3
- package/src/codeGenerators/app/sls_yaml/_policy/templates/ManagedPolicy_Yaml.ejs +2 -2
- package/src/codeGenerators/app/sls_yaml/templates/SharedResource_Yaml.ejs +1 -1
- package/src/codeGenerators/app/src/generatedCode/Flow/FlowObjects/EndpointsGenerator.js +1 -1
- package/src/codeGenerators/app/src/generatedCode/Flow/FlowObjects/templates/crud/CreateEndpoint_Main.ejs +6 -6
- package/src/codeGenerators/app/src/generatedCode/Flow/{FlowSchemas → FlowObjects}/templates/step/FlowEndpointComplete_Main.ejs +78 -69
- package/src/codeGenerators/app/src/generatedCode/Flow/FlowRelationships/templates/relationship/ProcessChangeRelationship_Main.ejs +2 -2
- package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/endpoint/FlowEndpoint_HdrWbs.ejs +2 -2
- package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/endpoint/FlowEndpoint_Main.ejs +8 -4
- package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/endpoint/FlowMain_Wbs.ejs +4 -4
- package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/s3/CreatePreSignUrl_Main.ejs +1 -1
- package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/s3/ProcessS3File_Main.ejs +1 -1
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/BaseDsqHandler.js +4 -13
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/BaseSqsHandler.js +14 -15
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/lambdaSyncApi.js +4 -13
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/lambdaSyncInv.js +4 -13
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/ownTopic.js +16 -4
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/handlers/FlowHandler_HdrDsq.ejs +79 -63
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/handlers/FlowHandler_HdrSqs.ejs +62 -50
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowEntryPointBase.js +7 -4
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowMainFunctionBase.js +23 -33
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowNaming.js +16 -0
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowStepBase.js +10 -5
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowStepNormalizer.js +21 -20
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowValidator.js +1 -13
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/propertyNormalizer.js +20 -0
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/roleNameDetection.js +49 -0
- package/src/codeGenerators/resource/sls_yaml/DynamoDBGenerator.js +1 -10
- package/src/codeGenerators/resource/sls_yaml/FlowOutGenerator.js +2 -10
- package/src/codeGenerators/resource/sls_yaml/FlowResourceYamlGenerator.js +2 -11
- package/src/core/validate.js +9 -5
- package/src/generate.js +2 -2
- package/src/generateCode.js +21 -0
- package/src/schemaGenerators/app/src/schemas/FlowSchemas/FlowSchemaGenerator.js +0 -43
- package/test_schema.js +2 -0
- package/test_generate.js +0 -7
- package/test_normalize.js +0 -17
- /package/src/codeGenerators/app/src/generatedCode/Flow/FlowObjects/templates/{FlowEndpointBeforeLogical_Main.ejs → step/FlowEndpointBeforeLogical_Main.ejs} +0 -0
package/src/codeGenerators/app/src/generatedCode/Flow/_shared/handlers/FlowHandler_HdrDsq.ejs
CHANGED
|
@@ -15,8 +15,8 @@ You should have received a copy of the GNU Affero General Public License
|
|
|
15
15
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import { middlewareHandler as middleware } from
|
|
19
|
-
import { recordHandlerSharedLib } from
|
|
18
|
+
import { middlewareHandler as middleware } from '@izara_project/izara-middleware';
|
|
19
|
+
import { recordHandlerSharedLib } from '@izara_project/izara-core-library-record-handler';
|
|
20
20
|
import Logger from '@izara_project/izara-core-library-logger';
|
|
21
21
|
import callingFlowSharedLib from '@izara_project/izara-core-library-calling-flow';
|
|
22
22
|
import <%= functionName %> from './<%= mainFileName %>.js';
|
|
@@ -27,11 +27,9 @@ let perRecordsValidatorSchema = {
|
|
|
27
27
|
<% if (typeof startConfig !== 'undefined' && startConfig !== null && startConfig.properties && startConfig.properties.length > 0) { -%>
|
|
28
28
|
type: 'object',
|
|
29
29
|
properties: {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
},
|
|
34
|
-
required: [ <%- startConfig.properties.filter(p => p.required !== false).map(p => `'${p.propertyName}'`).join(', ') %> ]
|
|
30
|
+
<% startConfig.properties.forEach((prop, index) => { %> <%- prop.propertyName %>: { type: '<%- prop.type || 'string' %>' }<%= index < startConfig.properties.length - 1 ? ',' : '' %>
|
|
31
|
+
<% }) %> },
|
|
32
|
+
required: [<%- startConfig.properties.filter(p => p.required !== false).map(p => `'${p.propertyName}'`).join(', ') %>]
|
|
35
33
|
<% } -%>
|
|
36
34
|
//(</validatorSchema>)
|
|
37
35
|
};
|
|
@@ -40,90 +38,108 @@ let perRecordsValidatorSchema = {
|
|
|
40
38
|
let messageAttributeValidatorSchema = {
|
|
41
39
|
type: 'object',
|
|
42
40
|
properties: {
|
|
43
|
-
|
|
44
|
-
'<%- prop.propertyName %>': {
|
|
41
|
+
<% startConfig.messageAttributes.forEach((prop, index) => { %> '<%- prop.propertyName %>': {
|
|
45
42
|
type: 'object',
|
|
46
43
|
properties: {
|
|
47
44
|
Type: { type: 'string' },
|
|
48
45
|
Value: { type: '<%- prop.type || 'string' %>' }
|
|
49
46
|
},
|
|
50
47
|
required: ['Type', 'Value']
|
|
51
|
-
},
|
|
52
|
-
|
|
53
|
-
},
|
|
54
|
-
required: [ <%- startConfig.messageAttributes.filter(p => p.required !== false).map(p => `'${p.propertyName}'`).join(', ') %> ]
|
|
48
|
+
}<%= index < startConfig.messageAttributes.length - 1 ? ',' : '' %>
|
|
49
|
+
<% }) %> },
|
|
50
|
+
required: [<%- startConfig.messageAttributes.filter(p => p.required !== false).map(p => `'${p.propertyName}'`).join(', ') %>]
|
|
55
51
|
};
|
|
56
52
|
<% } else { -%>
|
|
57
53
|
let messageAttributeValidatorSchema = null;
|
|
58
54
|
<% } -%>
|
|
59
55
|
|
|
60
|
-
middleware.setValidatorSchema(
|
|
61
|
-
{
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
56
|
+
middleware.setValidatorSchema(
|
|
57
|
+
recordHandlerSharedLib.baseValidatorSchema({
|
|
58
|
+
type: 'object',
|
|
59
|
+
required: ['body', 'messageAttributes'],
|
|
60
|
+
properties: {
|
|
61
|
+
body: {
|
|
62
|
+
type: 'object'
|
|
63
|
+
},
|
|
64
|
+
messageAttributes: {
|
|
65
|
+
type: 'object'
|
|
66
|
+
}
|
|
70
67
|
}
|
|
71
|
-
}
|
|
72
|
-
|
|
68
|
+
})
|
|
69
|
+
);
|
|
73
70
|
|
|
74
71
|
export const main = middleware.wrap(async (event, context) => {
|
|
75
|
-
|
|
76
72
|
try {
|
|
77
|
-
|
|
78
73
|
let recordPromises = [];
|
|
79
74
|
|
|
80
75
|
// loop each record and send to mainFunction
|
|
81
|
-
await Promise.all(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
76
|
+
await Promise.all(
|
|
77
|
+
event.Records.map(async record => {
|
|
78
|
+
// promise.all for map() function
|
|
79
|
+
|
|
80
|
+
let passOnProperties = [];
|
|
81
|
+
record = recordHandlerSharedLib.reformatDsqMessage(
|
|
82
|
+
record._izContext,
|
|
83
|
+
record
|
|
84
|
+
);
|
|
85
|
+
record._izContext.logger.debug('record ReceiveMsgOutHdrSqs', record);
|
|
86
|
+
|
|
87
|
+
//validate message (and MessageAttributes)
|
|
88
|
+
await recordHandlerSharedLib.validateRecord(
|
|
89
|
+
record, // one record will send to mainFunction
|
|
90
|
+
'<%= queueName %>', // queue name that need to retry or send to dlq
|
|
91
|
+
perRecordsValidatorSchema, // schema for record.Message
|
|
92
|
+
messageAttributeValidatorSchema
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
// add argument (to invoke lambda) to passOnProperties[]
|
|
96
|
+
passOnProperties.push(record.body.Message);
|
|
97
|
+
<% if (functionName.endsWith('Complete')) { %>
|
|
98
|
+
passOnProperties.push(
|
|
99
|
+
callingFlowSharedLib.addPassBackPropertiesToPassOnProperties(
|
|
100
|
+
record.body.Message
|
|
101
|
+
)
|
|
102
|
+
);
|
|
103
|
+
<% } else { %>
|
|
104
|
+
passOnProperties.push(
|
|
105
|
+
callingFlowSharedLib.addCallingFlowToPassOnProperties(
|
|
106
|
+
record.body.Message
|
|
107
|
+
)
|
|
108
|
+
);
|
|
109
|
+
<% } %>
|
|
110
|
+
//(<additionalParams>)
|
|
111
|
+
//(</additionalParams>)
|
|
112
|
+
record._izContext.logger.debug(
|
|
113
|
+
'passOnProperties in handler',
|
|
114
|
+
passOnProperties
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
// call recordHandlerSharedLib.recordHandler with 3 parameters and return promise(resolve)
|
|
118
|
+
let recordPromise = recordHandlerSharedLib.recordHandler(
|
|
119
|
+
record, // one record will send to mainFunction
|
|
120
|
+
<%= functionName %>, // mainFunction that need to invoke.
|
|
121
|
+
'<%= queueName %>', // queue name that need to retry or send to dlq
|
|
122
|
+
passOnProperties // all parameters that mainFunction needed.
|
|
123
|
+
);
|
|
124
|
+
record._izContext.logger.debug('after recordPromise in handler');
|
|
125
|
+
recordPromises.push(recordPromise); // push promise to recordPromises
|
|
126
|
+
})
|
|
127
|
+
);
|
|
112
128
|
|
|
113
129
|
Logger.debug('before Promise.all(recordPromises) in handler');
|
|
114
130
|
try {
|
|
115
131
|
// --- main await all promises
|
|
116
132
|
await Promise.all(recordPromises); // await all promises
|
|
117
133
|
|
|
118
|
-
return event.Records // return all for local testing
|
|
119
|
-
|
|
134
|
+
return event.Records; // return all for local testing
|
|
120
135
|
} catch {
|
|
121
|
-
Logger.debug(
|
|
136
|
+
Logger.debug(
|
|
137
|
+
'Promise.all(recordPromises) in handler threw error (at least one record did no resolve)'
|
|
138
|
+
);
|
|
122
139
|
}
|
|
123
140
|
Logger.debug('after Promise.all(recordPromises) in handler');
|
|
124
|
-
|
|
125
141
|
} catch (err) {
|
|
126
142
|
Logger.error('Unhandled Error, LambdaFunctionHdrSqs: ', err);
|
|
127
|
-
throw
|
|
143
|
+
throw err;
|
|
128
144
|
}
|
|
129
145
|
});
|
package/src/codeGenerators/app/src/generatedCode/Flow/_shared/handlers/FlowHandler_HdrSqs.ejs
CHANGED
|
@@ -15,8 +15,8 @@ You should have received a copy of the GNU Affero General Public License
|
|
|
15
15
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import { middlewareHandler as middleware } from
|
|
19
|
-
import { recordHandlerSharedLib } from
|
|
18
|
+
import { middlewareHandler as middleware } from '@izara_project/izara-middleware';
|
|
19
|
+
import { recordHandlerSharedLib } from '@izara_project/izara-core-library-record-handler';
|
|
20
20
|
import Logger from '@izara_project/izara-core-library-logger';
|
|
21
21
|
import callingFlowSharedLib from '@izara_project/izara-core-library-calling-flow';
|
|
22
22
|
import <%= functionName %> from './<%= mainFileName %>.js';
|
|
@@ -27,11 +27,9 @@ let perRecordsValidatorSchema = {
|
|
|
27
27
|
<% if (typeof startConfig !== 'undefined' && startConfig !== null && startConfig.properties && startConfig.properties.length > 0) { -%>
|
|
28
28
|
type: 'object',
|
|
29
29
|
properties: {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
},
|
|
34
|
-
required: [ <%- startConfig.properties.filter(p => p.required !== false).map(p => `'${p.propertyName}'`).join(', ') %> ]
|
|
30
|
+
<% startConfig.properties.forEach((prop, index) => { %> <%- prop.propertyName %>: { type: '<%- prop.type || 'string' %>' }<%= index < startConfig.properties.length - 1 ? ',' : '' %>
|
|
31
|
+
<% }) %> },
|
|
32
|
+
required: [<%- startConfig.properties.filter(p => p.required !== false).map(p => `'${p.propertyName}'`).join(', ') %>]
|
|
35
33
|
<% } -%>
|
|
36
34
|
//(</validatorSchema>)
|
|
37
35
|
};
|
|
@@ -40,18 +38,16 @@ let perRecordsValidatorSchema = {
|
|
|
40
38
|
let messageAttributeValidatorSchema = {
|
|
41
39
|
type: 'object',
|
|
42
40
|
properties: {
|
|
43
|
-
|
|
44
|
-
'<%- prop.propertyName %>': {
|
|
41
|
+
<% startConfig.messageAttributes.forEach((prop, index) => { %> '<%- prop.propertyName %>': {
|
|
45
42
|
type: 'object',
|
|
46
43
|
properties: {
|
|
47
44
|
Type: { type: 'string' },
|
|
48
45
|
Value: { type: '<%- prop.type || 'string' %>' }
|
|
49
46
|
},
|
|
50
47
|
required: ['Type', 'Value']
|
|
51
|
-
},
|
|
52
|
-
|
|
53
|
-
},
|
|
54
|
-
required: [ <%- startConfig.messageAttributes.filter(p => p.required !== false).map(p => `'${p.propertyName}'`).join(', ') %> ]
|
|
48
|
+
}<%= index < startConfig.messageAttributes.length - 1 ? ',' : '' %>
|
|
49
|
+
<% }) %> },
|
|
50
|
+
required: [<%- startConfig.messageAttributes.filter(p => p.required !== false).map(p => `'${p.propertyName}'`).join(', ') %>]
|
|
55
51
|
};
|
|
56
52
|
<% } else { -%>
|
|
57
53
|
let messageAttributeValidatorSchema = null;
|
|
@@ -59,57 +55,73 @@ let messageAttributeValidatorSchema = null;
|
|
|
59
55
|
middleware.setValidatorSchema(recordHandlerSharedLib.baseValidatorSchema());
|
|
60
56
|
|
|
61
57
|
export const main = middleware.wrap(async (event, context) => {
|
|
62
|
-
|
|
63
58
|
try {
|
|
64
|
-
|
|
65
59
|
let recordPromises = [];
|
|
66
60
|
|
|
67
61
|
// loop each record and send to mainFunction
|
|
68
|
-
await Promise.all(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
62
|
+
await Promise.all(
|
|
63
|
+
event.Records.map(async record => {
|
|
64
|
+
// promise.all for map() function
|
|
65
|
+
|
|
66
|
+
let passOnProperties = [];
|
|
67
|
+
record._izContext.logger.debug('record ReceiveMsgOutHdrSqs', record);
|
|
68
|
+
|
|
69
|
+
//validate message (and MessageAttributes)
|
|
70
|
+
await recordHandlerSharedLib.validateRecord(
|
|
71
|
+
record, // one record will send to mainFunction
|
|
72
|
+
'<%= queueName %>', // queue name that need to retry or send to dlq
|
|
73
|
+
perRecordsValidatorSchema, // schema for record.Message
|
|
74
|
+
messageAttributeValidatorSchema
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
// add argument (to invoke lambda) to passOnProperties[]
|
|
78
|
+
passOnProperties.push(record.body.Message);
|
|
79
|
+
<% if (functionName.endsWith('Complete')) { %>
|
|
80
|
+
passOnProperties.push(
|
|
81
|
+
callingFlowSharedLib.addPassBackPropertiesToPassOnProperties(
|
|
82
|
+
record.body.Message
|
|
83
|
+
)
|
|
84
|
+
);
|
|
85
|
+
<% } else { %>
|
|
86
|
+
passOnProperties.push(
|
|
87
|
+
callingFlowSharedLib.addCallingFlowToPassOnProperties(
|
|
88
|
+
record.body.Message
|
|
89
|
+
)
|
|
90
|
+
);
|
|
91
|
+
<% } %>
|
|
92
|
+
//(<additionalParams>)
|
|
93
|
+
//(</additionalParams>)
|
|
94
|
+
record._izContext.logger.debug(
|
|
95
|
+
'passOnProperties in handler',
|
|
96
|
+
passOnProperties
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
// call recordHandlerSharedLib.recordHandler with 3 parameters and return promise(resolve)
|
|
100
|
+
let recordPromise = recordHandlerSharedLib.recordHandler(
|
|
101
|
+
record, // one record will send to mainFunction
|
|
102
|
+
<%= functionName %>, // mainFunction that need to invoke.
|
|
103
|
+
'<%= queueName %>', // queue name that need to retry or send to dlq
|
|
104
|
+
passOnProperties // all parameters that mainFunction needed.
|
|
105
|
+
);
|
|
106
|
+
record._izContext.logger.debug('after recordPromise in handler');
|
|
107
|
+
recordPromises.push(recordPromise); // push promise to recordPromises
|
|
108
|
+
})
|
|
109
|
+
);
|
|
98
110
|
|
|
99
111
|
Logger.debug('before Promise.all(recordPromises) in handler');
|
|
100
112
|
try {
|
|
101
113
|
// --- main await all promises
|
|
102
114
|
await Promise.all(recordPromises); // await all promises
|
|
103
115
|
|
|
104
|
-
return event.Records // return all for local testing
|
|
105
|
-
|
|
116
|
+
return event.Records; // return all for local testing
|
|
106
117
|
} catch {
|
|
107
|
-
Logger.debug(
|
|
118
|
+
Logger.debug(
|
|
119
|
+
'Promise.all(recordPromises) in handler threw error (at least one record did no resolve)'
|
|
120
|
+
);
|
|
108
121
|
}
|
|
109
122
|
Logger.debug('after Promise.all(recordPromises) in handler');
|
|
110
|
-
|
|
111
123
|
} catch (err) {
|
|
112
124
|
Logger.error('Unhandled Error, LambdaFunctionHdrSqs: ', err);
|
|
113
|
-
throw
|
|
125
|
+
throw err;
|
|
114
126
|
}
|
|
115
127
|
});
|
|
@@ -4,9 +4,9 @@ import { fileURLToPath } from 'url';
|
|
|
4
4
|
import ejs from 'ejs';
|
|
5
5
|
import { EVENT_HANDLERS } from '../events/registry.js';
|
|
6
6
|
import { STATUS_HANDLERS } from './registry.js';
|
|
7
|
-
import { getFlowOutputSubDir, isRbacFlow, isRelationshipFlow } from './flowClassifier.js';
|
|
7
|
+
import { getFlowOutputSubDir, isCrudFlow, isRbacFlow, isRelationshipFlow } from './flowClassifier.js';
|
|
8
8
|
import { normalizeEvents } from './eventTypes.js';
|
|
9
|
-
import { processMainFileName, upperFirst } from './flowNaming.js';
|
|
9
|
+
import { processMainFileName, ownTopicMainFileName, upperFirst } from './flowNaming.js';
|
|
10
10
|
import { getFlowsForGeneration, getGeneratedCodeConfigs } from './flowSelection.js';
|
|
11
11
|
|
|
12
12
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -41,10 +41,13 @@ export async function generateFlowEntryPoint(allSchemas, options) {
|
|
|
41
41
|
const flowOutputDir = path.join(baseOutputDir, subDir, upperCaseFlowTag, 'source');
|
|
42
42
|
await fs.mkdir(flowOutputDir, { recursive: true });
|
|
43
43
|
|
|
44
|
-
// NOTE: Changed to Process${upperCaseFlowTag}_Main to match legacy.
|
|
45
|
-
const mainFileName = processMainFileName(flowTag);
|
|
46
44
|
// 2. Generate Handlers based on event array using Registry
|
|
47
45
|
const events = normalizeEvents(flow.event, ['ownTopic']);
|
|
46
|
+
|
|
47
|
+
const isOwnTopic = !isCrudFlow(flowTag) && !isRbacFlow(flowTag) && !isRelationshipFlow(flowTag) && events.includes('ownTopic');
|
|
48
|
+
const mainFileName = isOwnTopic
|
|
49
|
+
? ownTopicMainFileName(flowTag)
|
|
50
|
+
: processMainFileName(flowTag);
|
|
48
51
|
|
|
49
52
|
// Use invocationType from generatedCodeConfig if available
|
|
50
53
|
if (flow.generatedCodeConfig && flow.generatedCodeConfig.invocationType) {
|
package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowMainFunctionBase.js
CHANGED
|
@@ -3,8 +3,9 @@ import fs from 'fs/promises';
|
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
4
|
import ejs from 'ejs';
|
|
5
5
|
import { getFlowOutputSubDir, isCrudFlow, isRbacFlow, isRelationshipFlow } from './flowClassifier.js';
|
|
6
|
-
import { processMainFileName, upperFirst } from './flowNaming.js';
|
|
6
|
+
import { processMainFileName, processFunctionName, ownTopicMainFileName, ownTopicFunctionName, ownTopicWebSocketMainFileName, ownTopicWebSocketFunctionName, upperFirst } from './flowNaming.js';
|
|
7
7
|
import { getFlowsForGeneration, getGeneratedCodeConfigs } from './flowSelection.js';
|
|
8
|
+
import { normalizePropertyType } from './propertyNormalizer.js';
|
|
8
9
|
|
|
9
10
|
const __filename = fileURLToPath(import.meta.url);
|
|
10
11
|
const __dirname = path.dirname(__filename);
|
|
@@ -41,11 +42,13 @@ export async function generateFlowMainFunction(allSchemas, options) {
|
|
|
41
42
|
const flowOutputDir = path.join(baseOutputDir, subDir, upperCaseFlowTag, 'source');
|
|
42
43
|
await fs.mkdir(flowOutputDir, { recursive: true });
|
|
43
44
|
|
|
44
|
-
// For ownTopic flows the SNS-publish file is <FlowTag>_Main.js; others stay Process<FlowTag>_Main.js
|
|
45
45
|
const isOwnTopic = !isCrud && flow.event && flow.event.includes('ownTopic');
|
|
46
46
|
const mainFileName = isOwnTopic
|
|
47
|
-
?
|
|
47
|
+
? ownTopicMainFileName(flowTag)
|
|
48
48
|
: processMainFileName(flowTag);
|
|
49
|
+
const functionName = isOwnTopic
|
|
50
|
+
? ownTopicFunctionName(flowTag)
|
|
51
|
+
: processFunctionName(flowTag);
|
|
49
52
|
const topicArn = `${upperCaseFlowTag}_In`;
|
|
50
53
|
|
|
51
54
|
const generateCode = getGeneratedCodeConfigs(flows, flowTag, { includeFlowTag: true });
|
|
@@ -55,9 +58,6 @@ export async function generateFlowMainFunction(allSchemas, options) {
|
|
|
55
58
|
templateName = `${flowTag}Endpoint_Main.ejs`;
|
|
56
59
|
} else if (String(flowTag || '').toLowerCase().endsWith('rbacflow')) {
|
|
57
60
|
templateName = 'FlowRbac_Main.ejs';
|
|
58
|
-
} else if (isOwnTopic) {
|
|
59
|
-
// Non-CRUD flow with ownTopic: WebSocket entry that fetches flowSchema and publishes to SNS In topic
|
|
60
|
-
templateName = 'FlowMain_Wbs.ejs';
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
// crud templates live under FlowObjects (the only output child that uses them);
|
|
@@ -75,27 +75,15 @@ export async function generateFlowMainFunction(allSchemas, options) {
|
|
|
75
75
|
'utf-8'
|
|
76
76
|
);
|
|
77
77
|
|
|
78
|
-
const startStep = flow.flowSteps && flow.flowSteps.
|
|
79
|
-
s => s.stepName === 'start'
|
|
80
|
-
);
|
|
78
|
+
const startStep = flow.flowSteps && flow.flowSteps.length > 0 ? flow.flowSteps[0] : null;
|
|
81
79
|
let startConfig = startStep ? { ...startStep } : null;
|
|
82
80
|
|
|
83
81
|
if (startConfig) {
|
|
84
82
|
if (startConfig.properties && Array.isArray(startConfig.properties)) {
|
|
85
|
-
startConfig.properties = startConfig.properties.map(p =>
|
|
86
|
-
if (typeof p === 'string') {
|
|
87
|
-
return (flow.stepProperties && flow.stepProperties[p]) ? flow.stepProperties[p] : { propertyName: p, type: 'string' };
|
|
88
|
-
}
|
|
89
|
-
return p;
|
|
90
|
-
});
|
|
83
|
+
startConfig.properties = startConfig.properties.map(p => normalizePropertyType(p, flow.stepProperties));
|
|
91
84
|
}
|
|
92
85
|
if (startConfig.messageAttributes && Array.isArray(startConfig.messageAttributes)) {
|
|
93
|
-
startConfig.messageAttributes = startConfig.messageAttributes.map(p =>
|
|
94
|
-
if (typeof p === 'string') {
|
|
95
|
-
return (flow.stepMessageAttributes && flow.stepMessageAttributes[p]) ? flow.stepMessageAttributes[p] : { propertyName: p, type: 'string' };
|
|
96
|
-
}
|
|
97
|
-
return p;
|
|
98
|
-
});
|
|
86
|
+
startConfig.messageAttributes = startConfig.messageAttributes.map(p => normalizePropertyType(p, flow.stepMessageAttributes));
|
|
99
87
|
}
|
|
100
88
|
}
|
|
101
89
|
|
|
@@ -119,7 +107,8 @@ export async function generateFlowMainFunction(allSchemas, options) {
|
|
|
119
107
|
generateCode: generateCode,
|
|
120
108
|
flow: flow,
|
|
121
109
|
startConfig: startConfig,
|
|
122
|
-
tableName: tableName
|
|
110
|
+
tableName: tableName,
|
|
111
|
+
functionName: functionName
|
|
123
112
|
});
|
|
124
113
|
await fs.writeFile(
|
|
125
114
|
path.join(flowOutputDir, `${mainFileName}.js`),
|
|
@@ -127,34 +116,35 @@ export async function generateFlowMainFunction(allSchemas, options) {
|
|
|
127
116
|
'utf-8'
|
|
128
117
|
);
|
|
129
118
|
|
|
130
|
-
// For ownTopic flows:
|
|
119
|
+
// For ownTopic flows: generate WebSocket main that publishes to SNS In topic
|
|
131
120
|
if (isOwnTopic) {
|
|
132
|
-
const
|
|
133
|
-
path.join(__dirname, '..', '..', 'FlowSchemas', 'templates', 'endpoint', '
|
|
121
|
+
const wbsMainTemplateStr = await fs.readFile(
|
|
122
|
+
path.join(__dirname, '..', '..', 'FlowSchemas', 'templates', 'endpoint', 'FlowMain_Wbs.ejs'),
|
|
134
123
|
'utf-8'
|
|
135
124
|
);
|
|
136
|
-
const
|
|
125
|
+
const wbsMainContent = ejs.render(wbsMainTemplateStr, {
|
|
137
126
|
flowTag: flowTag,
|
|
138
127
|
upperCaseFlowTag: upperCaseFlowTag,
|
|
128
|
+
topicArn: topicArn,
|
|
139
129
|
generateCode: generateCode,
|
|
140
130
|
flow: flow,
|
|
141
131
|
startConfig: startConfig,
|
|
142
|
-
tableName: tableName
|
|
132
|
+
tableName: tableName,
|
|
133
|
+
functionName: ownTopicWebSocketFunctionName(flowTag)
|
|
143
134
|
});
|
|
144
135
|
await fs.writeFile(
|
|
145
|
-
path.join(flowOutputDir, `${
|
|
146
|
-
|
|
136
|
+
path.join(flowOutputDir, `${ownTopicWebSocketMainFileName(flowTag)}.js`),
|
|
137
|
+
wbsMainContent,
|
|
147
138
|
'utf-8'
|
|
148
139
|
);
|
|
140
|
+
generatedCount++;
|
|
149
141
|
}
|
|
150
142
|
|
|
151
143
|
// 2. Generate BeforeLogical Main Logic File if needed (CRUD flows only)
|
|
152
144
|
const beforeLogicalConfigs = generateCode.filter(c => c.codeHookTag === 'beforeLogical');
|
|
153
145
|
if (isCrud && beforeLogicalConfigs.length > 0) {
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
'utf-8'
|
|
157
|
-
);
|
|
146
|
+
const beforeLogicalTemplatePath = path.join(__dirname, '..', '..', 'FlowObjects', 'templates', 'step', 'FlowEndpointBeforeLogical_Main.ejs');
|
|
147
|
+
const beforeLogicalTemplateStr = await fs.readFile(beforeLogicalTemplatePath, 'utf-8');
|
|
158
148
|
|
|
159
149
|
const beforeLogicalFileName = `${upperCaseFlowTag}BeforeLogical_Main`;
|
|
160
150
|
const beforeLogicalContent = ejs.render(beforeLogicalTemplateStr, {
|
|
@@ -16,6 +16,22 @@ export function processFunctionName(flowTag) {
|
|
|
16
16
|
return `Process${upperFirst(flowTag)}`;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
export function ownTopicMainFileName(flowTag) {
|
|
20
|
+
return `${upperFirst(flowTag)}_Main`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function ownTopicFunctionName(flowTag) {
|
|
24
|
+
return `${upperFirst(flowTag)}_Main`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function ownTopicWebSocketMainFileName(flowTag) {
|
|
28
|
+
return `${upperFirst(flowTag)}_WbsMain`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function ownTopicWebSocketFunctionName(flowTag) {
|
|
32
|
+
return `${upperFirst(flowTag)}_WbsMain`;
|
|
33
|
+
}
|
|
34
|
+
|
|
19
35
|
export function flowSourceLocation(subDir, flowTag) {
|
|
20
36
|
return `src/generatedCode/${subDir}/${upperFirst(flowTag)}/source/`;
|
|
21
37
|
}
|
|
@@ -2,7 +2,7 @@ import path from 'path';
|
|
|
2
2
|
import fs from 'fs/promises';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
4
|
import ejs from 'ejs';
|
|
5
|
-
import { getFlowOutputSubDir, isRbacFlow, isRelationshipFlow } from './flowClassifier.js';
|
|
5
|
+
import { getFlowOutputSubDir, isRbacFlow, isRelationshipFlow, isCrudFlow } from './flowClassifier.js';
|
|
6
6
|
import { getStepEventHandlerConfig, normalizeEvents } from './eventTypes.js';
|
|
7
7
|
import { normalizeFlowSteps } from './flowStepNormalizer.js';
|
|
8
8
|
import { getFlowsForGeneration } from './flowSelection.js';
|
|
@@ -18,7 +18,7 @@ export async function generateFlowSteps(allSchemas, options) {
|
|
|
18
18
|
// Read templates
|
|
19
19
|
const templates = {
|
|
20
20
|
main: await fs.readFile(path.join(__dirname, '..', '..', 'FlowSchemas', 'templates', 'step', 'FlowStep_Main.ejs'), 'utf-8'),
|
|
21
|
-
complete: await fs.readFile(path.join(__dirname, '..', '..', '
|
|
21
|
+
complete: await fs.readFile(path.join(__dirname, '..', '..', 'FlowObjects', 'templates', 'step', 'FlowEndpointComplete_Main.ejs'), 'utf-8'),
|
|
22
22
|
sqs: await fs.readFile(path.join(__dirname, '..', 'handlers', 'FlowHandler_HdrSqs.ejs'), 'utf-8'),
|
|
23
23
|
dsq: await fs.readFile(path.join(__dirname, '..', 'handlers', 'FlowHandler_HdrDsq.ejs'), 'utf-8'),
|
|
24
24
|
api: await fs.readFile(path.join(__dirname, '..', 'handlers', 'FlowHandler_HdrApi.ejs'), 'utf-8'),
|
|
@@ -52,9 +52,14 @@ export async function generateFlowSteps(allSchemas, options) {
|
|
|
52
52
|
|
|
53
53
|
let createdDir = false;
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
const normalizedSteps = normalizeFlowSteps(flow.flowSteps);
|
|
56
|
+
for (let index = 0; index < normalizedSteps.length; index++) {
|
|
57
|
+
const stepConfig = normalizedSteps[index];
|
|
56
58
|
const stepName = stepConfig.stepName;
|
|
57
|
-
|
|
59
|
+
|
|
60
|
+
// Skip the first step (which is the entry point, handled by flowMainFunctionBase)
|
|
61
|
+
// Also skip traditional skipped steps by name for backward compatibility
|
|
62
|
+
if (index === 0 || ['in', 'start', 'out', 'beforelogical'].includes(stepName?.toLowerCase())) continue;
|
|
58
63
|
|
|
59
64
|
if (!createdDir) {
|
|
60
65
|
await fs.mkdir(flowOutputDir, { recursive: true });
|
|
@@ -79,7 +84,7 @@ export async function generateFlowSteps(allSchemas, options) {
|
|
|
79
84
|
functionName: `${flowTag}${stepName}`,
|
|
80
85
|
};
|
|
81
86
|
|
|
82
|
-
const isCompleteStep = stepName === 'Complete';
|
|
87
|
+
const isCompleteStep = stepName === 'Complete' && isCrudFlow(flowTag);
|
|
83
88
|
// Base Step Generation
|
|
84
89
|
if (isCompleteStep) {
|
|
85
90
|
templateToUse = templates.complete;
|
|
@@ -40,35 +40,36 @@ export function normalizeUnifiedFlows(rawFlows) {
|
|
|
40
40
|
// Ensure flowSteps is always an Array for the rest of the generation process
|
|
41
41
|
flow.flowSteps = normalizedSteps;
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
// ponytail: root-level event is standard, flowStep[0] has no event.
|
|
45
44
|
if (flow.event) {
|
|
46
|
-
|
|
45
|
+
const firstStep = flow.flowSteps[0];
|
|
46
|
+
const needsStartStep = !firstStep || firstStep.event;
|
|
47
|
+
|
|
48
|
+
if (needsStartStep) {
|
|
47
49
|
flow.flowSteps.unshift({
|
|
48
50
|
stepName: 'Start',
|
|
49
51
|
properties: flow.properties || [],
|
|
50
52
|
messageAttributes: flow.messageAttributes || []
|
|
51
53
|
});
|
|
52
54
|
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
stepName: '
|
|
66
|
-
|
|
67
|
-
messageAttributes: firstStep.messageAttributes || []
|
|
68
|
-
});
|
|
55
|
+
}
|
|
56
|
+
// Validate flowStep events
|
|
57
|
+
flow.flowSteps.forEach((step, index) => {
|
|
58
|
+
if (index === 0) {
|
|
59
|
+
if (step.event) {
|
|
60
|
+
throw new Error(`[Schema Error] Flow '${flow.flowTag || 'Unknown'}' -> stepName '${step.stepName}' (Index 0) must not have an 'event'. Set it at the flow root instead.`);
|
|
61
|
+
}
|
|
62
|
+
} else {
|
|
63
|
+
if (step.event) {
|
|
64
|
+
const validStepEvents = ['extTopic', 'lambdaSyncInv', 'dsq'];
|
|
65
|
+
const invalidEvents = step.event.filter(e => !validStepEvents.includes(e));
|
|
66
|
+
if (invalidEvents.length > 0) {
|
|
67
|
+
throw new Error(`[Schema Error] Flow '${flow.flowTag || 'Unknown'}' -> stepName '${step.stepName}' has invalid event: ${invalidEvents.join(', ')}. Allowed: ${validStepEvents.join(', ')}`);
|
|
68
|
+
}
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
|
-
}
|
|
71
|
+
});
|
|
72
|
+
|
|
72
73
|
return flow;
|
|
73
74
|
});
|
|
74
75
|
}
|