@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
@@ -19,7 +19,7 @@ import {
19
19
  objectHash as hash,
20
20
  identifierUuid
21
21
  } from '@izara_project/izara-shared-core';
22
- import { consts as coreConsts } from '@izara_project/izara-core-library-core';
22
+
23
23
  import {
24
24
  sns,
25
25
  lambda
@@ -29,17 +29,18 @@ import callingFlowSharedLib from '@izara_project/izara-core-library-calling-flow
29
29
  import lambdaSharedLib from '@izara_project/izara-core-library-lambda';
30
30
  import {
31
31
  consts,
32
- getObjectSchema,
33
32
  utils
34
33
  } from '@izara_project/izara-core-library-service-schemas';
35
34
  import snsSharedLib from '@izara_project/izara-core-library-sns';
36
35
 
37
- import { <%- flowTag %>LogicalLib } from './<%- upperCaseFlowTag %>LogicalLib.js';
36
+ import {
37
+ <%- flowTag %>LogicalLib,
38
+ resolveSchemaAndIdentity
39
+ } from './<%- upperCaseFlowTag %>LogicalLib.js';
38
40
 
39
41
  //(<optionalRequire>)
40
42
  //(</optionalRequire>)
41
43
 
42
- const { createObjType } = utils;
43
44
 
44
45
  /**
45
46
  * Deletes an object instance with optional RBAC routing
@@ -62,53 +63,13 @@ export default async function <%- flowTag %>(
62
63
  });
63
64
 
64
65
  const errorsFound = [];
65
- const objType = createObjType(requestParams.objectType);
66
66
 
67
67
  //(<beforeDelete>)
68
68
  //(</beforeDelete>)
69
69
 
70
- // ── Load schema ───────────────────────────────────────────────────────────
71
- const objectSchema = await getObjectSchema.getObjSchemaS3WithHierarchy(
72
- _izContext,
73
- objType
74
- );
75
- _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] objectSchema:`, objectSchema);
76
-
77
- // ── Resolve submittedByUserId / targetIdentifiers ─────────────────────────
78
- let submittedByUserId, targetIdentifiers;
79
- if (
80
- objectSchema.generatedBy === 'user' ||
81
- objectSchema.generatedBy === 'systemWithUser'
82
- ) {
83
- submittedByUserId =
84
- requestParams.submittedByUserId ||
85
- _izContext.correlationIds.get(coreConsts.SUBMITTED_BY_USER_ID);
86
-
87
- targetIdentifiers = requestParams.targetIdentifiers;
88
- delete requestParams.targetIdentifiers;
89
-
90
- if (!targetIdentifiers && objectSchema.belongTo?.objectType === 'user' && submittedByUserId) {
91
- targetIdentifiers = { submittedByUserId };
92
- }
93
-
94
- if (!submittedByUserId) errorsFound.push('Not have submittedByUserId');
95
- if (objectSchema.hasOwnProperty('belongTo') && !targetIdentifiers)
96
- errorsFound.push('not have targetIdentifiers');
97
-
98
- requestParams.submittedByUserId = submittedByUserId;
99
- if (targetIdentifiers) {
100
- if (!targetIdentifiers.submittedByUserId && submittedByUserId) {
101
- targetIdentifiers.submittedByUserId = submittedByUserId;
102
- }
103
- }
104
-
105
- _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] Identity & Target Context Resolved:`, {
106
- submittedByUserId: requestParams.submittedByUserId,
107
- targetIdentifiers,
108
- belongTo: objectSchema.belongTo,
109
- generatedBy: objectSchema.generatedBy
110
- });
111
- }
70
+ // ── Resolve Schema & Identity ─────────────────────────────────────────────
71
+ const { objType, objectSchema, targetIdentifiers } =
72
+ await resolveSchemaAndIdentity(_izContext, requestParams, errorsFound);
112
73
 
113
74
  //(<beforeQuery>)
114
75
  //(</beforeQuery>)
@@ -116,36 +77,36 @@ export default async function <%- flowTag %>(
116
77
  // ── Build identifiers used by asynchronous processing ────────────────────
117
78
  const identifiers = requestParams.identifiers;
118
79
 
119
- if (!objectSchema.hasOwnProperty('belongTo')) {
120
- if (!targetIdentifiers && identifiers) {
121
- targetIdentifiers = { ...identifiers };
122
- } else if (targetIdentifiers && identifiers) {
123
- for (const [key, value] of Object.entries(identifiers)) {
124
- if (targetIdentifiers[key] === undefined && value !== undefined) {
125
- targetIdentifiers[key] = value;
126
- }
127
- }
128
- }
129
- if (targetIdentifiers) {
130
- if (!targetIdentifiers.submittedByUserId && submittedByUserId) {
131
- targetIdentifiers.submittedByUserId = submittedByUserId;
132
- }
133
- }
134
- }
135
-
136
- if (targetIdentifiers && identifiers) {
137
- for (const [key, value] of Object.entries(identifiers)) {
138
- if (
139
- targetIdentifiers[key] !== undefined &&
140
- value !== undefined &&
141
- targetIdentifiers[key] !== value
142
- ) {
143
- errorsFound.push(
144
- `targetIdentifiers.${key} must match identifiers.${key}`
145
- );
146
- }
147
- }
148
- }
80
+ // if (!objectSchema.hasOwnProperty('belongTo')) {
81
+ // if (!targetIdentifiers && identifiers) {
82
+ // targetIdentifiers = { ...identifiers };
83
+ // } else if (targetIdentifiers && identifiers) {
84
+ // for (const [key, value] of Object.entries(identifiers)) {
85
+ // if (targetIdentifiers[key] === undefined && value !== undefined) {
86
+ // targetIdentifiers[key] = value;
87
+ // }
88
+ // }
89
+ // }
90
+ // if (targetIdentifiers) {
91
+ // if (!targetIdentifiers.submittedByUserId && submittedByUserId) {
92
+ // targetIdentifiers.submittedByUserId = submittedByUserId;
93
+ // }
94
+ // }
95
+ // }
96
+
97
+ // if (targetIdentifiers && identifiers) {
98
+ // for (const [key, value] of Object.entries(identifiers)) {
99
+ // if (
100
+ // targetIdentifiers[key] !== undefined &&
101
+ // value !== undefined &&
102
+ // targetIdentifiers[key] !== value
103
+ // ) {
104
+ // errorsFound.push(
105
+ // `targetIdentifiers.${key} must match identifiers.${key}`
106
+ // );
107
+ // }
108
+ // }
109
+ // }
149
110
 
150
111
  if (errorsFound.length > 0)
151
112
  return await <%- flowTag %>LogicalLib(
@@ -200,7 +161,8 @@ export default async function <%- flowTag %>(
200
161
  serviceTag: <%- rbacServiceTags.length === 1 ? rbacServiceTags[0] : `{ ${Object.entries(rbacServiceTagMap).map(([k, v]) => `'${k}': ${v}`).join(', ')} }[requestParams.objectType] || process.env.iz_serviceTag` %>
201
162
  },
202
163
  requestParams: requestParams,
203
- nextFlowStepName: '<%- plan?.hasRbacCallback ? `${flowTag}RbacCallback` : `${flowTag}Complete` %>'
164
+ nextFlowStepName: '<%- plan?.hasRbacCallback ? `${flowTag}RbacCallback` : `${flowTag}Complete` %>',
165
+ sync: true
204
166
  }
205
167
  );
206
168
 
@@ -209,119 +171,124 @@ export default async function <%- flowTag %>(
209
171
  resultPermissionCheck
210
172
  );
211
173
 
174
+ if (resultPermissionCheck && resultPermissionCheck.permission !== true) {
175
+ errorsFound.push('Permission denied');
176
+ return await <%- flowTag %>LogicalLib(
177
+ _izContext,
178
+ requestParams,
179
+ callingFlowConfig,
180
+ errorsFound
181
+ );
182
+ }
183
+
212
184
  //(<rbacPublish_<%- flowTag %>)
213
185
  //(</rbacPublish_<%- flowTag %>)
214
-
215
- return resultPermissionCheck;
216
186
  }
217
187
  <%_ } _%>
218
188
 
219
189
  // ── Optional phase extension point ────────────────────────────────────────
220
190
  <%_
221
- const groupedByObjType = [];
191
+ const beforeHooksByObjType = (plan?.beforeHooks || []).reduce((acc, hook) => {
192
+ const key = hook?.objType?.objectType;
193
+ if (!key) return acc;
194
+ if (!acc[key]) acc[key] = [];
195
+ acc[key].push(hook);
196
+ return acc;
197
+ }, {});
222
198
  _%>
223
- <%_ Object.entries(groupedByObjType).forEach(([objectType, configs]) => { _%>
199
+ <%_ Object.entries(beforeHooksByObjType).forEach(([objectType, configs]) => { _%>
224
200
  <%_
225
- const hasOwnTopic = configs.some(c => c.invocationType === 'ownTopic');
226
- const hasLambdaSyncInv = configs.some(c => c.invocationType === 'lambdaSyncInv');
227
- _%>
201
+ const hasOwnTopic = configs.some(c => c?.generatedCodeConfig?.invocationType === 'ownTopic' || c?.event?.includes('ownTopic'));
202
+ const hasLambdaSyncInv = configs.some(c => c?.generatedCodeConfig?.invocationType === 'lambdaSyncInv' || c?.event?.includes('lambdaSyncInv'));
203
+ _%>
228
204
  if (requestParams.objectType === '<%= objectType %>') {
229
205
  <%_ if (hasLambdaSyncInv) { _%>
230
- const lambdaSyncInvResults = await Promise.all([
231
- <%_ configs.filter(c => c.invocationType === 'lambdaSyncInv').forEach((config, index, arr) => { _%>
232
- // lambdaSyncInv <%= config.flowTag %>
233
- lambda
234
- .invokeSync(
206
+ const lambdaSyncInvResults = [];
207
+ <%_ for (const config of configs.filter(c => c?.generatedCodeConfig?.invocationType === 'lambdaSyncInv' || c?.event?.includes('lambdaSyncInv'))) { _%>
208
+ try {
209
+ const returnValue = await lambda.invokeSync(
210
+ _izContext,
211
+ await lambdaSharedLib.lambdaFunctionName(
235
212
  _izContext,
236
- await lambdaSharedLib.lambdaFunctionName(
237
- _izContext,
238
- 'Process<%= config.flowTag %>HdrInv'
239
- ),
240
- { requestParams, callingFlowConfig }
241
- )
242
- .then((returnValue) => ({
243
- flowTag: '<%= config.flowTag %>',
244
- returnValue
245
- })) /*__EJS_COMMA_14__*/
246
- // lambdaSyncInv <%= config.flowTag %>
247
- <%_ }) _%>
248
- ]);
213
+ '<%= config.flowTag %>'
214
+ ),
215
+ {
216
+ requestParams: {
217
+ objType,
218
+ identifiers: requestParams.identifiers,
219
+ targetIdentifiers,
220
+ submittedByUserId: requestParams.submittedByUserId
221
+ },
222
+ callingFlowConfig
223
+ }
224
+ );
225
+ lambdaSyncInvResults.push({
226
+ flowTag: '<%= config.flowTag %>',
227
+ returnValue
228
+ });
229
+ if (returnValue?.errorsFound?.length > 0) {
230
+ errorsFound.push(...returnValue.errorsFound);
231
+ } else if (returnValue?.status === 'error') {
232
+ errorsFound.push('Error from <%= config.flowTag %>');
233
+ } else {
234
+ if (returnValue?.identifiers && requestParams?.identifiers) {
235
+ Object.assign(requestParams.identifiers, returnValue.identifiers);
236
+ }
237
+ }
238
+ } catch (hookErr) {
239
+ _izContext.logger.error(
240
+ '[<%- flowTag %>] Sync hook <%= config.flowTag %> error:',
241
+ hookErr
242
+ );
243
+ errorsFound.push(hookErr.message || 'Hook <%= config.flowTag %> failed');
244
+ }
245
+ <%_ } _%>
246
+
247
+ if (errorsFound.length > 0) {
248
+ return await <%- flowTag %>LogicalLib(
249
+ _izContext,
250
+ requestParams,
251
+ callingFlowConfig,
252
+ errorsFound
253
+ );
254
+ }
249
255
  <%_ } _%>
250
256
 
251
257
  //(<afterBeforeLogical_<%= objectType %>>)
252
258
  //(</afterBeforeLogical_<%= objectType %>>)
253
259
 
254
260
  <%_ if (hasOwnTopic) { _%>
255
- // ── ownTopic (async — create awaitingSteps and then publish) ──────────
256
- const awaitingMultipleStepIds = [];
257
- const recordMsgs = [];
258
-
259
- <%_ configs.filter(c => c.invocationType === 'ownTopic').forEach(config => { _%>
260
- // ownTopic <%= config.flowTag %>
261
- awaitingMultipleStepIds.push({
262
- awaitingStepId: await asyncFlowSharedLib.createAwaitingStepId(
263
- hash(identifiers),
264
- 'logical_<%= objectType %>_<%= config.flowTag.charAt(0).toUpperCase() + config.flowTag.slice(1) %>'
265
- ),
266
- additionalAttributes: {}
267
- });
268
-
269
- recordMsgs.push({
270
- msg: callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
271
- requestParams,
261
+ // ── ownTopic (async — dispatch to before-hook and await callback) ──────────
262
+ <%_ configs.filter(c => c?.generatedCodeConfig?.invocationType === 'ownTopic' || c?.event?.includes('ownTopic')).forEach(config => { _%>
263
+ const hookMsg_<%= config.flowTag %> =
264
+ callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
265
+ {
266
+ objType,
267
+ identifiers: requestParams.identifiers,
268
+ targetIdentifiers,
269
+ submittedByUserId: requestParams.submittedByUserId
270
+ },
272
271
  callingFlowSharedLib.addParentCallingFlowConfig(
273
272
  callingFlowConfig,
274
273
  callingFlowSharedLib.createCallingFlowConfig(
275
- //(<callingFlowProperties_<%= config.flowTag %>>)
276
274
  await lambdaSharedLib.lambdaFunctionName(
277
275
  _izContext,
278
- '<%= flowTag.toLowerCase() %>Complete'
276
+ '<%- flowTag %>BeforeHookCallbackHdrSqs'
279
277
  ),
280
- {}
281
- //(</callingFlowProperties_<%= config.flowTag %>>)
278
+ {
279
+ originalRequestParams: {
280
+ ...requestParams,
281
+ objType,
282
+ targetIdentifiers
283
+ },
284
+ callingFlowConfig
285
+ }
282
286
  )
283
287
  )
284
- ),
285
- flowTag: '<%= config.flowTag.charAt(0).toUpperCase() + config.flowTag.slice(1) %>'
286
- });
287
- <%_ }) _%>
288
-
289
- <%_ if (hasLambdaSyncInv) { _%>
290
- // ── Add lambdaSyncInv results to awaitingSteps ────────────────────────
291
- for (const syncResult of lambdaSyncInvResults) {
292
- awaitingMultipleStepIds.push({
293
- awaitingStepId: await asyncFlowSharedLib.createAwaitingStepId(
294
- hash(identifiers),
295
- 'logical_<%= objectType %>_' + syncResult.flowTag
296
- ),
297
- additionalAttributes: {
298
- complete: true,
299
- errorsFound: [],
300
- returnValue: syncResult.returnValue
301
- }
302
- });
303
- }
304
- <%_ } _%>
305
-
306
- await asyncFlowSharedLib.createAwaitingMultipleSteps(
307
- _izContext,
308
- asyncFlowSharedLib.createPendingStepId(
309
- _izContext.uniqueRequestId,
310
- 'logical_<%= objectType %>'
311
- ),
312
- awaitingMultipleStepIds,
313
- {
314
- additionalAttributes: {
315
- callingFlowConfig
316
- }
317
- }
318
- );
319
-
320
- //(<beforePublish_<%= objectType %>>)
321
- //(</beforePublish_<%= objectType %>>)
288
+ );
322
289
 
323
- for (const recordMsg of recordMsgs) {
324
- const messageAttributes = sns.createStringMessageAttributes(
290
+ const messageAttributes_<%= config.flowTag %> =
291
+ sns.createStringMessageAttributes(
325
292
  _izContext,
326
293
  callingFlowSharedLib.addCallingFlowToSnsResponseMessageAttributes(
327
294
  callingFlowConfig,
@@ -329,32 +296,36 @@ export default async function <%- flowTag %>(
329
296
  )
330
297
  );
331
298
 
332
- const topicArn = snsSharedLib.snsTopicArnByFlowSchema(
333
- _izContext,
334
- `${recordMsg.flowTag}_In`
335
- );
299
+ const topicArn_<%= config.flowTag %> = snsSharedLib.snsTopicArnByFlowSchema(
300
+ _izContext,
301
+ '<%= config.flowTag %>_In'
302
+ );
336
303
 
337
- await sns.publishAsync(_izContext, {
338
- Message: JSON.stringify(recordMsg.msg),
339
- MessageAttributes: messageAttributes,
340
- TopicArn: topicArn
341
- });
342
- }
304
+ _izContext.logger.debug(
305
+ `[${process.env.iz_serviceTag}:<%- flowTag %>] Dispatching to BeforeHook:`,
306
+ {
307
+ topicArn: topicArn_<%= config.flowTag %>,
308
+ flowTag: '<%= config.flowTag %>'
309
+ }
310
+ );
343
311
 
344
- return 'complete logical <%= objectType %>';
312
+ await sns.publishAsync(_izContext, {
313
+ Message: JSON.stringify(hookMsg_<%= config.flowTag %>),
314
+ MessageAttributes: messageAttributes_<%= config.flowTag %>,
315
+ TopicArn: topicArn_<%= config.flowTag %>
316
+ });
317
+ <%_ }) _%>
345
318
 
319
+ return {
320
+ status: 'pending',
321
+ message: 'Dispatched to BeforeHook'
322
+ };
346
323
  <%_ } else { _%>
347
- // ── lambdaSyncInv only — collect results and proceed to deleteLogicalLib
348
- const phaseResults = Object.fromEntries(
349
- lambdaSyncInvResults.map(({ flowTag: tag, returnValue }) => [tag, returnValue])
350
- );
351
-
352
324
  return await <%- flowTag %>LogicalLib(
353
325
  _izContext,
354
326
  requestParams,
355
327
  callingFlowConfig,
356
- errorsFound,
357
- phaseResults
328
+ errorsFound
358
329
  );
359
330
  <%_ } _%>
360
331
  }
@@ -46,6 +46,135 @@ const { TOPIC_NAME_GENERATE_CODE } = consts;
46
46
  //(<optionalRequire>)
47
47
  //(</optionalRequire>)
48
48
 
49
+ // ── 1. Delete_Main Helpers ───────────────────────────────────────────────────
50
+
51
+ /**
52
+ * Loads ObjectSchema and resolves submittedByUserId and targetIdentifiers
53
+ * @param {Object} _izContext - Izara context object
54
+ * @param {Object} requestParams - Incoming request parameters
55
+ * @param {Array<string>} errorsFound - Array to collect validation errors
56
+ * @returns {Promise<{ objType: string, objectSchema: Object, targetIdentifiers?: Object }>}
57
+ */
58
+ export async function resolveSchemaAndIdentity(
59
+ _izContext,
60
+ requestParams,
61
+ errorsFound
62
+ ) {
63
+ const objType = createObjType(requestParams.objectType);
64
+ const objectSchema = await getObjectSchema.getObjSchemaS3WithHierarchy(
65
+ _izContext,
66
+ objType
67
+ );
68
+ _izContext.logger.debug(
69
+ `[${process.env.iz_serviceTag}:<%- flowTag %>] objectSchema:`,
70
+ objectSchema
71
+ );
72
+
73
+ let submittedByUserId;
74
+ let targetIdentifiers;
75
+ if (
76
+ objectSchema.generatedBy === 'user' ||
77
+ objectSchema.generatedBy === 'systemWithUser'
78
+ ) {
79
+ submittedByUserId =
80
+ requestParams.submittedByUserId ||
81
+ _izContext.correlationIds.get(coreConsts.SUBMITTED_BY_USER_ID);
82
+
83
+ targetIdentifiers = requestParams.targetIdentifiers;
84
+ delete requestParams.targetIdentifiers;
85
+
86
+ if (
87
+ !targetIdentifiers &&
88
+ objectSchema.belongTo?.objectType === 'user' &&
89
+ submittedByUserId
90
+ ) {
91
+ targetIdentifiers = { submittedByUserId };
92
+ }
93
+
94
+ if (!submittedByUserId) {
95
+ errorsFound.push('Not have submittedByUserId');
96
+ }
97
+ if (objectSchema.hasOwnProperty('belongTo') && !targetIdentifiers) {
98
+ errorsFound.push('not have targetIdentifiers');
99
+ }
100
+
101
+ requestParams.submittedByUserId = submittedByUserId;
102
+ if (targetIdentifiers) {
103
+ if (!targetIdentifiers.submittedByUserId && submittedByUserId) {
104
+ targetIdentifiers.submittedByUserId = submittedByUserId;
105
+ }
106
+ }
107
+
108
+ _izContext.logger.debug(
109
+ `[${process.env.iz_serviceTag}:<%- flowTag %>] Identity & Target Context Resolved:`,
110
+ {
111
+ submittedByUserId: requestParams.submittedByUserId,
112
+ targetIdentifiers,
113
+ belongTo: objectSchema.belongTo,
114
+ generatedBy: objectSchema.generatedBy
115
+ }
116
+ );
117
+ }
118
+
119
+ return { objType, objectSchema, targetIdentifiers };
120
+ }
121
+
122
+ /**
123
+ * Handles delete errors and publishes error response
124
+ * @param {Object} _izContext - Izara context object
125
+ * @param {Object} options - Error context details
126
+ * @returns {Promise<Object>} Error status result
127
+ */
128
+ export async function handleDeleteError(
129
+ _izContext,
130
+ {
131
+ objType,
132
+ identifiers,
133
+ targetIdentifiers,
134
+ callingFlowConfig,
135
+ errorsFound
136
+ }
137
+ ) {
138
+ const deleteNodeCompleteMessage =
139
+ callingFlowSharedLib.addPassBackPropertiesToSnsResponseMessageObject(
140
+ callingFlowConfig,
141
+ {
142
+ objType,
143
+ identifiers,
144
+ targetIdentifiers,
145
+ status: 'error',
146
+ errorsFound
147
+ }
148
+ );
149
+
150
+ _izContext.logger.debug(
151
+ 'messageParams OutDeleteNodeComplete::',
152
+ deleteNodeCompleteMessage
153
+ );
154
+ await sns.publishAsync(_izContext, {
155
+ Message: JSON.stringify(deleteNodeCompleteMessage),
156
+ MessageAttributes: sns.createStringMessageAttributes(
157
+ _izContext,
158
+ callingFlowSharedLib.addCallingFlowToSnsResponseMessageAttributes(
159
+ callingFlowConfig,
160
+ {}
161
+ )
162
+ ),
163
+ TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
164
+ _izContext,
165
+ TOPIC_NAME_GENERATE_CODE.outDeleteNodeComplete
166
+ )
167
+ });
168
+
169
+ return {
170
+ objType,
171
+ identifiers,
172
+ targetIdentifiers,
173
+ status: 'error',
174
+ errorsFound
175
+ };
176
+ }
177
+
49
178
  /**
50
179
  * Core logical processing library
51
180
  * @param {Object} _izContext - Context object with logger
@@ -93,36 +222,13 @@ export async function <%- flowTag %>LogicalLib(
93
222
 
94
223
  // ── Early exit on errors ──────────────────────────────────────────────────
95
224
  if (errorsFound.length) {
96
- const deleteNodeCompleteMessage =
97
- callingFlowSharedLib.addPassBackPropertiesToSnsResponseMessageObject(
98
- callingFlowConfig,
99
- {
100
- objType,
101
- identifiers: requestParams.identifiers,
102
- status: 'error',
103
- errorsFound
104
- }
105
- );
106
-
107
- _izContext.logger.debug(
108
- 'messageParams OutDeleteNodeComplete::',
109
- deleteNodeCompleteMessage
110
- );
111
- await sns.publishAsync(_izContext, {
112
- Message: JSON.stringify(deleteNodeCompleteMessage),
113
- TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
114
- _izContext,
115
- TOPIC_NAME_GENERATE_CODE.outDeleteNodeComplete
116
- )
117
- });
118
-
119
- return {
225
+ return await handleDeleteError(_izContext, {
120
226
  objType,
121
227
  identifiers: requestParams.identifiers,
122
228
  targetIdentifiers: requestParams.targetIdentifiers,
123
- status: 'error',
229
+ callingFlowConfig,
124
230
  errorsFound
125
- };
231
+ });
126
232
  }
127
233
 
128
234
  //(<validateBeforeDelete>)