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

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 (61) 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 +132 -17
  6. package/src/emit/crud/crudActionPlan.js +82 -0
  7. package/src/emit/crud/emitCrudApplicationArtifacts.js +162 -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/CreateEndpoint_Main.ejs +84 -512
  11. package/src/emit/crud/templates/CreateLogicalLib.ejs +536 -0
  12. package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +87 -202
  13. package/src/emit/crud/templates/DeleteLogicalLib.ejs +213 -0
  14. package/src/emit/crud/templates/FlowEndpointRbacCallback_Main.ejs +217 -0
  15. package/src/emit/crud/templates/GetEndpoint_Main.ejs +1 -1
  16. package/src/emit/crud/templates/GetRangeEndpoint_Main.ejs +9 -2
  17. package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +87 -444
  18. package/src/emit/crud/templates/UpdateLogicalLib.ejs +472 -0
  19. package/src/emit/custom/customFlows.js +27 -2
  20. package/src/emit/custom/emitCustomFlowApplicationArtifacts.js +1 -2
  21. package/src/emit/custom/templates/FlowEndpoint_Main.ejs +10 -3
  22. package/src/emit/custom/templates/FlowStep_Main.ejs +1 -1
  23. package/src/emit/custom/templates/s3/CreateObject_Main.ejs +1 -1
  24. package/src/emit/custom/templates/triggerCache/CheckTriggerCache_HdrSqs.ejs +2 -2
  25. package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +3 -9
  26. package/src/emit/rbac/emitRbacApplicationArtifacts.js +21 -16
  27. package/src/emit/rbac/rbacFlowTag.js +2 -7
  28. package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +148 -21
  29. package/src/emit/relationship/emitDynamicRelationshipFlowSchemas.js +4 -2
  30. package/src/emit/relationship/templates/ChangeRelationship_Main.ejs +1 -1
  31. package/src/emit/relationship/templates/CreateRelationship_Main.ejs +1 -1
  32. package/src/emit/relationship/templates/DeleteRelationship_Main.ejs +1 -1
  33. package/src/emit/relationship/templates/GetRelationship_Main.ejs +1 -1
  34. package/src/emit/relationship/templates/MoveRelationship_Main.ejs +1 -1
  35. package/src/emit/relationship/templates/UpdateRelationship_Main.ejs +1 -1
  36. package/src/emit/resource/emitResourceArtifacts.js +83 -68
  37. package/src/emit/resource/templates/GeneratedLambdaRoleServiceConfig.ejs +31 -5
  38. package/src/emit/resource/templates/SystemDynamoDB_Yaml.ejs +21 -0
  39. package/src/emit/resource/templates/WebSocketSubscription_Yaml.ejs +7 -0
  40. package/src/emit/shared/templates/FlowHandler_HdrApi.ejs +1 -1
  41. package/src/emit/shared/templates/FlowHandler_HdrDsq.ejs +2 -2
  42. package/src/emit/shared/templates/FlowHandler_HdrInv.ejs +1 -1
  43. package/src/emit/shared/templates/FlowHandler_HdrSqs.ejs +2 -2
  44. package/src/emit/systemText/emitSystemTextSchemas.js +246 -0
  45. package/src/emit/systemText/templates/SystemTextSchemas.ejs +10 -0
  46. package/src/generate.js +55 -8
  47. package/test/crudApplicationArtifacts.test.js +147 -19
  48. package/test/customFlowApplicationArtifacts.test.js +308 -16
  49. package/test/dynamicCrudFlowSchemas.test.js +150 -14
  50. package/test/dynamicRbacFlowSchemas.test.js +2 -2
  51. package/test/dynamicRelationshipFlowSchemas.test.js +1 -1
  52. package/test/graphDrivenFlowSchema.test.js +257 -0
  53. package/test/publicApi.test.js +14 -5
  54. package/test/resourceArtifacts.test.js +25 -19
  55. package/test/systemTextSchemas.test.js +154 -0
  56. package/src/emit/crud/templates/CreateComplete_HdrSqs.ejs +0 -99
  57. package/src/emit/crud/templates/DeleteComplete_HdrSqs.ejs +0 -99
  58. package/src/emit/crud/templates/FlowEndpointBeforeLogical_Main.ejs +0 -174
  59. package/src/emit/crud/templates/FlowEndpointComplete_Main.ejs +0 -187
  60. package/src/emit/crud/templates/UpdateComplete_HdrSqs.ejs +0 -99
  61. package/src/emit/resource/templates/ResourceBeforeLogicalYaml.ejs +0 -47
@@ -19,8 +19,6 @@ import {
19
19
  objectHash as hash,
20
20
  identifierUuid
21
21
  } from '@izara_project/izara-shared-core';
22
- import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
23
- import snsSharedLib from '@izara_project/izara-core-library-sns';
24
22
  import asyncFlowSharedLib from '@izara_project/izara-core-library-asynchronous-flow';
25
23
  import callingFlowSharedLib from '@izara_project/izara-core-library-calling-flow';
26
24
  import lambdaSharedLib from '@izara_project/izara-core-library-lambda';
@@ -28,7 +26,6 @@ import {
28
26
  consts as coreConsts,
29
27
  NoRetryError
30
28
  } from '@izara_project/izara-core-library-core';
31
- import { consts as middlewareConsts } from '@izara_project/izara-middleware';
32
29
  import {
33
30
  sns,
34
31
  lambda
@@ -42,497 +39,19 @@ import {
42
39
  identifiersObject,
43
40
  dataDetailsLib
44
41
  } from '@izara_project/izara-core-library-service-schemas';
45
- import graphSharedLibs from '@izara_project/izara-core-library-graph-service';
42
+ import snsSharedLib from '@izara_project/izara-core-library-sns';
43
+
44
+ import { <%- flowTag %>LogicalLib } from './<%- upperCaseFlowTag %>LogicalLib.js';
46
45
 
47
46
  //(<optionalRequire>)
48
47
  //(</optionalRequire>)
49
48
 
50
49
  const { createObjType, firstLetterUpperCase } = utils;
51
50
  const { createDataDetailsLib } = dataDetailsLib;
52
- const { dynamoDbIdentifiersByStorageResource, createIdentifiersByUseCase } =
53
- identifiersObject;
54
- const { TOPIC_NAME_GENERATE_CODE, TOPIC_NAME_GRAPH_HANDLER } = consts;
55
-
56
- const PREFIX = {
57
- ONE: 'one',
58
- MANY: 'many',
59
- CREATE_OBJECT_ASYNC: 'CreateAsyncEndpoint',
60
- CREATE_OBJECT_ASYNC_COMPLETE: 'CreateAsyncEndpointComplete',
61
- CREATE_OBJECT_EXTERNAL_TOPIC: 'CreateExternalTopicEndpoint'
62
- };
63
-
64
- /**
65
- * Core logical processing after beforeLogical phase completes
66
- * Called by both createMain (no beforeLogical) and createBeforeLogicalMain (after callback)
67
- * @param {Object} _izContext - Context object with logger
68
- * @param {Object} requestParams - { fieldNames, relationships[] }
69
- * @param {Object} callingFlowConfig - Calling flow configuration
70
- * @param {Object} beforeLogicalResults - Results from beforeLogical
71
- * @returns {Promise<Object>} Result with objType, objInstanceFull, relationships, status, errorsFound
72
- */
73
- export async function <%- flowTag %>MainLogical(
74
- _izContext,
75
- requestParams,
76
- callingFlowConfig = {},
77
- errorsFound = [],
78
- beforeLogicalResults = {}
79
- ) {
80
- try {
81
- _izContext.logger.debug('[<%- flowTag %>MainLogical] started', {
82
- requestParams,
83
- callingFlowConfig,
84
- beforeLogicalResults
85
- });
86
-
87
- //(<beforeCreateMainLogical>)
88
- //(</beforeCreateMainLogical>)
89
-
90
- const objType = createObjType(requestParams.objectType);
91
-
92
- // ── Load schema ───────────────────────────────────────────────────────────
93
- const objectSchema = await getObjectSchema.getObjSchemaS3WithHierarchy(
94
- _izContext,
95
- objType
96
- );
97
- _izContext.logger.debug('objectSchema', objectSchema);
98
-
99
- const objectSchemas =
100
- uploadUseCase.generateObjectSchemaForCombineFieldNames(
101
- _izContext,
102
- objectSchema
103
- );
104
- _izContext.logger.debug('objectSchemas', objectSchemas);
105
-
106
- // ── Parent object ─────────────────────────────────────────────────────────
107
- let parentObject;
108
- if (objectSchemas.hasOwnProperty('extendObjType')) {
109
- parentObject = await getObjectSchema.getObjSchemaS3WithHierarchy(
110
- _izContext,
111
- objectSchema.extendObjType
112
- );
113
- }
114
-
115
- // ── Detect invocation type ────────────────────────────────────────────────
116
- const directInvoke =
117
- requestParams.hasOwnProperty('__context__') &&
118
- requestParams.izEventSource?.eventSourceTag === 'DirectInvoke';
119
-
120
- // ── Build createDataDetails ───────────────────────────────────────────────
121
- const createDataDetails = await createDataDetailsLib(
122
- _izContext,
123
- objectSchemas
124
- );
125
- _izContext.logger.debug('createDataDetails:', createDataDetails);
126
-
127
- // ── Build objInstanceFull identifiers ─────────────────────────────────────
128
- const objInstanceFull = { identifiers: {}, fields: {} };
129
-
130
- for (const fieldName of Object.keys(requestParams.fieldNames)) {
131
- if (objectSchemas.identifierFieldNames.includes(fieldName)) {
132
- Object.assign(objInstanceFull.identifiers, {
133
- [fieldName]: requestParams.fieldNames[fieldName]
134
- });
135
- }
136
- }
137
-
138
- // ── Helper: extract fields per storageTag ─────────────────────────────────
139
- function createObjInstanceFullFieldsByStorageTag(
140
- _izContext,
141
- storageTag,
142
- createDataDetail
143
- ) {
144
- const fields = {};
145
- for (const fieldName of Object.keys(requestParams.fieldNames)) {
146
- if (
147
- createDataDetails[storageTag].fieldNames.includes(fieldName) &&
148
- createDataDetail.fieldNames.includes(fieldName) &&
149
- !objInstanceFull.identifiers.hasOwnProperty(fieldName) &&
150
- !fields.hasOwnProperty(fieldName)
151
- ) {
152
- Object.assign(fields, {
153
- [fieldName]: requestParams.fieldNames[fieldName]
154
- });
155
- }
156
- }
157
- return fields;
158
- }
159
-
160
- // ── Process storage resources ─────────────────────────────────────────────
161
- const objInstanceFullForDynamoDb = structuredClone(objInstanceFull);
162
- const objInstanceFullForGraph = structuredClone(objInstanceFull);
163
- const objInstanceFullForExternalTopic = structuredClone(objInstanceFull);
164
- const parentFlowId = identifierUuid();
165
- const allAwaitingStepsId = [];
166
- const listOfObjectForCreates = [];
167
- const listOfRecords = [];
168
-
169
- if (errorsFound.length === 0) {
170
- //(<validateBeforeCreate>)
171
- //(</validateBeforeCreate>)
172
-
173
- for (const [storageTag, createDataDetail] of Object.entries(
174
- createDataDetails
175
- )) {
176
- //(<beforeCreate>)
177
- //(</beforeCreate>)
178
-
179
- // ── DynamoDB ──────────────────────────────────────────────────────────
180
- if (createDataDetail.storageType === consts.STORAGE_TYPES.dynamoDB) {
181
- _izContext.logger.debug('::::::DynamoDB::::::', {
182
- storageTag,
183
- objInstanceFull
184
- });
185
-
186
- if (
187
- parentObject &&
188
- createDataDetail.tableName.includes(
189
- firstLetterUpperCase(`${parentObject.objectType}Records`)
190
- )
191
- ) {
192
- Object.assign(objInstanceFullForDynamoDb.fields, {
193
- [`${parentObject.objectType}HandlerServiceTag`]:
194
- process.env.iz_serviceTag
195
- });
196
- }
197
-
198
- Object.assign(
199
- objInstanceFullForDynamoDb.fields,
200
- createObjInstanceFullFieldsByStorageTag(
201
- _izContext,
202
- storageTag,
203
- createDataDetail
204
- )
205
- );
206
-
207
- _izContext.logger.debug(
208
- 'objInstanceFull before create item in dynamoDB',
209
- objInstanceFullForDynamoDb
210
- );
211
-
212
- const identifiersForCreateData =
213
- await dynamoDbIdentifiersByStorageResource(
214
- _izContext,
215
- objectSchema,
216
- createDataDetails,
217
- objInstanceFullForDynamoDb.identifiers
218
- );
219
- _izContext.logger.debug(
220
- 'identifiersForCreateData',
221
- identifiersForCreateData
222
- );
223
-
224
- //(<beforeCreateRecordDynamo>)
225
- //(</beforeCreateRecordDynamo>)
226
-
227
- if (
228
- Object.values(createDataDetails).some(
229
- (createDataDetail) =>
230
- createDataDetail.storageType === consts.STORAGE_TYPES.graph
231
- )
232
- ) {
233
- _izContext.logger.debug('must process graph first');
234
- listOfRecords.push({
235
- [storageTag]: {
236
- serviceTag: createDataDetail.serviceTag,
237
- tableName: createDataDetail.tableName,
238
- objInstanceFull: {
239
- identifiers: identifiersForCreateData,
240
- fields: objInstanceFullForDynamoDb.fields
241
- }
242
- }
243
- });
244
- } else {
245
- _izContext.logger.debug('can process record dynamo');
246
- await dynamodbSharedLib.putItem(
247
- _izContext,
248
- dynamodbSharedLib.tableName(
249
- _izContext,
250
- createDataDetail.tableName,
251
- createDataDetail.serviceTag
252
- ),
253
- {
254
- ...identifiersForCreateData,
255
- ...objInstanceFullForDynamoDb.fields
256
- }
257
- );
258
-
259
- objInstanceFullForDynamoDb.fields = {};
260
- }
261
-
262
- //(<afterCreateRecordDynamo>)
263
- //(</afterCreateRecordDynamo>)
264
-
265
- // ── Graph ─────────────────────────────────────────────────────────────
266
- } else if (
267
- createDataDetail.storageType === consts.STORAGE_TYPES.graph
268
- ) {
269
- //(<beforeCreateNode>)
270
- //(</beforeCreateNode>)
271
- _izContext.logger.debug('::::::Graph::::::', {
272
- storageTag,
273
- objInstanceFull
274
- });
275
-
276
- Object.assign(
277
- objInstanceFullForGraph.fields,
278
- createObjInstanceFullFieldsByStorageTag(
279
- _izContext,
280
- storageTag,
281
- createDataDetail
282
- )
283
- );
284
- _izContext.logger.debug(
285
- 'objInstanceFull before send to Graph',
286
- objInstanceFullForGraph
287
- );
288
-
289
- //(<additionalAttributeCreateNode>)
290
- const additionalAttributes = {};
291
- //(</additionalAttributeCreateNode>)
292
-
293
- const records = allAwaitingStepsId.length === 0 ? listOfRecords : [];
294
- allAwaitingStepsId.push({
295
- awaitingStepId: await asyncFlowSharedLib.createAwaitingStepId(
296
- parentFlowId,
297
- PREFIX.CREATE_OBJECT_ASYNC
298
- ),
299
- additionalAttributes: {
300
- listOfRecords: records,
301
- additionalAttributes: additionalAttributes
302
- }
303
- });
304
-
305
- listOfObjectForCreates.push({
306
- [storageTag]: {
307
- objInstanceFull: {
308
- identifiers: objInstanceFullForGraph.identifiers,
309
- fields: objInstanceFullForGraph.fields
310
- },
311
- allStorageTagComplete: false
312
- }
313
- });
314
-
315
- // ── External Topic ────────────────────────────────────────────────────
316
- } else if (
317
- createDataDetail.storageType === consts.STORAGE_TYPES.externalTopic
318
- ) {
319
- _izContext.logger.debug('::::::externalTopic::::::', {
320
- storageTag,
321
- createDataDetail
322
- });
323
- //(<beforeSendMessageToExternalTopic>)
324
- //(</beforeSendMessageToExternalTopic>)
325
-
326
- Object.assign(
327
- objInstanceFullForExternalTopic.fields,
328
- createObjInstanceFullFieldsByStorageTag(
329
- _izContext,
330
- storageTag,
331
- createDataDetail
332
- )
333
- );
334
- _izContext.logger.debug(
335
- 'objInstanceFull before send to external topic',
336
- objInstanceFullForExternalTopic
337
- );
338
-
339
- allAwaitingStepsId.push({
340
- awaitingStepId: await asyncFlowSharedLib.createAwaitingStepId(
341
- parentFlowId,
342
- PREFIX.CREATE_OBJECT_EXTERNAL_TOPIC
343
- ),
344
- additionalAttributes: {}
345
- });
346
-
347
- Object.assign(objInstanceFullForExternalTopic, {
348
- parentFlowId: parentFlowId
349
- });
350
-
351
- await sns.publishAsync(_izContext, {
352
- Message: JSON.stringify(objInstanceFullForExternalTopic),
353
- TopicArn: `arn:aws:sns:${createDataDetail.region}:${createDataDetail.accountId}:${createDataDetail.serviceTag}_${createDataDetail.stage}_Create_In`
354
- });
355
- }
356
- }
357
- }
358
-
359
- // ── Create awaiting multiple steps ────────────────────────────────────────
360
- _izContext.logger.debug('not api will create awaitingStep');
361
- await asyncFlowSharedLib.createAwaitingMultipleSteps(
362
- _izContext,
363
- asyncFlowSharedLib.createPendingStepId(
364
- _izContext.uniqueRequestId,
365
- PREFIX.CREATE_OBJECT_ASYNC_COMPLETE
366
- ),
367
- allAwaitingStepsId
368
- );
369
-
370
- // ── Process graph objects ─────────────────────────────────────────────────
371
- let messageObject = {};
372
- for (const objectCreate of listOfObjectForCreates) {
373
- for (const [graphServiceName, objectForCreate] of Object.entries(
374
- objectCreate
375
- )) {
376
- _izContext.logger.debug('Loop each graph:', {
377
- [graphServiceName]: objectForCreate
378
- });
379
-
380
- if (!objectForCreate.allStorageTagComplete) {
381
- //(<beforeSendMessageToGraph>)
382
- //(</beforeSendMessageToGraph>)
383
- messageObject = {
384
- objType,
385
- objInstanceFull: objectForCreate.objInstanceFull,
386
- deepPathConditional: requestParams.deepPathConditional || [],
387
- setFieldConditionals: requestParams.setFieldConditionals || [],
388
- relationships: requestParams.relationships || [],
389
- parentFlowId: parentFlowId
390
- };
391
- }
392
-
393
- if (errorsFound.length > 0) break;
394
-
395
- Object.assign(messageObject, {
396
- settings: { updatePropertiesOnMatch: false },
397
- originTimestamp: Date.now()
398
- });
399
-
400
- messageObject =
401
- callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
402
- messageObject,
403
- callingFlowSharedLib.addParentCallingFlowConfig(
404
- callingFlowConfig,
405
- callingFlowSharedLib.createCallingFlowConfig(
406
- //(<callingFlowProperties>)
407
- await lambdaSharedLib.lambdaFunctionName(
408
- _izContext,
409
- TOPIC_NAME_GENERATE_CODE.createNodeComplete
410
- ),
411
- {}
412
- //(</callingFlowProperties>)
413
- )
414
- )
415
- );
416
-
417
- await sns.publishAsync(_izContext, {
418
- Message: JSON.stringify(messageObject),
419
- TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
420
- _izContext,
421
- TOPIC_NAME_GRAPH_HANDLER.inCreateNode,
422
- graphServiceName
423
- )
424
- });
425
-
426
- //(<afterSendMessageToGraph>)
427
- //(</afterSendMessageToGraph>)
428
- return {
429
- objType,
430
- objInstanceFull: objInstanceFullForGraph,
431
- relationships: requestParams.relationships || [],
432
- status: 'complete',
433
- errorsFound
434
- };
435
- }
436
- if (errorsFound.length > 0) break;
437
- }
438
-
439
- // ── Handle errors ─────────────────────────────────────────────────────────
440
- if (errorsFound.length > 0) {
441
- _izContext.logger.debug('Case have errorsFound:::', errorsFound);
442
-
443
- await asyncFlowSharedLib.clearAllAwaitingSteps(
444
- _izContext,
445
- asyncFlowSharedLib.createPendingStepId(
446
- _izContext.uniqueRequestId,
447
- PREFIX.CREATE_OBJECT_ASYNC_COMPLETE
448
- )
449
- );
450
-
451
- messageObject =
452
- callingFlowSharedLib.addPassBackPropertiesToSnsResponseMessageObject(
453
- callingFlowConfig,
454
- { objType, identifiers: null, errorsFound }
455
- );
456
-
457
- await sns.publishAsync(_izContext, {
458
- Message: JSON.stringify(messageObject),
459
- MessageAttributes: sns.createStringMessageAttributes(
460
- _izContext,
461
- callingFlowSharedLib.addCallingFlowToSnsResponseMessageAttributes(
462
- callingFlowConfig,
463
- {}
464
- )
465
- ),
466
- TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
467
- _izContext,
468
- TOPIC_NAME_GENERATE_CODE.outCreateNodeComplete
469
- )
470
- });
471
-
472
- return {
473
- objType,
474
- objInstanceFull,
475
- relationships: requestParams.relationships || [],
476
- status: 'error',
477
- errorsFound
478
- };
479
- }
480
-
481
- // ── DynamoDB-only complete path ───────────────────────────────────────────
482
- if (
483
- allAwaitingStepsId.length === 0 &&
484
- listOfObjectForCreates.length === 0
485
- ) {
486
- const outMessage =
487
- callingFlowSharedLib.addPassBackPropertiesToSnsResponseMessageObject(
488
- callingFlowConfig,
489
- {
490
- objType: objType,
491
- objInstanceFull: {
492
- identifiers: objInstanceFullForDynamoDb.identifiers,
493
- fields: objInstanceFullForDynamoDb.fields
494
- }
495
- }
496
- );
497
-
498
- if (
499
- callingFlowConfig[callingFlowSharedLib.consts.CALLINGFLOW_PROPERTYNAME]
500
- ) {
501
- _izContext.logger.debug('HAVE CallingFlow');
502
- await sns.publishAsync(_izContext, {
503
- Message: JSON.stringify(outMessage),
504
- MessageAttributes: sns.createStringMessageAttributes(
505
- _izContext,
506
- callingFlowSharedLib.addCallingFlowToSnsResponseMessageAttributes(
507
- callingFlowConfig,
508
- {}
509
- )
510
- ),
511
- TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
512
- _izContext,
513
- TOPIC_NAME_GENERATE_CODE.outCreateNodeComplete
514
- )
515
- });
516
- }
517
- }
518
-
519
- return {
520
- objType,
521
- objInstanceFull: {
522
- identifiers: objInstanceFullForDynamoDb.identifiers,
523
- fields: objInstanceFullForDynamoDb.fields
524
- },
525
- relationships: requestParams.relationships || [],
526
- status: 'complete',
527
- errorsFound
528
- };
529
- } catch (err) {
530
- throw err;
531
- }
532
- }
51
+ const { createIdentifiersByUseCase } = identifiersObject;
533
52
 
534
53
  /**
535
- * Creates an object instance — handles beforeLogical phase routing or proceeds directly to logical
54
+ * Creates an object instance and proceeds directly to logical processing
536
55
  * @param {Object} _izContext - Context object with logger
537
56
  * @param {Object} requestParams - { fieldNames, relationships[] }
538
57
  * @param {Object} callingFlowConfig - Calling flow configuration
@@ -541,7 +60,7 @@ export async function <%- flowTag %>MainLogical(
541
60
  export default async function <%- flowTag %>(
542
61
  _izContext,
543
62
  requestParams,
544
- callingFlowConfig = {}
63
+ callingFlowConfig = {},
545
64
  //(<additionalParams>)
546
65
  //(</additionalParams>)
547
66
  ) {
@@ -663,7 +182,7 @@ export default async function <%- flowTag %>(
663
182
  _izContext.logger.debug('errorsFound::', errorsFound);
664
183
 
665
184
  if (errorsFound.length > 0)
666
- return await <%- flowTag %>MainLogical(
185
+ return await <%- flowTag %>LogicalLib(
667
186
  _izContext,
668
187
  requestParams,
669
188
  callingFlowConfig,
@@ -702,16 +221,69 @@ export default async function <%- flowTag %>(
702
221
  }
703
222
  }
704
223
 
705
- // ── beforeLogical phase check ─────────────────────────────────────────────
706
224
  <%_
707
- const groupedByObjType = generateCode
708
- .filter(c => c.codeHookTag === 'beforeLogical')
709
- .reduce((acc, config) => {
710
- const key = config.objType.objectType;
711
- if (!acc[key]) acc[key] = [];
712
- acc[key].push(config);
713
- return acc;
714
- }, {});
225
+ const rbacObjects = objects.filter(o => (o?.generatedBy === 'userGenerated' || o?.generatedBy === 'systemGenerated') && hasRbacAddOn(o));
226
+ const rbacObjectTypes = rbacObjects.map(o => o.objectType);
227
+ const rbacServiceTagMap = {};
228
+ for (const o of rbacObjects) {
229
+ const belongToTargets = o?.belongTo
230
+ ? Array.isArray(o.belongTo)
231
+ ? o.belongTo
232
+ : [o.belongTo]
233
+ : [];
234
+ if (belongToTargets.length > 0 && belongToTargets[0]?.serviceTag) {
235
+ rbacServiceTagMap[o.objectType] = `'${belongToTargets[0].serviceTag}'`;
236
+ } else if (o?.belongToSchema?.serviceTag) {
237
+ rbacServiceTagMap[o.objectType] = `'${o.belongToSchema.serviceTag}'`;
238
+ } else if (o?.serviceTag) {
239
+ rbacServiceTagMap[o.objectType] = `'${o.serviceTag}'`;
240
+ } else {
241
+ rbacServiceTagMap[o.objectType] = 'process.env.iz_serviceTag';
242
+ }
243
+ }
244
+ const rbacServiceTags = Array.from(new Set(Object.values(rbacServiceTagMap)));
245
+ _%>
246
+ <%_ if (rbacObjectTypes.length > 0) { _%>
247
+ // ── rbacCallback phase check ─────────────────────────────────────────────
248
+ if ([<%- rbacObjectTypes.map(t => `'${t}'`).join(', ') %>].includes(requestParams.objectType)) {
249
+ const { checkRbacPermission } =
250
+ await import('@izara_project/izara-authorization');
251
+
252
+ //(<rbacParameterGroups_<%- flowTag %>)
253
+ const parameterGroups = {};
254
+ //(</rbacParameterGroups_<%- flowTag %>)
255
+
256
+ const resultPermissionCheck = await checkRbacPermission(
257
+ _izContext,
258
+ {
259
+ flowTag: '<%- flowTag %>',
260
+ serviceTag: process.env.iz_serviceTag
261
+ },
262
+ parameterGroups,
263
+ {
264
+ rbacObjType: {
265
+ serviceTag: <%- rbacServiceTags.length === 1 ? rbacServiceTags[0] : `{ ${Object.entries(rbacServiceTagMap).map(([k, v]) => `'${k}': ${v}`).join(', ')} }[requestParams.objectType] || process.env.iz_serviceTag` %>
266
+ },
267
+ requestParams: requestParams,
268
+ nextFlowStepName: '<%- flowTag %>RbacCallback'
269
+ }
270
+ );
271
+
272
+ _izContext.logger.debug(
273
+ '[lib:auth:checkRbacPermission] resultPermissionCheck:',
274
+ resultPermissionCheck
275
+ );
276
+
277
+ //(<rbacPublish_<%- flowTag %>)
278
+ //(</rbacPublish_<%- flowTag %>)
279
+
280
+ return resultPermissionCheck;
281
+ }
282
+ <%_ } _%>
283
+
284
+ // ── Optional phase extension point ────────────────────────────────────────
285
+ <%_
286
+ const groupedByObjType = [];
715
287
  _%>
716
288
  <%_ Object.entries(groupedByObjType).forEach(([objectType, configs]) => { _%>
717
289
  <%_
@@ -755,7 +327,7 @@ export default async function <%- flowTag %>(
755
327
  awaitingMultipleStepIds.push({
756
328
  awaitingStepId: await asyncFlowSharedLib.createAwaitingStepId(
757
329
  hash(objInstanceFull.identifiers),
758
- '<%= config.codeHookTag %>_<%= objectType %>_<%= config.flowTag.charAt(0).toUpperCase() + config.flowTag.slice(1) %>'
330
+ 'logical_<%= objectType %>_<%= config.flowTag.charAt(0).toUpperCase() + config.flowTag.slice(1) %>'
759
331
  ),
760
332
  additionalAttributes: {}
761
333
  });
@@ -769,7 +341,7 @@ export default async function <%- flowTag %>(
769
341
  //(<callingFlowProperties_<%= config.flowTag %>>)
770
342
  await lambdaSharedLib.lambdaFunctionName(
771
343
  _izContext,
772
- '<%= config.generatedCodeTag %><%= config.codeHookTag.charAt(0).toUpperCase() + config.codeHookTag.slice(1) %>'
344
+ '<%= flowTag.toLowerCase() %>Complete'
773
345
  ),
774
346
  {}
775
347
  //(</callingFlowProperties_<%= config.flowTag %>>)
@@ -786,7 +358,7 @@ export default async function <%- flowTag %>(
786
358
  awaitingMultipleStepIds.push({
787
359
  awaitingStepId: await asyncFlowSharedLib.createAwaitingStepId(
788
360
  hash(objInstanceFull.identifiers),
789
- '<%= configs[0].codeHookTag %>_<%= objectType %>_' + syncResult.flowTag
361
+ 'logical_<%= objectType %>_' + syncResult.flowTag
790
362
  ),
791
363
  additionalAttributes: {
792
364
  complete: true,
@@ -801,7 +373,7 @@ export default async function <%- flowTag %>(
801
373
  _izContext,
802
374
  asyncFlowSharedLib.createPendingStepId(
803
375
  _izContext.uniqueRequestId,
804
- 'beforeLogical_<%= objectType %>'
376
+ 'logical_<%= objectType %>'
805
377
  ),
806
378
  awaitingMultipleStepIds
807
379
  );
@@ -830,20 +402,20 @@ export default async function <%- flowTag %>(
830
402
  });
831
403
  }
832
404
 
833
- return 'complete beforeLogical <%= objectType %>';
405
+ return 'complete logical <%= objectType %>';
834
406
 
835
407
  <%_ } else { _%>
836
- // ── lambdaSyncInv only — collect results and proceed to createMainLogical ────────────
837
- const beforeLogicalResults = lambdaSyncInvResults.reduce((acc, r) => {
838
- acc[r.flowTag] = r.returnValue;
839
- return acc;
840
- }, {});
408
+ // ── lambdaSyncInv only — collect results and proceed to createLogicalLib ────────────
409
+ const phaseResults = Object.fromEntries(
410
+ lambdaSyncInvResults.map(({ flowTag: tag, returnValue }) => [tag, returnValue])
411
+ );
841
412
 
842
- return await <%- flowTag %>MainLogical(
413
+ return await <%- flowTag %>LogicalLib(
843
414
  _izContext,
844
415
  requestParams,
845
416
  callingFlowConfig,
846
- beforeLogicalResults
417
+ errorsFound,
418
+ phaseResults
847
419
  );
848
420
  <%_ } _%>
849
421
  }
@@ -852,11 +424,11 @@ export default async function <%- flowTag %>(
852
424
  //(<beforeCreateMainLogical>)
853
425
  //(</beforeCreateMainLogical>)
854
426
 
855
- // ── No beforeLogical → proceed directly to logical ────────────────────────
856
- return await <%- flowTag %>MainLogical(
427
+ return await <%- flowTag %>LogicalLib(
857
428
  _izContext,
858
429
  requestParams,
859
- callingFlowConfig
430
+ callingFlowConfig,
431
+ errorsFound
860
432
  );
861
433
  } catch (err) {
862
434
  throw err;