@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
@@ -20,198 +20,29 @@ import {
20
20
  identifierUuid
21
21
  } from '@izara_project/izara-shared-core';
22
22
  import { consts as coreConsts } from '@izara_project/izara-core-library-core';
23
- import { consts as middlewareConsts } from '@izara_project/izara-middleware';
24
23
  import {
25
24
  sns,
26
25
  lambda
27
26
  } from '@izara_project/izara-core-library-external-request';
28
- import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
29
- import snsSharedLib from '@izara_project/izara-core-library-sns';
30
27
  import asyncFlowSharedLib from '@izara_project/izara-core-library-asynchronous-flow';
31
28
  import callingFlowSharedLib from '@izara_project/izara-core-library-calling-flow';
32
29
  import lambdaSharedLib from '@izara_project/izara-core-library-lambda';
33
30
  import {
34
31
  consts,
35
32
  getObjectSchema,
36
- dataDetailsLib,
37
- identifiersObject,
38
33
  utils
39
34
  } from '@izara_project/izara-core-library-service-schemas';
35
+ import snsSharedLib from '@izara_project/izara-core-library-sns';
40
36
 
41
- const { createObjType } = utils;
42
- const { createDeleteDataDetail } = dataDetailsLib;
43
- const { dynamoDbIdentifiersByStorageResource } = identifiersObject;
44
- const { TOPIC_NAME_GENERATE_CODE } = consts;
37
+ import { <%- flowTag %>LogicalLib } from './<%- upperCaseFlowTag %>LogicalLib.js';
45
38
 
46
39
  //(<optionalRequire>)
47
40
  //(</optionalRequire>)
48
41
 
49
- /**
50
- * Core logical processing after beforeLogical phase completes
51
- * Called by both deleteMain (no beforeLogical) and deleteBeforeLogicalMain (after callback)
52
- * @param {Object} _izContext - Context object with logger
53
- * @param {Object} requestParams - { identifiers, objectType }
54
- * @param {Object} callingFlowConfig - Calling flow configuration
55
- * @param {Object} beforeLogicalResults - Results from beforeLogical phase
56
- * @returns {Promise<Object>}
57
- */
58
- export async function <%- flowTag %>MainLogical(
59
- _izContext,
60
- requestParams,
61
- callingFlowConfig = {},
62
- errorsFound = [],
63
- beforeLogicalResults = {}
64
- ) {
65
- try {
66
- _izContext.logger.debug('[<%- flowTag %>MainLogical] started', {
67
- requestParams,
68
- callingFlowConfig,
69
- beforeLogicalResults
70
- });
71
-
72
- //(<beforeDeleteMainLogical>)
73
- //(</beforeDeleteMainLogical>)
74
-
75
- const objType = createObjType(requestParams.objectType);
76
-
77
- // ── Load schema ───────────────────────────────────────────────────────────
78
- const objectSchema = await getObjectSchema.getObjSchemaS3WithHierarchy(
79
- _izContext,
80
- objType
81
- );
82
- _izContext.logger.debug('objectSchema', objectSchema);
83
-
84
- // ── Build deleteDataDetails ───────────────────────────────────────────────
85
- const deleteDataDetails = await createDeleteDataDetail(
86
- _izContext,
87
- objectSchema
88
- );
89
- _izContext.logger.debug('deleteDataDetails', deleteDataDetails);
90
-
91
- if (objectSchema.canDelete === false || objectSchema.canDelete == null) {
92
- errorsFound.push("this objectSchema can't delete");
93
- }
94
-
95
- // ── Early exit on errors ──────────────────────────────────────────────────
96
- if (errorsFound.length) {
97
- const deleteNodeCompleteMessage =
98
- callingFlowSharedLib.addPassBackPropertiesToSnsResponseMessageObject(
99
- callingFlowConfig,
100
- {
101
- objType,
102
- identifiers: requestParams.identifiers,
103
- status: 'error',
104
- errorsFound
105
- }
106
- );
107
-
108
- _izContext.logger.debug(
109
- 'messageParams OutDeleteNodeComplete::',
110
- deleteNodeCompleteMessage
111
- );
112
- await sns.publishAsync(_izContext, {
113
- Message: JSON.stringify(deleteNodeCompleteMessage),
114
- TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
115
- _izContext,
116
- TOPIC_NAME_GENERATE_CODE.outDeleteNodeComplete
117
- )
118
- });
119
-
120
- return {
121
- objType,
122
- identifiers: requestParams.identifiers,
123
- status: 'error',
124
- errorsFound
125
- };
126
- }
127
-
128
- //(<validateBeforeDelete>)
129
- //(</validateBeforeDelete>)
130
-
131
- // ── Process storage resources ─────────────────────────────────────────────
132
- for (const [storageTag, deleteDataDetail] of Object.entries(
133
- deleteDataDetails
134
- )) {
135
- //(<beforeDelete>)
136
- //(</beforeDelete>)
137
-
138
- if (deleteDataDetail.storageType === consts.STORAGE_TYPES.dynamoDB) {
139
- //(<beforeDeleteRecordDynamo>)
140
- //(</beforeDeleteRecordDynamo>)
141
- _izContext.logger.debug('::::::DynamoDB::::::', { storageTag });
142
-
143
- const identifiersForDeleteData =
144
- await dynamoDbIdentifiersByStorageResource(
145
- _izContext,
146
- objectSchema,
147
- deleteDataDetail,
148
- requestParams.identifiers
149
- );
150
- _izContext.logger.debug(
151
- 'identifiersForDeleteData',
152
- identifiersForDeleteData
153
- );
154
-
155
- await dynamodbSharedLib.deleteItem(
156
- _izContext,
157
- await dynamodbSharedLib.tableName(
158
- _izContext,
159
- deleteDataDetail.tableName,
160
- deleteDataDetail.serviceTag
161
- ),
162
- identifiersForDeleteData
163
- );
164
-
165
- //(<afterDeleteRecordDynamo>)
166
- //(</afterDeleteRecordDynamo>)
167
- }
168
- }
169
-
170
- // ── Complete ──────────────────────────────────────────────────────────────
171
- const outMessage =
172
- callingFlowSharedLib.addPassBackPropertiesToSnsResponseMessageObject(
173
- callingFlowConfig,
174
- {
175
- objType,
176
- identifiers: requestParams.identifiers,
177
- status: 'complete',
178
- errorsFound
179
- }
180
- );
181
-
182
- if (
183
- callingFlowConfig[callingFlowSharedLib.consts.CALLINGFLOW_PROPERTYNAME]
184
- ) {
185
- _izContext.logger.debug('HAVE CallingFlow');
186
- await sns.publishAsync(_izContext, {
187
- Message: JSON.stringify(outMessage),
188
- MessageAttributes: sns.createStringMessageAttributes(
189
- _izContext,
190
- callingFlowSharedLib.addCallingFlowToSnsResponseMessageAttributes(
191
- callingFlowConfig,
192
- {}
193
- )
194
- ),
195
- TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
196
- _izContext,
197
- TOPIC_NAME_GENERATE_CODE.outDeleteNodeComplete
198
- )
199
- });
200
- }
201
-
202
- return {
203
- objType,
204
- identifiers: requestParams.identifiers,
205
- status: 'complete',
206
- errorsFound
207
- };
208
- } catch (err) {
209
- throw err;
210
- }
211
- }
42
+ const { createObjType } = utils;
212
43
 
213
44
  /**
214
- * Deletes an object instance — handles beforeLogical phase routing or proceeds directly to logical
45
+ * Deletes an object instance with optional RBAC routing
215
46
  * @param {Object} _izContext - Context object with logger
216
47
  * @param {Object} requestParams - { identifiers, objectType }
217
48
  * @param {Object} callingFlowConfig - Calling flow configuration
@@ -220,7 +51,7 @@ export async function <%- flowTag %>MainLogical(
220
51
  export default async function <%- flowTag %>(
221
52
  _izContext,
222
53
  requestParams,
223
- callingFlowConfig = {}
54
+ callingFlowConfig = {},
224
55
  //(<additionalParams>)
225
56
  //(</additionalParams>)
226
57
  ) {
@@ -255,27 +86,80 @@ export default async function <%- flowTag %>(
255
86
  //(<beforeQuery>)
256
87
  //(</beforeQuery>)
257
88
 
258
- // ── Build identifiers (used for hash in beforeLogical) ──────────────────
89
+ // ── Build identifiers used by asynchronous processing ────────────────────
259
90
  const identifiers = requestParams.identifiers;
260
91
 
261
92
  if (errorsFound.length > 0)
262
- return await createMainLogical(
93
+ return await <%- flowTag %>LogicalLib(
263
94
  _izContext,
264
95
  requestParams,
265
96
  callingFlowConfig,
266
97
  errorsFound
267
98
  );
268
99
 
269
- // ── beforeLogical phase check ─────────────────────────────────────────────
270
100
  <%_
271
- const groupedByObjType = generateCode
272
- .filter(c => c.codeHookTag === 'beforeLogical')
273
- .reduce((acc, config) => {
274
- const key = config.objType.objectType;
275
- if (!acc[key]) acc[key] = [];
276
- acc[key].push(config);
277
- return acc;
278
- }, {});
101
+ const rbacObjects = objects.filter(o => (o?.generatedBy === 'userGenerated' || o?.generatedBy === 'systemGenerated') && hasRbacAddOn(o));
102
+ const rbacObjectTypes = rbacObjects.map(o => o.objectType);
103
+ const rbacServiceTagMap = {};
104
+ for (const o of rbacObjects) {
105
+ const belongToTargets = o?.belongTo
106
+ ? Array.isArray(o.belongTo)
107
+ ? o.belongTo
108
+ : [o.belongTo]
109
+ : [];
110
+ if (belongToTargets.length > 0 && belongToTargets[0]?.serviceTag) {
111
+ rbacServiceTagMap[o.objectType] = `'${belongToTargets[0].serviceTag}'`;
112
+ } else if (o?.belongToSchema?.serviceTag) {
113
+ rbacServiceTagMap[o.objectType] = `'${o.belongToSchema.serviceTag}'`;
114
+ } else if (o?.serviceTag) {
115
+ rbacServiceTagMap[o.objectType] = `'${o.serviceTag}'`;
116
+ } else {
117
+ rbacServiceTagMap[o.objectType] = 'process.env.iz_serviceTag';
118
+ }
119
+ }
120
+ const rbacServiceTags = Array.from(new Set(Object.values(rbacServiceTagMap)));
121
+ _%>
122
+ <%_ if (rbacObjectTypes.length > 0) { _%>
123
+ // ── rbacCallback phase check ─────────────────────────────────────────────
124
+ if ([<%- rbacObjectTypes.map(t => `'${t}'`).join(', ') %>].includes(requestParams.objectType)) {
125
+ const { checkRbacPermission } =
126
+ await import('@izara_project/izara-authorization');
127
+
128
+ //(<rbacParameterGroups_<%- flowTag %>)
129
+ const parameterGroups = {};
130
+ //(</rbacParameterGroups_<%- flowTag %>)
131
+
132
+ const resultPermissionCheck = await checkRbacPermission(
133
+ _izContext,
134
+ {
135
+ flowTag: '<%- flowTag %>',
136
+ serviceTag: process.env.iz_serviceTag
137
+ },
138
+ parameterGroups,
139
+ {
140
+ rbacObjType: {
141
+ serviceTag: <%- rbacServiceTags.length === 1 ? rbacServiceTags[0] : `{ ${Object.entries(rbacServiceTagMap).map(([k, v]) => `'${k}': ${v}`).join(', ')} }[requestParams.objectType] || process.env.iz_serviceTag` %>
142
+ },
143
+ requestParams: requestParams,
144
+ nextFlowStepName: '<%- plan?.hasRbacCallback ? `${flowTag}RbacCallback` : `${flowTag}Complete` %>'
145
+ }
146
+ );
147
+
148
+ _izContext.logger.debug(
149
+ '[lib:auth:checkRbacPermission] resultPermissionCheck:',
150
+ resultPermissionCheck
151
+ );
152
+
153
+ //(<rbacPublish_<%- flowTag %>)
154
+ //(</rbacPublish_<%- flowTag %>)
155
+
156
+ return resultPermissionCheck;
157
+ }
158
+ <%_ } _%>
159
+
160
+ // ── Optional phase extension point ────────────────────────────────────────
161
+ <%_
162
+ const groupedByObjType = [];
279
163
  _%>
280
164
  <%_ Object.entries(groupedByObjType).forEach(([objectType, configs]) => { _%>
281
165
  <%_
@@ -299,7 +183,7 @@ export default async function <%- flowTag %>(
299
183
  .then((returnValue) => ({
300
184
  flowTag: '<%= config.flowTag %>',
301
185
  returnValue
302
- })) /*__EJS_COMMA_13__*/
186
+ })) /*__EJS_COMMA_14__*/
303
187
  // lambdaSyncInv <%= config.flowTag %>
304
188
  <%_ }) _%>
305
189
  ]);
@@ -318,7 +202,7 @@ export default async function <%- flowTag %>(
318
202
  awaitingMultipleStepIds.push({
319
203
  awaitingStepId: await asyncFlowSharedLib.createAwaitingStepId(
320
204
  hash(identifiers),
321
- '<%= config.codeHookTag %>_<%= objectType %>_<%= config.flowTag.charAt(0).toUpperCase() + config.flowTag.slice(1) %>'
205
+ 'logical_<%= objectType %>_<%= config.flowTag.charAt(0).toUpperCase() + config.flowTag.slice(1) %>'
322
206
  ),
323
207
  additionalAttributes: {}
324
208
  });
@@ -332,7 +216,7 @@ export default async function <%- flowTag %>(
332
216
  //(<callingFlowProperties_<%= config.flowTag %>>)
333
217
  await lambdaSharedLib.lambdaFunctionName(
334
218
  _izContext,
335
- '<%= config.generatedCodeTag %><%= config.codeHookTag.charAt(0).toUpperCase() + config.codeHookTag.slice(1) %>'
219
+ '<%= flowTag.toLowerCase() %>Complete'
336
220
  ),
337
221
  {}
338
222
  //(</callingFlowProperties_<%= config.flowTag %>>)
@@ -349,7 +233,7 @@ export default async function <%- flowTag %>(
349
233
  awaitingMultipleStepIds.push({
350
234
  awaitingStepId: await asyncFlowSharedLib.createAwaitingStepId(
351
235
  hash(identifiers),
352
- '<%= configs[0].codeHookTag %>_<%= objectType %>_' + syncResult.flowTag
236
+ 'logical_<%= objectType %>_' + syncResult.flowTag
353
237
  ),
354
238
  additionalAttributes: {
355
239
  complete: true,
@@ -363,10 +247,15 @@ export default async function <%- flowTag %>(
363
247
  await asyncFlowSharedLib.createAwaitingMultipleSteps(
364
248
  _izContext,
365
249
  asyncFlowSharedLib.createPendingStepId(
366
- hash(identifiers),
367
- 'beforeLogical_<%= objectType %>'
250
+ _izContext.uniqueRequestId,
251
+ 'logical_<%= objectType %>'
368
252
  ),
369
- awaitingMultipleStepIds
253
+ awaitingMultipleStepIds,
254
+ {
255
+ additionalAttributes: {
256
+ callingFlowConfig
257
+ }
258
+ }
370
259
  );
371
260
 
372
261
  //(<beforePublish_<%= objectType %>>)
@@ -393,20 +282,20 @@ export default async function <%- flowTag %>(
393
282
  });
394
283
  }
395
284
 
396
- return 'complete beforeLogical <%= objectType %>';
285
+ return 'complete logical <%= objectType %>';
397
286
 
398
287
  <%_ } else { _%>
399
- // ── lambdaSyncInv only — collect results and proceed to deleteMainLogical
400
- const beforeLogicalResults = lambdaSyncInvResults.reduce((acc, r) => {
401
- acc[r.flowTag] = r.returnValue;
402
- return acc;
403
- }, {});
288
+ // ── lambdaSyncInv only — collect results and proceed to deleteLogicalLib
289
+ const phaseResults = Object.fromEntries(
290
+ lambdaSyncInvResults.map(({ flowTag: tag, returnValue }) => [tag, returnValue])
291
+ );
404
292
 
405
- return await <%- flowTag %>MainLogical(
293
+ return await <%- flowTag %>LogicalLib(
406
294
  _izContext,
407
295
  requestParams,
408
296
  callingFlowConfig,
409
- beforeLogicalResults
297
+ errorsFound,
298
+ phaseResults
410
299
  );
411
300
  <%_ } _%>
412
301
  }
@@ -415,11 +304,12 @@ export default async function <%- flowTag %>(
415
304
  //(<beforeDeleteMainLogical>)
416
305
  //(</beforeDeleteMainLogical>)
417
306
 
418
- // ── No beforeLogical → proceed directly to logical ────────────────────────
419
- return await <%- flowTag %>MainLogical(
307
+ // ── No optional phase → proceed directly to logical ──────────────────────
308
+ return await <%- flowTag %>LogicalLib(
420
309
  _izContext,
421
310
  requestParams,
422
- callingFlowConfig
311
+ callingFlowConfig,
312
+ errorsFound
423
313
  );
424
314
  } catch (err) {
425
315
  throw err;
@@ -0,0 +1,213 @@
1
+ /*
2
+ Copyright (C) 2021 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 <http://www.gnu.org/licenses/>.
16
+ */
17
+
18
+ import {
19
+ objectHash as hash,
20
+ identifierUuid
21
+ } from '@izara_project/izara-shared-core';
22
+ import { consts as coreConsts } from '@izara_project/izara-core-library-core';
23
+ import { consts as middlewareConsts } from '@izara_project/izara-middleware';
24
+ import {
25
+ sns,
26
+ lambda
27
+ } from '@izara_project/izara-core-library-external-request';
28
+ import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
29
+ import snsSharedLib from '@izara_project/izara-core-library-sns';
30
+ import asyncFlowSharedLib from '@izara_project/izara-core-library-asynchronous-flow';
31
+ import callingFlowSharedLib from '@izara_project/izara-core-library-calling-flow';
32
+ import lambdaSharedLib from '@izara_project/izara-core-library-lambda';
33
+ import {
34
+ consts,
35
+ getObjectSchema,
36
+ dataDetailsLib,
37
+ identifiersObject,
38
+ utils
39
+ } from '@izara_project/izara-core-library-service-schemas';
40
+
41
+ const { createObjType } = utils;
42
+ const { createDeleteDataDetail } = dataDetailsLib;
43
+ const { dynamoDbIdentifiersByStorageResource } = identifiersObject;
44
+ const { TOPIC_NAME_GENERATE_CODE } = consts;
45
+
46
+ //(<optionalRequire>)
47
+ //(</optionalRequire>)
48
+
49
+ /**
50
+ * Core logical processing library
51
+ * @param {Object} _izContext - Context object with logger
52
+ * @param {Object} requestParams - { identifiers, objectType }
53
+ * @param {Object} callingFlowConfig - Calling flow configuration
54
+ * @param {Object} phaseResults - Results from preceding phases
55
+ * @returns {Promise<Object>}
56
+ */
57
+ export async function <%- flowTag %>LogicalLib(
58
+ _izContext,
59
+ requestParams,
60
+ callingFlowConfig = {},
61
+ errorsFound = [],
62
+ phaseResults = {}
63
+ ) {
64
+ try {
65
+ _izContext.logger.debug('[<%- flowTag %>LogicalLib] started', {
66
+ requestParams,
67
+ callingFlowConfig,
68
+ phaseResults
69
+ });
70
+
71
+ //(<beforeDeleteMainLogical>)
72
+ //(</beforeDeleteMainLogical>)
73
+
74
+ const objType = createObjType(requestParams.objectType);
75
+
76
+ // ── Load schema ───────────────────────────────────────────────────────────
77
+ const objectSchema = await getObjectSchema.getObjSchemaS3WithHierarchy(
78
+ _izContext,
79
+ objType
80
+ );
81
+ _izContext.logger.debug('objectSchema', objectSchema);
82
+
83
+ // ── Build deleteDataDetails ───────────────────────────────────────────────
84
+ const deleteDataDetails = await createDeleteDataDetail(
85
+ _izContext,
86
+ objectSchema
87
+ );
88
+ _izContext.logger.debug('deleteDataDetails', deleteDataDetails);
89
+
90
+ if (objectSchema.canDelete === false || objectSchema.canDelete == null) {
91
+ errorsFound.push("this objectSchema can't delete");
92
+ }
93
+
94
+ // ── Early exit on errors ──────────────────────────────────────────────────
95
+ if (errorsFound.length) {
96
+ const deleteNodeCompleteMessage =
97
+ callingFlowSharedLib.addPassBackPropertiesToSnsResponseMessageObject(
98
+ callingFlowConfig,
99
+ {
100
+ objType,
101
+ identifiers: requestParams.identifiers,
102
+ status: 'error',
103
+ errorsFound
104
+ }
105
+ );
106
+
107
+ _izContext.logger.debug(
108
+ 'messageParams OutDeleteNodeComplete::',
109
+ deleteNodeCompleteMessage
110
+ );
111
+ await sns.publishAsync(_izContext, {
112
+ Message: JSON.stringify(deleteNodeCompleteMessage),
113
+ TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
114
+ _izContext,
115
+ TOPIC_NAME_GENERATE_CODE.outDeleteNodeComplete
116
+ )
117
+ });
118
+
119
+ return {
120
+ objType,
121
+ identifiers: requestParams.identifiers,
122
+ status: 'error',
123
+ errorsFound
124
+ };
125
+ }
126
+
127
+ //(<validateBeforeDelete>)
128
+ //(</validateBeforeDelete>)
129
+
130
+ // ── Process storage resources ─────────────────────────────────────────────
131
+ for (const [storageTag, deleteDataDetail] of Object.entries(
132
+ deleteDataDetails
133
+ )) {
134
+ //(<beforeDelete>)
135
+ //(</beforeDelete>)
136
+
137
+ if (deleteDataDetail.storageType === consts.STORAGE_TYPES.dynamoDB) {
138
+ //(<beforeDeleteRecordDynamo>)
139
+ //(</beforeDeleteRecordDynamo>)
140
+ _izContext.logger.debug('::::::DynamoDB::::::', { storageTag });
141
+
142
+ const identifiersForDeleteData =
143
+ await dynamoDbIdentifiersByStorageResource(
144
+ _izContext,
145
+ objectSchema,
146
+ deleteDataDetail,
147
+ requestParams.identifiers
148
+ );
149
+ _izContext.logger.debug(
150
+ 'identifiersForDeleteData',
151
+ identifiersForDeleteData
152
+ );
153
+
154
+ await dynamodbSharedLib.deleteItem(
155
+ _izContext,
156
+ await dynamodbSharedLib.tableName(
157
+ _izContext,
158
+ deleteDataDetail.tableName,
159
+ deleteDataDetail.serviceTag
160
+ ),
161
+ identifiersForDeleteData
162
+ );
163
+
164
+ //(<afterDeleteRecordDynamo>)
165
+ //(</afterDeleteRecordDynamo>)
166
+ }
167
+ }
168
+
169
+ // ── Complete ──────────────────────────────────────────────────────────────
170
+ const outMessage =
171
+ callingFlowSharedLib.addPassBackPropertiesToSnsResponseMessageObject(
172
+ callingFlowConfig,
173
+ {
174
+ objType,
175
+ identifiers: requestParams.identifiers,
176
+ status: 'complete',
177
+ errorsFound
178
+ }
179
+ );
180
+
181
+ if (
182
+ callingFlowConfig[callingFlowSharedLib.consts.CALLINGFLOW_PROPERTYNAME]
183
+ ) {
184
+ _izContext.logger.debug('HAVE CallingFlow');
185
+ await sns.publishAsync(_izContext, {
186
+ Message: JSON.stringify(outMessage),
187
+ MessageAttributes: sns.createStringMessageAttributes(
188
+ _izContext,
189
+ callingFlowSharedLib.addCallingFlowToSnsResponseMessageAttributes(
190
+ callingFlowConfig,
191
+ {}
192
+ )
193
+ ),
194
+ TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
195
+ _izContext,
196
+ TOPIC_NAME_GENERATE_CODE.outDeleteNodeComplete
197
+ )
198
+ });
199
+ }
200
+
201
+ return {
202
+ objType,
203
+ identifiers: requestParams.identifiers,
204
+ status: 'complete',
205
+ errorsFound
206
+ };
207
+ } catch (err) {
208
+ throw err;
209
+ }
210
+ }
211
+
212
+ export const <%- flowTag %>MainLogical = <%- flowTag %>LogicalLib;
213
+ export default <%- flowTag %>LogicalLib;