@izara_project/izara-core-generate-service-code 1.0.54 → 1.0.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/package.json +1 -1
  2. package/src/codeGenerators/app/initial_setup/InitialSetupGenerator.js +223 -123
  3. package/src/codeGenerators/app/initial_setup/templates/InitialSetup_LambdaRole.ejs +6 -6
  4. package/src/codeGenerators/app/sls_yaml/FindDataYamlGenerator.js +1 -1
  5. package/src/codeGenerators/app/sls_yaml/FunctionYamlGenerator.js +303 -201
  6. package/src/codeGenerators/app/sls_yaml/RoleNameConfigGenerator.js +84 -60
  7. package/src/codeGenerators/app/sls_yaml/SharedResourceYamlGenerator.js +304 -271
  8. package/src/codeGenerators/app/sls_yaml/__tests__/SharedResourceYamlGenerator.test.js +91 -32
  9. package/src/codeGenerators/app/sls_yaml/templates/SharedResource_Yaml.ejs +2 -2
  10. package/src/codeGenerators/app/src/generatedCode/Flow/{FlowEndpoints → FlowObjects}/EndpointsGenerator.js +1 -1
  11. package/src/codeGenerators/app/src/generatedCode/Flow/FlowRbac/templates/rbac/FlowRbac_Main.ejs +252 -0
  12. package/src/codeGenerators/app/src/generatedCode/Flow/{FlowRelationshipEndpoints → FlowRelationships}/RelationshipFlowGenerator.js +1 -1
  13. package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/StatusFieldGenerator.js +1 -8
  14. package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/WebSocketGenerator.js +1 -7
  15. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/BaseSqsHandler.js +3 -3
  16. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowClassifier.js +3 -2
  17. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowMainFunctionBase.js +12 -5
  18. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/triggerCacheBase.js +1 -7
  19. package/src/codeGenerators/app/src/generatedCode/SystemFlowSchemas/RegisterGenerator.js +1 -7
  20. package/src/codeGenerators/app/src/generatedCode/libs/templates/Consts.ejs +23 -23
  21. package/src/codeGenerators/resource/sls_yaml/DynamoDBGenerator.js +8 -8
  22. package/src/codeGenerators/resource/sls_yaml/FlowOutGenerator.js +57 -51
  23. package/src/codeGenerators/resource/sls_yaml/FlowResourceYamlGenerator.js +164 -175
  24. package/src/codeGenerators/resource/sls_yaml/templates/SystemDynamoDB_Yaml.ejs +64 -0
  25. package/src/codeGenerators/resource/sls_yaml/templates/crud/ResourceYaml.ejs +10 -10
  26. package/src/generate.js +1 -1
  27. package/src/generateCode.js +181 -149
  28. package/src/generateSchema.js +1 -1
  29. package/src/schemaGenerators/app/src/schemas/FlowSchemas/FlowSchemaGenerator.js +0 -1
  30. package/src/schemaGenerators/app/src/schemas/FlowSchemas/RbacFlowSchemaGenerator.js +16 -2
  31. package/src/schemaGenerators/app/src/schemas/FlowSchemas/templates/DynamicFlowSchemaTemplate.ejs +3 -1
  32. package/src/schemaGenerators/app/src/schemas/FlowSchemas/templates/DynamicRbacFlowSchemaTemplate.ejs +1 -0
  33. package/src/schemaGenerators/app/src/schemas/FlowSchemas/templates/RelationshipFlowSchemaTemplate.ejs +6 -5
  34. package/src/schemaGenerators/app/src/schemas/FlowSchemas/templates/UserRbacFlowSchemaTemplate.ejs +22 -0
  35. /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowEndpoints → FlowObjects}/.gitkeep +0 -0
  36. /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowEndpoints → FlowObjects}/templates/FlowEndpointBeforeLogical_Main.ejs +0 -0
  37. /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowEndpoints → FlowObjects}/templates/crud/CreateEndpoint_Main.ejs +0 -0
  38. /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowEndpoints → FlowObjects}/templates/crud/DeleteEndpoint_Main.ejs +0 -0
  39. /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowEndpoints → FlowObjects}/templates/crud/GetEndpoint_Main.ejs +0 -0
  40. /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowEndpoints → FlowObjects}/templates/crud/UpdateEndpoint_Main.ejs +0 -0
  41. /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowRelationshipEndpoints → FlowRelationships}/templates/relationship/ProcessChangeRelationshipComplete_Main.ejs +0 -0
  42. /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowRelationshipEndpoints → FlowRelationships}/templates/relationship/ProcessChangeRelationship_Main.ejs +0 -0
  43. /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowRelationshipEndpoints → FlowRelationships}/templates/relationship/ProcessCreateRelationshipComplete_Main.ejs +0 -0
  44. /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowRelationshipEndpoints → FlowRelationships}/templates/relationship/ProcessCreateRelationship_Main.ejs +0 -0
  45. /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowRelationshipEndpoints → FlowRelationships}/templates/relationship/ProcessDeleteRelationshipComplete_Main.ejs +0 -0
  46. /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowRelationshipEndpoints → FlowRelationships}/templates/relationship/ProcessDeleteRelationship_Main.ejs +0 -0
  47. /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowRelationshipEndpoints → FlowRelationships}/templates/relationship/ProcessGetRelationshipComplete_Main.ejs +0 -0
  48. /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowRelationshipEndpoints → FlowRelationships}/templates/relationship/ProcessGetRelationship_Main.ejs +0 -0
  49. /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowRelationshipEndpoints → FlowRelationships}/templates/relationship/ProcessMoveRelationshipComplete_Main.ejs +0 -0
  50. /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowRelationshipEndpoints → FlowRelationships}/templates/relationship/ProcessMoveRelationship_Main.ejs +0 -0
  51. /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowRelationshipEndpoints → FlowRelationships}/templates/relationship/ProcessUpdateRelationshipComplete_Main.ejs +0 -0
  52. /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowRelationshipEndpoints → FlowRelationships}/templates/relationship/ProcessUpdateRelationship_Main.ejs +0 -0
@@ -3,228 +3,330 @@ import path from 'path';
3
3
  import ejs from 'ejs';
4
4
  import { fileURLToPath } from 'url';
5
5
  import { getFlowsForGeneration } from '../src/generatedCode/Flow/_shared/shared/flowSelection.js';
6
+ import { isRbacFlow } from '../src/generatedCode/Flow/_shared/shared/flowClassifier.js';
6
7
 
7
8
  const __filename = fileURLToPath(import.meta.url);
8
9
  const __dirname = path.dirname(__filename);
9
10
 
10
11
  export async function generateFunctionYaml(allSchemas, options) {
11
- console.log(' [FunctionYamlGenerator] Generating Function YAMLs...');
12
-
13
- const slsYamlDir = path.join(options.outputPath, 'app', 'sls_yaml', 'generatedCode', 'source');
14
- await fs.mkdir(slsYamlDir, { recursive: true });
15
-
16
- const templates = {
17
- sqs: await fs.readFile(path.join(__dirname, 'templates', 'FunctionYaml_Sqs.ejs'), 'utf-8'),
18
- inv: await fs.readFile(path.join(__dirname, 'templates', 'FunctionYaml_Inv.ejs'), 'utf-8'),
19
- api: await fs.readFile(path.join(__dirname, 'templates', 'FunctionYaml_Api.ejs'), 'utf-8'),
20
- wbs: await fs.readFile(path.join(__dirname, 'templates', 'FunctionYaml_Wbs.ejs'), 'utf-8'),
21
- eventBridge: await fs.readFile(path.join(__dirname, 'templates', 'FunctionYaml_EventBridge.ejs'), 'utf-8')
22
- };
23
- const flows = getFlowsForGeneration(allSchemas);
24
-
25
- const CRUD_FLOW_TAGS = ['Create', 'Update', 'Delete', 'Get'];
26
- const REL_FLOW_TAGS = [
27
- 'createRelationship', 'updateRelationship', 'deleteRelationship',
28
- 'getRelationship', 'changeRelationship', 'moveRelationship'
29
- ];
30
-
31
- let perActionYaml = '';
32
- let relActionYaml = '';
33
- let flowSchemaYaml = '';
34
-
35
- const upperCase = (str) => str.charAt(0).toUpperCase() + str.slice(1);
36
-
37
- // 1. Find all generated Handlers
38
- const generatedCodeDir = path.join(options.outputPath, 'app', 'src', 'generatedCode');
39
- const handlerFiles = [];
40
- async function getHandlerFiles(dir) {
41
- try {
42
- const dirents = await fs.readdir(dir, { withFileTypes: true });
43
- for (const dirent of dirents) {
44
- const res = path.resolve(dir, dirent.name);
45
- if (dirent.isDirectory()) {
46
- await getHandlerFiles(res);
47
- } else if (dirent.name.includes('_Hdr') && dirent.name.endsWith('.js')) {
48
- // Extract relative path from generatedCodeDir
49
- const relativePath = path.relative(generatedCodeDir, res);
50
- // normalize to forward slashes
51
- handlerFiles.push(relativePath.replace(/\\/g, '/'));
52
- }
53
- }
54
- } catch (e) {
55
- // directory might not exist if no flows generated
12
+ console.log(' [FunctionYamlGenerator] Generating Function YAMLs...');
13
+
14
+ const slsYamlDir = path.join(
15
+ options.outputPath,
16
+ 'app',
17
+ 'sls_yaml',
18
+ 'generatedCode',
19
+ 'source'
20
+ );
21
+ await fs.mkdir(slsYamlDir, { recursive: true });
22
+
23
+ const templates = {
24
+ sqs: await fs.readFile(
25
+ path.join(__dirname, 'templates', 'FunctionYaml_Sqs.ejs'),
26
+ 'utf-8'
27
+ ),
28
+ inv: await fs.readFile(
29
+ path.join(__dirname, 'templates', 'FunctionYaml_Inv.ejs'),
30
+ 'utf-8'
31
+ ),
32
+ api: await fs.readFile(
33
+ path.join(__dirname, 'templates', 'FunctionYaml_Api.ejs'),
34
+ 'utf-8'
35
+ ),
36
+ wbs: await fs.readFile(
37
+ path.join(__dirname, 'templates', 'FunctionYaml_Wbs.ejs'),
38
+ 'utf-8'
39
+ ),
40
+ eventBridge: await fs.readFile(
41
+ path.join(__dirname, 'templates', 'FunctionYaml_EventBridge.ejs'),
42
+ 'utf-8'
43
+ )
44
+ };
45
+ const flows = getFlowsForGeneration(allSchemas);
46
+
47
+ const CRUD_FLOW_TAGS = ['Create', 'Update', 'Delete', 'Get'];
48
+ const REL_FLOW_TAGS = [
49
+ 'createRelationship',
50
+ 'updateRelationship',
51
+ 'deleteRelationship',
52
+ 'getRelationship',
53
+ 'changeRelationship',
54
+ 'moveRelationship'
55
+ ];
56
+
57
+ let perActionYaml = '';
58
+ let relActionYaml = '';
59
+ let rbacYaml = '';
60
+ let flowSchemaYaml = '';
61
+ const customYmls = {};
62
+
63
+ const upperCase = str => str.charAt(0).toUpperCase() + str.slice(1);
64
+
65
+ // 1. Find all generated Handlers
66
+ const generatedCodeDir = path.join(
67
+ options.outputPath,
68
+ 'app',
69
+ 'src',
70
+ 'generatedCode'
71
+ );
72
+ const handlerFiles = [];
73
+ async function getHandlerFiles(dir) {
74
+ try {
75
+ const dirents = await fs.readdir(dir, { withFileTypes: true });
76
+ for (const dirent of dirents) {
77
+ const res = path.resolve(dir, dirent.name);
78
+ if (dirent.isDirectory()) {
79
+ await getHandlerFiles(res);
80
+ } else if (
81
+ dirent.name.includes('_Hdr') &&
82
+ dirent.name.endsWith('.js')
83
+ ) {
84
+ // Extract relative path from generatedCodeDir
85
+ const relativePath = path.relative(generatedCodeDir, res);
86
+ // normalize to forward slashes
87
+ handlerFiles.push(relativePath.replace(/\\/g, '/'));
56
88
  }
89
+ }
90
+ } catch (e) {
91
+ // directory might not exist if no flows generated
57
92
  }
58
- await getHandlerFiles(generatedCodeDir);
59
-
60
- // Prepare API routes
61
- const crudApiRoutes = allSchemas.objects.map(obj => ({
62
- objectName: obj.objectType,
63
- upperName: upperCase(obj.objectType)
64
- }));
65
- const relApiRoutes = allSchemas.relationships.map(rel => {
66
- const relName = Object.keys(rel)[0];
67
- return {
68
- objectName: relName,
69
- upperName: upperCase(relName)
70
- };
71
- });
72
-
73
- for (const handlerFile of handlerFiles) {
74
- // e.g. "Endpoints/Create/source/ProcessCreate_HdrSqs.js"
75
- const parts = handlerFile.split('/');
76
- if (parts.length < 4) continue;
77
-
78
- const subDir = parts[0]; // e.g. FlowEndpoints, FlowSchemas, SystemFlowSchemas
79
- if (subDir === 'SystemFlowSchemas') continue;
80
-
81
- const flowTag = parts[1];
82
- const fileName = parts[3]; // e.g. ProcessCreate_HdrSqs.js
83
-
84
- const fileNameWithoutExt = fileName.replace('.js', '');
85
- // e.g. ProcessCreate_HdrSqs
86
- const splitFileName = fileNameWithoutExt.split('_');
87
- const handlerBaseName = splitFileName[0]; // e.g. ProcessCreate or CreateComplete
88
- const handlerSuffix = splitFileName[1]; // e.g. HdrSqs, HdrApi, HdrInv
89
-
90
- const isCrud = CRUD_FLOW_TAGS.map(t => t.toLowerCase()).includes(flowTag.toLowerCase());
91
- const isRel = REL_FLOW_TAGS.map(t => t.toLowerCase()).includes(flowTag.toLowerCase());
92
- const isCustom = !isCrud && !isRel;
93
-
94
- // Role mapping
95
- let roleName = '';
96
- if (isCrud) {
97
- roleName = 'PerActionEndpointRole';
98
- } else if (isRel) {
99
- roleName = 'RelationshipRole';
100
- } else {
101
- roleName = `${upperCase(flowTag)}Role`;
102
- }
93
+ }
94
+ await getHandlerFiles(generatedCodeDir);
103
95
 
104
- // Function Name Config
105
- // e.g. ProcessCreateSqs or CreateCompleteSqs or GetApi
106
- let suffixType = handlerSuffix.replace('Hdr', ''); // Sqs, Api, Inv
107
- let functionNameConfig = `${handlerBaseName}${suffixType}`;
108
- if (isCrud && handlerBaseName === `Process${upperCase(flowTag)}`) {
109
- // Legacy matches: CreateSqs, GetApi instead of ProcessCreateSqs
110
- functionNameConfig = `${upperCase(flowTag)}${suffixType}`;
111
- }
112
- if (isRel && handlerBaseName === `Process${upperCase(flowTag)}`) {
113
- // Legacy matches: CreateRelSqs
114
- functionNameConfig = `${upperCase(flowTag).replace('Relationship', 'Rel')}${suffixType}`;
115
- }
116
- if (handlerBaseName.endsWith('Complete')) {
117
- // e.g. CreateObjectComp or CreateCompleteSqs
118
- if (isCrud) {
119
- // Legacy: DeleteNodeComp, UpdateNodeComp, CreateObjectComp
120
- const crudType = upperCase(flowTag);
121
- if (crudType === 'Create') functionNameConfig = `CreateObjectComp`;
122
- else functionNameConfig = `${crudType}NodeComp`;
123
- } else if (isRel) {
124
- // Legacy: UpdateRelComp
125
- functionNameConfig = `${upperCase(flowTag).replace('Relationship', 'Rel')}Comp`;
126
- } else {
127
- functionNameConfig = `${handlerBaseName}${suffixType}`;
128
- }
129
- }
96
+ // Prepare API routes
97
+ const crudApiRoutes = allSchemas.objects.map(obj => ({
98
+ objectName: obj.objectType,
99
+ upperName: upperCase(obj.objectType)
100
+ }));
101
+ const relApiRoutes = allSchemas.relationships.map(rel => {
102
+ const relName = Object.keys(rel)[0];
103
+ return {
104
+ objectName: relName,
105
+ upperName: upperCase(relName)
106
+ };
107
+ });
130
108
 
131
- let queueName = '';
132
- const flowDefForQueue = flows.find(f => f.flowTag === flowTag);
133
-
134
- if (isCrud || isRel) {
135
- queueName = handlerBaseName.replace('Process', '');
136
- if (handlerSuffix === 'HdrSqs' || handlerSuffix === 'HdrDsq') {
137
- queueName += handlerSuffix.replace('Hdr', '');
138
- }
139
- } else {
140
- // For Custom Flows (e.g. OwnTopicFlowProcess, ProcessExtTopicFlow)
141
- // The queue name exactly matches the handler name without the underscore.
142
- if (handlerSuffix === 'HdrSqs' || handlerSuffix === 'HdrDsq') {
143
- if (handlerBaseName === `Process${upperCase(flowTag)}` && flowDefForQueue && flowDefForQueue.event && flowDefForQueue.event.includes('ownTopic')) {
144
- // ownTopic flows in FlowResourceYamlGenerator omit 'Process' for the queue
145
- queueName = flowTag + handlerSuffix.replace('Hdr', '');
146
- } else {
147
- queueName = handlerBaseName + handlerSuffix.replace('Hdr', '');
148
- }
149
- } else {
150
- queueName = handlerBaseName;
151
- }
152
- }
109
+ for (const handlerFile of handlerFiles) {
110
+ // e.g. "Endpoints/Create/source/ProcessCreate_HdrSqs.js"
111
+ const parts = handlerFile.split('/');
112
+ if (parts.length < 4) continue;
153
113
 
154
- // Api routes
155
- let apiRoutes = [];
156
- if (suffixType === 'Api') {
157
- const routesList = isCrud ? crudApiRoutes : (isRel ? relApiRoutes : []);
158
- const actionPath = flowTag.toLowerCase().replace('relationship', '');
159
- apiRoutes = routesList.map(r => ({
160
- path: `/TST/${r.objectName}/${actionPath}`,
161
- upperName: r.upperName
162
- }));
163
- }
114
+ const subDir = parts[0]; // e.g. FlowObjects, FlowSchemas, SystemFlowSchemas
115
+ if (subDir === 'SystemFlowSchemas') continue;
164
116
 
165
- // Handler Path
166
- const handlerPath = `src/generatedCode/${subDir}/${flowTag}/source/${fileNameWithoutExt}.main`;
117
+ const flowTag = parts[1];
118
+ const fileName = parts[3]; // e.g. ProcessCreate_HdrSqs.js
167
119
 
168
- let filterPatterns = '';
169
- if (handlerBaseName.endsWith('Complete') && (suffixType === 'Sqs' || suffixType === 'Dsq')) {
170
- filterPatterns = ` filterPatterns: #**** need to update serverless framework upper v.2.69.1
171
- - body: {"MessageAttributes":{"callingFlow":{"Value":["\${self:custom.iz_resourcePrefix}${functionNameConfig}"]}}} # functionName of callingFlow
172
- - body: {"MessageAttributes":{"callingFlow":{"Value":[{"exists":false}]}}}`;
173
- }
120
+ const fileNameWithoutExt = fileName.replace('.js', '');
121
+ // e.g. ProcessCreate_HdrSqs
122
+ const splitFileName = fileNameWithoutExt.split('_');
123
+ const handlerBaseName = splitFileName[0]; // e.g. ProcessCreate or CreateComplete
124
+ const handlerSuffix = splitFileName[1]; // e.g. HdrSqs, HdrApi, HdrInv
174
125
 
175
- const flowDef = flows.find(f => f.flowTag === flowTag);
176
- let schedules = [];
177
- if (flowDef && flowDef.schedules) {
178
- schedules = flowDef.schedules;
179
- }
126
+ const isCrud = CRUD_FLOW_TAGS.map(t => t.toLowerCase()).includes(
127
+ flowTag.toLowerCase()
128
+ );
129
+ const isRel = REL_FLOW_TAGS.map(t => t.toLowerCase()).includes(
130
+ flowTag.toLowerCase()
131
+ );
132
+ const isRbac =
133
+ isRbacFlow(flowTag) ||
134
+ String(flowTag || '')
135
+ .toLowerCase()
136
+ .endsWith('rbacflow');
137
+ const isCustom = !isCrud && !isRel && !isRbac;
180
138
 
181
- const renderVars = {
182
- functionNameConfig,
183
- handlerPath,
184
- roleName,
185
- queueName,
186
- apiRoutes,
187
- filterPatterns,
188
- schedules,
189
- flowTag
190
- };
191
-
192
- let yamlBlock = '';
193
- if (schedules.length > 0 && suffixType === 'Inv') {
194
- yamlBlock = ejs.render(templates.eventBridge, renderVars);
195
- } else if (suffixType === 'Sqs' || suffixType === 'Dsq') {
196
- yamlBlock = ejs.render(templates.sqs, renderVars);
197
- } else if (suffixType === 'Inv') {
198
- yamlBlock = ejs.render(templates.inv, renderVars);
199
- } else if (suffixType === 'Api') {
200
- yamlBlock = ejs.render(templates.api, renderVars);
201
- } else if (suffixType === 'Wbs') {
202
- renderVars.routeName = flowTag;
203
- yamlBlock = ejs.render(templates.wbs, renderVars);
204
- } else {
205
- // Fallback for others
206
- yamlBlock = ejs.render(templates.inv, renderVars); // Simple no-events template
207
- }
139
+ // Role mapping
140
+ let roleName = '';
141
+ if (isCrud) {
142
+ roleName = 'FlowObjectsRole';
143
+ } else if (isRbac) {
144
+ roleName = 'FlowRbacRole';
145
+ } else if (isRel) {
146
+ roleName = 'FlowRelationshipRole';
147
+ } else {
148
+ roleName = `${upperCase(flowTag)}Role`;
149
+ }
150
+
151
+ // Function Name Config
152
+ // e.g. ProcessCreateSqs or CreateCompleteSqs or GetApi
153
+ let suffixType = handlerSuffix.startsWith('Hdr')
154
+ ? handlerSuffix
155
+ : handlerSuffix.replace('Hdr', '');
156
+ let functionNameConfig = `${handlerBaseName}${suffixType}`;
157
+ if (isCrud && handlerBaseName === `Process${upperCase(flowTag)}`) {
158
+ // Legacy matches: CreateSqs, GetApi instead of ProcessCreateSqs
159
+ functionNameConfig = `${upperCase(flowTag)}${suffixType}`;
160
+ }
161
+ if (isRel && handlerBaseName === `Process${upperCase(flowTag)}`) {
162
+ // Legacy matches: CreateRelSqs
163
+ functionNameConfig = `${upperCase(flowTag).replace('Relationship', 'Rel')}${suffixType}`;
164
+ }
165
+ if (handlerBaseName.endsWith('Complete')) {
166
+ // e.g. CreateObjectComp or CreateCompleteSqs
167
+ if (isCrud) {
168
+ // Legacy: DeleteNodeComp, UpdateNodeComp, CreateObjectComp
169
+ const crudType = upperCase(flowTag);
170
+ if (crudType === 'Create') functionNameConfig = `CreateObjectComp`;
171
+ else functionNameConfig = `${crudType}NodeComp`;
172
+ } else if (isRel) {
173
+ // Legacy: UpdateRelComp
174
+ functionNameConfig = `${upperCase(flowTag).replace('Relationship', 'Rel')}Comp`;
175
+ } else {
176
+ functionNameConfig = `${handlerBaseName}${suffixType}`;
177
+ }
178
+ }
208
179
 
209
- if (isCrud) {
210
- perActionYaml += yamlBlock + '\n\n';
211
- } else if (isRel) {
212
- relActionYaml += yamlBlock + '\n\n';
180
+ let queueName = '';
181
+ const flowDefForQueue = flows.find(f => f.flowTag === flowTag);
182
+
183
+ if (isCrud || isRel) {
184
+ queueName = handlerBaseName.replace('Process', '');
185
+ if (handlerSuffix === 'HdrSqs' || handlerSuffix === 'HdrDsq') {
186
+ queueName += handlerSuffix;
187
+ }
188
+ } else {
189
+ // For Custom Flows (e.g. OwnTopicFlowProcess, ProcessExtTopicFlow)
190
+ // The queue name exactly matches the handler name without the underscore.
191
+ if (handlerSuffix === 'HdrSqs' || handlerSuffix === 'HdrDsq') {
192
+ if (
193
+ handlerBaseName === `Process${upperCase(flowTag)}` &&
194
+ flowDefForQueue &&
195
+ flowDefForQueue.event &&
196
+ flowDefForQueue.event.includes('ownTopic')
197
+ ) {
198
+ // ownTopic flows in FlowResourceYamlGenerator omit 'Process' for the queue
199
+ queueName = flowTag + handlerSuffix;
213
200
  } else {
214
- flowSchemaYaml += yamlBlock + '\n\n';
201
+ queueName = handlerBaseName + handlerSuffix;
215
202
  }
203
+ } else {
204
+ queueName = handlerBaseName;
205
+ }
216
206
  }
217
207
 
218
- if (perActionYaml) {
219
- await fs.writeFile(path.join(slsYamlDir, 'per-action-function.yml'), perActionYaml, 'utf-8');
208
+ // Api routes
209
+ let apiRoutes = [];
210
+ if (suffixType === 'HdrApi' || suffixType === 'Api') {
211
+ const routesList = isCrud ? crudApiRoutes : isRel ? relApiRoutes : [];
212
+ const actionPath = flowTag.toLowerCase().replace('relationship', '');
213
+ apiRoutes = routesList.map(r => ({
214
+ path: `/TST/${r.objectName}/${actionPath}`,
215
+ upperName: r.upperName
216
+ }));
220
217
  }
221
- if (relActionYaml) {
222
- await fs.writeFile(path.join(slsYamlDir, 'relationship-per-action.yml'), relActionYaml, 'utf-8');
218
+
219
+ // Handler Path
220
+ const handlerPath = `src/generatedCode/${subDir}/${flowTag}/source/${fileNameWithoutExt}.main`;
221
+
222
+ let filterPatterns = '';
223
+ if (
224
+ handlerBaseName.endsWith('Complete') &&
225
+ (suffixType === 'HdrSqs' ||
226
+ suffixType === 'HdrDsq' ||
227
+ suffixType === 'Sqs' ||
228
+ suffixType === 'Dsq')
229
+ ) {
230
+ filterPatterns = ` filterPatterns: #**** need to update serverless framework upper v.2.69.1
231
+ - body: {"MessageAttributes":{"callingFlow":{"Value":["\${self:custom.iz_resourcePrefix}${functionNameConfig}"]}}} # functionName of callingFlow
232
+ - body: {"MessageAttributes":{"callingFlow":{"Value":[{"exists":false}]}}}`;
223
233
  }
224
- if (flowSchemaYaml) {
225
- // Append to flow-schema.yml just in case WebSocket/TriggerCache already created it, or create new.
226
- await fs.appendFile(path.join(slsYamlDir, 'flow-schema.yml'), flowSchemaYaml, 'utf-8');
234
+
235
+ const flowDef = flows.find(f => f.flowTag === flowTag);
236
+ let schedules = [];
237
+ if (flowDef && flowDef.schedules) {
238
+ schedules = flowDef.schedules;
239
+ }
240
+
241
+ const renderVars = {
242
+ functionNameConfig,
243
+ handlerPath,
244
+ roleName,
245
+ queueName,
246
+ apiRoutes,
247
+ filterPatterns,
248
+ schedules,
249
+ flowTag
250
+ };
251
+
252
+ let yamlBlock = '';
253
+ if (
254
+ schedules.length > 0 &&
255
+ (suffixType === 'HdrInv' || suffixType === 'Inv')
256
+ ) {
257
+ yamlBlock = ejs.render(templates.eventBridge, renderVars);
258
+ } else if (
259
+ suffixType === 'HdrSqs' ||
260
+ suffixType === 'HdrDsq' ||
261
+ suffixType === 'Sqs' ||
262
+ suffixType === 'Dsq'
263
+ ) {
264
+ yamlBlock = ejs.render(templates.sqs, renderVars);
265
+ } else if (suffixType === 'HdrInv' || suffixType === 'Inv') {
266
+ yamlBlock = ejs.render(templates.inv, renderVars);
267
+ } else if (suffixType === 'HdrApi' || suffixType === 'Api') {
268
+ yamlBlock = ejs.render(templates.api, renderVars);
269
+ } else if (suffixType === 'HdrWbs' || suffixType === 'Wbs') {
270
+ renderVars.routeName = flowTag;
271
+ yamlBlock = ejs.render(templates.wbs, renderVars);
272
+ } else {
273
+ // Fallback for others
274
+ yamlBlock = ejs.render(templates.inv, renderVars); // Simple no-events template
227
275
  }
228
276
 
229
- console.log(` [FunctionYamlGenerator] Wrote YAML functions for CRUD, Relationships, and Custom Flows.`);
277
+ const customYamlFile =
278
+ flowDef && flowDef.fileName ? flowDef.fileName : null;
279
+
280
+ if (customYamlFile) {
281
+ if (!customYmls[customYamlFile]) customYmls[customYamlFile] = '';
282
+ customYmls[customYamlFile] += yamlBlock + '\n\n';
283
+ } else if (isCrud) {
284
+ perActionYaml += yamlBlock + '\n\n';
285
+ } else if (isRel) {
286
+ relActionYaml += yamlBlock + '\n\n';
287
+ } else if (isRbac) {
288
+ rbacYaml += yamlBlock + '\n\n';
289
+ } else {
290
+ flowSchemaYaml += yamlBlock + '\n\n';
291
+ }
292
+ }
293
+
294
+ if (perActionYaml) {
295
+ await fs.writeFile(
296
+ path.join(slsYamlDir, 'flow-objects.yml'),
297
+ perActionYaml,
298
+ 'utf-8'
299
+ );
300
+ }
301
+ if (relActionYaml) {
302
+ await fs.writeFile(
303
+ path.join(slsYamlDir, 'flow-relationships.yml'),
304
+ relActionYaml,
305
+ 'utf-8'
306
+ );
307
+ }
308
+ if (rbacYaml) {
309
+ await fs.writeFile(
310
+ path.join(slsYamlDir, 'flow-rbac.yml'),
311
+ rbacYaml,
312
+ 'utf-8'
313
+ );
314
+ }
315
+ if (flowSchemaYaml) {
316
+ // Append to flow-schema.yml just in case WebSocket/TriggerCache already created it, or create new.
317
+ await fs.appendFile(
318
+ path.join(slsYamlDir, 'flow-schema.yml'),
319
+ flowSchemaYaml,
320
+ 'utf-8'
321
+ );
322
+ }
323
+
324
+ for (const [fName, content] of Object.entries(customYmls)) {
325
+ const fullFileName = fName.endsWith('.yml') ? fName : `${fName}.yml`;
326
+ await fs.writeFile(path.join(slsYamlDir, fullFileName), content, 'utf-8');
327
+ }
328
+
329
+ console.log(
330
+ ` [FunctionYamlGenerator] Wrote YAML functions for CRUD, Relationships, and Custom Flows.`
331
+ );
230
332
  }