@izara_project/izara-core-generate-service-code 1.0.85 → 1.0.87

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 (43) hide show
  1. package/package.json +1 -1
  2. package/src/compile/compileProject.js +1 -2
  3. package/src/compile/loadSchemas.js +29 -17
  4. package/src/emit/coreFunction/emitCoreFunctionArtifacts.js +2 -1
  5. package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +32 -14
  6. package/src/emit/crud/crudActionPlan.js +1 -1
  7. package/src/emit/crud/emitCrudApplicationArtifacts.js +10 -4
  8. package/src/emit/crud/emitDynamicCrudFlowSchemas.js +16 -8
  9. package/src/emit/crud/templates/CreateEndpoint_Main.ejs +12 -3
  10. package/src/emit/crud/templates/CreateLogicalLib.ejs +85 -20
  11. package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +48 -7
  12. package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +47 -6
  13. package/src/emit/crud/templates/UpdateLogicalLib.ejs +754 -353
  14. package/src/emit/function/functionYamlArtifact.js +4 -2
  15. package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +5 -5
  16. package/src/emit/rbac/emitRbacApplicationArtifacts.js +70 -89
  17. package/src/emit/rbac/templates/CancelUsage_Main.ejs +14 -10
  18. package/src/emit/rbac/templates/ConfirmUsage_Main.ejs +14 -10
  19. package/src/emit/rbac/templates/CreateTargetRole_Main.ejs +56 -16
  20. package/src/emit/rbac/templates/DeleteTargetRole_Main.ejs +96 -0
  21. package/src/emit/rbac/templates/GetMyPermissions_Main.ejs +110 -0
  22. package/src/emit/rbac/templates/GetTargetRole_Main.ejs +62 -0
  23. package/src/emit/rbac/templates/ReservedDynamicUsage_Main.ejs +76 -34
  24. package/src/emit/rbac/templates/UpdateTargetRole_Main.ejs +107 -0
  25. package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +24 -21
  26. package/src/emit/rbac/templates/UserRoleMutation_Main.ejs +12 -0
  27. package/src/emit/resource/emitResourceArtifacts.js +75 -8
  28. package/src/emit/resource/templates/GeneratedLambdaRoleServiceConfig.ejs +4 -2
  29. package/src/emit/resource/templates/SystemDynamoDB_Yaml.ejs +14 -18
  30. package/src/emit/system/templates/WebSocketComplete_Yaml.ejs +4 -2
  31. package/src/emit/systemText/emitSystemTextSchemas.js +5 -2
  32. package/src/generate.js +18 -12
  33. package/src/generateResources/IntTest/generateResources/generateResources.js +1 -1
  34. package/src/generateResources/IntTest/generateTests/generateTemplate.js +1 -1
  35. package/src/generateResources/IntTest/upload/uploadIntTest.js +8 -2
  36. package/test/createTargetRoleHandler.test.js +42 -15
  37. package/test/crudApplicationArtifacts.test.js +62 -3
  38. package/test/customFlowApplicationArtifacts.test.js +3 -5
  39. package/test/dynamicCrudFlowSchemas.test.js +5 -17
  40. package/test/dynamicRbacFlowSchemas.test.js +5 -5
  41. package/test/functionYamlArtifact.test.js +4 -2
  42. package/test/publicApi.test.js +18 -14
  43. package/test/resourceArtifacts.test.js +7 -3
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright (C) 2020 Sven Mason <http: //izara.io>
2
+ Copyright (C) 2021 Sven Mason <http://izara.io>
3
3
 
4
4
  This program is free software: you can redistribute it and/or modify
5
5
  it under the terms of the GNU Affero General Public License as
@@ -8,12 +8,11 @@ License, or (at your option) any later version.
8
8
 
9
9
  This program is distributed in the hope that it will be useful,
10
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
12
  GNU Affero General Public License for more details.
13
13
 
14
14
  You should have received a copy of the GNU Affero General Public License
15
- along with this program. If not, see
16
- <http: //www.gnu.org/licenses />.
15
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
17
16
  */
18
17
 
19
18
  // ==================== Shared Core Utilities ====================
@@ -35,10 +34,6 @@ import {
35
34
  dataDetailsLib,
36
35
  uploadUseCase
37
36
  } from '@izara_project/izara-core-library-service-schemas';
38
- const { createObjType } = utils;
39
- const { dynamoDbIdentifiersByStorageResource } = identifiersObject;
40
- const { createUpdateDataDetail } = dataDetailsLib;
41
- const { PREFIX, TOPIC_NAME_GENERATE_CODE, TOPIC_NAME_GRAPH_HANDLER } = consts;
42
37
 
43
38
  // ==================== Shared Libraries ====================
44
39
  import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
@@ -56,13 +51,632 @@ import {
56
51
  //(<optionalRequire>)
57
52
  //(</optionalRequire>)
58
53
 
54
+ const { createObjType } = utils;
55
+ const { dynamoDbIdentifiersByStorageResource } = identifiersObject;
56
+ const { createUpdateDataDetail } = dataDetailsLib;
57
+ const { PREFIX: _constPrefix, TOPIC_NAME_GENERATE_CODE, TOPIC_NAME_GRAPH_HANDLER } = consts;
58
+
59
+ const PREFIX = {
60
+ ASYNC: _constPrefix.updateNode,
61
+ UPDATE_OBJECT_ASYNC_COMPLETE: 'UpdateAsyncEndpointComplete'
62
+ };
63
+
64
+ // ── 1. Update_Main Helpers ───────────────────────────────────────────────────
65
+
66
+ /**
67
+ * Loads ObjectSchema and resolves submittedByUserId and targetIdentifiers
68
+ * @param {Object} _izContext - Izara context object
69
+ * @param {Object} requestParams - Incoming request parameters
70
+ * @param {Array<string>} errorsFound - Array to collect validation errors
71
+ * @returns {Promise<{ objType: string, objectSchema: Object }>}
72
+ */
73
+ export async function resolveSchemaAndIdentity(_izContext, requestParams, errorsFound) {
74
+ const objType = createObjType(requestParams.objectType);
75
+ const objectSchema = await getObjectSchema.getObjSchemaS3WithHierarchy(
76
+ _izContext,
77
+ objType
78
+ );
79
+ _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] objectSchema:`, objectSchema);
80
+
81
+ let submittedByUserId;
82
+ let targetIdentifiers;
83
+ if (
84
+ objectSchema.generatedBy === 'user' ||
85
+ objectSchema.generatedBy === 'systemWithUser'
86
+ ) {
87
+ if (requestParams.submittedByUserId) {
88
+ submittedByUserId = requestParams.submittedByUserId;
89
+ } else if (_izContext.correlationIds) {
90
+ submittedByUserId = _izContext.correlationIds.get(coreConsts.SUBMITTED_BY_USER_ID);
91
+ }
92
+
93
+ targetIdentifiers = requestParams.targetIdentifiers;
94
+
95
+ if (!targetIdentifiers && objectSchema.belongTo?.objectType === 'user' && submittedByUserId) {
96
+ targetIdentifiers = { submittedByUserId };
97
+ }
98
+
99
+ if (!submittedByUserId) {
100
+ errorsFound.push('Not have submittedByUserId');
101
+ }
102
+ if (objectSchema.hasOwnProperty('belongTo') && !targetIdentifiers) {
103
+ errorsFound.push('not have targetIdentifiers');
104
+ }
105
+
106
+ requestParams.submittedByUserId = submittedByUserId;
107
+ if (targetIdentifiers) {
108
+ if (!targetIdentifiers.submittedByUserId && submittedByUserId) {
109
+ targetIdentifiers.submittedByUserId = submittedByUserId;
110
+ }
111
+ requestParams.targetIdentifiers = targetIdentifiers;
112
+ }
113
+
114
+ _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] Identity & Target Context Resolved:`, {
115
+ submittedByUserId: requestParams.submittedByUserId,
116
+ targetIdentifiers: requestParams.targetIdentifiers,
117
+ belongTo: objectSchema.belongTo,
118
+ generatedBy: objectSchema.generatedBy
119
+ });
120
+ } else if (objectSchema.generatedBy === 'searchResultGenerated') {
121
+ throw new NoRetryError(
122
+ 'error searchResultGenerated should not happen here'
123
+ );
124
+ }
125
+
126
+ requestParams.submittedByUserId = submittedByUserId;
127
+ return { objType, objectSchema };
128
+ }
129
+
130
+ // ── 2. UpdateRbacCallback_Main Helpers ────────────────────────────────────────
131
+
132
+ /**
133
+ * Checks awaiting steps status and collects returned results from App and Target RBAC
134
+ * @param {Object} _izContext - Izara context object
135
+ * @param {Object} requestParams - Request parameters with parentFlowId
136
+ * @returns {Promise<{ isComplete: boolean, rbacResults?: Object, originalRequestParams?: Object, collectedErrors?: Array<string> }>}
137
+ */
138
+ export async function collectRbacAwaitingResults(_izContext, requestParams) {
139
+ const parts = requestParams.parentFlowId.split('_');
140
+ const rbacType = parts.pop();
141
+ const rbacPendingStepId = '<%- flowTag %>RbacCallback_' + parts.join('_');
142
+ const currentAwaitingStepId = requestParams.parentFlowId;
143
+
144
+ _izContext.logger.debug(
145
+ '[<%- flowTag %>RbacCallbackMain] Parsed RBAC pending details:',
146
+ {
147
+ rbacType,
148
+ rbacPendingStepId,
149
+ currentAwaitingStepId,
150
+ parentFlowId: requestParams.parentFlowId
151
+ }
152
+ );
153
+
154
+ const rbacAwaitingStepsResult =
155
+ await asyncFlowSharedLib.checkAllAwaitingStepsFinishedWithReturnParams(
156
+ _izContext,
157
+ rbacPendingStepId,
158
+ currentAwaitingStepId,
159
+ requestParams.errorsFound,
160
+ {
161
+ returnValue: requestParams.returnValue,
162
+ rbacType
163
+ }
164
+ );
165
+
166
+ _izContext.logger.debug(
167
+ '[<%- flowTag %>RbacCallbackMain] checkAllAwaitingStepsFinishedWithReturnParams result:',
168
+ {
169
+ rbacAwaitingStepsResult
170
+ }
171
+ );
172
+
173
+ const {
174
+ isComplete,
175
+ collectedReturnValueByAwaitingStepId,
176
+ collectedErrors: errorsFound = [],
177
+ additionalAttributes
178
+ } = rbacAwaitingStepsResult;
179
+
180
+ if (isComplete === false) {
181
+ _izContext.logger.debug(
182
+ '[<%- flowTag %>RbacCallbackMain] Awaiting steps still pending completion:',
183
+ {
184
+ rbacPendingStepId,
185
+ isComplete
186
+ }
187
+ );
188
+ return { isComplete: false };
189
+ }
190
+
191
+ _izContext.logger.debug(
192
+ '[<%- flowTag %>RbacCallbackMain] All awaiting steps completed — clearing awaiting steps:',
193
+ {
194
+ rbacPendingStepId
195
+ }
196
+ );
197
+
198
+ await asyncFlowSharedLib.clearAllAwaitingSteps(
199
+ _izContext,
200
+ rbacPendingStepId
201
+ );
202
+
203
+ let originalRequestParams = {};
204
+ if (additionalAttributes?.requestParams) {
205
+ originalRequestParams = additionalAttributes.requestParams;
206
+ }
207
+
208
+ const rbacResults = {};
209
+ if (collectedReturnValueByAwaitingStepId) {
210
+ for (const [stepId, attrs] of Object.entries(collectedReturnValueByAwaitingStepId)) {
211
+ const type = stepId.split('_').pop();
212
+ rbacResults[type] = attrs;
213
+ }
214
+ }
215
+
216
+ return {
217
+ isComplete: true,
218
+ rbacResults,
219
+ originalRequestParams,
220
+ collectedErrors: errorsFound
221
+ };
222
+ }
223
+
59
224
  /**
60
- * Core logical processing library
225
+ * Asserts RBAC permission and publishes rejected response if unauthorized
226
+ * @param {Object} _izContext - Izara context object
227
+ * @param {Object} options - Validation options
228
+ * @returns {Promise<{ hasError: boolean, errorResult?: Object, rbacCallbackResults: Object }>}
229
+ */
230
+ export async function assertRbacPermission(_izContext, { rbacResults, originalRequestParams, errorsFound }) {
231
+ const rbacCallbackResults = {};
232
+ let hasError = false;
233
+
234
+ for (const [type, result] of Object.entries(rbacResults || {})) {
235
+ if (result && result.error) {
236
+ errorsFound.push(result.error);
237
+ hasError = true;
238
+ } else {
239
+ rbacCallbackResults[type] = result;
240
+ }
241
+ }
242
+
243
+ let isAllowed = false;
244
+ for (const item of Object.values(rbacCallbackResults)) {
245
+ if (item?.returnValue?.permission === true) {
246
+ isAllowed = true;
247
+ break;
248
+ }
249
+ }
250
+
251
+ if (!isAllowed) {
252
+ errorsFound.push('Permission denied');
253
+ }
254
+
255
+ _izContext.logger.debug(
256
+ '[<%- flowTag %>RbacCallbackMain] Final rbacCallbackResults before calling <%- flowTag %>MainLogical:',
257
+ {
258
+ rbacCallbackResults,
259
+ isAllowed,
260
+ errorsFound
261
+ }
262
+ );
263
+
264
+ if (hasError || errorsFound.length > 0) {
265
+ const errorResult = {
266
+ errorsFound,
267
+ status: 'rejected',
268
+ requestParams: originalRequestParams
269
+ };
270
+
271
+ _izContext.logger.debug(
272
+ '[<%- flowTag %>RbacCallbackMain] RBAC check failed, publishing rejected status:',
273
+ errorResult
274
+ );
275
+
276
+ await sns.publishAsync(_izContext, {
277
+ TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
278
+ _izContext,
279
+ '<%- upperCaseFlowTag %>_Out',
280
+ process.env.iz_serviceTag
281
+ ),
282
+ Message: JSON.stringify(errorResult)
283
+ });
284
+
285
+ return { hasError: true, errorResult, rbacCallbackResults };
286
+ }
287
+
288
+ return { hasError: false, rbacCallbackResults };
289
+ }
290
+
291
+ // ── 3. UpdateLogicalLib Internal Helpers ──────────────────────────────────────
292
+
293
+ /**
294
+ * Resolves and combines object schemas and updateDataDetails
295
+ * @param {Object} _izContext - Izara context object
296
+ * @param {string} objectType - Object type identifier
297
+ * @returns {Promise<{ objType: string, objectSchema: Object, objectSchemas: Object, updateDataDetails: Object }>}
298
+ */
299
+ export async function resolveObjectSchemas(_izContext, objectType) {
300
+ const objType = createObjType(objectType);
301
+ const objectSchema = await getObjectSchema.getObjSchemaS3WithHierarchy(
302
+ _izContext,
303
+ objType
304
+ );
305
+ _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>LogicalLib] objectSchema:`, objectSchema);
306
+
307
+ const objectSchemas =
308
+ await uploadUseCase.generateObjectSchemaForCombineFieldNames(
309
+ _izContext,
310
+ objectSchema
311
+ );
312
+ _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>LogicalLib] objectSchemas:`, objectSchemas);
313
+
314
+ const updateDataDetails = await createUpdateDataDetail(
315
+ _izContext,
316
+ objectSchemas
317
+ );
318
+ _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>LogicalLib] updateDataDetails:`, updateDataDetails);
319
+
320
+ return { objType, objectSchema, objectSchemas, updateDataDetails };
321
+ }
322
+
323
+ /**
324
+ * Validates versionedDataIds against object schema and request fields
325
+ * @param {Object} requestParams - Request parameters
326
+ * @param {Object} objectSchema - Object schema
327
+ * @param {Object} versionedDataIds - Versioned data IDs map
328
+ * @param {Array<string>} errorsFound - Array to collect validation errors
329
+ */
330
+ export function validateVersionedDataIds(
331
+ requestParams,
332
+ objectSchema,
333
+ versionedDataIds,
334
+ errorsFound
335
+ ) {
336
+ const versionedDataIdsKeys = Object.keys(versionedDataIds || {});
337
+ if (versionedDataIdsKeys.length === 0) {
338
+ return;
339
+ }
340
+
341
+ const updateMainNodeData = {};
342
+ const updateVersionedData = {};
343
+
344
+ for (const [fieldProp, fieldVal] of Object.entries(
345
+ requestParams.objInstanceFull?.fields || {}
346
+ )) {
347
+ const fieldSetting = objectSchema.fieldNames[fieldProp];
348
+ if (fieldSetting?.hasOwnProperty('versionedDataLabel')) {
349
+ const label = fieldSetting.versionedDataLabel;
350
+ if (!updateVersionedData[label]) {
351
+ updateVersionedData[label] = {};
352
+ }
353
+ Object.assign(updateVersionedData[label], { [fieldProp]: fieldVal });
354
+ } else {
355
+ Object.assign(updateMainNodeData, { [fieldProp]: fieldVal });
356
+ }
357
+ }
358
+
359
+ const versionedDataIdLabelKeys = Object.keys(versionedDataIds);
360
+ const updateVersionedDataLabelKeys = Object.keys(updateVersionedData);
361
+
362
+ const missingVersionedDataIdLabels = updateVersionedDataLabelKeys.filter(
363
+ (l) => !versionedDataIdLabelKeys.includes(l)
364
+ );
365
+ const missingDataVersionedDataLabels = versionedDataIdLabelKeys.filter(
366
+ (l) => !updateVersionedDataLabelKeys.includes(l)
367
+ );
368
+
369
+ if (missingVersionedDataIdLabels.length > 0) {
370
+ errorsFound.push(
371
+ `missing versionedDataIds of versionedDataLabel '${missingVersionedDataIdLabels.join(', ')}'`
372
+ );
373
+ }
374
+ if (missingDataVersionedDataLabels.length > 0) {
375
+ errorsFound.push(
376
+ `missing data of versionedDataLabels '${missingDataVersionedDataLabels.join(', ')}'`
377
+ );
378
+ }
379
+ if (Object.keys(updateMainNodeData).length > 0) {
380
+ errorsFound.push('cannot update mainNode if have versionedDataIds');
381
+ }
382
+ }
383
+
384
+ /**
385
+ * Extracts fields matching storage resource specifications
386
+ * @param {Object} _izContext - Izara context object
387
+ * @param {string} storageTag - Storage resource tag
388
+ * @param {Object} updateDataDetails - Complete update data details map
389
+ * @param {Object} updateDataDetail - Current storage update data detail
390
+ * @param {Object} requestParams - Request parameters
391
+ * @param {Object} identifiers - Identifiers map
392
+ * @returns {Object} Extracted fields object
393
+ */
394
+ export function extractFieldsByStorageTag(
395
+ _izContext,
396
+ storageTag,
397
+ updateDataDetails,
398
+ updateDataDetail,
399
+ requestParams,
400
+ identifiers
401
+ ) {
402
+ const result = {};
403
+ for (const fieldName of Object.keys(
404
+ requestParams.objInstanceFull?.fields || {}
405
+ )) {
406
+ if (
407
+ updateDataDetails[storageTag].fieldNames.includes(fieldName) &&
408
+ updateDataDetail.fieldNames.includes(fieldName) &&
409
+ !identifiers.hasOwnProperty(fieldName) &&
410
+ !result.hasOwnProperty(fieldName)
411
+ ) {
412
+ Object.assign(result, {
413
+ [fieldName]: requestParams.objInstanceFull.fields[fieldName]
414
+ });
415
+ }
416
+ }
417
+ return result;
418
+ }
419
+
420
+ /**
421
+ * Builds objInstanceFull matching updated object fields
422
+ * @param {Object} object - Source data object
423
+ * @param {Object} requestParams - Request parameters
424
+ * @returns {Object} Full object instance with identifiers and fields
425
+ */
426
+ export function createObjInstanceFullFromParams(object, requestParams) {
427
+ const objInstanceFull = { identifiers: {}, fields: {} };
428
+ for (const field of Object.keys(object || {})) {
429
+ if (requestParams.objInstanceFull?.identifiers?.hasOwnProperty(field)) {
430
+ Object.assign(objInstanceFull.identifiers, {
431
+ [field]: requestParams.objInstanceFull.identifiers[field]
432
+ });
433
+ }
434
+ if (requestParams.objInstanceFull?.fields?.hasOwnProperty(field)) {
435
+ Object.assign(objInstanceFull.fields, {
436
+ [field]: requestParams.objInstanceFull.fields[field]
437
+ });
438
+ }
439
+ }
440
+ return objInstanceFull;
441
+ }
442
+
443
+ /**
444
+ * Dispatches node update request to Graph Service
445
+ * @param {Object} _izContext - Izara context object
446
+ * @param {Object} options - Graph dispatch configuration
447
+ * @returns {Promise<void>}
448
+ */
449
+ export async function dispatchToGraphEngine(
450
+ _izContext,
451
+ {
452
+ objType,
453
+ identifiers,
454
+ graphFields,
455
+ versionedDataIds,
456
+ originTimestamp,
457
+ settings,
458
+ parentFlowId,
459
+ callingFlowConfig,
460
+ storageTag,
461
+ records = []
462
+ }
463
+ ) {
464
+ const awaitingStepIds = [{
465
+ awaitingStepId: asyncFlowSharedLib.createAwaitingStepId(
466
+ parentFlowId,
467
+ PREFIX.ASYNC
468
+ ),
469
+ additionalAttributes: {
470
+ listOfRecords: records,
471
+ additionalAttributes: {}
472
+ }
473
+ }];
474
+
475
+ await asyncFlowSharedLib.createAwaitingMultipleSteps(
476
+ _izContext,
477
+ asyncFlowSharedLib.createPendingStepId(_izContext.uniqueRequestId),
478
+ awaitingStepIds,
479
+ {
480
+ additionalAttributes: {
481
+ callingFlowConfig
482
+ }
483
+ }
484
+ );
485
+
486
+ let updateNodeParams = {
487
+ objType,
488
+ objInstanceFull: { identifiers, fields: graphFields },
489
+ versionedDataIds,
490
+ originTimestamp,
491
+ settings,
492
+ parentFlowId
493
+ };
494
+
495
+ updateNodeParams =
496
+ callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
497
+ updateNodeParams,
498
+ callingFlowSharedLib.addParentCallingFlowConfig(
499
+ callingFlowConfig,
500
+ callingFlowSharedLib.createCallingFlowConfig(
501
+ //(<callingFlowProperties>)
502
+ await lambdaSharedLib.lambdaFunctionName(
503
+ _izContext,
504
+ TOPIC_NAME_GENERATE_CODE.updateNodeComplete
505
+ ),
506
+ {}
507
+ //(</callingFlowProperties>)
508
+ )
509
+ )
510
+ );
511
+
512
+ _izContext.logger.debug(
513
+ 'messageObject before send message:',
514
+ updateNodeParams
515
+ );
516
+
517
+ await sns.publishAsync(_izContext, {
518
+ Message: JSON.stringify(updateNodeParams),
519
+ MessageAttributes: sns.createStringMessageAttributes(
520
+ _izContext,
521
+ callingFlowSharedLib.addCallingFlowToSnsResponseMessageAttributes(
522
+ callingFlowConfig,
523
+ {}
524
+ )
525
+ ),
526
+ TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
527
+ _izContext,
528
+ TOPIC_NAME_GRAPH_HANDLER.inUpdateNode,
529
+ storageTag
530
+ )
531
+ });
532
+ }
533
+
534
+ /**
535
+ * Handles DynamoDB-only complete notification when no Graph callback is required
536
+ * @param {Object} _izContext - Izara context object
537
+ * @param {Object} options - Completion parameters
538
+ * @returns {Promise<void>}
539
+ */
540
+ export async function handleDynamoDbOnlyComplete(
541
+ _izContext,
542
+ {
543
+ objType,
544
+ updateItem,
545
+ requestParams,
546
+ callingFlowConfig
547
+ }
548
+ ) {
549
+ let messageObject = {
550
+ objType,
551
+ objInstanceFull: createObjInstanceFullFromParams(
552
+ updateItem,
553
+ requestParams
554
+ )
555
+ };
556
+
557
+ //(<additionalProperties>)
558
+ //(</additionalProperties>)
559
+
560
+ if (
561
+ callingFlowConfig[
562
+ callingFlowSharedLib.consts.CALLINGFLOWPROPERTIES_PROPERTYNAME
563
+ ]
564
+ ) {
565
+ _izContext.logger.debug('HAVE CALLING FLOW');
566
+ messageObject =
567
+ callingFlowSharedLib.addPassBackPropertiesToSnsResponseMessageObject(
568
+ callingFlowConfig,
569
+ messageObject
570
+ );
571
+
572
+ _izContext.logger.debug('after create callingFlow', messageObject);
573
+ await sns.publishAsync(_izContext, {
574
+ Message: JSON.stringify(messageObject),
575
+ MessageAttributes: sns.createStringMessageAttributes(
576
+ _izContext,
577
+ callingFlowSharedLib.addCallingFlowToSnsResponseMessageAttributes(
578
+ callingFlowConfig,
579
+ {}
580
+ )
581
+ ),
582
+ TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
583
+ _izContext,
584
+ TOPIC_NAME_GENERATE_CODE.outUpdateNodeComplete
585
+ )
586
+ });
587
+ }
588
+ }
589
+
590
+ /**
591
+ * Handles update errors and publishes error response
592
+ * @param {Object} _izContext - Izara context object
593
+ * @param {Object} options - Error context details
594
+ * @returns {Promise<Object>} Error status result
595
+ */
596
+ export async function handleUpdateError(
597
+ _izContext,
598
+ {
599
+ objType,
600
+ identifiers,
601
+ fields,
602
+ versionedDataIds,
603
+ callingFlowConfig,
604
+ errorsFound
605
+ }
606
+ ) {
607
+ const updateNodeCompleteMessage =
608
+ callingFlowSharedLib.addPassBackPropertiesToSnsResponseMessageObject(
609
+ callingFlowConfig,
610
+ {
611
+ objType,
612
+ objInstanceFull: { identifiers, fields },
613
+ versionedDataIds,
614
+ status: 'error',
615
+ errorsFound
616
+ }
617
+ );
618
+
619
+ _izContext.logger.debug(
620
+ 'messageParams OutUpdateNodeComplete:::',
621
+ updateNodeCompleteMessage
622
+ );
623
+
624
+ await sns.publishAsync(_izContext, {
625
+ Message: JSON.stringify(updateNodeCompleteMessage),
626
+ MessageAttributes: sns.createStringMessageAttributes(
627
+ _izContext,
628
+ callingFlowSharedLib.addCallingFlowToSnsResponseMessageAttributes(
629
+ callingFlowConfig,
630
+ {}
631
+ )
632
+ ),
633
+ TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
634
+ _izContext,
635
+ TOPIC_NAME_GENERATE_CODE.outUpdateNodeComplete
636
+ )
637
+ });
638
+
639
+ return updateNodeCompleteMessage;
640
+ }
641
+
642
+ /**
643
+ * Publishes completion message to SNS
644
+ * @param {Object} _izContext - Izara context object
645
+ * @param {Object} message - Response message object
646
+ * @param {Object} messageAttributes - Message attributes
647
+ * @returns {Promise<void>}
648
+ */
649
+ export async function publishCompletionMessage(_izContext, message, messageAttributes) {
650
+ const topicArn = snsSharedLib.snsTopicArnByFlowSchema(
651
+ _izContext,
652
+ TOPIC_NAME_GENERATE_CODE.outUpdateNodeComplete
653
+ );
654
+
655
+ _izContext.logger.debug('[UpdateComplete] publishing to SNS', {
656
+ TopicArn: topicArn,
657
+ message
658
+ });
659
+
660
+ await sns.publishAsync(_izContext, {
661
+ Message: JSON.stringify(message),
662
+ MessageAttributes: sns.createStringMessageAttributes(
663
+ _izContext,
664
+ messageAttributes
665
+ ),
666
+ TopicArn: topicArn
667
+ });
668
+ }
669
+
670
+ // ── 4. Main Logical Function ──────────────────────────────────────────────────
671
+
672
+ /**
673
+ * Core logical processing library for <%- flowTag %> flow
61
674
  * @param {Object} _izContext - Context object with logger
62
675
  * @param {Object} requestParams - { objectType, objInstanceFull, versionedDataIds, additionalParams }
63
676
  * @param {Object} callingFlowConfig - Calling flow configuration
677
+ * @param {Array<string>} errorsFound - Array of preceding errors
64
678
  * @param {Object} phaseResults - Results from preceding phases
65
- * @returns {Promise<Object>}
679
+ * @returns {Promise<Object>} Result with objType, objInstanceFull, versionedDataIds, status, errorsFound
66
680
  */
67
681
  export async function <%- flowTag %>LogicalLib(
68
682
  _izContext,
@@ -72,7 +686,7 @@ export async function <%- flowTag %>LogicalLib(
72
686
  phaseResults = {}
73
687
  ) {
74
688
  try {
75
- _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>LogicalLib] started`, {
689
+ _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>LogicalLib] started`, {
76
690
  requestParams,
77
691
  callingFlowConfig,
78
692
  phaseResults
@@ -81,381 +695,169 @@ export async function <%- flowTag %>LogicalLib(
81
695
  //(<beforeUpdateMainLogical>)
82
696
  //(</beforeUpdateMainLogical>)
83
697
 
84
- // ── Settings ──────────────────────────────────────────────────────────────
85
- const settings = requestParams.additionalParams?.settings ?? {};
698
+ const settings = {};
699
+ if (requestParams.additionalParams?.settings) {
700
+ Object.assign(settings, requestParams.additionalParams.settings);
701
+ }
86
702
  const returnSystemFieldsName = settings.returnSystemFieldsName === true;
87
703
  const returnOldData = settings.returnOldData === true;
88
704
 
89
- const objType = createObjType(requestParams.objectType);
90
- const identifiers = requestParams.objInstanceFull.identifiers;
91
- const fields = requestParams.objInstanceFull.fields;
92
- const versionedDataIds = requestParams.versionedDataIds ?? {};
93
- const parentFlowId = identifierUuid();
94
- // ── Load schema ───────────────────────────────────────────────────────────
95
- const objectSchema = await getObjectSchema.getObjSchemaS3WithHierarchy(
96
- _izContext,
97
- objType
98
- );
99
- _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>LogicalLib] objectSchema:`, objectSchema);
100
-
101
- const objectSchemas =
102
- await uploadUseCase.generateObjectSchemaForCombineFieldNames(
103
- _izContext,
104
- objectSchema
105
- );
106
- _izContext.logger.debug('objectSchemas', objectSchemas);
705
+ let identifiers = {};
706
+ if (requestParams.objInstanceFull?.identifiers) {
707
+ identifiers = requestParams.objInstanceFull.identifiers;
708
+ }
709
+ let fields = {};
710
+ if (requestParams.objInstanceFull?.fields) {
711
+ fields = requestParams.objInstanceFull.fields;
712
+ }
107
713
 
108
- // ── Build updateDataDetails ───────────────────────────────────────────────
109
- const updateDataDetails = await createUpdateDataDetail(
110
- _izContext,
111
- objectSchemas
112
- );
113
- _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>LogicalLib] updateDataDetails:`, updateDataDetails);
714
+ let versionedDataIds = {};
715
+ if (requestParams.versionedDataIds) {
716
+ versionedDataIds = requestParams.versionedDataIds;
717
+ }
114
718
 
719
+ const parentFlowId = identifierUuid();
115
720
  const originTimestamp = Date.now();
116
721
 
117
- // ── Validate versionedDataIds ─────────────────────────────────────────────
118
- const haveVersionedDataIdsToUpdate =
119
- Object.keys(versionedDataIds).length > 0;
120
- if (haveVersionedDataIdsToUpdate) {
121
- const updateMainNodeData = {};
122
- const updateVersionedData = {};
123
-
124
- for (const [fieldProp, fieldVal] of Object.entries(
125
- requestParams.objInstanceFull.fields
126
- )) {
127
- const fieldSetting = objectSchema.fieldNames[fieldProp];
128
- if (fieldSetting.hasOwnProperty('versionedDataLabel')) {
129
- updateVersionedData[fieldSetting.versionedDataLabel] ??= {};
130
- Object.assign(updateVersionedData[fieldSetting.versionedDataLabel], {
131
- [fieldProp]: fieldVal
132
- });
133
- } else {
134
- Object.assign(updateMainNodeData, { [fieldProp]: fieldVal });
135
- }
136
- }
137
-
138
- _izContext.logger.debug('updateMainNodeData::', updateMainNodeData);
139
- _izContext.logger.debug('updateVersionedData::', updateVersionedData);
140
-
141
- const versionedDataIdLabelKeys = Object.keys(versionedDataIds);
142
- const updateVersionedDataLabelKeys = Object.keys(updateVersionedData);
722
+ // 1. Resolve schemas & data details
723
+ const { objType, objectSchema, updateDataDetails } =
724
+ await resolveObjectSchemas(_izContext, requestParams.objectType);
143
725
 
144
- const missingVersionedDataIdLabels = updateVersionedDataLabelKeys.filter(
145
- (l) => !versionedDataIdLabelKeys.includes(l)
146
- );
147
- const missingDataVersionedDataLabels = versionedDataIdLabelKeys.filter(
148
- (l) => !updateVersionedDataLabelKeys.includes(l)
149
- );
150
-
151
- if (missingVersionedDataIdLabels.length)
152
- errorsFound.push(
153
- `missing versionedDataIds of versionedDataLabel '${missingVersionedDataIdLabels.join(', ')}'`
154
- );
155
- if (missingDataVersionedDataLabels.length)
156
- errorsFound.push(
157
- `missing data of versionedDataLabels '${missingDataVersionedDataLabels.join(', ')}'`
158
- );
159
- if (Object.keys(updateMainNodeData).length)
160
- errorsFound.push('cannot update mainNode if have versionedDataIds');
161
- }
726
+ // 2. Validate versioned data IDs
727
+ validateVersionedDataIds(
728
+ requestParams,
729
+ objectSchema,
730
+ versionedDataIds,
731
+ errorsFound
732
+ );
162
733
 
163
734
  //(<validateBeforeUpdate>)
164
735
  //(</validateBeforeUpdate>)
165
736
 
166
- // ── Early exit on errors ──────────────────────────────────────────────────
167
- if (errorsFound.length) {
168
- const updateNodeCompleteMessage =
169
- callingFlowSharedLib.addPassBackPropertiesToSnsResponseMessageObject(
170
- callingFlowConfig,
171
- {
172
- objType,
173
- objInstanceFull: { identifiers, fields },
174
- versionedDataIds,
175
- status: 'error',
176
- errorsFound
177
- }
178
- );
179
-
180
- _izContext.logger.debug(
181
- 'messageParams OutUpdateNodeComplete:::',
182
- updateNodeCompleteMessage
183
- );
184
- await sns.publishAsync(_izContext, {
185
- Message: JSON.stringify(updateNodeCompleteMessage),
186
- MessageAttributes: sns.createStringMessageAttributes(
187
- _izContext,
188
- callingFlowSharedLib.addCallingFlowToSnsResponseMessageAttributes(
189
- callingFlowConfig,
190
- {}
191
- )
192
- ),
193
- TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
194
- _izContext,
195
- TOPIC_NAME_GENERATE_CODE.outUpdateNodeComplete
196
- )
737
+ // 3. Early exit on errors
738
+ if (errorsFound.length > 0) {
739
+ return await handleUpdateError(_izContext, {
740
+ objType,
741
+ identifiers,
742
+ fields,
743
+ versionedDataIds,
744
+ callingFlowConfig,
745
+ errorsFound
197
746
  });
198
-
199
- return updateNodeCompleteMessage;
200
- }
201
-
202
- // ── Helper: extract fields per storageTag ─────────────────────────────────
203
- function createObjInstanceFullFieldsByStorageTag(
204
- _izContext,
205
- storageTag,
206
- updateDataDetail
207
- ) {
208
- const result = {};
209
- for (const fieldName of Object.keys(
210
- requestParams.objInstanceFull.fields
211
- )) {
212
- if (
213
- updateDataDetails[storageTag].fieldNames.includes(fieldName) &&
214
- updateDataDetail.fieldNames.includes(fieldName) &&
215
- !identifiers.hasOwnProperty(fieldName) &&
216
- !result.hasOwnProperty(fieldName)
217
- ) {
218
- Object.assign(result, {
219
- [fieldName]: requestParams.objInstanceFull.fields[fieldName]
220
- });
221
- }
222
- }
223
- return result;
224
- }
225
-
226
- // ── Helper: build objInstanceFull from updateItem ─────────────────────────
227
- function createObjInstanceFullFromParams(object, requestParams) {
228
- const objInstanceFull = { identifiers: {}, fields: {} };
229
- for (const field of Object.keys(object)) {
230
- if (requestParams.objInstanceFull.identifiers.hasOwnProperty(field)) {
231
- Object.assign(objInstanceFull.identifiers, {
232
- [field]: requestParams.objInstanceFull.identifiers[field]
233
- });
234
- }
235
- if (requestParams.objInstanceFull.fields.hasOwnProperty(field)) {
236
- Object.assign(objInstanceFull.fields, {
237
- [field]: requestParams.objInstanceFull.fields[field]
238
- });
239
- }
240
- }
241
- return objInstanceFull;
242
747
  }
243
748
 
244
- // ── Process storage resources ─────────────────────────────────────────────
245
- const awaitingStepIds = [];
749
+ // 4. Process storage resources
750
+ let hasGraphStorage = false;
246
751
  const listOfRecords = [];
247
752
  let updateItem;
248
753
 
249
- await Promise.all(
250
- Object.entries(updateDataDetails).map(
251
- async ([storageTag, updateDataDetail]) => {
252
- // ── Graph ─────────────────────────────────────────────────────────────
253
- if (updateDataDetail.storageType === consts.STORAGE_TYPES.graph) {
254
- //(<beforeUpdateGraph>)
255
- //(</beforeUpdateGraph>)
754
+ for (const [storageTag, updateDataDetail] of Object.entries(updateDataDetails)) {
755
+ if (updateDataDetail.storageType === consts.STORAGE_TYPES.graph) {
756
+ const graphFields = extractFieldsByStorageTag(
757
+ _izContext,
758
+ storageTag,
759
+ updateDataDetails,
760
+ updateDataDetail,
761
+ requestParams,
762
+ identifiers
763
+ );
764
+ if (Object.keys(graphFields).length > 0) {
765
+ hasGraphStorage = true;
766
+ //(<beforeUpdateGraph>)
767
+ //(</beforeUpdateGraph>)
256
768
 
257
- const graphFields = createObjInstanceFullFieldsByStorageTag(
258
- _izContext,
259
- storageTag,
260
- updateDataDetail
261
- );
262
- if (!Object.keys(graphFields).length) return;
769
+ //(<beforeUpdateNode>)
770
+ //(</beforeUpdateNode>)
263
771
 
264
- //(<beforeUpdateNode>)
265
- //(</beforeUpdateNode>)
772
+ //(<additionalAttributes>)
773
+ //(</additionalAttributes>)
266
774
 
267
- //(<additionalAttributes>)
268
- const additionalAttributes = {};
269
- //(</additionalAttributes>)
775
+ await dispatchToGraphEngine(_izContext, {
776
+ objType,
777
+ identifiers,
778
+ graphFields,
779
+ versionedDataIds,
780
+ originTimestamp,
781
+ settings: { returnSystemFieldsName, returnOldData },
782
+ parentFlowId,
783
+ callingFlowConfig,
784
+ storageTag,
785
+ records: listOfRecords
786
+ });
787
+ }
788
+ } else if (updateDataDetail.storageType === consts.STORAGE_TYPES.dynamoDB) {
789
+ const dynamoFields = extractFieldsByStorageTag(
790
+ _izContext,
791
+ storageTag,
792
+ updateDataDetails,
793
+ updateDataDetail,
794
+ requestParams,
795
+ identifiers
796
+ );
797
+ if (Object.keys(dynamoFields).length > 0) {
798
+ //(<beforeUpdateDynamoDb>)
799
+ //(</beforeUpdateDynamoDb>)
270
800
 
271
- const records = awaitingStepIds.length === 0 ? listOfRecords : [];
272
- awaitingStepIds.push({
273
- awaitingStepId: asyncFlowSharedLib.createAwaitingStepId(
274
- parentFlowId,
275
- PREFIX.updateNode
276
- ),
277
- additionalAttributes: {
278
- listOfRecords: records,
279
- additionalAttributes: additionalAttributes
280
- }
281
- });
801
+ const identifiersForUpdateData =
802
+ await dynamoDbIdentifiersByStorageResource(
803
+ _izContext,
804
+ objectSchema,
805
+ updateDataDetail,
806
+ identifiers
807
+ );
808
+ _izContext.logger.debug(
809
+ 'identifiersForUpdateData',
810
+ identifiersForUpdateData
811
+ );
282
812
 
283
- if (awaitingStepIds.length) {
284
- const awaitingMultipleStep =
285
- await asyncFlowSharedLib.createAwaitingMultipleSteps(
286
- _izContext,
287
- asyncFlowSharedLib.createPendingStepId(
288
- _izContext.uniqueRequestId
289
- ),
290
- awaitingStepIds,
291
- {
292
- additionalAttributes: {
293
- callingFlowConfig
294
- }
295
- }
296
- );
297
- _izContext.logger.debug(
298
- 'awaitingMultipleStep',
299
- awaitingMultipleStep
300
- );
813
+ let hasGraphInSchema = false;
814
+ for (const d of Object.values(updateDataDetails)) {
815
+ if (d.storageType === consts.STORAGE_TYPES.graph) {
816
+ hasGraphInSchema = true;
817
+ break;
301
818
  }
819
+ }
302
820
 
303
- let updateNodeParams = {
304
- objType,
305
- objInstanceFull: { identifiers, fields: graphFields },
306
- versionedDataIds,
307
- originTimestamp,
308
- settings: { returnSystemFieldsName, returnOldData },
309
- parentFlowId
310
- };
311
-
312
- updateNodeParams =
313
- callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
314
- updateNodeParams,
315
- callingFlowSharedLib.addParentCallingFlowConfig(
316
- callingFlowConfig,
317
- callingFlowSharedLib.createCallingFlowConfig(
318
- //(<callingFlowProperties>)
319
- await lambdaSharedLib.lambdaFunctionName(
320
- _izContext,
321
- TOPIC_NAME_GENERATE_CODE.updateNodeComplete
322
- ),
323
- {}
324
- //(</callingFlowProperties>)
325
- )
326
- )
327
- );
328
-
329
- _izContext.logger.debug(
330
- 'messageObject before send message:',
331
- updateNodeParams
332
- );
333
-
334
- const resSNS = await sns.publishAsync(_izContext, {
335
- Message: JSON.stringify(updateNodeParams),
336
- MessageAttributes: sns.createStringMessageAttributes(
337
- _izContext,
338
- callingFlowSharedLib.addCallingFlowToSnsResponseMessageAttributes(
339
- callingFlowConfig,
340
- {}
341
- )
342
- ),
343
- TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
344
- _izContext,
345
- TOPIC_NAME_GRAPH_HANDLER.inUpdateNode,
346
- storageTag
347
- )
821
+ if (hasGraphInSchema) {
822
+ _izContext.logger.debug('must process graph first');
823
+ listOfRecords.push({
824
+ [storageTag]: {
825
+ serviceTag: updateDataDetail.serviceTag,
826
+ tableName: updateDataDetail.tableName,
827
+ objInstanceFull: {
828
+ identifiers: identifiersForUpdateData,
829
+ fields: dynamoFields
830
+ }
831
+ }
348
832
  });
349
- _izContext.logger.debug(
350
- 'resSNS send to topic InUpdateNode finish!',
351
- resSNS
352
- );
353
-
354
- // ── DynamoDB ──────────────────────────────────────────────────────────
355
- } else if (
356
- updateDataDetail.storageType === consts.STORAGE_TYPES.dynamoDB
357
- ) {
358
- const dynamoFields = createObjInstanceFullFieldsByStorageTag(
833
+ } else {
834
+ _izContext.logger.debug('can process record dynamo');
835
+ updateItem = await dynamodbSharedLib.updateItem(
359
836
  _izContext,
360
- storageTag,
361
- updateDataDetail
362
- );
363
- if (!Object.keys(dynamoFields).length) return;
364
-
365
- //(<beforeUpdateDynamoDb>)
366
- //(</beforeUpdateDynamoDb>)
367
-
368
- const identifiersForUpdateData =
369
- await dynamoDbIdentifiersByStorageResource(
837
+ await dynamodbSharedLib.tableName(
370
838
  _izContext,
371
- objectSchema,
372
- updateDataDetail,
373
- identifiers
374
- );
375
- _izContext.logger.debug(
376
- 'identifiersForUpdateData',
377
- identifiersForUpdateData
839
+ updateDataDetail.tableName,
840
+ updateDataDetail.serviceTag
841
+ ),
842
+ identifiersForUpdateData,
843
+ dynamoFields,
844
+ { returnValues: 'ALL_NEW' }
378
845
  );
379
846
 
380
- if (
381
- Object.values(updateDataDetails).some(
382
- (updateDataDetail) =>
383
- updateDataDetail.storageType === consts.STORAGE_TYPES.graph
384
- )
385
- ) {
386
- _izContext.logger.debug('must process graph first');
387
- listOfRecords.push({
388
- [storageTag]: {
389
- serviceTag: updateDataDetail.serviceTag,
390
- tableName: updateDataDetail.tableName,
391
- objInstanceFull: {
392
- identifiers: identifiersForUpdateData,
393
- fields: dynamoFields
394
- }
395
- }
396
- });
397
- } else {
398
- _izContext.logger.debug('can process record dynamo');
399
- updateItem = await dynamodbSharedLib.updateItem(
400
- _izContext,
401
- await dynamodbSharedLib.tableName(
402
- _izContext,
403
- updateDataDetail.tableName,
404
- updateDataDetail.serviceTag
405
- ),
406
- identifiersForUpdateData,
407
- dynamoFields,
408
- { returnValues: 'ALL_NEW' }
409
- );
410
-
411
- _izContext.logger.debug('updateItem:', updateItem);
412
- }
847
+ _izContext.logger.debug('updateItem:', updateItem);
413
848
  }
414
849
  }
415
- )
416
- );
850
+ }
851
+ }
417
852
 
418
- // ── DynamoDB-only complete path ───────────────────────────────────────────
419
- if (awaitingStepIds.length === 0) {
420
- let messageObject = {
853
+ // 5. If no graph storage, complete immediately
854
+ if (!hasGraphStorage) {
855
+ await handleDynamoDbOnlyComplete(_izContext, {
421
856
  objType,
422
- objInstanceFull: createObjInstanceFullFromParams(
423
- updateItem,
424
- requestParams
425
- )
426
- };
427
-
428
- //(<additionalProperties>)
429
- //(</additionalProperties>)
430
-
431
- if (
432
- callingFlowConfig[
433
- callingFlowSharedLib.consts.CALLINGFLOWPROPERTIES_PROPERTYNAME
434
- ]
435
- ) {
436
- _izContext.logger.debug('HAVE CALLING FLOW');
437
- messageObject =
438
- callingFlowSharedLib.addPassBackPropertiesToSnsResponseMessageObject(
439
- callingFlowConfig,
440
- messageObject
441
- );
442
-
443
- _izContext.logger.debug('after create callingFlow', messageObject);
444
- await sns.publishAsync(_izContext, {
445
- Message: JSON.stringify(messageObject),
446
- MessageAttributes: sns.createStringMessageAttributes(
447
- _izContext,
448
- callingFlowSharedLib.addCallingFlowToSnsResponseMessageAttributes(
449
- callingFlowConfig,
450
- {}
451
- )
452
- ),
453
- TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
454
- _izContext,
455
- TOPIC_NAME_GENERATE_CODE.outUpdateNodeComplete
456
- )
457
- });
458
- }
857
+ updateItem,
858
+ requestParams,
859
+ callingFlowConfig
860
+ });
459
861
  }
460
862
 
461
863
  return {
@@ -469,7 +871,6 @@ export async function <%- flowTag %>LogicalLib(
469
871
  };
470
872
  } catch (err) {
471
873
  _izContext.logger.error(`[${process.env.iz_serviceTag}:<%- flowTag %>LogicalLib] error:`, err);
472
- _izContext.logger.error('[<%- flowTag %>LogicalLib] error:', err);
473
874
  throw err;
474
875
  }
475
876
  }