@izara_project/izara-core-generate-service-code 1.0.78 → 1.0.80

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 (70) hide show
  1. package/package.json +2 -2
  2. package/src/compile/flowValidator.js +163 -0
  3. package/src/compile/loadSchemas.js +15 -5
  4. package/src/emit/coreFunction/emitCoreFunctionArtifacts.js +137 -7
  5. package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +137 -17
  6. package/src/emit/crud/crudActionPlan.js +82 -0
  7. package/src/emit/crud/emitCrudApplicationArtifacts.js +169 -112
  8. package/src/emit/crud/emitDynamicCrudFlowSchemas.js +43 -65
  9. package/src/emit/crud/generateDynamicCrudFlowSchemas.js +4 -1
  10. package/src/emit/crud/templates/CreateComplete_Main.ejs +8 -3
  11. package/src/emit/crud/templates/CreateEndpoint_Main.ejs +90 -513
  12. package/src/emit/crud/templates/CreateLogicalLib.ejs +541 -0
  13. package/src/emit/crud/templates/DeleteComplete_Main.ejs +8 -3
  14. package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +93 -203
  15. package/src/emit/crud/templates/DeleteLogicalLib.ejs +213 -0
  16. package/src/emit/crud/templates/FlowEndpointRbacCallback_Main.ejs +217 -0
  17. package/src/emit/crud/templates/GetEndpoint_Main.ejs +1 -1
  18. package/src/emit/crud/templates/GetRangeEndpoint_Main.ejs +118 -37
  19. package/src/emit/crud/templates/UpdateComplete_Main.ejs +8 -3
  20. package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +92 -444
  21. package/src/emit/crud/templates/UpdateLogicalLib.ejs +477 -0
  22. package/src/emit/custom/customFlows.js +27 -2
  23. package/src/emit/custom/emitCustomFlowApplicationArtifacts.js +1 -2
  24. package/src/emit/custom/templates/FlowEndpoint_Main.ejs +10 -3
  25. package/src/emit/custom/templates/FlowStep_Main.ejs +1 -1
  26. package/src/emit/custom/templates/s3/CreateObject_Main.ejs +1 -1
  27. package/src/emit/custom/templates/triggerCache/CheckTriggerCache_HdrSqs.ejs +2 -2
  28. package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +3 -9
  29. package/src/emit/rbac/emitRbacApplicationArtifacts.js +21 -16
  30. package/src/emit/rbac/rbacFlowTag.js +2 -7
  31. package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +148 -21
  32. package/src/emit/relationship/emitDynamicRelationshipFlowSchemas.js +4 -2
  33. package/src/emit/relationship/templates/ChangeRelationshipComplete_Main.ejs +7 -2
  34. package/src/emit/relationship/templates/ChangeRelationship_Main.ejs +6 -2
  35. package/src/emit/relationship/templates/CreateRelationshipComplete_Main.ejs +7 -2
  36. package/src/emit/relationship/templates/CreateRelationship_Main.ejs +6 -2
  37. package/src/emit/relationship/templates/DeleteRelationshipComplete_Main.ejs +7 -2
  38. package/src/emit/relationship/templates/DeleteRelationship_Main.ejs +6 -2
  39. package/src/emit/relationship/templates/GetRelationship_Main.ejs +1 -1
  40. package/src/emit/relationship/templates/MoveRelationshipComplete_Main.ejs +7 -2
  41. package/src/emit/relationship/templates/MoveRelationship_Main.ejs +6 -2
  42. package/src/emit/relationship/templates/UpdateRelationshipComplete_Main.ejs +7 -2
  43. package/src/emit/relationship/templates/UpdateRelationship_Main.ejs +6 -2
  44. package/src/emit/resource/emitResourceArtifacts.js +149 -79
  45. package/src/emit/resource/templates/DynamoDBTable_Yaml.ejs +4 -4
  46. package/src/emit/resource/templates/GeneratedLambdaRoleServiceConfig.ejs +31 -5
  47. package/src/emit/resource/templates/SystemDynamoDB_Yaml.ejs +21 -0
  48. package/src/emit/resource/templates/WebSocketSubscription_Yaml.ejs +7 -0
  49. package/src/emit/shared/templates/FlowHandler_HdrApi.ejs +1 -1
  50. package/src/emit/shared/templates/FlowHandler_HdrDsq.ejs +2 -2
  51. package/src/emit/shared/templates/FlowHandler_HdrInv.ejs +1 -1
  52. package/src/emit/shared/templates/FlowHandler_HdrSqs.ejs +2 -2
  53. package/src/emit/systemText/emitSystemTextSchemas.js +246 -0
  54. package/src/emit/systemText/templates/SystemTextSchemas.ejs +10 -0
  55. package/src/generate.js +55 -8
  56. package/test/crudApplicationArtifacts.test.js +158 -19
  57. package/test/customFlowApplicationArtifacts.test.js +307 -16
  58. package/test/dynamicCrudFlowSchemas.test.js +150 -14
  59. package/test/dynamicRbacFlowSchemas.test.js +2 -2
  60. package/test/dynamicRelationshipFlowSchemas.test.js +1 -1
  61. package/test/graphDrivenFlowSchema.test.js +257 -0
  62. package/test/publicApi.test.js +14 -5
  63. package/test/resourceArtifacts.test.js +66 -19
  64. package/test/systemTextSchemas.test.js +154 -0
  65. package/src/emit/crud/templates/CreateComplete_HdrSqs.ejs +0 -99
  66. package/src/emit/crud/templates/DeleteComplete_HdrSqs.ejs +0 -99
  67. package/src/emit/crud/templates/FlowEndpointBeforeLogical_Main.ejs +0 -174
  68. package/src/emit/crud/templates/FlowEndpointComplete_Main.ejs +0 -187
  69. package/src/emit/crud/templates/UpdateComplete_HdrSqs.ejs +0 -99
  70. package/src/emit/resource/templates/ResourceBeforeLogicalYaml.ejs +0 -47
@@ -53,424 +53,13 @@ import {
53
53
  lambda
54
54
  } from '@izara_project/izara-core-library-external-request';
55
55
 
56
+ import { <%- flowTag %>LogicalLib } from './<%- upperCaseFlowTag %>LogicalLib.js';
57
+
56
58
  //(<optionalRequire>)
57
59
  //(</optionalRequire>)
58
60
 
59
61
  /**
60
- * Core logical processing after beforeLogical phase completes
61
- * Called by both updateMain (no beforeLogical) and updateBeforeLogicalMain (after callback)
62
- * @param {Object} _izContext - Context object with logger
63
- * @param {Object} requestParams - { objectType, objInstanceFull, versionedDataIds, additionalParams }
64
- * @param {Object} callingFlowConfig - Calling flow configuration
65
- * @param {Object} beforeLogicalResults - Results from beforeLogical phase
66
- * @returns {Promise<Object>}
67
- */
68
- export async function <%- flowTag %>MainLogical(
69
- _izContext,
70
- requestParams,
71
- callingFlowConfig = {},
72
- errorsFound = [],
73
- beforeLogicalResults = {}
74
- ) {
75
- try {
76
- _izContext.logger.debug('[<%- flowTag %>MainLogical] started', {
77
- requestParams,
78
- callingFlowConfig,
79
- beforeLogicalResults
80
- });
81
-
82
- //(<beforeUpdateMainLogical>)
83
- //(</beforeUpdateMainLogical>)
84
-
85
- // ── Settings ──────────────────────────────────────────────────────────────
86
- const settings = requestParams.additionalParams?.settings ?? {};
87
- const returnSystemFieldsName = settings.returnSystemFieldsName === true;
88
- const returnOldData = settings.returnOldData === true;
89
-
90
- const objType = createObjType(requestParams.objectType);
91
- const identifiers = requestParams.objInstanceFull.identifiers;
92
- const fields = requestParams.objInstanceFull.fields;
93
- const versionedDataIds = requestParams.versionedDataIds ?? {};
94
- const parentFlowId = identifierUuid();
95
- // ── Load schema ───────────────────────────────────────────────────────────
96
- const objectSchema = await getObjectSchema.getObjSchemaS3WithHierarchy(
97
- _izContext,
98
- objType
99
- );
100
- _izContext.logger.debug('objectSchema', objectSchema);
101
-
102
- const objectSchemas =
103
- await uploadUseCase.generateObjectSchemaForCombineFieldNames(
104
- _izContext,
105
- objectSchema
106
- );
107
- _izContext.logger.debug('objectSchemas', objectSchemas);
108
-
109
- // ── Build updateDataDetails ───────────────────────────────────────────────
110
- const updateDataDetails = await createUpdateDataDetail(
111
- _izContext,
112
- objectSchemas
113
- );
114
- _izContext.logger.debug('updateDataDetails', updateDataDetails);
115
-
116
- const originTimestamp = Date.now();
117
-
118
- // ── Validate versionedDataIds ─────────────────────────────────────────────
119
- const haveVersionedDataIdsToUpdate =
120
- Object.keys(versionedDataIds).length > 0;
121
- if (haveVersionedDataIdsToUpdate) {
122
- const updateMainNodeData = {};
123
- const updateVersionedData = {};
124
-
125
- for (const [fieldProp, fieldVal] of Object.entries(
126
- requestParams.objInstanceFull.fields
127
- )) {
128
- const fieldSetting = objectSchema.fieldNames[fieldProp];
129
- if (fieldSetting.hasOwnProperty('versionedDataLabel')) {
130
- updateVersionedData[fieldSetting.versionedDataLabel] ??= {};
131
- Object.assign(updateVersionedData[fieldSetting.versionedDataLabel], {
132
- [fieldProp]: fieldVal
133
- });
134
- } else {
135
- Object.assign(updateMainNodeData, { [fieldProp]: fieldVal });
136
- }
137
- }
138
-
139
- _izContext.logger.debug('updateMainNodeData::', updateMainNodeData);
140
- _izContext.logger.debug('updateVersionedData::', updateVersionedData);
141
-
142
- const versionedDataIdLabelKeys = Object.keys(versionedDataIds);
143
- const updateVersionedDataLabelKeys = Object.keys(updateVersionedData);
144
-
145
- const missingVersionedDataIdLabels = updateVersionedDataLabelKeys.filter(
146
- (l) => !versionedDataIdLabelKeys.includes(l)
147
- );
148
- const missingDataVersionedDataLabels = versionedDataIdLabelKeys.filter(
149
- (l) => !updateVersionedDataLabelKeys.includes(l)
150
- );
151
-
152
- if (missingVersionedDataIdLabels.length)
153
- errorsFound.push(
154
- `missing versionedDataIds of versionedDataLabel '${missingVersionedDataIdLabels.join(', ')}'`
155
- );
156
- if (missingDataVersionedDataLabels.length)
157
- errorsFound.push(
158
- `missing data of versionedDataLabels '${missingDataVersionedDataLabels.join(', ')}'`
159
- );
160
- if (Object.keys(updateMainNodeData).length)
161
- errorsFound.push('cannot update mainNode if have versionedDataIds');
162
- }
163
-
164
- //(<validateBeforeUpdate>)
165
- //(</validateBeforeUpdate>)
166
-
167
- // ── Early exit on errors ──────────────────────────────────────────────────
168
- if (errorsFound.length) {
169
- const updateNodeCompleteMessage =
170
- callingFlowSharedLib.addPassBackPropertiesToSnsResponseMessageObject(
171
- callingFlowConfig,
172
- {
173
- objType,
174
- objInstanceFull: { identifiers, fields },
175
- versionedDataIds,
176
- status: 'error',
177
- errorsFound
178
- }
179
- );
180
-
181
- _izContext.logger.debug(
182
- 'messageParams OutUpdateNodeComplete:::',
183
- updateNodeCompleteMessage
184
- );
185
- await sns.publishAsync(_izContext, {
186
- Message: JSON.stringify(updateNodeCompleteMessage),
187
- MessageAttributes: sns.createStringMessageAttributes(
188
- _izContext,
189
- callingFlowSharedLib.addCallingFlowToSnsResponseMessageAttributes(
190
- callingFlowConfig,
191
- {}
192
- )
193
- ),
194
- TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
195
- _izContext,
196
- TOPIC_NAME_GENERATE_CODE.outUpdateNodeComplete
197
- )
198
- });
199
-
200
- return updateNodeCompleteMessage;
201
- }
202
-
203
- // ── Helper: extract fields per storageTag ─────────────────────────────────
204
- function createObjInstanceFullFieldsByStorageTag(
205
- _izContext,
206
- storageTag,
207
- updateDataDetail
208
- ) {
209
- const result = {};
210
- for (const fieldName of Object.keys(
211
- requestParams.objInstanceFull.fields
212
- )) {
213
- if (
214
- updateDataDetails[storageTag].fieldNames.includes(fieldName) &&
215
- updateDataDetail.fieldNames.includes(fieldName) &&
216
- !identifiers.hasOwnProperty(fieldName) &&
217
- !result.hasOwnProperty(fieldName)
218
- ) {
219
- Object.assign(result, {
220
- [fieldName]: requestParams.objInstanceFull.fields[fieldName]
221
- });
222
- }
223
- }
224
- return result;
225
- }
226
-
227
- // ── Helper: build objInstanceFull from updateItem ─────────────────────────
228
- function createObjInstanceFullFromParams(object, requestParams) {
229
- const objInstanceFull = { identifiers: {}, fields: {} };
230
- for (const field of Object.keys(object)) {
231
- if (requestParams.objInstanceFull.identifiers.hasOwnProperty(field)) {
232
- Object.assign(objInstanceFull.identifiers, {
233
- [field]: requestParams.objInstanceFull.identifiers[field]
234
- });
235
- }
236
- if (requestParams.objInstanceFull.fields.hasOwnProperty(field)) {
237
- Object.assign(objInstanceFull.fields, {
238
- [field]: requestParams.objInstanceFull.fields[field]
239
- });
240
- }
241
- }
242
- return objInstanceFull;
243
- }
244
-
245
- // ── Process storage resources ─────────────────────────────────────────────
246
- const awaitingStepIds = [];
247
- const listOfRecords = [];
248
- let updateItem;
249
-
250
- await Promise.all(
251
- Object.entries(updateDataDetails).map(
252
- async ([storageTag, updateDataDetail]) => {
253
- // ── Graph ─────────────────────────────────────────────────────────────
254
- if (updateDataDetail.storageType === consts.STORAGE_TYPES.graph) {
255
- //(<beforeUpdateGraph>)
256
- //(</beforeUpdateGraph>)
257
-
258
- const graphFields = createObjInstanceFullFieldsByStorageTag(
259
- _izContext,
260
- storageTag,
261
- updateDataDetail
262
- );
263
- if (!Object.keys(graphFields).length) return;
264
-
265
- //(<beforeUpdateNode>)
266
- //(</beforeUpdateNode>)
267
-
268
- //(<additionalAttributes>)
269
- const additionalAttributes = {};
270
- //(</additionalAttributes>)
271
-
272
- const records = awaitingStepIds.length === 0 ? listOfRecords : [];
273
- awaitingStepIds.push({
274
- awaitingStepId: asyncFlowSharedLib.createAwaitingStepId(
275
- parentFlowId,
276
- PREFIX.updateNode
277
- ),
278
- additionalAttributes: {
279
- listOfRecords: records,
280
- additionalAttributes: additionalAttributes
281
- }
282
- });
283
-
284
- if (awaitingStepIds.length) {
285
- const awaitingMultipleStep =
286
- await asyncFlowSharedLib.createAwaitingMultipleSteps(
287
- _izContext,
288
- asyncFlowSharedLib.createPendingStepId(
289
- _izContext.uniqueRequestId
290
- ),
291
- awaitingStepIds
292
- );
293
- _izContext.logger.debug(
294
- 'awaitingMultipleStep',
295
- awaitingMultipleStep
296
- );
297
- }
298
-
299
- let updateNodeParams = {
300
- objType,
301
- objInstanceFull: { identifiers, fields: graphFields },
302
- versionedDataIds,
303
- originTimestamp,
304
- settings: { returnSystemFieldsName, returnOldData },
305
- parentFlowId
306
- };
307
-
308
- updateNodeParams =
309
- callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
310
- updateNodeParams,
311
- callingFlowSharedLib.addParentCallingFlowConfig(
312
- callingFlowConfig,
313
- callingFlowSharedLib.createCallingFlowConfig(
314
- //(<callingFlowProperties>)
315
- await lambdaSharedLib.lambdaFunctionName(
316
- _izContext,
317
- TOPIC_NAME_GENERATE_CODE.updateNodeComplete
318
- ),
319
- {}
320
- //(</callingFlowProperties>)
321
- )
322
- )
323
- );
324
-
325
- _izContext.logger.debug(
326
- 'messageObject before send message:',
327
- updateNodeParams
328
- );
329
-
330
- const resSNS = await sns.publishAsync(_izContext, {
331
- Message: JSON.stringify(updateNodeParams),
332
- MessageAttributes: sns.createStringMessageAttributes(
333
- _izContext,
334
- callingFlowSharedLib.addCallingFlowToSnsResponseMessageAttributes(
335
- callingFlowConfig,
336
- {}
337
- )
338
- ),
339
- TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
340
- _izContext,
341
- TOPIC_NAME_GRAPH_HANDLER.inUpdateNode,
342
- storageTag
343
- )
344
- });
345
- _izContext.logger.debug(
346
- 'resSNS send to topic InUpdateNode finish!',
347
- resSNS
348
- );
349
-
350
- // ── DynamoDB ──────────────────────────────────────────────────────────
351
- } else if (
352
- updateDataDetail.storageType === consts.STORAGE_TYPES.dynamoDB
353
- ) {
354
- const dynamoFields = createObjInstanceFullFieldsByStorageTag(
355
- _izContext,
356
- storageTag,
357
- updateDataDetail
358
- );
359
- if (!Object.keys(dynamoFields).length) return;
360
-
361
- //(<beforeUpdateDynamoDb>)
362
- //(</beforeUpdateDynamoDb>)
363
-
364
- const identifiersForUpdateData =
365
- await dynamoDbIdentifiersByStorageResource(
366
- _izContext,
367
- objectSchema,
368
- updateDataDetail,
369
- identifiers
370
- );
371
- _izContext.logger.debug(
372
- 'identifiersForUpdateData',
373
- identifiersForUpdateData
374
- );
375
-
376
- if (
377
- Object.values(updateDataDetails).some(
378
- (updateDataDetail) =>
379
- updateDataDetail.storageType === consts.STORAGE_TYPES.graph
380
- )
381
- ) {
382
- _izContext.logger.debug('must process graph first');
383
- listOfRecords.push({
384
- [storageTag]: {
385
- serviceTag: updateDataDetail.serviceTag,
386
- tableName: updateDataDetail.tableName,
387
- objInstanceFull: {
388
- identifiers: identifiersForUpdateData,
389
- fields: dynamoFields
390
- }
391
- }
392
- });
393
- } else {
394
- _izContext.logger.debug('can process record dynamo');
395
- updateItem = await dynamodbSharedLib.updateItem(
396
- _izContext,
397
- await dynamodbSharedLib.tableName(
398
- _izContext,
399
- updateDataDetail.tableName,
400
- updateDataDetail.serviceTag
401
- ),
402
- identifiersForUpdateData,
403
- dynamoFields,
404
- { returnValues: 'ALL_NEW' }
405
- );
406
-
407
- _izContext.logger.debug('updateItem:', updateItem);
408
- }
409
- }
410
- }
411
- )
412
- );
413
-
414
- // ── DynamoDB-only complete path ───────────────────────────────────────────
415
- if (awaitingStepIds.length === 0) {
416
- let messageObject = {
417
- objType,
418
- objInstanceFull: createObjInstanceFullFromParams(
419
- updateItem,
420
- requestParams
421
- )
422
- };
423
-
424
- //(<additionalProperties>)
425
- //(</additionalProperties>)
426
-
427
- if (
428
- callingFlowConfig[
429
- callingFlowSharedLib.consts.CALLINGFLOWPROPERTIES_PROPERTYNAME
430
- ]
431
- ) {
432
- _izContext.logger.debug('HAVE CALLING FLOW');
433
- messageObject =
434
- callingFlowSharedLib.addPassBackPropertiesToSnsResponseMessageObject(
435
- callingFlowConfig,
436
- messageObject
437
- );
438
-
439
- _izContext.logger.debug('after create callingFlow', messageObject);
440
- await sns.publishAsync(_izContext, {
441
- Message: JSON.stringify(messageObject),
442
- MessageAttributes: sns.createStringMessageAttributes(
443
- _izContext,
444
- callingFlowSharedLib.addCallingFlowToSnsResponseMessageAttributes(
445
- callingFlowConfig,
446
- {}
447
- )
448
- ),
449
- TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
450
- _izContext,
451
- TOPIC_NAME_GENERATE_CODE.outUpdateNodeComplete
452
- )
453
- });
454
- }
455
- }
456
-
457
- return {
458
- returnValues: {
459
- objType,
460
- objInstanceFull: { identifiers, fields },
461
- versionedDataIds
462
- },
463
- status: 'complete',
464
- errorsFound
465
- };
466
- } catch (err) {
467
- _izContext.logger.error('[<%- flowTag %>MainLogical] error:', err);
468
- throw err;
469
- }
470
- }
471
-
472
- /**
473
- * Updates an object instance — handles beforeLogical phase routing or proceeds directly to logical
62
+ * Updates an object instance with optional RBAC routing
474
63
  * @param {Object} _izContext - Context object with logger
475
64
  * @param {Object} requestParams - { objectType, objInstanceFull, versionedDataIds, additionalParams }
476
65
  * @param {Object} callingFlowConfig - Calling flow configuration
@@ -479,7 +68,7 @@ export async function <%- flowTag %>MainLogical(
479
68
  export default async function <%- flowTag %>(
480
69
  _izContext,
481
70
  requestParams,
482
- callingFlowConfig = {}
71
+ callingFlowConfig = {},
483
72
  //(<additionalParams>)
484
73
  //(</additionalParams>)
485
74
  ) {
@@ -489,7 +78,7 @@ export default async function <%- flowTag %>(
489
78
  callingFlowConfig
490
79
  });
491
80
 
492
- // ── Build identifiers (used for hash in beforeLogical) ──────────────────
81
+ // ── Build identifiers used by asynchronous processing ────────────────────
493
82
  const identifiers = requestParams.objInstanceFull.identifiers;
494
83
  const errorsFound = [];
495
84
 
@@ -497,23 +86,76 @@ export default async function <%- flowTag %>(
497
86
  //(</validateBeforeUpdate>)
498
87
 
499
88
  if (errorsFound.length > 0)
500
- return await createMainLogical(
89
+ return await <%- flowTag %>LogicalLib(
501
90
  _izContext,
502
91
  requestParams,
503
92
  callingFlowConfig,
504
93
  errorsFound
505
94
  );
506
95
 
507
- // ── beforeLogical phase check ─────────────────────────────────────────────
508
96
  <%_
509
- const groupedByObjType = generateCode
510
- .filter(c => c.codeHookTag === 'beforeLogical')
511
- .reduce((acc, config) => {
512
- const key = config.objType.objectType;
513
- if (!acc[key]) acc[key] = [];
514
- acc[key].push(config);
515
- return acc;
516
- }, {});
97
+ const rbacObjects = objects.filter(o => (o?.generatedBy === 'userGenerated' || o?.generatedBy === 'systemGenerated') && hasRbacAddOn(o));
98
+ const rbacObjectTypes = rbacObjects.map(o => o.objectType);
99
+ const rbacServiceTagMap = {};
100
+ for (const o of rbacObjects) {
101
+ const belongToTargets = o?.belongTo
102
+ ? Array.isArray(o.belongTo)
103
+ ? o.belongTo
104
+ : [o.belongTo]
105
+ : [];
106
+ if (belongToTargets.length > 0 && belongToTargets[0]?.serviceTag) {
107
+ rbacServiceTagMap[o.objectType] = `'${belongToTargets[0].serviceTag}'`;
108
+ } else if (o?.belongToSchema?.serviceTag) {
109
+ rbacServiceTagMap[o.objectType] = `'${o.belongToSchema.serviceTag}'`;
110
+ } else if (o?.serviceTag) {
111
+ rbacServiceTagMap[o.objectType] = `'${o.serviceTag}'`;
112
+ } else {
113
+ rbacServiceTagMap[o.objectType] = 'process.env.iz_serviceTag';
114
+ }
115
+ }
116
+ const rbacServiceTags = Array.from(new Set(Object.values(rbacServiceTagMap)));
117
+ _%>
118
+ <%_ if (rbacObjectTypes.length > 0) { _%>
119
+ // ── rbacCallback phase check ─────────────────────────────────────────────
120
+ if ([<%- rbacObjectTypes.map(t => `'${t}'`).join(', ') %>].includes(requestParams.objectType)) {
121
+ const { checkRbacPermission } =
122
+ await import('@izara_project/izara-authorization');
123
+
124
+ //(<rbacParameterGroups_<%- flowTag %>)
125
+ const parameterGroups = {};
126
+ //(</rbacParameterGroups_<%- flowTag %>)
127
+
128
+ const resultPermissionCheck = await checkRbacPermission(
129
+ _izContext,
130
+ {
131
+ flowTag: '<%- flowTag %>',
132
+ serviceTag: process.env.iz_serviceTag
133
+ },
134
+ parameterGroups,
135
+ {
136
+ rbacObjType: {
137
+ serviceTag: <%- rbacServiceTags.length === 1 ? rbacServiceTags[0] : `{ ${Object.entries(rbacServiceTagMap).map(([k, v]) => `'${k}': ${v}`).join(', ')} }[requestParams.objectType] || process.env.iz_serviceTag` %>
138
+ },
139
+ requestParams: requestParams,
140
+ nextFlowStepName: '<%- plan?.hasRbacCallback ? `${flowTag}RbacCallback` : `${flowTag}Complete` %>'
141
+ }
142
+ );
143
+
144
+ _izContext.logger.debug(
145
+ '[lib:auth:checkRbacPermission] resultPermissionCheck:',
146
+ resultPermissionCheck
147
+ );
148
+
149
+ //(<rbacPublish_<%- flowTag %>)
150
+ //(</rbacPublish_<%- flowTag %>)
151
+
152
+ return resultPermissionCheck;
153
+ }
154
+ <%_ } _%>
155
+
156
+ // ── Optional phase extension point ────────────────────────────────────────
157
+ <%_
158
+ const groupedByObjType = [];
517
159
  _%>
518
160
  <%_ Object.entries(groupedByObjType).forEach(([objectType, configs]) => { _%>
519
161
  <%_
@@ -556,7 +198,7 @@ export default async function <%- flowTag %>(
556
198
  awaitingMultipleStepIds.push({
557
199
  awaitingStepId: await asyncFlowSharedLib.createAwaitingStepId(
558
200
  hash(identifiers),
559
- '<%= config.codeHookTag %>_<%= objectType %>_<%= config.flowTag.charAt(0).toUpperCase() + config.flowTag.slice(1) %>'
201
+ 'logical_<%= objectType %>_<%= config.flowTag.charAt(0).toUpperCase() + config.flowTag.slice(1) %>'
560
202
  ),
561
203
  additionalAttributes: {}
562
204
  });
@@ -570,7 +212,7 @@ export default async function <%- flowTag %>(
570
212
  //(<callingFlowProperties_<%= config.flowTag %>>)
571
213
  await lambdaSharedLib.lambdaFunctionName(
572
214
  _izContext,
573
- '<%= config.generatedCodeTag %><%= config.codeHookTag.charAt(0).toUpperCase() + config.codeHookTag.slice(1) %>'
215
+ '<%= flowTag.toLowerCase() %>Complete'
574
216
  ),
575
217
  {}
576
218
  //(</callingFlowProperties_<%= config.flowTag %>>)
@@ -587,7 +229,7 @@ export default async function <%- flowTag %>(
587
229
  awaitingMultipleStepIds.push({
588
230
  awaitingStepId: await asyncFlowSharedLib.createAwaitingStepId(
589
231
  hash(identifiers),
590
- '<%= configs[0].codeHookTag %>_<%= objectType %>_' + syncResult.flowTag
232
+ 'logical_<%= objectType %>_' + syncResult.flowTag
591
233
  ),
592
234
  additionalAttributes: {
593
235
  complete: true,
@@ -598,13 +240,18 @@ export default async function <%- flowTag %>(
598
240
  }
599
241
  <%_ } _%>
600
242
 
601
- await asyncFlowSharedLib.initAwaitingStepsWithAttrs(
243
+ await asyncFlowSharedLib.createAwaitingMultipleSteps(
602
244
  _izContext,
603
- awaitingMultipleStepIds,
604
245
  asyncFlowSharedLib.createPendingStepId(
605
246
  _izContext.uniqueRequestId,
606
- 'beforeLogical_<%= objectType %>'
607
- )
247
+ 'logical_<%= objectType %>'
248
+ ),
249
+ awaitingMultipleStepIds,
250
+ {
251
+ additionalAttributes: {
252
+ callingFlowConfig
253
+ }
254
+ }
608
255
  );
609
256
 
610
257
  //(<beforePublish_<%= objectType %>>)
@@ -631,20 +278,20 @@ export default async function <%- flowTag %>(
631
278
  });
632
279
  }
633
280
 
634
- return 'complete beforeLogical <%= objectType %>';
281
+ return 'complete logical <%= objectType %>';
635
282
 
636
283
  <%_ } else { _%>
637
- // ── lambdaSyncInv only — collect results and proceed to updateMainLogical
638
- const beforeLogicalResults = lambdaSyncInvResults.reduce((acc, r) => {
639
- acc[r.flowTag] = r.returnValue;
640
- return acc;
641
- }, {});
284
+ // ── lambdaSyncInv only — collect results and proceed to updateLogicalLib
285
+ const phaseResults = Object.fromEntries(
286
+ lambdaSyncInvResults.map(({ flowTag: tag, returnValue }) => [tag, returnValue])
287
+ );
642
288
 
643
- return await <%- flowTag %>MainLogical(
289
+ return await <%- flowTag %>LogicalLib(
644
290
  _izContext,
645
291
  requestParams,
646
292
  callingFlowConfig,
647
- beforeLogicalResults
293
+ errorsFound,
294
+ phaseResults
648
295
  );
649
296
  <%_ } _%>
650
297
  }
@@ -653,11 +300,12 @@ export default async function <%- flowTag %>(
653
300
  //(<beforeUpdateMainLogical>)
654
301
  //(</beforeUpdateMainLogical>)
655
302
 
656
- // ── No beforeLogical → proceed directly to logical ────────────────────────
657
- return await <%- flowTag %>MainLogical(
303
+ // ── No optional phase → proceed directly to logical ──────────────────────
304
+ return await <%- flowTag %>LogicalLib(
658
305
  _izContext,
659
306
  requestParams,
660
- callingFlowConfig
307
+ callingFlowConfig,
308
+ errorsFound
661
309
  );
662
310
  } catch (err) {
663
311
  _izContext.logger.error('[<%- flowTag %>] error:', err);