@izara_project/izara-core-generate-service-code 1.0.86 → 1.0.88

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 (38) hide show
  1. package/package.json +1 -1
  2. package/src/compile/loadSchemas.js +45 -10
  3. package/src/emit/coreFunction/emitCoreFunctionArtifacts.js +1 -1
  4. package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +22 -15
  5. package/src/emit/crud/crudActionPlan.js +47 -6
  6. package/src/emit/crud/emitCrudApplicationArtifacts.js +63 -3
  7. package/src/emit/crud/emitDynamicCrudFlowSchemas.js +6 -4
  8. package/src/emit/crud/templates/CreateAfterHookCallback_Main.ejs +121 -0
  9. package/src/emit/crud/templates/CreateBeforeHookCallback_Main.ejs +108 -0
  10. package/src/emit/crud/templates/CreateEndpoint_Main.ejs +138 -335
  11. package/src/emit/crud/templates/CreateLogicalLib.ejs +205 -42
  12. package/src/emit/crud/templates/CreateNodeCallback_Main.ejs +80 -0
  13. package/src/emit/crud/templates/DeleteBeforeHookCallback_Main.ejs +99 -0
  14. package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +153 -182
  15. package/src/emit/crud/templates/DeleteLogicalLib.ejs +132 -26
  16. package/src/emit/crud/templates/UpdateBeforeHookCallback_Main.ejs +112 -0
  17. package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +166 -188
  18. package/src/emit/crud/templates/UpdateLogicalLib.ejs +2 -2
  19. package/src/emit/custom/customFlows.js +3 -1
  20. package/src/emit/function/functionYamlArtifact.js +4 -2
  21. package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +0 -3
  22. package/src/emit/rbac/emitRbacApplicationArtifacts.js +1 -116
  23. package/src/emit/rbac/templates/CancelUsage_Main.ejs +14 -10
  24. package/src/emit/rbac/templates/ConfirmUsage_Main.ejs +14 -10
  25. package/src/emit/rbac/templates/CreateTargetRole_Main.ejs +22 -12
  26. package/src/emit/rbac/templates/GetMyPermissions_Main.ejs +14 -10
  27. package/src/emit/rbac/templates/ReservedDynamicUsage_Main.ejs +76 -34
  28. package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +12 -9
  29. package/src/emit/resource/emitResourceArtifacts.js +141 -62
  30. package/src/emit/resource/templates/SystemDynamoDB_Yaml.ejs +14 -18
  31. package/src/emit/system/templates/WebSocketComplete_Yaml.ejs +4 -2
  32. package/test/createTargetRoleHandler.test.js +1 -15
  33. package/test/crudApplicationArtifacts.test.js +540 -3
  34. package/test/customFlowApplicationArtifacts.test.js +3 -5
  35. package/test/dynamicCrudFlowSchemas.test.js +5 -17
  36. package/test/dynamicRbacFlowSchemas.test.js +0 -3
  37. package/test/functionYamlArtifact.test.js +4 -2
  38. package/test/resourceArtifacts.test.js +203 -14
@@ -102,27 +102,27 @@ export async function resolveSchemaAndIdentity(_izContext, requestParams, errors
102
102
  targetIdentifiers.submittedByUserId = submittedByUserId;
103
103
  }
104
104
 
105
- if (Array.isArray(objectSchema.identifiers)) {
106
- for (const identifier of objectSchema.identifiers) {
107
- if (identifier.fieldName) {
108
- if (targetIdentifiers[identifier.fieldName] === undefined) {
109
- targetIdentifiers[identifier.fieldName] = null;
110
- }
111
- } else if (Array.isArray(identifier.fieldNames)) {
112
- for (const fn of identifier.fieldNames) {
113
- if (targetIdentifiers[fn] === undefined) {
114
- targetIdentifiers[fn] = null;
115
- }
116
- }
117
- } else if (identifier.name) {
118
- if (targetIdentifiers[identifier.name] === undefined) {
119
- targetIdentifiers[identifier.name] = null;
120
- }
121
- }
122
- }
123
- }
124
-
125
- requestParams.targetIdentifiers = targetIdentifiers;
105
+ // if (Array.isArray(objectSchema.identifiers)) {
106
+ // for (const identifier of objectSchema.identifiers) {
107
+ // if (identifier.fieldName) {
108
+ // if (targetIdentifiers[identifier.fieldName] === undefined) {
109
+ // targetIdentifiers[identifier.fieldName] = null;
110
+ // }
111
+ // } else if (Array.isArray(identifier.fieldNames)) {
112
+ // for (const fn of identifier.fieldNames) {
113
+ // if (targetIdentifiers[fn] === undefined) {
114
+ // targetIdentifiers[fn] = null;
115
+ // }
116
+ // }
117
+ // } else if (identifier.name) {
118
+ // if (targetIdentifiers[identifier.name] === undefined) {
119
+ // targetIdentifiers[identifier.name] = null;
120
+ // }
121
+ // }
122
+ // }
123
+ // }
124
+
125
+ // requestParams.targetIdentifiers = targetIdentifiers;
126
126
  }
127
127
 
128
128
  _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] Identity & Target Context Resolved:`, {
@@ -136,7 +136,7 @@ export async function resolveSchemaAndIdentity(_izContext, requestParams, errors
136
136
  }
137
137
 
138
138
  requestParams.submittedByUserId = submittedByUserId;
139
- return { objType, objectSchema };
139
+ return { objType, objectSchema, targetIdentifiers };
140
140
  }
141
141
 
142
142
  /**
@@ -385,21 +385,51 @@ export async function autoProvisionOwnerTargetRole(_izContext, { node, submitted
385
385
  }
386
386
 
387
387
  const identifiers = node.objInstanceFull.identifiers;
388
- const targetIdentKeys = Object.entries(identifiers)
389
- .filter(([k]) => k !== 'submittedByUserId')
390
- .map(([k, v]) => `${k}#${v}`)
391
- .join('|');
392
-
393
- const targetIdentifiersConcat =
394
- targetIdentKeys ||
395
- (identifiers[Object.keys(identifiers)[0]]
396
- ? `${Object.keys(identifiers)[0]}#${identifiers[Object.keys(identifiers)[0]]}`
397
- : '');
388
+ const sortedKeys = Object.keys(identifiers)
389
+ .filter(
390
+ (k) =>
391
+ k !== 'submittedByUserId' &&
392
+ k !== 'identifierConcat' &&
393
+ k !== 'identifiersConcat'
394
+ )
395
+ .sort();
396
+ const parts = [];
397
+ for (const key of sortedKeys) {
398
+ const value = identifiers[key];
399
+ if (value !== undefined && value !== null) {
400
+ parts.push(`${key}#${value}`);
401
+ }
402
+ }
403
+ const targetIdentifiersConcat = parts.join('|');
398
404
 
399
405
  if (!targetIdentifiersConcat) {
400
406
  return;
401
407
  }
402
408
 
409
+ const targetPlanTier =
410
+ node?.objInstanceFull?.planTier ||
411
+ node?.objInstanceFull?.targetIdentifiers?.planTier ||
412
+ 'tier-free';
413
+ let planTierName = 'Free Plan';
414
+ if (targetPlanTier === 'tier-pro') {
415
+ planTierName = 'Professional Plan';
416
+ } else if (targetPlanTier === 'tier-enterprise') {
417
+ planTierName = 'Enterprise Plan';
418
+ }
419
+
420
+ await dynamodbSharedLib.putItem(
421
+ _izContext,
422
+ dynamodbSharedLib.tableName(_izContext, 'TargetRoles'),
423
+ {
424
+ identifiersConcat: targetIdentifiersConcat,
425
+ roleIdKey: targetPlanTier,
426
+ roleType: 'plan_tier',
427
+ roleName: planTierName,
428
+ submittedByUserId,
429
+ createdAt: new Date().toISOString()
430
+ }
431
+ );
432
+
403
433
  const roleIdKey = `${targetIdentifiersConcat}_owner`;
404
434
  _izContext.logger.debug(
405
435
  '[CreateNodeCallback] Auto-provisioning owner TargetRole:',
@@ -417,8 +447,9 @@ export async function autoProvisionOwnerTargetRole(_izContext, { node, submitted
417
447
  {
418
448
  identifiersConcat: targetIdentifiersConcat,
419
449
  roleIdKey,
450
+ roleType: 'tenant_role',
451
+ roleName: 'Owner',
420
452
  submittedByUserId,
421
- roleName: 'owner',
422
453
  assignedAt: new Date().toISOString()
423
454
  }
424
455
  );
@@ -816,16 +847,49 @@ export async function autoProvisionOwnerTargetRoleForDynamoOnly(
816
847
  _izContext.correlationIds?.get(coreConsts.SUBMITTED_BY_USER_ID);
817
848
 
818
849
  if (submittedByUserId) {
819
- const targetIdentKeys = Object.entries(identifiersForCreateData)
820
- .map(([k, v]) => `${k}#${v}`)
821
- .join('|');
822
- const targetIdentifiersConcat =
823
- targetIdentKeys ||
824
- (identifiersForCreateData[Object.keys(identifiersForCreateData)[0]]
825
- ? `${Object.keys(identifiersForCreateData)[0]}#${identifiersForCreateData[Object.keys(identifiersForCreateData)[0]]}`
826
- : '');
850
+ const sortedKeys = Object.keys(identifiersForCreateData)
851
+ .filter(
852
+ (k) =>
853
+ k !== 'submittedByUserId' &&
854
+ k !== 'identifierConcat' &&
855
+ k !== 'identifiersConcat'
856
+ )
857
+ .sort();
858
+ const parts = [];
859
+ for (const key of sortedKeys) {
860
+ const value = identifiersForCreateData[key];
861
+ if (value !== undefined && value !== null) {
862
+ parts.push(`${key}#${value}`);
863
+ }
864
+ }
865
+ const targetIdentifiersConcat = parts.join('|');
827
866
 
828
867
  if (targetIdentifiersConcat) {
868
+ const targetPlanTier =
869
+ actionData?.planTier ||
870
+ requestParams?.planTier ||
871
+ requestParams?.passBackProperties?.planTier ||
872
+ 'tier-free';
873
+ let planTierName = 'Free Plan';
874
+ if (targetPlanTier === 'tier-pro') {
875
+ planTierName = 'Professional Plan';
876
+ } else if (targetPlanTier === 'tier-enterprise') {
877
+ planTierName = 'Enterprise Plan';
878
+ }
879
+
880
+ await dynamodbSharedLib.putItem(
881
+ _izContext,
882
+ dynamodbSharedLib.tableName(_izContext, 'TargetRoles'),
883
+ {
884
+ identifiersConcat: targetIdentifiersConcat,
885
+ roleIdKey: targetPlanTier,
886
+ roleType: 'plan_tier',
887
+ roleName: planTierName,
888
+ submittedByUserId,
889
+ createdAt: new Date().toISOString()
890
+ }
891
+ );
892
+
829
893
  const roleIdKey = `${targetIdentifiersConcat}_owner`;
830
894
  _izContext.logger.debug(
831
895
  '[<%- flowTag %>LogicalLib] Auto-provisioning owner TargetRole for DynamoDB-only:',
@@ -843,8 +907,9 @@ export async function autoProvisionOwnerTargetRoleForDynamoOnly(
843
907
  {
844
908
  identifiersConcat: targetIdentifiersConcat,
845
909
  roleIdKey,
910
+ roleType: 'tenant_role',
911
+ roleName: 'Owner',
846
912
  submittedByUserId,
847
- roleName: 'owner',
848
913
  assignedAt: new Date().toISOString()
849
914
  }
850
915
  );
@@ -1279,6 +1344,7 @@ export async function <%- flowTag %>LogicalLib(
1279
1344
  }
1280
1345
  );
1281
1346
 
1347
+ const fieldsForHook = { ...objInstanceFullForDynamoDb.fields };
1282
1348
  objInstanceFullForDynamoDb.fields = {};
1283
1349
 
1284
1350
  // Auto-provision owner TargetRole for DynamoDB-only
@@ -1287,6 +1353,101 @@ export async function <%- flowTag %>LogicalLib(
1287
1353
  identifiersForCreateData,
1288
1354
  requestParams
1289
1355
  });
1356
+
1357
+ <%_ if (plan?.hasAfterHookSync) { _%>
1358
+ // ── Synchronous After Hooks ──
1359
+ <%_ plan.afterHooks.filter(h => h?.generatedCodeConfig?.invocationType === 'lambdaSyncInv').forEach(hook => { _%>
1360
+ <%_ if (hook.objType?.objectType) { _%>
1361
+ if (objType.objectType === '<%= hook.objType.objectType %>') {
1362
+ <%_ } _%>
1363
+ try {
1364
+ const hookResult = await lambda.invokeSync(
1365
+ _izContext,
1366
+ await lambdaSharedLib.lambdaFunctionName(
1367
+ _izContext,
1368
+ '<%= hook.flowTag %>'
1369
+ ),
1370
+ {
1371
+ requestParams: {
1372
+ objType,
1373
+ objInstanceFull: {
1374
+ identifiers: identifiersForCreateData,
1375
+ fields: fieldsForHook
1376
+ },
1377
+ relationships: requestParams.relationships || [],
1378
+ targetIdentifiers: requestParams.targetIdentifiers,
1379
+ submittedByUserId: requestParams.submittedByUserId
1380
+ },
1381
+ callingFlowConfig
1382
+ }
1383
+ );
1384
+ if (hookResult?.errorsFound?.length > 0 || hookResult?.status === 'error') {
1385
+ errorsFound.push(...(hookResult.errorsFound || ['Hook <%= hook.flowTag %> failed']));
1386
+ }
1387
+ } catch (hookErr) {
1388
+ _izContext.logger.error('[<%- flowTag %>LogicalLib] Sync hook <%= hook.flowTag %> error:', hookErr);
1389
+ errorsFound.push(hookErr.message || 'Hook <%= hook.flowTag %> failed');
1390
+ }
1391
+ <%_ if (hook.objType?.objectType) { _%>
1392
+ }
1393
+ <%_ } _%>
1394
+ <%_ }) _%>
1395
+ <%_ } _%>
1396
+
1397
+ <%_ if (plan?.hasAfterHookAsync) { _%>
1398
+ // ── Asynchronous After Hooks ──
1399
+ <%_ plan.afterHooks.filter(h => h?.generatedCodeConfig?.invocationType === 'ownTopic').forEach(hook => { _%>
1400
+ <%_ if (hook.objType?.objectType) { _%>
1401
+ if (objType.objectType === '<%= hook.objType.objectType %>') {
1402
+ <%_ } _%>
1403
+ const hookMsg_<%= hook.flowTag %> = callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
1404
+ {
1405
+ objType,
1406
+ objInstanceFull: {
1407
+ identifiers: identifiersForCreateData,
1408
+ fields: fieldsForHook
1409
+ },
1410
+ relationships: requestParams.relationships || [],
1411
+ targetIdentifiers: requestParams.targetIdentifiers,
1412
+ submittedByUserId: requestParams.submittedByUserId
1413
+ },
1414
+ callingFlowSharedLib.addParentCallingFlowConfig(
1415
+ callingFlowConfig,
1416
+ callingFlowSharedLib.createCallingFlowConfig(
1417
+ await lambdaSharedLib.lambdaFunctionName(
1418
+ _izContext,
1419
+ '<%- flowTag %>AfterHookCallbackHdrSqs'
1420
+ ),
1421
+ {
1422
+ actionData: {
1423
+ objType,
1424
+ objInstanceFull: {
1425
+ identifiers: identifiersForCreateData,
1426
+ fields: fieldsForHook
1427
+ },
1428
+ relationships: requestParams.relationships || [],
1429
+ targetIdentifiers: requestParams.targetIdentifiers,
1430
+ status: 'complete',
1431
+ errorsFound
1432
+ }
1433
+ }
1434
+ )
1435
+ )
1436
+ );
1437
+
1438
+ await sns.publishAsync(_izContext, {
1439
+ TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
1440
+ _izContext,
1441
+ '<%= hook.flowTag %>_In'
1442
+ ),
1443
+ Message: JSON.stringify(hookMsg_<%= hook.flowTag %>),
1444
+ MessageAttributes: sns.createStringMessageAttributes(_izContext, {})
1445
+ });
1446
+ <%_ if (hook.objType?.objectType) { _%>
1447
+ }
1448
+ <%_ } _%>
1449
+ <%_ }) _%>
1450
+ <%_ } _%>
1290
1451
  }
1291
1452
 
1292
1453
  //(<afterCreateRecordDynamo>)
@@ -1440,11 +1601,13 @@ export async function <%- flowTag %>LogicalLib(
1440
1601
 
1441
1602
  // 7. Handle DynamoDB-only Complete Path
1442
1603
  if (allAwaitingStepsId.length === 0 && listOfObjectForCreates.length === 0) {
1604
+ <%_ if (!plan?.hasAfterHookAsync) { _%>
1443
1605
  await handleDynamoDbOnlyComplete(_izContext, {
1444
1606
  objType,
1445
1607
  objInstanceFullForDynamoDb,
1446
1608
  callingFlowConfig
1447
1609
  });
1610
+ <%_ } _%>
1448
1611
  }
1449
1612
 
1450
1613
  return {
@@ -171,6 +171,43 @@ export default async function CreateNodeCallbackMain(
171
171
  node,
172
172
  submittedByUserId
173
173
  });
174
+
175
+ <%_ if (plan?.hasAfterHookSync) { _%>
176
+ // ── Synchronous After Hooks ──
177
+ <%_ plan.afterHooks.filter(h => h?.generatedCodeConfig?.invocationType === 'lambdaSyncInv').forEach(hook => { _%>
178
+ <%_ if (hook.objType?.objectType) { _%>
179
+ if (returnValue.requestParams?.objType?.objectType === '<%= hook.objType.objectType %>') {
180
+ <%_ } _%>
181
+ try {
182
+ const hookResult = await lambda.invokeSync(
183
+ _izContext,
184
+ await lambdaSharedLib.lambdaFunctionName(
185
+ _izContext,
186
+ '<%= hook.flowTag %>'
187
+ ),
188
+ {
189
+ requestParams: {
190
+ objType: returnValue.requestParams.objType,
191
+ objInstanceFull: node.objInstanceFull,
192
+ relationships: node.relationships || [],
193
+ targetIdentifiers: requestParams.targetIdentifiers,
194
+ submittedByUserId
195
+ },
196
+ callingFlowConfig
197
+ }
198
+ );
199
+ if (hookResult?.errorsFound?.length > 0 || hookResult?.status === 'error') {
200
+ errorsFound.push(...(hookResult.errorsFound || ['Hook <%= hook.flowTag %> failed']));
201
+ }
202
+ } catch (hookErr) {
203
+ _izContext.logger.error('[CreateNodeCallback] Sync hook <%= hook.flowTag %> error:', hookErr);
204
+ errorsFound.push(hookErr.message || 'Hook <%= hook.flowTag %> failed');
205
+ }
206
+ <%_ if (hook.objType?.objectType) { _%>
207
+ }
208
+ <%_ } _%>
209
+ <%_ }) _%>
210
+ <%_ } _%>
174
211
  }
175
212
 
176
213
  const callingFlowConfig =
@@ -198,6 +235,48 @@ export default async function CreateNodeCallbackMain(
198
235
  _izContext
199
236
  );
200
237
 
238
+ <%_ if (plan?.hasAfterHookAsync) { _%>
239
+ // ── Asynchronous After Hooks ──
240
+ <%_ plan.afterHooks.filter(h => h?.generatedCodeConfig?.invocationType === 'ownTopic').forEach(hook => { _%>
241
+ <%_ if (hook.objType?.objectType) { _%>
242
+ if (returnValue.requestParams?.objType?.objectType === '<%= hook.objType.objectType %>') {
243
+ <%_ } _%>
244
+ const hookMsg_<%= hook.flowTag %> = callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
245
+ {
246
+ objType: returnValue.requestParams.objType,
247
+ objInstanceFull: node.objInstanceFull,
248
+ relationships: node.relationships || [],
249
+ targetIdentifiers: requestParams.targetIdentifiers,
250
+ submittedByUserId
251
+ },
252
+ callingFlowSharedLib.addParentCallingFlowConfig(
253
+ callingFlowConfig,
254
+ callingFlowSharedLib.createCallingFlowConfig(
255
+ await lambdaSharedLib.lambdaFunctionName(
256
+ _izContext,
257
+ 'CreateAfterHookCallbackHdrSqs'
258
+ ),
259
+ {
260
+ quotaKeys,
261
+ actionData
262
+ }
263
+ )
264
+ )
265
+ );
266
+
267
+ await sns.publishAsync(_izContext, {
268
+ TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
269
+ _izContext,
270
+ '<%= hook.flowTag %>_In'
271
+ ),
272
+ Message: JSON.stringify(hookMsg_<%= hook.flowTag %>),
273
+ MessageAttributes: sns.createStringMessageAttributes(_izContext, {})
274
+ });
275
+ <%_ if (hook.objType?.objectType) { _%>
276
+ }
277
+ <%_ } _%>
278
+ <%_ }) _%>
279
+ <%_ } else { _%>
201
280
  await forwardToQuotaConfirmation(_izContext, {
202
281
  status,
203
282
  errorsFound,
@@ -205,6 +284,7 @@ export default async function CreateNodeCallbackMain(
205
284
  actionData,
206
285
  callingFlowConfig
207
286
  });
287
+ <%_ } _%>
208
288
  }
209
289
 
210
290
  await asyncFlowSharedLib.removeAwaitingMultipleStep(
@@ -0,0 +1,99 @@
1
+ /*
2
+ Copyright (C) 2026 Sven Mason <http://izara.io>
3
+
4
+ This program is free software: you can redistribute it and/or modify
5
+ it under the terms of the GNU Affero General Public License as
6
+ published by the Free Software Foundation, either version 3 of the
7
+ License, or (at your option) any later version.
8
+
9
+ This program is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ GNU Affero General Public License for more details.
13
+
14
+ You should have received a copy of the GNU Affero General Public License
15
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ */
17
+
18
+ import {
19
+ <%- flowTag %>LogicalLib,
20
+ handleDeleteError
21
+ } from './<%- upperCaseFlowTag %>LogicalLib.js';
22
+
23
+ //(<optionalRequire>)
24
+ //(</optionalRequire>)
25
+
26
+ /**
27
+ * Handles callback after async BeforeHook completion
28
+ * @param {Object} _izContext - Izara context object
29
+ * @param {Object} requestParams - Callback request parameters
30
+ * @param {Object} passBackProperties - Pass-back properties
31
+ * @returns {Promise<Object>} Result object
32
+ */
33
+ export default async function <%- upperCaseFlowTag %>BeforeHookCallbackMain(
34
+ _izContext,
35
+ requestParams,
36
+ passBackProperties
37
+ //(<additionalParams>)
38
+ //(</additionalParams>)
39
+ ) {
40
+ try {
41
+ _izContext.logger.debug('[<%- upperCaseFlowTag %>BeforeHookCallback] started', {
42
+ requestParams,
43
+ passBackProperties
44
+ });
45
+
46
+ const {
47
+ status,
48
+ errorsFound = [],
49
+ returnValue,
50
+ parentFlowId
51
+ } = requestParams;
52
+
53
+ const mergedErrors = Array.isArray(errorsFound) ? [...errorsFound] : [];
54
+ if (status === 'error' && mergedErrors.length === 0) {
55
+ mergedErrors.push('BeforeHook execution reported error');
56
+ }
57
+
58
+ const callingFlowConfig =
59
+ passBackProperties?.callingFlowConfig ||
60
+ requestParams?.passBackProperties?.callingFlowConfig ||
61
+ {};
62
+
63
+ const originalRequestParams =
64
+ passBackProperties?.originalRequestParams ||
65
+ requestParams?.passBackProperties?.originalRequestParams ||
66
+ passBackProperties?.requestParams ||
67
+ passBackProperties;
68
+
69
+ if (mergedErrors.length > 0) {
70
+ _izContext.logger.warn(
71
+ '[<%- upperCaseFlowTag %>BeforeHookCallback] BeforeHook reported errors:',
72
+ mergedErrors
73
+ );
74
+ return await handleDeleteError(_izContext, {
75
+ objType: originalRequestParams?.objType,
76
+ identifiers: originalRequestParams?.identifiers || {},
77
+ targetIdentifiers: originalRequestParams?.targetIdentifiers,
78
+ callingFlowConfig,
79
+ errorsFound: mergedErrors
80
+ });
81
+ }
82
+
83
+ if (returnValue?.identifiers && originalRequestParams?.identifiers) {
84
+ Object.assign(originalRequestParams.identifiers, returnValue.identifiers);
85
+ }
86
+
87
+ //(<beforeLogicalExecution>)
88
+ //(</beforeLogicalExecution>)
89
+
90
+ return await <%- flowTag %>LogicalLib(
91
+ _izContext,
92
+ originalRequestParams,
93
+ callingFlowConfig
94
+ );
95
+ } catch (error) {
96
+ _izContext.logger.error('[<%- upperCaseFlowTag %>BeforeHookCallback] error:', error);
97
+ throw error;
98
+ }
99
+ }