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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/package.json +2 -2
  2. package/src/compile/flowValidator.js +163 -0
  3. package/src/compile/loadSchemas.js +15 -5
  4. package/src/emit/coreFunction/emitCoreFunctionArtifacts.js +137 -7
  5. package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +137 -17
  6. package/src/emit/crud/crudActionPlan.js +82 -0
  7. package/src/emit/crud/emitCrudApplicationArtifacts.js +169 -112
  8. package/src/emit/crud/emitDynamicCrudFlowSchemas.js +43 -65
  9. package/src/emit/crud/generateDynamicCrudFlowSchemas.js +4 -1
  10. package/src/emit/crud/templates/CreateComplete_Main.ejs +8 -3
  11. package/src/emit/crud/templates/CreateEndpoint_Main.ejs +90 -513
  12. package/src/emit/crud/templates/CreateLogicalLib.ejs +541 -0
  13. package/src/emit/crud/templates/DeleteComplete_Main.ejs +8 -3
  14. package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +93 -203
  15. package/src/emit/crud/templates/DeleteLogicalLib.ejs +213 -0
  16. package/src/emit/crud/templates/FlowEndpointRbacCallback_Main.ejs +217 -0
  17. package/src/emit/crud/templates/GetEndpoint_Main.ejs +1 -1
  18. package/src/emit/crud/templates/GetRangeEndpoint_Main.ejs +118 -37
  19. package/src/emit/crud/templates/UpdateComplete_Main.ejs +8 -3
  20. package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +92 -444
  21. package/src/emit/crud/templates/UpdateLogicalLib.ejs +477 -0
  22. package/src/emit/custom/customFlows.js +27 -2
  23. package/src/emit/custom/emitCustomFlowApplicationArtifacts.js +1 -2
  24. package/src/emit/custom/templates/FlowEndpoint_Main.ejs +10 -3
  25. package/src/emit/custom/templates/FlowStep_Main.ejs +1 -1
  26. package/src/emit/custom/templates/s3/CreateObject_Main.ejs +1 -1
  27. package/src/emit/custom/templates/triggerCache/CheckTriggerCache_HdrSqs.ejs +2 -2
  28. package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +3 -9
  29. package/src/emit/rbac/emitRbacApplicationArtifacts.js +21 -16
  30. package/src/emit/rbac/rbacFlowTag.js +2 -7
  31. package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +148 -21
  32. package/src/emit/relationship/emitDynamicRelationshipFlowSchemas.js +4 -2
  33. package/src/emit/relationship/templates/ChangeRelationshipComplete_Main.ejs +7 -2
  34. package/src/emit/relationship/templates/ChangeRelationship_Main.ejs +6 -2
  35. package/src/emit/relationship/templates/CreateRelationshipComplete_Main.ejs +7 -2
  36. package/src/emit/relationship/templates/CreateRelationship_Main.ejs +6 -2
  37. package/src/emit/relationship/templates/DeleteRelationshipComplete_Main.ejs +7 -2
  38. package/src/emit/relationship/templates/DeleteRelationship_Main.ejs +6 -2
  39. package/src/emit/relationship/templates/GetRelationship_Main.ejs +1 -1
  40. package/src/emit/relationship/templates/MoveRelationshipComplete_Main.ejs +7 -2
  41. package/src/emit/relationship/templates/MoveRelationship_Main.ejs +6 -2
  42. package/src/emit/relationship/templates/UpdateRelationshipComplete_Main.ejs +7 -2
  43. package/src/emit/relationship/templates/UpdateRelationship_Main.ejs +6 -2
  44. package/src/emit/resource/emitResourceArtifacts.js +149 -79
  45. package/src/emit/resource/templates/DynamoDBTable_Yaml.ejs +4 -4
  46. package/src/emit/resource/templates/GeneratedLambdaRoleServiceConfig.ejs +31 -5
  47. package/src/emit/resource/templates/SystemDynamoDB_Yaml.ejs +21 -0
  48. package/src/emit/resource/templates/WebSocketSubscription_Yaml.ejs +7 -0
  49. package/src/emit/shared/templates/FlowHandler_HdrApi.ejs +1 -1
  50. package/src/emit/shared/templates/FlowHandler_HdrDsq.ejs +2 -2
  51. package/src/emit/shared/templates/FlowHandler_HdrInv.ejs +1 -1
  52. package/src/emit/shared/templates/FlowHandler_HdrSqs.ejs +2 -2
  53. package/src/emit/systemText/emitSystemTextSchemas.js +246 -0
  54. package/src/emit/systemText/templates/SystemTextSchemas.ejs +10 -0
  55. package/src/generate.js +55 -8
  56. package/test/crudApplicationArtifacts.test.js +158 -19
  57. package/test/customFlowApplicationArtifacts.test.js +307 -16
  58. package/test/dynamicCrudFlowSchemas.test.js +150 -14
  59. package/test/dynamicRbacFlowSchemas.test.js +2 -2
  60. package/test/dynamicRelationshipFlowSchemas.test.js +1 -1
  61. package/test/graphDrivenFlowSchema.test.js +257 -0
  62. package/test/publicApi.test.js +14 -5
  63. package/test/resourceArtifacts.test.js +66 -19
  64. package/test/systemTextSchemas.test.js +154 -0
  65. package/src/emit/crud/templates/CreateComplete_HdrSqs.ejs +0 -99
  66. package/src/emit/crud/templates/DeleteComplete_HdrSqs.ejs +0 -99
  67. package/src/emit/crud/templates/FlowEndpointBeforeLogical_Main.ejs +0 -174
  68. package/src/emit/crud/templates/FlowEndpointComplete_Main.ejs +0 -187
  69. package/src/emit/crud/templates/UpdateComplete_HdrSqs.ejs +0 -99
  70. package/src/emit/resource/templates/ResourceBeforeLogicalYaml.ejs +0 -47
@@ -0,0 +1,477 @@
1
+ /*
2
+ Copyright (C) 2020 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
16
+ <http: //www.gnu.org/licenses />.
17
+ */
18
+
19
+ // ==================== Shared Core Utilities ====================
20
+ import {
21
+ objectHash as hash,
22
+ identifierUuid
23
+ } from '@izara_project/izara-shared-core';
24
+ import {
25
+ consts as coreConsts,
26
+ NoRetryError
27
+ } from '@izara_project/izara-core-library-core';
28
+
29
+ // ==================== Core Service Schemas ====================
30
+ import {
31
+ getObjectSchema,
32
+ consts,
33
+ utils,
34
+ identifiersObject,
35
+ dataDetailsLib,
36
+ uploadUseCase
37
+ } 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
+
43
+ // ==================== Shared Libraries ====================
44
+ import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
45
+ import snsSharedLib from '@izara_project/izara-core-library-sns';
46
+ import asyncFlowSharedLib from '@izara_project/izara-core-library-asynchronous-flow';
47
+ import callingFlowSharedLib from '@izara_project/izara-core-library-calling-flow';
48
+ import lambdaSharedLib from '@izara_project/izara-core-library-lambda';
49
+
50
+ // ==================== External Services ====================
51
+ import {
52
+ sns,
53
+ lambda
54
+ } from '@izara_project/izara-core-library-external-request';
55
+
56
+ //(<optionalRequire>)
57
+ //(</optionalRequire>)
58
+
59
+ /**
60
+ * Core logical processing library
61
+ * @param {Object} _izContext - Context object with logger
62
+ * @param {Object} requestParams - { objectType, objInstanceFull, versionedDataIds, additionalParams }
63
+ * @param {Object} callingFlowConfig - Calling flow configuration
64
+ * @param {Object} phaseResults - Results from preceding phases
65
+ * @returns {Promise<Object>}
66
+ */
67
+ export async function <%- flowTag %>LogicalLib(
68
+ _izContext,
69
+ requestParams,
70
+ callingFlowConfig = {},
71
+ errorsFound = [],
72
+ phaseResults = {}
73
+ ) {
74
+ try {
75
+ _izContext.logger.debug('[<%- flowTag %>LogicalLib] started', {
76
+ requestParams,
77
+ callingFlowConfig,
78
+ phaseResults
79
+ });
80
+
81
+ //(<beforeUpdateMainLogical>)
82
+ //(</beforeUpdateMainLogical>)
83
+
84
+ // ── Settings ──────────────────────────────────────────────────────────────
85
+ const settings = requestParams.additionalParams?.settings ?? {};
86
+ const returnSystemFieldsName = settings.returnSystemFieldsName === true;
87
+ const returnOldData = settings.returnOldData === true;
88
+
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('objectSchema', objectSchema);
100
+
101
+ const objectSchemas =
102
+ await uploadUseCase.generateObjectSchemaForCombineFieldNames(
103
+ _izContext,
104
+ objectSchema
105
+ );
106
+ _izContext.logger.debug('objectSchemas', objectSchemas);
107
+
108
+ // ── Build updateDataDetails ───────────────────────────────────────────────
109
+ const updateDataDetails = await createUpdateDataDetail(
110
+ _izContext,
111
+ objectSchemas
112
+ );
113
+ _izContext.logger.debug('updateDataDetails', updateDataDetails);
114
+
115
+ const originTimestamp = Date.now();
116
+
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);
143
+
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
+ }
162
+
163
+ //(<validateBeforeUpdate>)
164
+ //(</validateBeforeUpdate>)
165
+
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
+ )
197
+ });
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
+ }
243
+
244
+ // ── Process storage resources ─────────────────────────────────────────────
245
+ const awaitingStepIds = [];
246
+ const listOfRecords = [];
247
+ let updateItem;
248
+
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>)
256
+
257
+ const graphFields = createObjInstanceFullFieldsByStorageTag(
258
+ _izContext,
259
+ storageTag,
260
+ updateDataDetail
261
+ );
262
+ if (!Object.keys(graphFields).length) return;
263
+
264
+ //(<beforeUpdateNode>)
265
+ //(</beforeUpdateNode>)
266
+
267
+ //(<additionalAttributes>)
268
+ const additionalAttributes = {};
269
+ //(</additionalAttributes>)
270
+
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
+ });
282
+
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
+ );
301
+ }
302
+
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
+ )
348
+ });
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(
359
+ _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(
370
+ _izContext,
371
+ objectSchema,
372
+ updateDataDetail,
373
+ identifiers
374
+ );
375
+ _izContext.logger.debug(
376
+ 'identifiersForUpdateData',
377
+ identifiersForUpdateData
378
+ );
379
+
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
+ }
413
+ }
414
+ }
415
+ )
416
+ );
417
+
418
+ // ── DynamoDB-only complete path ───────────────────────────────────────────
419
+ if (awaitingStepIds.length === 0) {
420
+ let messageObject = {
421
+ 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
+ }
459
+ }
460
+
461
+ return {
462
+ returnValues: {
463
+ objType,
464
+ objInstanceFull: { identifiers, fields },
465
+ versionedDataIds
466
+ },
467
+ status: 'complete',
468
+ errorsFound
469
+ };
470
+ } catch (err) {
471
+ _izContext.logger.error('[<%- flowTag %>LogicalLib] error:', err);
472
+ throw err;
473
+ }
474
+ }
475
+
476
+ export const <%- flowTag %>MainLogical = <%- flowTag %>LogicalLib;
477
+ export default <%- flowTag %>LogicalLib;
@@ -198,10 +198,36 @@ export function customFlowNextSteps(flows) {
198
198
  const roleName = upperFirst(flow.flowTag);
199
199
  const steps = flow.flowSteps ?? [];
200
200
  const nextStepsList = [];
201
+ const seenKeys = new Set();
201
202
  for (const step of steps) {
202
203
  const items = _stepNextSteps(step);
203
204
  for (const item of items) {
204
- nextStepsList.push(item);
205
+ const topicVal = item.topicName || item.topic;
206
+ const functionVal = item.functionName || item.topicName || item.topic;
207
+ const targetType = item.targetType || '';
208
+ const serviceTag = item.serviceTag || '';
209
+ let targetVal = '';
210
+ if (targetType === 'lambdaSyncInv') {
211
+ targetVal = functionVal;
212
+ } else if (targetType === 'extTopic' || targetType === 'ownTopic') {
213
+ targetVal = topicVal;
214
+ } else {
215
+ targetVal = topicVal || functionVal;
216
+ }
217
+ let typeCategory = targetType;
218
+ if (targetType === 'extTopic' || targetType === 'ownTopic') {
219
+ typeCategory = 'sns';
220
+ }
221
+ const dedupeKey = `${typeCategory}:${serviceTag}:${targetVal}`;
222
+ if (!seenKeys.has(dedupeKey)) {
223
+ seenKeys.add(dedupeKey);
224
+ nextStepsList.push({
225
+ ...item,
226
+ topic: topicVal,
227
+ topicName: topicVal,
228
+ functionName: functionVal
229
+ });
230
+ }
205
231
  }
206
232
  }
207
233
  if (nextStepsList.length > 0) {
@@ -214,4 +240,3 @@ export function customFlowNextSteps(flows) {
214
240
  }
215
241
  return results;
216
242
  }
217
-
@@ -646,8 +646,7 @@ function _startConfig(flow) {
646
646
  ) ??
647
647
  steps.find(
648
648
  (s) =>
649
- typeof s?.stepName === 'string' &&
650
- s.stepName.toLowerCase() === 'start'
649
+ typeof s?.stepName === 'string' && s.stepName.toLowerCase() === 'start'
651
650
  ) ??
652
651
  steps[0];
653
652
  if (start) {
@@ -61,7 +61,7 @@ const { createFlowTypeConcat } = utils;
61
61
  export default async function <%- typeof functionName !== 'undefined' ? functionName : upperCaseFlowTag %>(
62
62
  _izContext,
63
63
  requestParams,
64
- callingFlowConfig = {}
64
+ callingFlowConfig = {},
65
65
  //(<additionalParams>)
66
66
  //(</additionalParams>)
67
67
  ) {
@@ -109,7 +109,7 @@ export default async function <%- typeof functionName !== 'undefined' ? function
109
109
  //(</checkStoredCacheHook>)
110
110
  }
111
111
  <% } -%>
112
- <% if (typeof flow !== 'undefined' && flow.isRbac) { -%>
112
+ <% if (typeof flow !== 'undefined' && flow.isRbac && !flow.generatedCodeConfig) { -%>
113
113
 
114
114
  const { checkRbacPermission } =
115
115
  await import('@izara_project/izara-authorization');
@@ -121,7 +121,14 @@ export default async function <%- typeof functionName !== 'undefined' ? function
121
121
  const resultPermissionCheck = await checkRbacPermission(
122
122
  _izContext,
123
123
  { flowTag: '<%- flow.flowTag %>', serviceTag: '<%- flow.serviceTag || (flow.objType ? flow.objType.serviceTag : "") %>' },
124
- parameterGroups
124
+ parameterGroups,
125
+ {
126
+ rbacObjType: {
127
+ serviceTag: '<%- (flow.objType?.belongTo ? (Array.isArray(flow.objType.belongTo) ? flow.objType.belongTo[0]?.serviceTag : flow.objType.belongTo?.serviceTag) : null) || flow.serviceTag || (flow.objType ? flow.objType.serviceTag : "") %>'
128
+ },
129
+ requestParams: typeof requestParams !== 'undefined' ? requestParams : {},
130
+ nextFlowStepName: '<%- flow.flowTag %>RbacCallback'
131
+ }
125
132
  );
126
133
 
127
134
  _izContext.logger.debug(
@@ -37,7 +37,7 @@ import { identifierUuid } from '@izara_project/izara-shared-core';
37
37
  export default async function <%= functionName %>(
38
38
  _izContext,
39
39
  requestParams,
40
- callingFlowConfig = {}
40
+ callingFlowConfig = {},
41
41
  //(<additionalParams>)
42
42
  //(</additionalParams>)
43
43
  ) {
@@ -51,7 +51,7 @@ const { TOPIC_NAME_GENERATE_CODE } = schemaConsts;
51
51
  export default async function createObject(
52
52
  _izContext,
53
53
  requestParams,
54
- callingFlowConfig = {}
54
+ callingFlowConfig = {},
55
55
  //(<additionalParams>)
56
56
  //(</additionalParams>)
57
57
  ) {
@@ -11,7 +11,7 @@ let perRecordsValidatorSchema = {
11
11
  properties: {
12
12
  <%_ startConfig.properties.forEach((prop, index) => { _%>
13
13
  <%- /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(prop.propertyName) ? prop.propertyName : `'${prop.propertyName}'` %>: {
14
- type: '<%- prop.type || 'string' %>'<% if (typeof prop.default !== 'undefined') { %>,
14
+ type: <%- prop.type === 'mixed' ? "['string', 'number', 'integer', 'boolean', 'null', 'object', 'array']" : `'${prop.type || 'string'}'` %><% if (typeof prop.default !== 'undefined') { %>,
15
15
  default: <%- typeof prop.default === 'string' ? `'${prop.default.replace(/'/g, "\\'")}'` : JSON.stringify(prop.default) %><% } %>
16
16
  }<%- index < startConfig.properties.length - 1 ? ',' : '' %>
17
17
  <%_ }) _%>
@@ -29,7 +29,7 @@ let messageAttributeValidatorSchema = {
29
29
  type: 'object',
30
30
  properties: {
31
31
  Type: { type: 'string' },
32
- Value: { type: '<%- prop.type || 'string' %>' }
32
+ Value: { type: <%- prop.type === 'mixed' ? "['string', 'number', 'integer', 'boolean', 'null', 'object', 'array']" : `'${prop.type || 'string'}'` %> }
33
33
  },
34
34
  required: ['Type', 'Value']
35
35
  }<%- index < startConfig.messageAttributes.length - 1 ? ',' : '' %>
@@ -74,13 +74,7 @@ function _hasSelfRbacAddOn(object) {
74
74
  }
75
75
 
76
76
  function _hasRbacAddOn(object) {
77
- const selfHasRbac = _hasSelfRbacAddOn(object);
78
- const belongToHasRbac =
79
- Array.isArray(object?.belongToSchema?.addOnDataStructure) &&
80
- object.belongToSchema.addOnDataStructure.some(
81
- (addOn) => addOn?.type === 'rbac'
82
- );
83
- return selfHasRbac || belongToHasRbac;
77
+ return _hasSelfRbacAddOn(object);
84
78
  }
85
79
 
86
80
  async function _artifact(flowTag, flow) {
@@ -108,7 +102,7 @@ function _createSharedRbacFlow(flowTag, event) {
108
102
  },
109
103
  flowSteps: [
110
104
  {
111
- stepName: 'start',
105
+ stepName: 'Start',
112
106
  properties: [],
113
107
  messageAttributes: [],
114
108
  returnValues: {
@@ -135,7 +129,7 @@ function _createUserRbacFlow(flowTag, serviceTag, objectType) {
135
129
  },
136
130
  flowSteps: [
137
131
  {
138
- stepName: 'start',
132
+ stepName: 'Start',
139
133
  messageAttributes: ['userId', 'correlationId']
140
134
  }
141
135
  ]