@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
@@ -41,7 +41,12 @@ import {
41
41
  } from '@izara_project/izara-core-library-service-schemas';
42
42
  import snsSharedLib from '@izara_project/izara-core-library-sns';
43
43
 
44
- import { <%- flowTag %>LogicalLib } from './<%- upperCaseFlowTag %>LogicalLib.js';
44
+ import {
45
+ <%- flowTag %>LogicalLib,
46
+ resolveSchemaAndIdentity,
47
+ resolveAndGenerateIdentifiers,
48
+ validateFieldNames
49
+ } from './<%- upperCaseFlowTag %>LogicalLib.js';
45
50
 
46
51
  //(<optionalRequire>)
47
52
  //(</optionalRequire>)
@@ -50,228 +55,6 @@ const { createObjType, firstLetterUpperCase } = utils;
50
55
  const { createDataDetailsLib } = dataDetailsLib;
51
56
  const { createIdentifiersByUseCase } = identifiersObject;
52
57
 
53
- // ── Helper Functions ──────────────────────────────────────────────────────────
54
-
55
- /**
56
- * Loads Schema and resolves submittedByUserId and targetIdentifiers
57
- * @param {Object} _izContext - Izara context object
58
- * @param {Object} requestParams - Request parameters
59
- * @param {Array<string>} errorsFound - Error list
60
- * @returns {Promise<{ objType: Object, objectSchema: Object, targetIdentifiers?: Object }>}
61
- */
62
- async function resolveSchemaAndIdentity(_izContext, requestParams, errorsFound) {
63
- const objType = createObjType(requestParams.objectType);
64
- const objectSchema = await getObjectSchema.getObjSchemaS3WithHierarchy(
65
- _izContext,
66
- objType
67
- );
68
- _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] objectSchema:`, objectSchema);
69
-
70
- let submittedByUserId, targetIdentifiers;
71
- if (
72
- objectSchema.generatedBy === 'user' ||
73
- objectSchema.generatedBy === 'systemWithUser'
74
- ) {
75
- submittedByUserId =
76
- requestParams.submittedByUserId ||
77
- _izContext.correlationIds.get(coreConsts.SUBMITTED_BY_USER_ID);
78
-
79
- targetIdentifiers = requestParams.targetIdentifiers;
80
-
81
- if (!targetIdentifiers && submittedByUserId) {
82
- targetIdentifiers = { submittedByUserId };
83
- }
84
-
85
- if (!submittedByUserId) errorsFound.push('Not have submittedByUserId');
86
- if (objectSchema.hasOwnProperty('belongTo') && !targetIdentifiers)
87
- errorsFound.push('not have targetIdentifiers');
88
-
89
- if (targetIdentifiers) {
90
- if (!targetIdentifiers.submittedByUserId && submittedByUserId) {
91
- targetIdentifiers.submittedByUserId = submittedByUserId;
92
- }
93
-
94
- if (Array.isArray(objectSchema.identifiers)) {
95
- for (const identifier of objectSchema.identifiers) {
96
- if (identifier.fieldName) {
97
- if (targetIdentifiers[identifier.fieldName] === undefined) {
98
- targetIdentifiers[identifier.fieldName] = null;
99
- }
100
- } else if (Array.isArray(identifier.fieldNames)) {
101
- for (const fn of identifier.fieldNames) {
102
- if (targetIdentifiers[fn] === undefined) {
103
- targetIdentifiers[fn] = null;
104
- }
105
- }
106
- } else if (identifier.name) {
107
- if (targetIdentifiers[identifier.name] === undefined) {
108
- targetIdentifiers[identifier.name] = null;
109
- }
110
- }
111
- }
112
- }
113
-
114
- requestParams.targetIdentifiers = targetIdentifiers;
115
- }
116
-
117
- _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] Identity & Target Context Resolved:`, {
118
- submittedByUserId: requestParams.submittedByUserId,
119
- targetIdentifiers: requestParams.targetIdentifiers,
120
- belongTo: objectSchema.belongTo,
121
- generatedBy: objectSchema.generatedBy
122
- });
123
- } else if (objectSchema.generatedBy === 'searchResultGenerated') {
124
- throw new NoRetryError(
125
- 'error searchResultGenerated should not happen here'
126
- );
127
- }
128
-
129
- return { objType, objectSchema, targetIdentifiers };
130
- }
131
-
132
- /**
133
- * Resolves fromRequiredOnCreate fields and generates identifiers
134
- * @param {Object} _izContext - Izara context object
135
- * @param {Object} requestParams - Request parameters
136
- * @param {Object} objectSchema - Base object schema
137
- * @param {Object} objType - Object type
138
- * @param {Object} targetIdentifiers - Target identifiers
139
- * @param {Array<string>} errorsFound - Error list
140
- * @returns {Promise<{ objectSchemas: Object, createDataDetails: Object }>}
141
- */
142
- async function resolveAndGenerateIdentifiers(
143
- _izContext,
144
- requestParams,
145
- objectSchema,
146
- objType,
147
- targetIdentifiers,
148
- errorsFound
149
- ) {
150
- const objectSchemas =
151
- uploadUseCase.generateObjectSchemaForCombineFieldNames(
152
- _izContext,
153
- objectSchema
154
- );
155
- _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] objectSchemas:`, objectSchemas);
156
-
157
- const createDataDetails = await createDataDetailsLib(
158
- _izContext,
159
- objectSchemas
160
- );
161
- _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] createDataDetails:`, createDataDetails);
162
-
163
- if (requestParams.relationships?.length > 0) {
164
- //(<beforeValidateRelationships>)
165
- //(</beforeValidateRelationships>)
166
- }
167
-
168
- errorsFound.push(
169
- ...(await createNodeLib.validateRequiredOnCreateLinks(
170
- _izContext,
171
- objType,
172
- requestParams.relationships
173
- ))
174
- );
175
- _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] errorsFound:`, errorsFound);
176
-
177
- // ── Resolve fromRequiredOnCreate fields ──
178
- if (objectSchemas.fieldNames) {
179
- if (!requestParams.fieldNames) requestParams.fieldNames = {};
180
- for (const [fieldName, val] of Object.entries(objectSchemas.fieldNames)) {
181
- if (val.fromRequiredOnCreate && requestParams.fieldNames[fieldName] === undefined) {
182
- const fromConfig = val.fromRequiredOnCreate;
183
- const sourceField = fromConfig.fieldName || fieldName;
184
- if (fromConfig.belongToObjType === true && targetIdentifiers) {
185
- const targetValue =
186
- targetIdentifiers[sourceField] !== undefined
187
- ? targetIdentifiers[sourceField]
188
- : Object.values(targetIdentifiers)[0];
189
- requestParams.fieldNames[fieldName] = targetValue;
190
- } else if (fromConfig.relType && requestParams.relationships?.length > 0) {
191
- const matchedRel = requestParams.relationships.find(
192
- (rel) =>
193
- rel.relType?.serviceTag === fromConfig.relType.serviceTag &&
194
- rel.relType?.relationshipTag === fromConfig.relType.relationshipTag
195
- );
196
- if (matchedRel?.targetIdentifiers?.[sourceField] !== undefined) {
197
- requestParams.fieldNames[fieldName] = matchedRel.targetIdentifiers[sourceField];
198
- }
199
- }
200
- }
201
- }
202
- }
203
-
204
- // ── Resolve identifiers ──
205
- let errors;
206
- const identifiers = objectSchemas.identifiers;
207
- let optionalOnCreateIdentifiers;
208
-
209
- if (
210
- identifiers.length === 1 &&
211
- !identifiers[0].hasOwnProperty('fieldNames')
212
- ) {
213
- [requestParams, errors] = await createIdentifiersByUseCase(
214
- _izContext,
215
- requestParams,
216
- objectSchemas,
217
- identifiers[0],
218
- optionalOnCreateIdentifiers
219
- );
220
- errorsFound.push(...errors);
221
- } else if (identifiers.length > 1) {
222
- for (const identifier of identifiers) {
223
- [requestParams, errors] = await createIdentifiersByUseCase(
224
- _izContext,
225
- requestParams,
226
- objectSchemas,
227
- identifier,
228
- optionalOnCreateIdentifiers
229
- );
230
- errorsFound.push(...errors);
231
- }
232
- }
233
-
234
- return { objectSchemas, createDataDetails };
235
- }
236
-
237
- /**
238
- * Validates request field names against schema
239
- * @param {Object} requestParams - Request parameters
240
- * @param {Object} objectSchemas - Combined schema
241
- * @param {Array<string>} errorsFound - Error list
242
- */
243
- function validateFieldNames(requestParams, objectSchemas, errorsFound) {
244
- const listOfRequiredOnCreate = [];
245
- const listOfOptionalOnCreate = [];
246
-
247
- for (const [key, val] of Object.entries(objectSchemas.fieldNames)) {
248
- if (
249
- val.randomOnCreate === true ||
250
- val.requiredOnCreate === true ||
251
- val.fromRequiredOnCreate ||
252
- val.hashOnCreate?.length
253
- ) {
254
- listOfRequiredOnCreate.push(key);
255
- }
256
- if (val.requiredOnCreate === false && val.optionalOnCreate === true) {
257
- listOfOptionalOnCreate.push(key);
258
- }
259
- }
260
-
261
- for (const fieldName of Object.keys(requestParams.fieldNames)) {
262
- if (
263
- !listOfRequiredOnCreate.includes(fieldName) &&
264
- !listOfOptionalOnCreate.includes(fieldName)
265
- ) {
266
- errorsFound.push('[invalid] over fieldNames create object');
267
- }
268
- if (errorsFound.length > 0) {
269
- _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] HaveError:`, errorsFound);
270
- break;
271
- }
272
- }
273
- }
274
-
275
58
  // ── Main Entry Function ───────────────────────────────────────────────────────
276
59
 
277
60
  /**
@@ -284,15 +67,18 @@ function validateFieldNames(requestParams, objectSchemas, errorsFound) {
284
67
  export default async function <%- flowTag %>(
285
68
  _izContext,
286
69
  requestParams,
287
- callingFlowConfig = {},
70
+ callingFlowConfig = {}
288
71
  //(<additionalParams>)
289
72
  //(</additionalParams>)
290
73
  ) {
291
74
  try {
292
- _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] createMain:`, {
293
- requestParams,
294
- callingFlowConfig
295
- });
75
+ _izContext.logger.debug(
76
+ `[${process.env.iz_serviceTag}:<%- flowTag %>] createMain:`,
77
+ {
78
+ requestParams,
79
+ callingFlowConfig
80
+ }
81
+ );
296
82
 
297
83
  const errorsFound = [];
298
84
 
@@ -323,7 +109,7 @@ export default async function <%- flowTag %>(
323
109
  }
324
110
 
325
111
  // Step 3: Validate FieldNames
326
- validateFieldNames(requestParams, objectSchemas, errorsFound);
112
+ validateFieldNames(_izContext, requestParams, objectSchemas, errorsFound);
327
113
 
328
114
  if (errorsFound.length > 0) {
329
115
  return await <%- flowTag %>LogicalLib(
@@ -381,11 +167,12 @@ export default async function <%- flowTag %>(
381
167
  },
382
168
  parameterGroups,
383
169
  {
170
+ targetIdentifiers,
384
171
  rbacObjType: {
385
172
  serviceTag: <%- rbacServiceTags.length === 1 ? rbacServiceTags[0] : `{ ${Object.entries(rbacServiceTagMap).map(([k, v]) => `'${k}': ${v}`).join(', ')} }[requestParams.objectType] || process.env.iz_serviceTag` %>
386
173
  },
387
174
  requestParams: requestParams,
388
- nextFlowStepName: '<%- plan?.hasRbacCallback ? `${flowTag}RbacCallback` : `${flowTag}Complete` %>'
175
+ sync: true
389
176
  }
390
177
  );
391
178
 
@@ -394,120 +181,129 @@ export default async function <%- flowTag %>(
394
181
  resultPermissionCheck
395
182
  );
396
183
 
184
+ if (resultPermissionCheck && resultPermissionCheck.permission !== true) {
185
+ errorsFound.push('Permission denied');
186
+ return await <%- flowTag %>LogicalLib(
187
+ _izContext,
188
+ requestParams,
189
+ callingFlowConfig,
190
+ errorsFound
191
+ );
192
+ }
193
+
397
194
  //(<rbacPublish_<%- flowTag %>)
398
195
  //(</rbacPublish_<%- flowTag %>)
399
-
400
- return resultPermissionCheck;
401
196
  }
402
197
  <%_ } _%>
403
198
 
404
199
  // ── Optional phase extension point ────────────────────────────────────────
405
200
  <%_
406
- const groupedByObjType = [];
201
+ const beforeHooksByObjType = (plan?.beforeHooks || []).reduce((acc, hook) => {
202
+ const key = hook?.objType?.objectType;
203
+ if (!key) return acc;
204
+ if (!acc[key]) acc[key] = [];
205
+ acc[key].push(hook);
206
+ return acc;
207
+ }, {});
407
208
  _%>
408
- <%_ Object.entries(groupedByObjType).forEach(([objectType, configs]) => { _%>
209
+ <%_ Object.entries(beforeHooksByObjType).forEach(([objectType, configs]) => { _%>
409
210
  <%_
410
- const hasOwnTopic = configs.some(c => c.invocationType === 'ownTopic');
411
- const hasLambdaSyncInv = configs.some(c => c.invocationType === 'lambdaSyncInv');
412
- _%>
211
+ const hasOwnTopic = configs.some(c => c?.generatedCodeConfig?.invocationType === 'ownTopic' || c?.event?.includes('ownTopic'));
212
+ const hasLambdaSyncInv = configs.some(c => c?.generatedCodeConfig?.invocationType === 'lambdaSyncInv' || c?.event?.includes('lambdaSyncInv'));
213
+ _%>
413
214
  if (requestParams.objectType === '<%= objectType %>') {
414
215
  <%_ if (hasLambdaSyncInv) { _%>
415
- const lambdaSyncInvResults = await Promise.all([
416
- <%_ configs.filter(c => c.invocationType === 'lambdaSyncInv').forEach((config, index, arr) => { _%>
417
- // lambdaSyncInv <%= config.flowTag %>
418
- lambda
419
- .invokeSync(
216
+ const lambdaSyncInvResults = [];
217
+ <%_ for (const config of configs.filter(c => c?.generatedCodeConfig?.invocationType === 'lambdaSyncInv' || c?.event?.includes('lambdaSyncInv'))) { _%>
218
+ try {
219
+ const returnValue = await lambda.invokeSync(
220
+ _izContext,
221
+ await lambdaSharedLib.lambdaFunctionName(
420
222
  _izContext,
421
- await lambdaSharedLib.lambdaFunctionName(
422
- _izContext,
423
- 'Process<%= config.flowTag %>HdrInv'
424
- ),
425
- { requestParams, callingFlowConfig }
426
- )
427
- .then((returnValue) => ({
428
- flowTag: '<%= config.flowTag %>',
429
- returnValue
430
- })) /*__EJS_COMMA_14__*/
431
- // lambdaSyncInv <%= config.flowTag %>
432
- <%_ }) _%>
433
- ]);
223
+ '<%= config.flowTag %>'
224
+ ),
225
+ {
226
+ requestParams: {
227
+ objType,
228
+ fieldNames: requestParams.fieldNames,
229
+ relationships: requestParams.relationships || [],
230
+ targetIdentifiers,
231
+ submittedByUserId: requestParams.submittedByUserId
232
+ },
233
+ callingFlowConfig
234
+ }
235
+ );
236
+ lambdaSyncInvResults.push({
237
+ flowTag: '<%= config.flowTag %>',
238
+ returnValue
239
+ });
240
+ if (returnValue?.errorsFound?.length > 0) {
241
+ errorsFound.push(...returnValue.errorsFound);
242
+ } else if (returnValue?.status === 'error') {
243
+ errorsFound.push('Error from <%= config.flowTag %>');
244
+ } else {
245
+ if (returnValue?.fieldNames && requestParams?.fieldNames) {
246
+ Object.assign(requestParams.fieldNames, returnValue.fieldNames);
247
+ }
248
+ if (returnValue?.relationships && requestParams) {
249
+ requestParams.relationships = returnValue.relationships;
250
+ }
251
+ }
252
+ } catch (hookErr) {
253
+ _izContext.logger.error(
254
+ '[<%- flowTag %>] Sync hook <%= config.flowTag %> error:',
255
+ hookErr
256
+ );
257
+ errorsFound.push(hookErr.message || 'Hook <%= config.flowTag %> failed');
258
+ }
259
+ <%_ } _%>
434
260
 
261
+ if (errorsFound.length > 0) {
262
+ return await <%- flowTag %>LogicalLib(
263
+ _izContext,
264
+ requestParams,
265
+ callingFlowConfig,
266
+ errorsFound
267
+ );
268
+ }
435
269
  <%_ } _%>
436
270
 
437
271
  //(<afterBeforeLogical_<%= objectType %>>)
438
272
  //(</afterBeforeLogical_<%= objectType %>>)
439
273
 
440
274
  <%_ if (hasOwnTopic) { _%>
441
- // ── ownTopic (async — create awaitingSteps and then publish) ──────────────
442
- const awaitingMultipleStepIds = [];
443
- const recordMsgs = [];
444
-
445
- <%_ configs.filter(c => c.invocationType === 'ownTopic').forEach(config => { _%>
446
- // ownTopic <%= config.flowTag %>
447
- awaitingMultipleStepIds.push({
448
- awaitingStepId: await asyncFlowSharedLib.createAwaitingStepId(
449
- hash(objInstanceFull.identifiers),
450
- 'logical_<%= objectType %>_<%= config.flowTag.charAt(0).toUpperCase() + config.flowTag.slice(1) %>'
451
- ),
452
- additionalAttributes: {}
453
- });
454
-
455
- recordMsgs.push({
456
- msg: callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
457
- requestParams,
275
+ // ── ownTopic (async — dispatch to before-hook and await callback) ──────────
276
+ <%_ configs.filter(c => c?.generatedCodeConfig?.invocationType === 'ownTopic' || c?.event?.includes('ownTopic')).forEach(config => { _%>
277
+ const hookMsg_<%= config.flowTag %> =
278
+ callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
279
+ {
280
+ objType,
281
+ fieldNames: requestParams.fieldNames,
282
+ relationships: requestParams.relationships || [],
283
+ targetIdentifiers,
284
+ submittedByUserId: requestParams.submittedByUserId
285
+ },
458
286
  callingFlowSharedLib.addParentCallingFlowConfig(
459
287
  callingFlowConfig,
460
288
  callingFlowSharedLib.createCallingFlowConfig(
461
- //(<callingFlowProperties_<%= config.flowTag %>>)
462
289
  await lambdaSharedLib.lambdaFunctionName(
463
290
  _izContext,
464
- '<%= flowTag.toLowerCase() %>Complete'
291
+ '<%- flowTag %>BeforeHookCallbackHdrSqs'
465
292
  ),
466
- {}
467
- //(</callingFlowProperties_<%= config.flowTag %>>)
293
+ {
294
+ originalRequestParams: {
295
+ ...requestParams,
296
+ objType,
297
+ targetIdentifiers
298
+ },
299
+ callingFlowConfig
300
+ }
468
301
  )
469
302
  )
470
- ),
471
- flowTag: '<%= config.flowTag.charAt(0).toUpperCase() + config.flowTag.slice(1) %>'
472
- });
473
- <%_ }) _%>
474
-
475
- <%_ if (hasLambdaSyncInv) { _%>
476
- // ── Add lambdaSyncInv results to awaitingSteps ────────────────────────
477
- for (const syncResult of lambdaSyncInvResults) {
478
- awaitingMultipleStepIds.push({
479
- awaitingStepId: await asyncFlowSharedLib.createAwaitingStepId(
480
- hash(objInstanceFull.identifiers),
481
- 'logical_<%= objectType %>_' + syncResult.flowTag
482
- ),
483
- additionalAttributes: {
484
- complete: true,
485
- errorsFound: [],
486
- returnValue: syncResult.returnValue
487
- }
488
- });
489
- }
490
- <%_ } _%>
491
-
492
- await asyncFlowSharedLib.createAwaitingMultipleSteps(
493
- _izContext,
494
- asyncFlowSharedLib.createPendingStepId(
495
- _izContext.uniqueRequestId,
496
- 'logical_<%= objectType %>'
497
- ),
498
- awaitingMultipleStepIds,
499
- {
500
- additionalAttributes: {
501
- callingFlowConfig
502
- }
503
- }
504
- );
505
-
506
- //(<beforePublish_<%= objectType %>>)
507
- //(</beforePublish_<%= objectType %>>)
303
+ );
508
304
 
509
- for (const recordMsg of recordMsgs) {
510
- const messageAttributes = sns.createStringMessageAttributes(
305
+ const messageAttributes_<%= config.flowTag %> =
306
+ sns.createStringMessageAttributes(
511
307
  _izContext,
512
308
  callingFlowSharedLib.addCallingFlowToSnsResponseMessageAttributes(
513
309
  callingFlowConfig,
@@ -515,32 +311,36 @@ export default async function <%- flowTag %>(
515
311
  )
516
312
  );
517
313
 
518
- const topicArn = snsSharedLib.snsTopicArnByFlowSchema(
519
- _izContext,
520
- `${recordMsg.flowTag}_In`
521
- );
314
+ const topicArn_<%= config.flowTag %> = snsSharedLib.snsTopicArnByFlowSchema(
315
+ _izContext,
316
+ '<%= config.flowTag %>_In'
317
+ );
522
318
 
523
- await sns.publishAsync(_izContext, {
524
- Message: JSON.stringify(recordMsg.msg),
525
- MessageAttributes: messageAttributes,
526
- TopicArn: topicArn
527
- });
528
- }
319
+ _izContext.logger.debug(
320
+ `[${process.env.iz_serviceTag}:<%- flowTag %>] Dispatching to BeforeHook:`,
321
+ {
322
+ topicArn: topicArn_<%= config.flowTag %>,
323
+ flowTag: '<%= config.flowTag %>'
324
+ }
325
+ );
529
326
 
530
- return 'complete logical <%= objectType %>';
327
+ await sns.publishAsync(_izContext, {
328
+ Message: JSON.stringify(hookMsg_<%= config.flowTag %>),
329
+ MessageAttributes: messageAttributes_<%= config.flowTag %>,
330
+ TopicArn: topicArn_<%= config.flowTag %>
331
+ });
332
+ <%_ }) _%>
531
333
 
334
+ return {
335
+ status: 'pending',
336
+ message: 'Dispatched to BeforeHook'
337
+ };
532
338
  <%_ } else { _%>
533
- // ── lambdaSyncInv only — collect results and proceed to createLogicalLib ────────────
534
- const phaseResults = Object.fromEntries(
535
- lambdaSyncInvResults.map(({ flowTag: tag, returnValue }) => [tag, returnValue])
536
- );
537
-
538
339
  return await <%- flowTag %>LogicalLib(
539
340
  _izContext,
540
341
  requestParams,
541
342
  callingFlowConfig,
542
- errorsFound,
543
- phaseResults
343
+ errorsFound
544
344
  );
545
345
  <%_ } _%>
546
346
  }
@@ -556,7 +356,10 @@ export default async function <%- flowTag %>(
556
356
  errorsFound
557
357
  );
558
358
  } catch (err) {
559
- _izContext.logger.error(`[${process.env.iz_serviceTag}:<%- flowTag %>] error:`, err);
359
+ _izContext.logger.error(
360
+ `[${process.env.iz_serviceTag}:<%- flowTag %>] error:`,
361
+ err
362
+ );
560
363
  throw err;
561
364
  }
562
365
  }