@izara_project/izara-core-generate-service-code 1.0.93 → 1.0.95

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 (27) hide show
  1. package/package.json +1 -1
  2. package/src/compile/compileProject.js +3 -1
  3. package/src/compile/flowValidator.js +182 -18
  4. package/src/compile/loadSchemas.js +144 -9
  5. package/src/emit/coreFunction/emitCoreFunctionArtifacts.js +1 -26
  6. package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +1 -31
  7. package/src/emit/custom/customFlowPaths.js +3 -16
  8. package/src/emit/custom/customFlowS3.js +9 -4
  9. package/src/emit/custom/customFlowSteps.js +14 -47
  10. package/src/emit/custom/customFlows.js +27 -6
  11. package/src/emit/custom/emitCustomFlowApplicationArtifacts.js +1 -47
  12. package/src/emit/custom/templates/FlowEndpoint_Main.ejs +75 -2
  13. package/src/emit/relationship/templates/ChangeRelationship_Main.ejs +7 -7
  14. package/src/emit/relationship/templates/CreateRelationship_Main.ejs +5 -5
  15. package/src/emit/relationship/templates/DeleteRelationship_Main.ejs +3 -3
  16. package/src/emit/relationship/templates/GetRelationship_Main.ejs +1 -1
  17. package/src/emit/relationship/templates/MoveRelationship_Main.ejs +5 -5
  18. package/src/emit/relationship/templates/UpdateRelationship_Main.ejs +5 -5
  19. package/src/emit/resource/iamResourceArtifacts.js +6 -6
  20. package/src/emit/resource/resourceState.js +3 -9
  21. package/src/emit/system/emitSystemFindDataArtifacts.js +15 -14
  22. package/test/core.test.js +13 -0
  23. package/test/customFlowApplicationArtifacts.test.js +285 -17
  24. package/test/graphDrivenFlowSchema.test.js +325 -0
  25. package/test/relationshipApplicationArtifacts.test.js +29 -0
  26. package/test/resourceArtifacts.test.js +46 -1
  27. package/test/systemFindDataArtifacts.test.js +73 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@izara_project/izara-core-generate-service-code",
3
- "version": "1.0.93",
3
+ "version": "1.0.95",
4
4
  "description": "Code for locally generating per service files",
5
5
  "homepage": "https://bitbucket.org/izara-core-support-services/izara-core-support-services-generate-service-code#readme",
6
6
  "repository": {
@@ -32,7 +32,9 @@ export function compileProject(request = {}) {
32
32
  }
33
33
  }
34
34
  } catch (err) {
35
- console.log('Could not read serverless.config.yml', err);
35
+ throw new Error(
36
+ `Failed to read or parse configuration at ${configPath}: ${err.message}`
37
+ );
36
38
  }
37
39
  }
38
40
 
@@ -1,8 +1,67 @@
1
+ export const VALID_EVENT_ENUM = [
2
+ 'eventBridge',
3
+ 'extTopic',
4
+ 'lambdaSyncInv',
5
+ 'lambdaSyncApi',
6
+ 'ownTopic',
7
+ 's3',
8
+ 'dsq',
9
+ 'generateCode'
10
+ ];
11
+
1
12
  export function validateFlowSchema(flowSchema) {
2
13
  if (!flowSchema || typeof flowSchema !== 'object') {
3
14
  throw new TypeError('flowSchema must be an object');
4
15
  }
5
16
 
17
+ if (
18
+ typeof flowSchema.flowTag !== 'string' ||
19
+ flowSchema.flowTag.trim() === ''
20
+ ) {
21
+ throw new Error(
22
+ 'FlowSchema validation error: flowTag is required and must be a non-empty string'
23
+ );
24
+ }
25
+ const flowTag = flowSchema.flowTag;
26
+
27
+ if (!Array.isArray(flowSchema.event) || flowSchema.event.length === 0) {
28
+ throw new Error(
29
+ `FlowSchema validation error: Flow '${flowTag}' requires a non-empty 'event' array`
30
+ );
31
+ }
32
+
33
+ for (const [eIdx, eventName] of flowSchema.event.entries()) {
34
+ if (
35
+ typeof eventName !== 'string' ||
36
+ !VALID_EVENT_ENUM.includes(eventName)
37
+ ) {
38
+ throw new Error(
39
+ `FlowSchema validation error: Flow '${flowTag}' event[${eIdx}] '${eventName}' is invalid. Must be one of ${JSON.stringify(VALID_EVENT_ENUM)}`
40
+ );
41
+ }
42
+ }
43
+
44
+ if (
45
+ flowSchema.event.includes('generateCode') &&
46
+ flowSchema.event.length > 1
47
+ ) {
48
+ throw new Error(
49
+ `FlowSchema validation error: Flow '${flowTag}' with event 'generateCode' must be a standalone event and cannot co-exist with other events`
50
+ );
51
+ }
52
+
53
+ if (flowSchema.event.includes('s3')) {
54
+ if (
55
+ !flowSchema.bucketName ||
56
+ typeof flowSchema.bucketName !== 'string' ||
57
+ flowSchema.bucketName.trim() === ''
58
+ ) {
59
+ throw new Error(
60
+ `FlowSchema validation error: Flow '${flowTag}' with event 's3' requires 'bucketName' as a non-empty string`
61
+ );
62
+ }
63
+ }
64
+
6
65
  if (flowSchema.initiateBy !== undefined) {
7
66
  const validInitiateBy = [
8
67
  'user',
@@ -25,6 +84,110 @@ export function validateFlowSchema(flowSchema) {
25
84
  }
26
85
  }
27
86
 
87
+ if (flowSchema.statusType !== undefined) {
88
+ const validStatusType = [
89
+ 'none',
90
+ 'statusField',
91
+ 'storedCache',
92
+ 'triggerCache'
93
+ ];
94
+ if (!validStatusType.includes(flowSchema.statusType)) {
95
+ throw new Error(
96
+ `FlowSchema validation error: Flow '${flowTag}' statusType must be one of ${JSON.stringify(validStatusType)}, got '${flowSchema.statusType}'`
97
+ );
98
+ }
99
+
100
+ if (flowSchema.statusType !== 'none') {
101
+ if (!flowSchema.objType) {
102
+ throw new Error(
103
+ `FlowSchema validation error: Flow '${flowTag}' with statusType '${flowSchema.statusType}' requires 'objType'`
104
+ );
105
+ }
106
+
107
+ if (flowSchema.statusType === 'storedCache') {
108
+ const objTypeVal =
109
+ typeof flowSchema.objType === 'string'
110
+ ? flowSchema.objType
111
+ : flowSchema.objType?.objectType;
112
+ if (typeof objTypeVal !== 'string' || objTypeVal.trim() === '') {
113
+ throw new Error(
114
+ `FlowSchema validation error: Flow '${flowTag}' with statusType 'storedCache' requires 'objType' to be a non-empty string or object with string 'objectType'`
115
+ );
116
+ }
117
+ }
118
+
119
+ if (flowSchema.statusType === 'triggerCache') {
120
+ if (
121
+ !Array.isArray(flowSchema.triggerFlowTypes) ||
122
+ flowSchema.triggerFlowTypes.length === 0
123
+ ) {
124
+ throw new Error(
125
+ `FlowSchema validation error: Flow '${flowTag}' with statusType 'triggerCache' requires a non-empty 'triggerFlowTypes' array`
126
+ );
127
+ }
128
+ for (const [tIdx, item] of flowSchema.triggerFlowTypes.entries()) {
129
+ if (!item || (typeof item !== 'string' && typeof item !== 'object')) {
130
+ throw new Error(
131
+ `FlowSchema validation error: Flow '${flowTag}' triggerFlowTypes[${tIdx}] must be a non-empty string or object`
132
+ );
133
+ }
134
+ if (typeof item === 'string' && item.trim() === '') {
135
+ throw new Error(
136
+ `FlowSchema validation error: Flow '${flowTag}' triggerFlowTypes[${tIdx}] must not be an empty string`
137
+ );
138
+ }
139
+ }
140
+ }
141
+ }
142
+ }
143
+
144
+ if (
145
+ flowSchema.event.includes('generateCode') &&
146
+ !flowSchema.generatedCodeConfig
147
+ ) {
148
+ throw new Error(
149
+ `FlowSchema validation error: Flow '${flowTag}' with event 'generateCode' requires 'generatedCodeConfig'`
150
+ );
151
+ }
152
+
153
+ if (flowSchema.generatedCodeConfig) {
154
+ const config = flowSchema.generatedCodeConfig;
155
+ if (
156
+ config.invocationType !== undefined &&
157
+ !['ownTopic', 'lambdaSyncInv'].includes(config.invocationType)
158
+ ) {
159
+ throw new Error(
160
+ `FlowSchema validation error: Flow '${flowTag}' generatedCodeConfig.invocationType '${config.invocationType}' is invalid. Must be 'ownTopic' or 'lambdaSyncInv'`
161
+ );
162
+ }
163
+ const isOwnTopic = flowSchema.event.includes('ownTopic');
164
+ const isDsq = flowSchema.event.includes('dsq');
165
+ const isHook = Boolean(
166
+ config.generateCodeTag ||
167
+ config.invocationType ||
168
+ config.objType ||
169
+ flowSchema.event.includes('generateCode') ||
170
+ (!isOwnTopic && !isDsq)
171
+ );
172
+
173
+ const hookTag = config.codeHookTag;
174
+ if (hookTag === 'beforeLogical') {
175
+ throw new Error(
176
+ `FlowSchema validation error: Flow '${flowTag}' generatedCodeConfig.codeHookTag is no longer supported`
177
+ );
178
+ }
179
+ if (isHook && !hookTag) {
180
+ throw new Error(
181
+ `FlowSchema validation error: Flow '${flowTag}' generatedCodeConfig requires 'codeHookTag' ('before' | 'after'), got '${hookTag}'`
182
+ );
183
+ }
184
+ if (hookTag !== undefined && hookTag !== 'before' && hookTag !== 'after') {
185
+ throw new Error(
186
+ `FlowSchema validation error: Flow '${flowTag}' generatedCodeConfig.codeHookTag '${hookTag}' is invalid. Must be 'before' or 'after'`
187
+ );
188
+ }
189
+ }
190
+
28
191
  const steps = flowSchema.flowSteps;
29
192
  if (!Array.isArray(steps) || steps.length === 0) {
30
193
  throw new Error(
@@ -32,10 +195,7 @@ export function validateFlowSchema(flowSchema) {
32
195
  );
33
196
  }
34
197
 
35
- let flowEvents = [];
36
- if (Array.isArray(flowSchema.event)) {
37
- flowEvents = flowSchema.event;
38
- }
198
+ const flowEvents = flowSchema.event;
39
199
  const syncEvents = ['lambdaSyncInv', 'lambdaSyncApi'];
40
200
  let hasSyncEvent = false;
41
201
  for (const eventName of flowEvents) {
@@ -52,10 +212,6 @@ export function validateFlowSchema(flowSchema) {
52
212
  }
53
213
 
54
214
  if (hasSyncEvent && steps.length > 1) {
55
- let flowTag = 'unknown';
56
- if (flowSchema.flowTag) {
57
- flowTag = flowSchema.flowTag;
58
- }
59
215
  throw new Error(
60
216
  `FlowSchema validation error: Flow '${flowTag}' with synchronous ` +
61
217
  `events ('lambdaSyncInv' | 'lambdaSyncApi') must only define a ` +
@@ -110,6 +266,17 @@ export function validateFlowSchema(flowSchema) {
110
266
  );
111
267
  }
112
268
 
269
+ if (step.stepName.toLowerCase().includes('checktrigger')) {
270
+ if (
271
+ !Array.isArray(flowSchema.triggerFlowTypes) ||
272
+ flowSchema.triggerFlowTypes.length === 0
273
+ ) {
274
+ throw new Error(
275
+ `FlowSchema validation error: Flow '${flowTag}' defines step '${step.stepName}' but requires a non-empty 'triggerFlowTypes' array`
276
+ );
277
+ }
278
+ }
279
+
113
280
  if (Array.isArray(step.nextSteps) && step.nextSteps.length > 0) {
114
281
  for (let nIdx = 0; nIdx < step.nextSteps.length; nIdx++) {
115
282
  const item = step.nextSteps[nIdx];
@@ -128,9 +295,10 @@ export function validateFlowSchema(flowSchema) {
128
295
  );
129
296
  }
130
297
  if (item.targetType === 'ownTopic') {
298
+ const ownTopicTarget = item.stepName || item.topic;
131
299
  if (
132
- typeof item.stepName !== 'string' ||
133
- item.stepName.trim() === ''
300
+ typeof ownTopicTarget !== 'string' ||
301
+ ownTopicTarget.trim() === ''
134
302
  ) {
135
303
  throw new Error(
136
304
  `FlowSchema validation error: flowSteps[${idx}].nextSteps[${nIdx}] ownTopic target requires non-empty 'stepName'`
@@ -145,10 +313,8 @@ export function validateFlowSchema(flowSchema) {
145
313
  `FlowSchema validation error: flowSteps[${idx}].nextSteps[${nIdx}] extTopic target requires non-empty 'serviceTag'`
146
314
  );
147
315
  }
148
- if (
149
- typeof item.topicName !== 'string' ||
150
- item.topicName.trim() === ''
151
- ) {
316
+ const extTopicName = item.topicName || item.topic;
317
+ if (typeof extTopicName !== 'string' || extTopicName.trim() === '') {
152
318
  throw new Error(
153
319
  `FlowSchema validation error: flowSteps[${idx}].nextSteps[${nIdx}] extTopic target requires non-empty 'topicName'`
154
320
  );
@@ -203,10 +369,8 @@ export function validateFlowSchema(flowSchema) {
203
369
  `FlowSchema validation error: flowSteps[${idx}].previousSteps[${pIdx}] extTopic source requires non-empty 'serviceTag'`
204
370
  );
205
371
  }
206
- if (
207
- typeof item.topicName !== 'string' ||
208
- item.topicName.trim() === ''
209
- ) {
372
+ const extSourceName = item.topicName || item.topic;
373
+ if (typeof extSourceName !== 'string' || extSourceName.trim() === '') {
210
374
  throw new Error(
211
375
  `FlowSchema validation error: flowSteps[${idx}].previousSteps[${pIdx}] extTopic source requires non-empty 'topicName'`
212
376
  );
@@ -206,6 +206,118 @@ export async function loadLocalSchemaDirectory(
206
206
 
207
207
  if (directoryName === 'FlowSchemas') {
208
208
  for (const schema of loadedSchemas) {
209
+ if (!schema?._sourceFile) {
210
+ schema._sourceFile = entry.name;
211
+ }
212
+ if (
213
+ !schema?.flowTag ||
214
+ typeof schema.flowTag !== 'string' ||
215
+ schema.flowTag.trim() === ''
216
+ ) {
217
+ throw new Error(
218
+ `FlowSchema validation error in ${entry.name}: flowTag is required and must be a non-empty string`
219
+ );
220
+ }
221
+ const flowTag = schema.flowTag;
222
+
223
+ if (!Array.isArray(schema.event) || schema.event.length === 0) {
224
+ throw new Error(
225
+ `FlowSchema validation error in ${entry.name}: Flow '${flowTag}' requires a non-empty 'event' array`
226
+ );
227
+ }
228
+
229
+ for (const [eIdx, eventName] of schema.event.entries()) {
230
+ if (
231
+ typeof eventName !== 'string' ||
232
+ !VALID_EVENT_ENUM.includes(eventName)
233
+ ) {
234
+ throw new Error(
235
+ `FlowSchema validation error in ${entry.name}: Flow '${flowTag}' event[${eIdx}] '${eventName}' is invalid. ` +
236
+ `Must be one of ${JSON.stringify(VALID_EVENT_ENUM)}`
237
+ );
238
+ }
239
+ }
240
+
241
+ if (
242
+ schema.event.includes('generateCode') &&
243
+ schema.event.length > 1
244
+ ) {
245
+ throw new Error(
246
+ `FlowSchema validation error in ${entry.name}: Flow '${flowTag}' with event 'generateCode' must be a standalone event and cannot co-exist with other events`
247
+ );
248
+ }
249
+
250
+ if (schema?.statusType !== undefined && schema?.statusType !== 'none') {
251
+ const validStatusTypes = [
252
+ 'statusField',
253
+ 'storedCache',
254
+ 'triggerCache',
255
+ 'none'
256
+ ];
257
+ if (!validStatusTypes.includes(schema.statusType)) {
258
+ throw new Error(
259
+ `FlowSchema validation error in ${entry.name}: Flow '${flowTag}' statusType must be one of ${JSON.stringify(validStatusTypes)}, got '${schema.statusType}'`
260
+ );
261
+ }
262
+ if (!schema.objType) {
263
+ throw new Error(
264
+ `FlowSchema validation error in ${entry.name}: Flow '${flowTag}' with statusType '${schema.statusType}' requires 'objType'`
265
+ );
266
+ }
267
+ if (schema.statusType === 'storedCache') {
268
+ const objTypeVal =
269
+ typeof schema.objType === 'string'
270
+ ? schema.objType
271
+ : schema.objType?.objectType;
272
+ if (typeof objTypeVal !== 'string' || objTypeVal.trim() === '') {
273
+ throw new Error(
274
+ `FlowSchema validation error in ${entry.name}: Flow '${flowTag}' with statusType 'storedCache' requires 'objType' to be a non-empty string or object with string 'objectType'`
275
+ );
276
+ }
277
+ }
278
+ if (schema.statusType === 'triggerCache') {
279
+ if (
280
+ !Array.isArray(schema.triggerFlowTypes) ||
281
+ schema.triggerFlowTypes.length === 0
282
+ ) {
283
+ throw new Error(
284
+ `FlowSchema validation error in ${entry.name}: Flow '${flowTag}' with statusType 'triggerCache' requires a non-empty 'triggerFlowTypes' array`
285
+ );
286
+ }
287
+ for (const [tIdx, item] of schema.triggerFlowTypes.entries()) {
288
+ if (
289
+ !item ||
290
+ (typeof item !== 'string' && typeof item !== 'object')
291
+ ) {
292
+ throw new Error(
293
+ `FlowSchema validation error in ${entry.name}: Flow '${flowTag}' triggerFlowTypes[${tIdx}] must be a non-empty string or object`
294
+ );
295
+ }
296
+ if (typeof item === 'string' && item.trim() === '') {
297
+ throw new Error(
298
+ `FlowSchema validation error in ${entry.name}: Flow '${flowTag}' triggerFlowTypes[${tIdx}] must not be an empty string`
299
+ );
300
+ }
301
+ }
302
+ }
303
+ }
304
+ if (Array.isArray(schema?.flowSteps)) {
305
+ for (const step of schema.flowSteps) {
306
+ if (
307
+ typeof step?.stepName === 'string' &&
308
+ step.stepName.toLowerCase().includes('checktrigger')
309
+ ) {
310
+ if (
311
+ !Array.isArray(schema.triggerFlowTypes) ||
312
+ schema.triggerFlowTypes.length === 0
313
+ ) {
314
+ throw new Error(
315
+ `FlowSchema validation error in ${entry.name}: Flow '${flowTag}' defines step '${step.stepName}' but requires a non-empty 'triggerFlowTypes' array`
316
+ );
317
+ }
318
+ }
319
+ }
320
+ }
209
321
  if (
210
322
  Array.isArray(schema?.event) &&
211
323
  schema.event.includes('generateCode') &&
@@ -234,19 +346,37 @@ export async function loadLocalSchemaDirectory(
234
346
  );
235
347
  }
236
348
  }
237
- if (
238
- Object.prototype.hasOwnProperty.call(
239
- schema?.generatedCodeConfig ?? {},
240
- 'codeHookTag'
241
- )
242
- ) {
243
- const hookTag = schema.generatedCodeConfig.codeHookTag;
349
+ if (schema?.generatedCodeConfig) {
350
+ const config = schema.generatedCodeConfig;
351
+ const isOwnTopic =
352
+ Array.isArray(schema.event) && schema.event.includes('ownTopic');
353
+ const isDsq =
354
+ Array.isArray(schema.event) && schema.event.includes('dsq');
355
+ const isHook = Boolean(
356
+ config.generateCodeTag ||
357
+ config.invocationType ||
358
+ config.objType ||
359
+ (Array.isArray(schema.event) &&
360
+ schema.event.includes('generateCode')) ||
361
+ (!isOwnTopic && !isDsq)
362
+ );
363
+
364
+ const hookTag = config.codeHookTag;
244
365
  if (hookTag === 'beforeLogical') {
245
366
  throw new Error(
246
367
  `Unsupported FlowHook configuration in ${entry.name}: generatedCodeConfig.codeHookTag is no longer supported`
247
368
  );
248
369
  }
249
- if (hookTag !== 'before' && hookTag !== 'after') {
370
+ if (isHook && !hookTag) {
371
+ throw new Error(
372
+ `Unsupported FlowHook configuration in ${entry.name}: Flow '${flowTag}' with generatedCodeConfig requires 'codeHookTag' ('before' or 'after')`
373
+ );
374
+ }
375
+ if (
376
+ hookTag !== undefined &&
377
+ hookTag !== 'before' &&
378
+ hookTag !== 'after'
379
+ ) {
250
380
  throw new Error(
251
381
  `Unsupported FlowHook configuration in ${entry.name}: generatedCodeConfig.codeHookTag '${hookTag}' is invalid. Must be 'before' or 'after'`
252
382
  );
@@ -718,6 +848,11 @@ function _isTestEnvironment() {
718
848
  process.env.NODE_ENV === 'test' ||
719
849
  process.env.npm_lifecycle_event === 'test' ||
720
850
  Boolean(process.execArgv?.includes('--test')) ||
721
- Boolean(process.argv?.includes('--test'))
851
+ Boolean(process.argv?.includes('--test')) ||
852
+ Boolean(
853
+ process.argv?.some(
854
+ (arg) => arg.includes('.test.') || arg.includes('test/')
855
+ )
856
+ )
722
857
  );
723
858
  }
@@ -1,7 +1,7 @@
1
1
  import ejsLib from 'ejs';
2
2
  import { readFile } from 'node:fs/promises';
3
3
 
4
- import { customFlowNextSteps, flowHasRbac, upperFirst } from '../custom/customFlows.js';
4
+ import { customFlowNextSteps } from '../custom/customFlows.js';
5
5
  import { createCrudActionPlans } from '../crud/crudActionPlan.js';
6
6
 
7
7
  const TEMPLATE_URL = new URL('./templates/', import.meta.url);
@@ -217,29 +217,6 @@ export async function emitCoreFunctionArtifacts({ project, objects = [], relatio
217
217
  (objects || []).filter(o => o.belongTo?.serviceTag && o.belongTo.serviceTag !== 'Rbac').map(o => o.belongTo.serviceTag)
218
218
  )).sort();
219
219
 
220
- const customRbacFlows = (flows || []).filter((f) => flowHasRbac(f, objects));
221
- const customRbacFlowTags = customRbacFlows.map((f) => f.flowTag);
222
- const customRbacFlowsWithTags = customRbacFlows.map((f) => {
223
- const roleName = upperFirst(f.flowTag);
224
- const matched = objects.find((o) => o.objectType === f.objType?.objectType);
225
- const targetServiceTags = [];
226
- const belongTo = matched?.belongTo;
227
- if (belongTo) {
228
- if (Array.isArray(belongTo)) {
229
- for (const b of belongTo) {
230
- if (b?.serviceTag) targetServiceTags.push(b.serviceTag);
231
- }
232
- } else if (belongTo.serviceTag) {
233
- targetServiceTags.push(belongTo.serviceTag);
234
- }
235
- }
236
- return {
237
- roleName,
238
- flowTag: f.flowTag,
239
- targetServiceTags: Array.from(new Set(targetServiceTags))
240
- };
241
- });
242
-
243
220
  const crudPlans = createCrudActionPlans(objects);
244
221
  const hasQuotaReservation = crudPlans?.Create?.hasQuotaReservation ?? false;
245
222
 
@@ -250,8 +227,6 @@ export async function emitCoreFunctionArtifacts({ project, objects = [], relatio
250
227
  relationships,
251
228
  flows,
252
229
  customFlowNextSteps: customFlowNextSteps(flows),
253
- customRbacFlowTags,
254
- customRbacFlowsWithTags,
255
230
  objectGraphServiceTags,
256
231
  relationshipGraphServiceTags,
257
232
  crud,
@@ -160,7 +160,7 @@ const tableConfigs = {
160
160
  (flow?.flowSteps || []).forEach(function(step) {
161
161
  if (Array.isArray(step?.previousSteps)) {
162
162
  const stepName = step?.stepName ? step.stepName[0].toUpperCase() + step.stepName.slice(1) : '';
163
- const functionName = stepName.startsWith(flowTag) ? stepName : `${flowTag}${stepName}`;
163
+ const functionName = `${flowTag}${stepName}`;
164
164
  const queueName = `${functionName}HdrSqs`;
165
165
  step.previousSteps.forEach(function(prev) {
166
166
  if (prev && prev.sourceType === 'extTopic' && prev.serviceTag && prev.topicName) {
@@ -178,23 +178,6 @@ const tableConfigs = {
178
178
  }
179
179
  });
180
180
  });
181
-
182
- const currentServiceTag = (typeof serviceTag !== 'undefined' && serviceTag) ? serviceTag : ((typeof project !== 'undefined' && project?.serviceTag) ? project.serviceTag : '');
183
- const rbacSubs = [];
184
-
185
- if (typeof customRbacFlowTags !== 'undefined' && customRbacFlowTags && customRbacFlowTags.length > 0) {
186
- const allRbacTags = Array.from(new Set([
187
- 'Rbac',
188
- currentServiceTag,
189
- ...(typeof rbacValidatorServiceTags !== 'undefined' ? rbacValidatorServiceTags : [])
190
- ])).filter(Boolean);
191
- customRbacFlowTags.forEach(function(flowTag) {
192
- const tagUpper = flowTag[0].toUpperCase() + flowTag.slice(1);
193
- allRbacTags.forEach(function(tag) {
194
- rbacSubs.push({ serviceTag: tag, topicName: 'ValidatorRbac_Out', sqsEndpoint: `${tagUpper}RbacCallbackHdrSqs` });
195
- });
196
- });
197
- }
198
181
  -%>
199
182
  const snsTopicSubscriptions = [
200
183
  <% if (relSubs.length > 0) { -%>
@@ -247,19 +230,6 @@ const snsTopicSubscriptions = [
247
230
  sqsEndpoint: '<%= sub.sqsEndpoint %>'
248
231
  },
249
232
  <% }); -%>
250
- <% } -%>
251
- <% if (rbacSubs.length > 0) { -%>
252
-
253
- // ------------------------------------------------------------
254
- // RBAC Validator Subscriptions
255
- // ------------------------------------------------------------
256
- <% rbacSubs.forEach(function(sub, idx) { -%>
257
- {
258
- serviceTag: '<%= sub.serviceTag %>',
259
- topicName: '<%= sub.topicName %>',
260
- sqsEndpoint: '<%= sub.sqsEndpoint %>'
261
- },
262
- <% }); -%>
263
233
  <% } -%>
264
234
 
265
235
  //(<additionalSubscription>)
@@ -4,8 +4,7 @@ import {
4
4
  generatedDsqFlows,
5
5
  generatedOwnTopicFlows,
6
6
  supportedCustomFlows,
7
- upperFirst,
8
- flowHasRbac
7
+ upperFirst
9
8
  } from './customFlows.js';
10
9
 
11
10
  export const YAML_PATH = 'app/sls_yaml/generatedCode/source/flow-schema.yml';
@@ -35,12 +34,6 @@ export function ownTopicRootPaths(flow, objects = []) {
35
34
  `${source}/${tag}_WbsMain.js`,
36
35
  `${source}/${tag}_HdrWbs.js`
37
36
  ];
38
- if (flowHasRbac(flow, objects)) {
39
- paths.push(
40
- `${source}/${tag}RbacCallback_Main.js`,
41
- `${source}/${tag}RbacCallback_HdrSqs.js`
42
- );
43
- }
44
37
  return paths;
45
38
  }
46
39
 
@@ -52,12 +45,6 @@ export function flowPaths(flow, objects = []) {
52
45
  if (needsProcessMain(flow)) {
53
46
  paths.push(`${source}/${process}_Main.js`);
54
47
  }
55
- if (flowHasRbac(flow, objects)) {
56
- paths.push(
57
- `${source}/${tag}RbacCallback_Main.js`,
58
- `${source}/${tag}RbacCallback_HdrSqs.js`
59
- );
60
- }
61
48
  if (flow.event.includes('extTopic') && !flow.event.includes('ownTopic')) {
62
49
  paths.push(`${source}/${process}_HdrSqs.js`);
63
50
  }
@@ -116,7 +103,7 @@ export function customFlowApplicationManagedPaths(
116
103
  const extSteps = flowExtTopicSteps(flows);
117
104
  const dsqSteps = flowDsqSteps(flows);
118
105
 
119
- return [
106
+ return Array.from(new Set([
120
107
  ...customFlowList.flatMap((flow) => flowPaths(flow, objects)),
121
108
  ...generatedRoots.flatMap((flow) => ownTopicRootPaths(flow, objects)),
122
109
  ...extSteps.flatMap(({ flowTag, stepName }) => {
@@ -145,5 +132,5 @@ export function customFlowApplicationManagedPaths(
145
132
  dsqSteps.length > 0
146
133
  ? [YAML_PATH]
147
134
  : [])
148
- ];
135
+ ]));
149
136
  }
@@ -88,13 +88,18 @@ export async function emitS3Flow(flow, source, handlerRoot) {
88
88
  filterPatternFunctionName
89
89
  });
90
90
  } else if (type === 's3') {
91
- let bucketName = '';
92
- if (flow.bucketName) {
93
- bucketName = flow.bucketName;
91
+ if (
92
+ !flow.bucketName ||
93
+ typeof flow.bucketName !== 'string' ||
94
+ flow.bucketName.trim() === ''
95
+ ) {
96
+ throw new Error(
97
+ `FlowSchema validation error: Flow '${flow.flowTag}' with event 's3' requires 'bucketName' as a non-empty string`
98
+ );
94
99
  }
95
100
  functionYaml = renderS3FunctionYaml({
96
101
  ...descriptor,
97
- bucketName,
102
+ bucketName: flow.bucketName,
98
103
  flowTag: flow.flowTag,
99
104
  flowStepName: ''
100
105
  });