@izara_project/izara-core-generate-service-code 1.0.99 → 1.0.101

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 (51) hide show
  1. package/package.json +1 -1
  2. package/src/compile/compileProject.js +16 -5
  3. package/src/compile/flowValidator.js +3 -1
  4. package/src/compile/loadSchemas.js +18 -4
  5. package/src/compile/schemaValidatorSetup.js +16 -0
  6. package/src/emit/application/coreFunction/emitCoreFunctionArtifacts.js +108 -108
  7. package/src/emit/application/coreFunction/templates/InitialSetupRunner.ejs +2 -2
  8. package/src/emit/application/crud/templates/CreateComplete_Main.ejs +2 -0
  9. package/src/emit/application/crud/templates/CreateLogicalLib.ejs +20 -7
  10. package/src/emit/application/crud/templates/DeleteComplete_Main.ejs +2 -0
  11. package/src/emit/application/crud/templates/FlowEndpoint_HdrWbs.ejs +7 -5
  12. package/src/emit/application/crud/templates/UpdateComplete_Main.ejs +2 -0
  13. package/src/emit/application/custom/customFlowPaths.js +13 -16
  14. package/src/emit/application/custom/customFlowS3.js +456 -63
  15. package/src/emit/application/custom/customFlows.js +131 -0
  16. package/src/emit/application/custom/emitCustomFlowApplicationArtifacts.js +7 -4
  17. package/src/emit/application/custom/templates/s3/ConfirmAfterUpload_HdrSqs.ejs +111 -0
  18. package/src/emit/application/custom/templates/s3/ConfirmAfterUpload_Main.ejs +89 -0
  19. package/src/emit/application/custom/templates/s3/ConfirmComplete_HdrSqs.ejs +111 -0
  20. package/src/emit/application/custom/templates/s3/ConfirmComplete_Main.ejs +100 -0
  21. package/src/emit/application/custom/templates/s3/CreateObject_HdrWbs.ejs +2 -1
  22. package/src/emit/application/custom/templates/s3/CreateObject_Main.ejs +4 -0
  23. package/src/emit/application/custom/templates/s3/CreatePreSignUrl_HdrSqs.ejs +42 -0
  24. package/src/emit/application/custom/templates/s3/CreatePreSignUrl_Main.ejs +23 -0
  25. package/src/emit/application/custom/templates/s3/ProcessS3File_Main.ejs +240 -27
  26. package/src/emit/application/custom/templates/s3/Start_Main.ejs +216 -0
  27. package/src/emit/application/rbac/emitDynamicRbacFlowSchemas.js +5 -1
  28. package/src/emit/application/rbac/emitRbacApplicationArtifacts.js +67 -60
  29. package/src/emit/application/rbac/templates/ReservedDynamicUsage_Main.ejs +27 -9
  30. package/src/emit/application/rbac/templates/UserRbacFlow_Main.ejs +4 -3
  31. package/src/emit/application/system/templates/Register_HdrWbs.ejs +2 -1
  32. package/src/emit/infrastructure/functions/functionYamlArtifact.js +3 -8
  33. package/src/emit/infrastructure/functions/templates/S3Function_Yaml.ejs +2 -3
  34. package/src/emit/infrastructure/resources/iamResourceArtifacts.js +22 -0
  35. package/src/emit/infrastructure/resources/resourceState.js +15 -5
  36. package/src/emit/infrastructure/resources/s3ResourceArtifacts.js +19 -3
  37. package/src/emit/infrastructure/resources/templates/S3Bucket_Yaml.ejs +1 -1
  38. package/src/emit/infrastructure/resources/templates/SystemDynamoDB_Yaml.ejs +2 -2
  39. package/src/emit/schemas/error/emitErrorSchemas.js +120 -10
  40. package/src/emit/schemas/error/templates/errorConsts.ejs +12 -0
  41. package/src/generate.js +32 -30
  42. package/src/plan/domainRegistry.js +2 -1
  43. package/test/integration/publicApi.test.js +33 -24
  44. package/test/unit/application/createTargetRoleHandler.test.js +33 -10
  45. package/test/unit/application/customFlowApplicationArtifacts.test.js +6 -6
  46. package/test/unit/application/customFlowS3.test.js +858 -0
  47. package/test/unit/infrastructure/functionYamlArtifact.test.js +6 -4
  48. package/test/unit/infrastructure/resourceArtifacts.test.js +51 -0
  49. package/test/unit/schemas/dynamicRbacFlowSchemas.test.js +8 -6
  50. package/test/unit/schemas/dynamicRelationshipFlowSchemas.test.js +51 -0
  51. package/test/unit/schemas/errorSchemas.test.js +84 -5
@@ -1,5 +1,10 @@
1
1
  import { renderCustom } from './customFlowTemplates.js';
2
- import { customFlowRoleName, upperFirst } from './customFlows.js';
2
+ import {
3
+ customFlowRoleName,
4
+ upperFirst,
5
+ resolveS3Parts,
6
+ flowHasRbac
7
+ } from './customFlows.js';
3
8
  import {
4
9
  renderInvFunctionYaml,
5
10
  renderS3FunctionYaml,
@@ -7,63 +12,82 @@ import {
7
12
  renderWbsFunctionYaml
8
13
  } from '../../infrastructure/functions/functionYamlArtifact.js';
9
14
 
10
- export async function emitS3Flow(flow, source, handlerRoot) {
15
+ export function isSimplifiedS3Flow(flow) {
16
+ if (!Array.isArray(flow?.flowSteps) || flow.flowSteps.length === 0) {
17
+ return false;
18
+ }
19
+ const stepNames = flow.flowSteps.map((s) => s.stepName);
20
+ if (stepNames.includes('ReservedLimit')) {
21
+ return false;
22
+ }
23
+ return true;
24
+ }
25
+
26
+ export async function emitS3Flow(
27
+ flow,
28
+ source,
29
+ handlerRoot,
30
+ { objects = [], relationships = [] } = {}
31
+ ) {
11
32
  const tag = upperFirst(flow.flowTag);
12
33
  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
- ];
34
+ const parts = resolveS3Parts(flow);
35
+ const isSimplifiedS3 = isSimplifiedS3Flow(flow);
50
36
 
51
37
  const emitted = await Promise.all(
52
38
  parts.map(
53
- async ({ action, handler, type, mainTemplate, handlerTemplate }) => {
54
- const functionName = `${tag}${action}`;
55
- const mainFileName = `${functionName}_Main`;
56
- const handlerFileName = `${functionName}_${handler}`;
39
+ async (
40
+ { action, handler, type, mainTemplate, handlerTemplate },
41
+ index
42
+ ) => {
43
+ let isStart = false;
44
+ if (typeof action === 'string' && action.toLowerCase() === 'start') {
45
+ isStart = true;
46
+ }
47
+ let functionName = `${tag}${action}`;
48
+ let mainFileName = `${functionName}_Main`;
49
+ let handlerFileName = `${functionName}_${handler}`;
50
+ let slsFunctionName = `${functionName}${handler}`;
51
+ let flowStepName = action;
52
+ if (isStart) {
53
+ functionName = tag;
54
+ mainFileName = `${tag}_Main`;
55
+ handlerFileName = `${tag}_${handler}`;
56
+ slsFunctionName = `${tag}${handler}`;
57
+ flowStepName = '';
58
+ }
59
+
60
+ const nextPart = parts.find((p, i) => i > index && p.type === 'sqs');
61
+ let nextStepFunctionName = null;
62
+ if (nextPart) {
63
+ nextStepFunctionName = `${tag}${nextPart.action}${nextPart.handler}`;
64
+ }
65
+
57
66
  const mainContent = await renderCustom(
58
67
  `s3/${mainTemplate}`,
59
- _s3TemplateData({ action, flow, functionName })
68
+ _s3TemplateData({
69
+ action,
70
+ flow,
71
+ functionName,
72
+ nextStepFunctionName,
73
+ isSimplifiedS3,
74
+ objects,
75
+ relationships
76
+ })
60
77
  );
61
78
  const handlerContent = await renderCustom(
62
79
  `s3/${handlerTemplate}`,
63
- _s3HandlerData({ action, flow, functionName, mainFileName, handler })
80
+ _s3HandlerData({
81
+ action,
82
+ flow,
83
+ functionName,
84
+ mainFileName,
85
+ handler,
86
+ isSimplifiedS3
87
+ })
64
88
  );
65
89
  const descriptor = {
66
- functionName: `${functionName}${handler}`,
90
+ functionName: slsFunctionName,
67
91
  handlerPath: `${handlerRoot}/${handlerFileName}.main`,
68
92
  roleName
69
93
  };
@@ -73,11 +97,11 @@ export async function emitS3Flow(flow, source, handlerRoot) {
73
97
  ...descriptor,
74
98
  routeName: tag,
75
99
  flowTag: flow.flowTag,
76
- flowStepName: action
100
+ flowStepName
77
101
  });
78
102
  } else if (type === 'sqs') {
79
103
  let filterPatternFunctionName = descriptor.functionName;
80
- if (action === 'CreatePreSignUrl') {
104
+ if (!isSimplifiedS3 && action === 'CreatePreSignUrl') {
81
105
  filterPatternFunctionName = 'CreatePresignUrlHdrSqs';
82
106
  }
83
107
  functionYaml = renderSqsFunctionYaml({
@@ -100,6 +124,7 @@ export async function emitS3Flow(flow, source, handlerRoot) {
100
124
  functionYaml = renderS3FunctionYaml({
101
125
  ...descriptor,
102
126
  bucketName: flow.bucketName,
127
+ s3KeyPrefix: flow.s3KeyPrefix,
103
128
  flowTag: flow.flowTag,
104
129
  flowStepName: action
105
130
  });
@@ -127,23 +152,390 @@ export async function emitS3Flow(flow, source, handlerRoot) {
127
152
  };
128
153
  }
129
154
 
130
- function _s3TemplateData({ action, flow, functionName }) {
131
- if (action === 'CreateObject') {
132
- return {
133
- flowTag: flow.flowTag,
134
- objectType: flow.objType?.objectType,
135
- functionName
136
- };
155
+ export function extractIdentifierFieldNames(identifiers) {
156
+ if (!Array.isArray(identifiers) || identifiers.length === 0) {
157
+ return [];
158
+ }
159
+ const keys = [];
160
+ for (const item of identifiers) {
161
+ if (typeof item === 'string') {
162
+ if (item && !keys.includes(item)) {
163
+ keys.push(item);
164
+ }
165
+ } else if (item && typeof item === 'object') {
166
+ if (Array.isArray(item.fieldNames) && item.fieldNames.length > 0) {
167
+ for (const fn of item.fieldNames) {
168
+ if (typeof fn === 'string' && fn && !keys.includes(fn)) {
169
+ keys.push(fn);
170
+ }
171
+ }
172
+ } else if (typeof item.fieldName === 'string' && item.fieldName) {
173
+ if (!keys.includes(item.fieldName)) {
174
+ keys.push(item.fieldName);
175
+ }
176
+ } else if (typeof item.name === 'string' && item.name) {
177
+ if (!keys.includes(item.name)) {
178
+ keys.push(item.name);
179
+ }
180
+ }
181
+ }
182
+ }
183
+ return keys;
184
+ }
185
+
186
+ export function resolveParentIdentifierInfo(flow, objects = []) {
187
+ let parentObjectType = null;
188
+ let parentServiceTag = null;
189
+ const targetObjType =
190
+ typeof flow.objType === 'string'
191
+ ? flow.objType
192
+ : flow.objType?.objectType || flow.objectType;
193
+ const matchedObject = (objects || []).find(
194
+ (o) => o.objectType === targetObjType
195
+ );
196
+
197
+ if (flow.parentObjectType) {
198
+ parentObjectType = flow.parentObjectType;
199
+ } else if (flow.belongTo?.objectType) {
200
+ parentObjectType = flow.belongTo.objectType;
201
+ parentServiceTag = flow.belongTo.serviceTag;
202
+ } else if (Array.isArray(flow.belongTo) && flow.belongTo[0]?.objectType) {
203
+ parentObjectType = flow.belongTo[0].objectType;
204
+ parentServiceTag = flow.belongTo[0].serviceTag;
205
+ }
206
+
207
+ if (!parentObjectType && matchedObject?.belongTo) {
208
+ const belongTo = matchedObject.belongTo;
209
+ if (Array.isArray(belongTo) && belongTo[0]?.objectType) {
210
+ parentObjectType = belongTo[0].objectType;
211
+ parentServiceTag = belongTo[0].serviceTag;
212
+ } else if (belongTo.objectType) {
213
+ parentObjectType = belongTo.objectType;
214
+ parentServiceTag = belongTo.serviceTag;
215
+ }
216
+ }
217
+
218
+ const belongToDef = flow.belongTo || matchedObject?.belongTo;
219
+ const singleBelongTo = Array.isArray(belongToDef) ? belongToDef[0] : belongToDef;
220
+
221
+ let parentIdKeys = [];
222
+ if (Array.isArray(flow.parentIdentifierKeys) && flow.parentIdentifierKeys.length > 0) {
223
+ parentIdKeys = [...flow.parentIdentifierKeys];
224
+ } else if (flow.parentIdentifierKey) {
225
+ parentIdKeys = [flow.parentIdentifierKey];
226
+ } else if (
227
+ Array.isArray(singleBelongTo?.parentIdentifierKeys) &&
228
+ singleBelongTo.parentIdentifierKeys.length > 0
229
+ ) {
230
+ parentIdKeys = [...singleBelongTo.parentIdentifierKeys];
231
+ } else if (
232
+ Array.isArray(singleBelongTo?.identifiers) &&
233
+ singleBelongTo.identifiers.length > 0
234
+ ) {
235
+ parentIdKeys = extractIdentifierFieldNames(singleBelongTo.identifiers);
236
+ } else {
237
+ const parentObj =
238
+ Array.isArray(objects) && parentObjectType
239
+ ? objects.find((o) => o.objectType === parentObjectType)
240
+ : null;
241
+ const parentIdentifiers =
242
+ parentObj?.identifiers || matchedObject?.belongToSchema?.identifiers;
243
+ if (Array.isArray(parentIdentifiers) && parentIdentifiers.length > 0) {
244
+ parentIdKeys = extractIdentifierFieldNames(parentIdentifiers);
245
+ }
246
+ if (parentIdKeys.length === 0 && parentObjectType) {
247
+ parentIdKeys = [`${parentObjectType}Id`];
248
+ }
249
+ }
250
+
251
+ let parentIdKey = null;
252
+ if (parentIdKeys.length > 0) {
253
+ parentIdKey = parentIdKeys[0];
254
+ }
255
+
256
+ return {
257
+ parentObjectType,
258
+ parentServiceTag,
259
+ parentIdKey,
260
+ parentIdKeys
261
+ };
262
+ }
263
+
264
+ export function resolveFlowRelationships(
265
+ flow,
266
+ { objects = [], relationships = [] } = {}
267
+ ) {
268
+ if (Array.isArray(flow.relationships) && flow.relationships.length > 0) {
269
+ const list = [];
270
+ for (const rel of flow.relationships) {
271
+ let targetObj = {
272
+ objectType: '',
273
+ serviceTag: ''
274
+ };
275
+ if (rel.targetObjType) {
276
+ targetObj = {
277
+ objectType: rel.targetObjType.objectType || '',
278
+ serviceTag: rel.targetObjType.serviceTag || ''
279
+ };
280
+ } else if (rel.objectType) {
281
+ targetObj = {
282
+ objectType: rel.objectType,
283
+ serviceTag: rel.serviceTag || ''
284
+ };
285
+ }
286
+
287
+ let relType = {
288
+ relationshipTag: '',
289
+ serviceTag: targetObj.serviceTag
290
+ };
291
+ if (rel.relType) {
292
+ relType = {
293
+ relationshipTag: rel.relType.relationshipTag || '',
294
+ serviceTag: rel.relType.serviceTag || targetObj.serviceTag
295
+ };
296
+ } else if (rel.relationshipTag) {
297
+ relType = {
298
+ relationshipTag: rel.relationshipTag,
299
+ serviceTag: rel.serviceTag || targetObj.serviceTag
300
+ };
301
+ }
302
+
303
+ let targetIdentifierKey = '';
304
+ if (rel.targetIdentifierKey) {
305
+ targetIdentifierKey = rel.targetIdentifierKey;
306
+ } else if (rel.targetIdentifiers) {
307
+ const idKeys = Object.keys(rel.targetIdentifiers);
308
+ if (idKeys.length > 0) {
309
+ targetIdentifierKey = idKeys[0];
310
+ }
311
+ }
312
+ if (!targetIdentifierKey && targetObj.objectType) {
313
+ targetIdentifierKey = `${targetObj.objectType}Id`;
314
+ }
315
+
316
+ let direction = 'to';
317
+ if (rel.relationshipDirection) {
318
+ direction = rel.relationshipDirection;
319
+ }
320
+
321
+ list.push({
322
+ targetObjType: targetObj,
323
+ relType,
324
+ targetIdentifierKey,
325
+ relationshipProperties: rel.relationshipProperties || {},
326
+ relationshipDirection: direction
327
+ });
328
+ }
329
+ return list;
137
330
  }
138
- if (action === 'CreatePreSignUrl') {
139
- return { flowTag: flow.flowTag };
331
+
332
+ let targetObjType = '';
333
+ if (typeof flow.objType === 'string') {
334
+ targetObjType = flow.objType;
335
+ } else if (flow.objType?.objectType) {
336
+ targetObjType = flow.objType.objectType;
337
+ } else if (flow.objectType) {
338
+ targetObjType = flow.objectType;
339
+ }
340
+
341
+ if (
342
+ !targetObjType ||
343
+ !Array.isArray(relationships) ||
344
+ relationships.length === 0
345
+ ) {
346
+ return [];
140
347
  }
141
- return { flowTag: flow.flowTag, functionName };
348
+
349
+ const resolved = [];
350
+ for (const relItem of relationships) {
351
+ if (!relItem || typeof relItem !== 'object') {
352
+ continue;
353
+ }
354
+
355
+ if (
356
+ relItem.objectType &&
357
+ relItem.objectType.toLowerCase() === targetObjType.toLowerCase() &&
358
+ relItem.relationshipTag &&
359
+ relItem.relationshipServiceTag
360
+ ) {
361
+ const parentService = relItem.relationshipServiceTag;
362
+ let parentObjType = '';
363
+ if (relItem.targetObjectType) {
364
+ parentObjType = relItem.targetObjectType;
365
+ } else if (parentService.length > 0) {
366
+ parentObjType =
367
+ parentService[0].toLowerCase() + parentService.slice(1);
368
+ }
369
+ let targetIdentifierKey = `${parentObjType}Id`;
370
+ if (relItem.targetIdentifierKey) {
371
+ targetIdentifierKey = relItem.targetIdentifierKey;
372
+ }
373
+ let direction = 'to';
374
+ if (relItem.relationshipDirection) {
375
+ direction = relItem.relationshipDirection;
376
+ }
377
+ resolved.push({
378
+ targetObjType: {
379
+ objectType: parentObjType,
380
+ serviceTag: parentService
381
+ },
382
+ relType: {
383
+ relationshipTag: relItem.relationshipTag,
384
+ serviceTag: parentService
385
+ },
386
+ targetIdentifierKey,
387
+ relationshipProperties: {},
388
+ relationshipDirection: direction
389
+ });
390
+ continue;
391
+ }
392
+
393
+ const relKeys = Object.keys(relItem);
394
+ for (const relTag of relKeys) {
395
+ const relDef = relItem[relTag];
396
+ if (!relDef || !Array.isArray(relDef.links)) {
397
+ continue;
398
+ }
399
+ for (const link of relDef.links) {
400
+ if (!link || !link.from || !link.to) {
401
+ continue;
402
+ }
403
+
404
+ const isToTarget =
405
+ link.to.objType?.objectType?.toLowerCase() ===
406
+ targetObjType.toLowerCase();
407
+ if (isToTarget && link.to.requiredOnCreate) {
408
+ const fromObj = link.from.objType || {};
409
+ const fromObjType = fromObj.objectType || '';
410
+ const targetIdentifierKey = `${fromObjType}Id`;
411
+ resolved.push({
412
+ targetObjType: {
413
+ objectType: fromObjType,
414
+ serviceTag: fromObj.serviceTag || ''
415
+ },
416
+ relType: {
417
+ relationshipTag: relTag,
418
+ serviceTag: fromObj.serviceTag || ''
419
+ },
420
+ targetIdentifierKey,
421
+ relationshipProperties: {},
422
+ relationshipDirection: 'to'
423
+ });
424
+ }
425
+ }
426
+ }
427
+ }
428
+
429
+ return resolved;
430
+ }
431
+
432
+ function _s3TemplateData({
433
+ action,
434
+ flow,
435
+ functionName,
436
+ nextStepFunctionName,
437
+ isSimplifiedS3,
438
+ objects = [],
439
+ relationships = []
440
+ }) {
441
+ let maxFileSizeMb = 50;
442
+ if (flow.maxFileSizeMb) {
443
+ maxFileSizeMb = flow.maxFileSizeMb;
444
+ }
445
+ let expires = 86400;
446
+ if (flow.expires) {
447
+ expires = flow.expires;
448
+ }
449
+ let contentTypePrefix = 'video/';
450
+ if (flow.contentTypePrefix) {
451
+ contentTypePrefix = flow.contentTypePrefix;
452
+ } else if (flow.contentType) {
453
+ contentTypePrefix = flow.contentType;
454
+ }
455
+ const { parentObjectType, parentServiceTag, parentIdKey, parentIdKeys } =
456
+ resolveParentIdentifierInfo(flow, objects);
457
+ let s3KeyPrefix = 'uploads/';
458
+ if (flow.s3KeyPrefix) {
459
+ s3KeyPrefix = flow.s3KeyPrefix;
460
+ }
461
+ let defaultImportType = 'bin';
462
+ if (flow.defaultImportType) {
463
+ defaultImportType = flow.defaultImportType;
464
+ } else if (flow.importType) {
465
+ defaultImportType = flow.importType;
466
+ } else if (
467
+ typeof contentTypePrefix === 'string' &&
468
+ contentTypePrefix.startsWith('video/')
469
+ ) {
470
+ defaultImportType = 'mp4';
471
+ } else if (
472
+ typeof contentTypePrefix === 'string' &&
473
+ contentTypePrefix.startsWith('image/')
474
+ ) {
475
+ defaultImportType = 'jpg';
476
+ }
477
+
478
+ let isRbac = false;
479
+ if (typeof flow.isRbac === 'boolean') {
480
+ isRbac = flow.isRbac;
481
+ } else if (flowHasRbac(flow, objects)) {
482
+ isRbac = true;
483
+ } else if (parentObjectType && parentServiceTag) {
484
+ isRbac = true;
485
+ }
486
+
487
+ let rbacServiceTag = parentServiceTag;
488
+ if (!rbacServiceTag) {
489
+ rbacServiceTag = flow.objType?.serviceTag || flow.serviceTag || 'Rbac';
490
+ }
491
+
492
+ const flowRelationships = resolveFlowRelationships(flow, {
493
+ objects,
494
+ relationships
495
+ });
496
+
497
+ return {
498
+ action,
499
+ flowTag: flow.flowTag,
500
+ objectType: flow.objType?.objectType,
501
+ functionName,
502
+ nextStepFunctionName,
503
+ isSimplifiedS3,
504
+ bucketName: flow.bucketName,
505
+ s3KeyPrefix,
506
+ maxFileSizeMb,
507
+ expires,
508
+ contentTypePrefix,
509
+ parentObjectType,
510
+ parentServiceTag,
511
+ parentIdKey,
512
+ parentIdKeys,
513
+ defaultImportType,
514
+ isRbac,
515
+ rbacServiceTag,
516
+ flowRelationships
517
+ };
142
518
  }
143
519
 
144
- function _s3HandlerData({ action, flow, functionName, mainFileName, handler }) {
145
- if (action === 'CreateObject') {
146
- return { functionName, handlerType: handler, route: flow.flowTag };
520
+ function _s3HandlerData({
521
+ action,
522
+ flow,
523
+ functionName,
524
+ mainFileName,
525
+ handler,
526
+ isSimplifiedS3
527
+ }) {
528
+ const isStartOrCreate =
529
+ action === 'CreateObject' ||
530
+ (typeof action === 'string' && action.toLowerCase() === 'start');
531
+ if (isStartOrCreate) {
532
+ return {
533
+ functionName,
534
+ mainFileName,
535
+ handlerType: handler,
536
+ route: flow.flowTag,
537
+ isSimplifiedS3
538
+ };
147
539
  }
148
540
  if (action === 'ProcessAfterUpload') {
149
541
  let bucketName = '';
@@ -154,8 +546,9 @@ function _s3HandlerData({ action, flow, functionName, mainFileName, handler }) {
154
546
  flowTag: flow.flowTag,
155
547
  functionName,
156
548
  mainFileName,
157
- s3Bucket: bucketName
549
+ s3Bucket: bucketName,
550
+ isSimplifiedS3
158
551
  };
159
552
  }
160
- return { functionName, handlerType: handler };
553
+ return { functionName, mainFileName, handlerType: handler, isSimplifiedS3 };
161
554
  }
@@ -79,6 +79,9 @@ export function flowExtTopicSteps(flows) {
79
79
  if (typeof flow?.flowTag !== 'string' || flow.flowTag === '') {
80
80
  return [];
81
81
  }
82
+ if (Array.isArray(flow.event) && flow.event.includes('s3')) {
83
+ return [];
84
+ }
82
85
  const hasTriggerFlowTypes =
83
86
  Array.isArray(flow.triggerFlowTypes) && flow.triggerFlowTypes.length > 0;
84
87
  if (flow.statusType === 'triggerCache' && !hasTriggerFlowTypes) {
@@ -341,3 +344,131 @@ function normalizeBelongTo(object) {
341
344
  if (!belongTo) return [];
342
345
  return Array.isArray(belongTo) ? belongTo : [belongTo];
343
346
  }
347
+
348
+ export const LEGACY_S3_PARTS = [
349
+ {
350
+ action: 'CreateObject',
351
+ handler: 'HdrWbs',
352
+ type: 'wbs',
353
+ mainTemplate: 'CreateObject_Main.ejs',
354
+ handlerTemplate: 'CreateObject_HdrWbs.ejs'
355
+ },
356
+ {
357
+ action: 'ReservedLimit',
358
+ handler: 'HdrSqs',
359
+ type: 'sqs',
360
+ mainTemplate: 'ReservedLimit_Main.ejs',
361
+ handlerTemplate: 'ReservedLimit_HdrSqs.ejs'
362
+ },
363
+ {
364
+ action: 'CreatePreSignUrl',
365
+ handler: 'HdrSqs',
366
+ type: 'sqs',
367
+ mainTemplate: 'CreatePreSignUrl_Main.ejs',
368
+ handlerTemplate: 'CreatePreSignUrl_HdrSqs.ejs'
369
+ },
370
+ {
371
+ action: 'ProcessAfterUpload',
372
+ handler: 'HdrS3',
373
+ type: 's3',
374
+ mainTemplate: 'ProcessS3File_Main.ejs',
375
+ handlerTemplate: 'FlowHandler_HdrS3.ejs'
376
+ },
377
+ {
378
+ action: 'ConfirmAfterUpload',
379
+ handler: 'HdrSqs',
380
+ type: 'sqs',
381
+ mainTemplate: 'ConfirmReserved_Main.ejs',
382
+ handlerTemplate: 'ConfirmReserved_HdrSqs.ejs'
383
+ }
384
+ ];
385
+
386
+ export function resolveS3Parts(flow) {
387
+ if (!Array.isArray(flow?.flowSteps) || flow.flowSteps.length === 0) {
388
+ return LEGACY_S3_PARTS;
389
+ }
390
+
391
+ const stepNames = flow.flowSteps.map((s) => s.stepName);
392
+ if (
393
+ stepNames.includes('CreateObject') &&
394
+ stepNames.includes('ReservedLimit') &&
395
+ stepNames.includes('ConfirmAfterUpload')
396
+ ) {
397
+ return LEGACY_S3_PARTS;
398
+ }
399
+
400
+ const hasS3Step = flow.flowSteps.some(
401
+ (step) =>
402
+ (Array.isArray(step.event) && step.event.includes('s3')) ||
403
+ (typeof step.stepName === 'string' &&
404
+ step.stepName.toLowerCase().includes('afterupload'))
405
+ );
406
+
407
+ if (!hasS3Step) {
408
+ return LEGACY_S3_PARTS;
409
+ }
410
+
411
+ const isDeferredNodeFlow =
412
+ !stepNames.includes('CreatePreSignUrl') &&
413
+ (stepNames.includes('ConfirmComplete') ||
414
+ stepNames.includes('ConfirmAfterUpload') ||
415
+ stepNames.length <= 3);
416
+
417
+ return flow.flowSteps.map((step) => {
418
+ const action = upperFirst(step.stepName);
419
+ const eventType = Array.isArray(step.event) ? step.event[0] : 'sqs';
420
+
421
+ if (eventType === 'wbs' || action === 'Start' || action === 'CreateObject') {
422
+ let mainTemplate = 'CreateObject_Main.ejs';
423
+ if (isDeferredNodeFlow) {
424
+ mainTemplate = 'Start_Main.ejs';
425
+ }
426
+ return {
427
+ action,
428
+ handler: 'HdrWbs',
429
+ type: 'wbs',
430
+ mainTemplate,
431
+ handlerTemplate: 'CreateObject_HdrWbs.ejs'
432
+ };
433
+ }
434
+
435
+ if (eventType === 's3' || action === 'ProcessAfterUpload') {
436
+ return {
437
+ action,
438
+ handler: 'HdrS3',
439
+ type: 's3',
440
+ mainTemplate: 'ProcessS3File_Main.ejs',
441
+ handlerTemplate: 'FlowHandler_HdrS3.ejs'
442
+ };
443
+ }
444
+
445
+ if (action === 'ConfirmComplete') {
446
+ return {
447
+ action,
448
+ handler: 'HdrSqs',
449
+ type: 'sqs',
450
+ mainTemplate: 'ConfirmComplete_Main.ejs',
451
+ handlerTemplate: 'ConfirmComplete_HdrSqs.ejs'
452
+ };
453
+ }
454
+
455
+ if (action === 'ConfirmAfterUpload') {
456
+ return {
457
+ action,
458
+ handler: 'HdrSqs',
459
+ type: 'sqs',
460
+ mainTemplate: 'ConfirmAfterUpload_Main.ejs',
461
+ handlerTemplate: 'ConfirmAfterUpload_HdrSqs.ejs'
462
+ };
463
+ }
464
+
465
+ return {
466
+ action,
467
+ handler: 'HdrSqs',
468
+ type: 'sqs',
469
+ mainTemplate: 'CreatePreSignUrl_Main.ejs',
470
+ handlerTemplate: 'CreatePreSignUrl_HdrSqs.ejs'
471
+ };
472
+ });
473
+ }
474
+