@izara_project/izara-core-generate-service-code 1.0.88 → 1.0.89
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.
- package/package.json +1 -1
- package/src/compile/flowValidator.js +25 -0
- package/src/compile/loadSchemas.js +154 -0
- package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +3 -7
- package/src/emit/crud/crudActionPlan.js +67 -9
- package/src/emit/crud/emitDynamicCrudFlowSchemas.js +15 -32
- package/src/emit/crud/templates/CreateEndpoint_Main.ejs +33 -27
- package/src/emit/crud/templates/CreateLogicalLib.ejs +247 -89
- package/src/emit/crud/templates/CreateNodeCallback_Main.ejs +30 -20
- package/src/emit/crud/templates/DeleteAfterHookCallback_Main.ejs +118 -0
- package/src/emit/crud/templates/DeleteComplete_Main.ejs +124 -10
- package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +26 -16
- package/src/emit/crud/templates/DeleteLogicalLib.ejs +112 -1
- package/src/emit/crud/templates/UpdateAfterHookCallback_Main.ejs +120 -0
- package/src/emit/crud/templates/UpdateComplete_Main.ejs +104 -10
- package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +34 -22
- package/src/emit/crud/templates/UpdateLogicalLib.ejs +121 -1
- package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +8 -2
- package/src/emit/rbac/templates/CancelUsage_Main.ejs +34 -14
- package/src/emit/rbac/templates/ConfirmUsage_Main.ejs +34 -14
- package/src/emit/resource/emitResourceArtifacts.js +9 -2
- package/test/crudApplicationArtifacts.test.js +345 -0
- package/test/dynamicCrudFlowSchemas.test.js +10 -5
- package/test/dynamicRbacFlowSchemas.test.js +24 -2
- package/test/graphDrivenFlowSchema.test.js +36 -0
- package/test/resourceArtifacts.test.js +71 -0
|
@@ -122,7 +122,11 @@ export async function resolveSchemaAndIdentity(_izContext, requestParams, errors
|
|
|
122
122
|
// }
|
|
123
123
|
// }
|
|
124
124
|
|
|
125
|
-
|
|
125
|
+
requestParams.targetIdentifiers = targetIdentifiers;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (requestParams.rbacTargetIdentifiers === undefined && targetIdentifiers) {
|
|
129
|
+
requestParams.rbacTargetIdentifiers = targetIdentifiers;
|
|
126
130
|
}
|
|
127
131
|
|
|
128
132
|
_izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] Identity & Target Context Resolved:`, {
|
|
@@ -140,50 +144,161 @@ export async function resolveSchemaAndIdentity(_izContext, requestParams, errors
|
|
|
140
144
|
}
|
|
141
145
|
|
|
142
146
|
/**
|
|
143
|
-
* Resolves and generates
|
|
147
|
+
* Resolves fromRequiredOnCreate fields and generates identifiers
|
|
144
148
|
* @param {Object} _izContext - Izara context object
|
|
145
|
-
* @param {Object}
|
|
146
|
-
* @param {Object}
|
|
147
|
-
* @
|
|
149
|
+
* @param {Object} requestParams - Request parameters
|
|
150
|
+
* @param {Object} objectSchema - Base object schema
|
|
151
|
+
* @param {Array<string>} errorsFound - Error list
|
|
152
|
+
* @returns {Promise<{ objectSchemas: Object }>}
|
|
148
153
|
*/
|
|
149
|
-
export async function resolveAndGenerateIdentifiers(
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
+
export async function resolveAndGenerateIdentifiers(
|
|
155
|
+
_izContext,
|
|
156
|
+
requestParams,
|
|
157
|
+
objectSchema,
|
|
158
|
+
errorsFound
|
|
159
|
+
) {
|
|
160
|
+
const objType = createObjType(requestParams.objectType);
|
|
161
|
+
const targetIdentifiers = requestParams.targetIdentifiers;
|
|
162
|
+
|
|
163
|
+
const objectSchemas =
|
|
164
|
+
uploadUseCase.generateObjectSchemaForCombineFieldNames(
|
|
165
|
+
_izContext,
|
|
166
|
+
objectSchema
|
|
167
|
+
);
|
|
168
|
+
_izContext.logger.debug(
|
|
169
|
+
`[${process.env.iz_serviceTag}:<%- flowTag %>] objectSchemas:`,
|
|
170
|
+
objectSchemas
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
errorsFound.push(
|
|
174
|
+
...(await createNodeLib.validateRequiredOnCreateLinks(
|
|
175
|
+
_izContext,
|
|
176
|
+
objType,
|
|
177
|
+
requestParams.relationships
|
|
178
|
+
))
|
|
179
|
+
);
|
|
180
|
+
_izContext.logger.debug(
|
|
181
|
+
`[${process.env.iz_serviceTag}:<%- flowTag %>] errorsFound:`,
|
|
182
|
+
errorsFound
|
|
154
183
|
);
|
|
155
184
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
185
|
+
// ── Resolve fromRequiredOnCreate fields ──────────────────────────────────
|
|
186
|
+
if (objectSchemas.fieldNames) {
|
|
187
|
+
if (!requestParams.fieldNames) {
|
|
188
|
+
requestParams.fieldNames = {};
|
|
189
|
+
}
|
|
190
|
+
for (const [fieldName, val] of Object.entries(objectSchemas.fieldNames)) {
|
|
191
|
+
if (
|
|
192
|
+
val.fromRequiredOnCreate &&
|
|
193
|
+
requestParams.fieldNames[fieldName] === undefined
|
|
194
|
+
) {
|
|
195
|
+
const fromConfig = val.fromRequiredOnCreate;
|
|
196
|
+
const sourceField = fromConfig.fieldName || fieldName;
|
|
197
|
+
if (fromConfig.belongToObjType === true && targetIdentifiers) {
|
|
198
|
+
let targetValue = targetIdentifiers[sourceField];
|
|
199
|
+
if (targetValue === undefined) {
|
|
200
|
+
targetValue = Object.values(targetIdentifiers)[0];
|
|
201
|
+
}
|
|
202
|
+
requestParams.fieldNames[fieldName] = targetValue;
|
|
203
|
+
} else if (
|
|
204
|
+
fromConfig.relType &&
|
|
205
|
+
requestParams.relationships?.length > 0
|
|
206
|
+
) {
|
|
207
|
+
const matchedRel = requestParams.relationships.find(
|
|
208
|
+
(rel) =>
|
|
209
|
+
rel.relType?.serviceTag === fromConfig.relType.serviceTag &&
|
|
210
|
+
rel.relType?.relationshipTag === fromConfig.relType.relationshipTag
|
|
211
|
+
);
|
|
212
|
+
if (matchedRel?.targetIdentifiers?.[sourceField] !== undefined) {
|
|
213
|
+
requestParams.fieldNames[fieldName] =
|
|
214
|
+
matchedRel.targetIdentifiers[sourceField];
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// ── Resolve identifiers ───────────────────────────────────────────────────
|
|
222
|
+
let errors;
|
|
223
|
+
const identifiers = objectSchemas.identifiers;
|
|
224
|
+
let optionalOnCreateIdentifiers;
|
|
225
|
+
|
|
226
|
+
if (
|
|
227
|
+
identifiers?.length === 1 &&
|
|
228
|
+
!identifiers[0].hasOwnProperty('fieldNames')
|
|
229
|
+
) {
|
|
230
|
+
[requestParams, errors] = await createIdentifiersByUseCase(
|
|
231
|
+
_izContext,
|
|
232
|
+
requestParams,
|
|
233
|
+
objectSchemas,
|
|
234
|
+
identifiers[0],
|
|
235
|
+
optionalOnCreateIdentifiers
|
|
236
|
+
);
|
|
237
|
+
if (errors?.length > 0) {
|
|
238
|
+
errorsFound.push(...errors);
|
|
239
|
+
}
|
|
240
|
+
} else if (identifiers?.length > 1) {
|
|
241
|
+
for (const identifier of identifiers) {
|
|
242
|
+
[requestParams, errors] = await createIdentifiersByUseCase(
|
|
243
|
+
_izContext,
|
|
244
|
+
requestParams,
|
|
245
|
+
objectSchemas,
|
|
246
|
+
identifier,
|
|
247
|
+
optionalOnCreateIdentifiers
|
|
248
|
+
);
|
|
249
|
+
if (errors?.length > 0) {
|
|
250
|
+
errorsFound.push(...errors);
|
|
251
|
+
}
|
|
159
252
|
}
|
|
160
253
|
}
|
|
161
254
|
|
|
162
|
-
|
|
163
|
-
`[${process.env.iz_serviceTag}:<%- flowTag %>] Identifiers generated:`,
|
|
164
|
-
identifiers
|
|
165
|
-
);
|
|
255
|
+
return { objectSchemas };
|
|
166
256
|
}
|
|
167
257
|
|
|
168
258
|
/**
|
|
169
259
|
* Validates request field names against schema definition
|
|
170
260
|
* @param {Object} _izContext - Izara context object
|
|
171
|
-
* @param {Object} objectSchemas - Combined object schema
|
|
172
261
|
* @param {Object} requestParams - Incoming request parameters
|
|
262
|
+
* @param {Object} objectSchemas - Combined object schema
|
|
173
263
|
* @param {Array<string>} errorsFound - Array to collect validation errors
|
|
174
264
|
*/
|
|
175
|
-
export function validateFieldNames(
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
265
|
+
export function validateFieldNames(
|
|
266
|
+
_izContext,
|
|
267
|
+
requestParams,
|
|
268
|
+
objectSchemas,
|
|
269
|
+
errorsFound
|
|
270
|
+
) {
|
|
271
|
+
const listOfRequiredOnCreate = [];
|
|
272
|
+
const listOfOptionalOnCreate = [];
|
|
273
|
+
|
|
274
|
+
for (const [key, val] of Object.entries(objectSchemas?.fieldNames || {})) {
|
|
275
|
+
if (
|
|
276
|
+
val.randomOnCreate === true ||
|
|
277
|
+
val.requiredOnCreate === true ||
|
|
278
|
+
val.fromRequiredOnCreate ||
|
|
279
|
+
val.hashOnCreate?.length
|
|
280
|
+
) {
|
|
281
|
+
listOfRequiredOnCreate.push(key);
|
|
282
|
+
}
|
|
283
|
+
if (val.requiredOnCreate === false && val.optionalOnCreate === true) {
|
|
284
|
+
listOfOptionalOnCreate.push(key);
|
|
180
285
|
}
|
|
181
286
|
}
|
|
182
287
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
288
|
+
for (const fieldName of Object.keys(requestParams.fieldNames || {})) {
|
|
289
|
+
if (
|
|
290
|
+
!listOfRequiredOnCreate.includes(fieldName) &&
|
|
291
|
+
!listOfOptionalOnCreate.includes(fieldName)
|
|
292
|
+
) {
|
|
293
|
+
errorsFound.push('[invalid] over fieldNames create object');
|
|
294
|
+
}
|
|
295
|
+
if (errorsFound.length > 0) {
|
|
296
|
+
_izContext.logger.debug(
|
|
297
|
+
`[${process.env.iz_serviceTag}:<%- flowTag %>] HaveError:`,
|
|
298
|
+
errorsFound
|
|
299
|
+
);
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
187
302
|
}
|
|
188
303
|
}
|
|
189
304
|
|
|
@@ -641,60 +756,93 @@ export function resolveQuotaDeductionKeys(
|
|
|
641
756
|
}
|
|
642
757
|
|
|
643
758
|
/**
|
|
644
|
-
* Forwards quota confirmation
|
|
759
|
+
* Forwards quota confirmation or cancellation to RBAC via synchronous invoke
|
|
760
|
+
* and publishes final completion message to outCreateNodeComplete
|
|
645
761
|
* @param {Object} _izContext - Izara context object
|
|
646
762
|
* @param {Object} options - Message forwarding options
|
|
647
|
-
* @returns {Promise<
|
|
763
|
+
* @returns {Promise<Object>} Quota invocation result
|
|
648
764
|
*/
|
|
649
765
|
export async function forwardToQuotaConfirmation(
|
|
650
766
|
_izContext,
|
|
651
767
|
{
|
|
652
768
|
status,
|
|
653
|
-
errorsFound,
|
|
769
|
+
errorsFound = [],
|
|
654
770
|
quotaKeys,
|
|
655
771
|
actionData,
|
|
656
772
|
callingFlowConfig
|
|
657
773
|
}
|
|
658
774
|
) {
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
775
|
+
let quotaResult = null;
|
|
776
|
+
if (quotaKeys && (quotaKeys.limitTag || quotaKeys.flowTypeConcat)) {
|
|
777
|
+
let targetFunction = 'CancelUsageHdrInv';
|
|
778
|
+
if (status === 'complete' && errorsFound.length === 0) {
|
|
779
|
+
targetFunction = 'ConfirmUsageHdrInv';
|
|
780
|
+
}
|
|
663
781
|
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
parentPassBackProperties: actionData
|
|
669
|
-
},
|
|
670
|
-
callingFlowSharedLib.addParentCallingFlowConfig(
|
|
671
|
-
callingFlowConfig,
|
|
672
|
-
callingFlowSharedLib.createCallingFlowConfig(
|
|
673
|
-
await lambdaSharedLib.lambdaFunctionName(
|
|
674
|
-
_izContext,
|
|
675
|
-
'CreateCompleteHdrSqs'
|
|
676
|
-
),
|
|
677
|
-
{}
|
|
678
|
-
)
|
|
679
|
-
)
|
|
782
|
+
const functionName = await lambdaSharedLib.lambdaFunctionName(
|
|
783
|
+
_izContext,
|
|
784
|
+
targetFunction,
|
|
785
|
+
'Rbac'
|
|
680
786
|
);
|
|
681
787
|
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
788
|
+
const forwardMessage = {
|
|
789
|
+
...quotaKeys,
|
|
790
|
+
parentPassBackProperties: actionData,
|
|
791
|
+
callingFlowConfig
|
|
792
|
+
};
|
|
793
|
+
|
|
794
|
+
_izContext.logger.debug('[CreateLogicalLib] invoking RBAC quota sync', {
|
|
795
|
+
targetFunction,
|
|
796
|
+
functionName,
|
|
797
|
+
forwardMessage
|
|
798
|
+
});
|
|
799
|
+
|
|
800
|
+
try {
|
|
801
|
+
quotaResult = await lambda.invokeSync(
|
|
802
|
+
_izContext,
|
|
803
|
+
functionName,
|
|
804
|
+
forwardMessage
|
|
805
|
+
);
|
|
806
|
+
} catch (err) {
|
|
807
|
+
_izContext.logger.error(
|
|
808
|
+
`[CreateLogicalLib] error invoking ${targetFunction}:`,
|
|
809
|
+
err
|
|
810
|
+
);
|
|
811
|
+
if (targetFunction === 'ConfirmUsageHdrInv') {
|
|
812
|
+
try {
|
|
813
|
+
const cancelFunctionName = await lambdaSharedLib.lambdaFunctionName(
|
|
814
|
+
_izContext,
|
|
815
|
+
'CancelUsageHdrInv',
|
|
816
|
+
'Rbac'
|
|
817
|
+
);
|
|
818
|
+
await lambda.invokeSync(
|
|
819
|
+
_izContext,
|
|
820
|
+
cancelFunctionName,
|
|
821
|
+
forwardMessage
|
|
822
|
+
);
|
|
823
|
+
} catch (cancelErr) {
|
|
824
|
+
_izContext.logger.error(
|
|
825
|
+
'[CreateLogicalLib] error invoking CancelUsageHdrInv fallback:',
|
|
826
|
+
cancelErr
|
|
827
|
+
);
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
errorsFound.push(err.message || 'Quota confirmation failed');
|
|
831
|
+
if (actionData) {
|
|
832
|
+
actionData.status = 'error';
|
|
833
|
+
actionData.errorsFound = errorsFound;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
const { message, messageAttributes } = buildCompletionPayload(
|
|
839
|
+
callingFlowConfig,
|
|
840
|
+
actionData
|
|
686
841
|
);
|
|
687
842
|
|
|
688
|
-
_izContext
|
|
689
|
-
nextTargetTopic,
|
|
690
|
-
TopicArn: topicArn,
|
|
691
|
-
forwardMessage
|
|
692
|
-
});
|
|
843
|
+
await publishCompletionMessage(_izContext, message, messageAttributes);
|
|
693
844
|
|
|
694
|
-
|
|
695
|
-
Message: JSON.stringify(forwardMessage),
|
|
696
|
-
TopicArn: topicArn
|
|
697
|
-
});
|
|
845
|
+
return quotaResult;
|
|
698
846
|
}
|
|
699
847
|
|
|
700
848
|
// ── 4. CreateComplete_Main Helpers ───────────────────────────────────────────
|
|
@@ -1357,10 +1505,24 @@ export async function <%- flowTag %>LogicalLib(
|
|
|
1357
1505
|
<%_ if (plan?.hasAfterHookSync) { _%>
|
|
1358
1506
|
// ── Synchronous After Hooks ──
|
|
1359
1507
|
<%_ plan.afterHooks.filter(h => h?.generatedCodeConfig?.invocationType === 'lambdaSyncInv').forEach(hook => { _%>
|
|
1360
|
-
<%_ if (hook.
|
|
1361
|
-
if (objType.objectType === '<%= hook.
|
|
1508
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length === 1) { _%>
|
|
1509
|
+
if (objType.objectType === '<%= hook.targetObjectTypes[0] %>') {
|
|
1510
|
+
<%_ } else if (hook.targetObjectTypes && hook.targetObjectTypes.length > 1) { _%>
|
|
1511
|
+
if (<%- JSON.stringify(hook.targetObjectTypes) %>.includes(objType.objectType)) {
|
|
1362
1512
|
<%_ } _%>
|
|
1363
1513
|
try {
|
|
1514
|
+
let hookPayload_<%= hook.flowTag %> = {
|
|
1515
|
+
objType,
|
|
1516
|
+
objInstanceFull: {
|
|
1517
|
+
identifiers: identifiersForCreateData,
|
|
1518
|
+
fields: fieldsForHook
|
|
1519
|
+
},
|
|
1520
|
+
relationships: requestParams.relationships || [],
|
|
1521
|
+
targetIdentifiers: requestParams.targetIdentifiers,
|
|
1522
|
+
submittedByUserId: requestParams.submittedByUserId
|
|
1523
|
+
};
|
|
1524
|
+
//(<beforeSendHook_<%= hook.flowTag %>>)
|
|
1525
|
+
//(</beforeSendHook_<%= hook.flowTag %>>)
|
|
1364
1526
|
const hookResult = await lambda.invokeSync(
|
|
1365
1527
|
_izContext,
|
|
1366
1528
|
await lambdaSharedLib.lambdaFunctionName(
|
|
@@ -1368,16 +1530,7 @@ export async function <%- flowTag %>LogicalLib(
|
|
|
1368
1530
|
'<%= hook.flowTag %>'
|
|
1369
1531
|
),
|
|
1370
1532
|
{
|
|
1371
|
-
requestParams:
|
|
1372
|
-
objType,
|
|
1373
|
-
objInstanceFull: {
|
|
1374
|
-
identifiers: identifiersForCreateData,
|
|
1375
|
-
fields: fieldsForHook
|
|
1376
|
-
},
|
|
1377
|
-
relationships: requestParams.relationships || [],
|
|
1378
|
-
targetIdentifiers: requestParams.targetIdentifiers,
|
|
1379
|
-
submittedByUserId: requestParams.submittedByUserId
|
|
1380
|
-
},
|
|
1533
|
+
requestParams: hookPayload_<%= hook.flowTag %>,
|
|
1381
1534
|
callingFlowConfig
|
|
1382
1535
|
}
|
|
1383
1536
|
);
|
|
@@ -1388,7 +1541,7 @@ export async function <%- flowTag %>LogicalLib(
|
|
|
1388
1541
|
_izContext.logger.error('[<%- flowTag %>LogicalLib] Sync hook <%= hook.flowTag %> error:', hookErr);
|
|
1389
1542
|
errorsFound.push(hookErr.message || 'Hook <%= hook.flowTag %> failed');
|
|
1390
1543
|
}
|
|
1391
|
-
<%_ if (hook.
|
|
1544
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length > 0) { _%>
|
|
1392
1545
|
}
|
|
1393
1546
|
<%_ } _%>
|
|
1394
1547
|
<%_ }) _%>
|
|
@@ -1397,20 +1550,25 @@ export async function <%- flowTag %>LogicalLib(
|
|
|
1397
1550
|
<%_ if (plan?.hasAfterHookAsync) { _%>
|
|
1398
1551
|
// ── Asynchronous After Hooks ──
|
|
1399
1552
|
<%_ plan.afterHooks.filter(h => h?.generatedCodeConfig?.invocationType === 'ownTopic').forEach(hook => { _%>
|
|
1400
|
-
<%_ if (hook.
|
|
1401
|
-
if (objType.objectType === '<%= hook.
|
|
1553
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length === 1) { _%>
|
|
1554
|
+
if (objType.objectType === '<%= hook.targetObjectTypes[0] %>') {
|
|
1555
|
+
<%_ } else if (hook.targetObjectTypes && hook.targetObjectTypes.length > 1) { _%>
|
|
1556
|
+
if (<%- JSON.stringify(hook.targetObjectTypes) %>.includes(objType.objectType)) {
|
|
1402
1557
|
<%_ } _%>
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
fields: fieldsForHook
|
|
1409
|
-
},
|
|
1410
|
-
relationships: requestParams.relationships || [],
|
|
1411
|
-
targetIdentifiers: requestParams.targetIdentifiers,
|
|
1412
|
-
submittedByUserId: requestParams.submittedByUserId
|
|
1558
|
+
let hookPayload_<%= hook.flowTag %> = {
|
|
1559
|
+
objType,
|
|
1560
|
+
objInstanceFull: {
|
|
1561
|
+
identifiers: identifiersForCreateData,
|
|
1562
|
+
fields: fieldsForHook
|
|
1413
1563
|
},
|
|
1564
|
+
relationships: requestParams.relationships || [],
|
|
1565
|
+
targetIdentifiers: requestParams.targetIdentifiers,
|
|
1566
|
+
submittedByUserId: requestParams.submittedByUserId
|
|
1567
|
+
};
|
|
1568
|
+
//(<beforeSendHook_<%= hook.flowTag %>>)
|
|
1569
|
+
//(</beforeSendHook_<%= hook.flowTag %>>)
|
|
1570
|
+
const hookMsg_<%= hook.flowTag %> = callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
|
|
1571
|
+
hookPayload_<%= hook.flowTag %>,
|
|
1414
1572
|
callingFlowSharedLib.addParentCallingFlowConfig(
|
|
1415
1573
|
callingFlowConfig,
|
|
1416
1574
|
callingFlowSharedLib.createCallingFlowConfig(
|
|
@@ -1443,7 +1601,7 @@ export async function <%- flowTag %>LogicalLib(
|
|
|
1443
1601
|
Message: JSON.stringify(hookMsg_<%= hook.flowTag %>),
|
|
1444
1602
|
MessageAttributes: sns.createStringMessageAttributes(_izContext, {})
|
|
1445
1603
|
});
|
|
1446
|
-
<%_ if (hook.
|
|
1604
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length > 0) { _%>
|
|
1447
1605
|
}
|
|
1448
1606
|
<%_ } _%>
|
|
1449
1607
|
<%_ }) _%>
|
|
@@ -175,10 +175,21 @@ export default async function CreateNodeCallbackMain(
|
|
|
175
175
|
<%_ if (plan?.hasAfterHookSync) { _%>
|
|
176
176
|
// ── Synchronous After Hooks ──
|
|
177
177
|
<%_ plan.afterHooks.filter(h => h?.generatedCodeConfig?.invocationType === 'lambdaSyncInv').forEach(hook => { _%>
|
|
178
|
-
<%_ if (hook.
|
|
179
|
-
if (returnValue.requestParams?.objType?.objectType === '<%= hook.
|
|
178
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length === 1) { _%>
|
|
179
|
+
if (returnValue.requestParams?.objType?.objectType === '<%= hook.targetObjectTypes[0] %>') {
|
|
180
|
+
<%_ } else if (hook.targetObjectTypes && hook.targetObjectTypes.length > 1) { _%>
|
|
181
|
+
if (<%- JSON.stringify(hook.targetObjectTypes) %>.includes(returnValue.requestParams?.objType?.objectType)) {
|
|
180
182
|
<%_ } _%>
|
|
181
183
|
try {
|
|
184
|
+
let hookPayload_<%= hook.flowTag %> = {
|
|
185
|
+
objType: returnValue.requestParams.objType,
|
|
186
|
+
objInstanceFull: node.objInstanceFull,
|
|
187
|
+
relationships: node.relationships || [],
|
|
188
|
+
targetIdentifiers: requestParams.targetIdentifiers,
|
|
189
|
+
submittedByUserId
|
|
190
|
+
};
|
|
191
|
+
//(<beforeSendHook_<%= hook.flowTag %>>)
|
|
192
|
+
//(</beforeSendHook_<%= hook.flowTag %>>)
|
|
182
193
|
const hookResult = await lambda.invokeSync(
|
|
183
194
|
_izContext,
|
|
184
195
|
await lambdaSharedLib.lambdaFunctionName(
|
|
@@ -186,13 +197,7 @@ export default async function CreateNodeCallbackMain(
|
|
|
186
197
|
'<%= hook.flowTag %>'
|
|
187
198
|
),
|
|
188
199
|
{
|
|
189
|
-
requestParams:
|
|
190
|
-
objType: returnValue.requestParams.objType,
|
|
191
|
-
objInstanceFull: node.objInstanceFull,
|
|
192
|
-
relationships: node.relationships || [],
|
|
193
|
-
targetIdentifiers: requestParams.targetIdentifiers,
|
|
194
|
-
submittedByUserId
|
|
195
|
-
},
|
|
200
|
+
requestParams: hookPayload_<%= hook.flowTag %>,
|
|
196
201
|
callingFlowConfig
|
|
197
202
|
}
|
|
198
203
|
);
|
|
@@ -203,7 +208,7 @@ export default async function CreateNodeCallbackMain(
|
|
|
203
208
|
_izContext.logger.error('[CreateNodeCallback] Sync hook <%= hook.flowTag %> error:', hookErr);
|
|
204
209
|
errorsFound.push(hookErr.message || 'Hook <%= hook.flowTag %> failed');
|
|
205
210
|
}
|
|
206
|
-
<%_ if (hook.
|
|
211
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length > 0) { _%>
|
|
207
212
|
}
|
|
208
213
|
<%_ } _%>
|
|
209
214
|
<%_ }) _%>
|
|
@@ -238,17 +243,22 @@ export default async function CreateNodeCallbackMain(
|
|
|
238
243
|
<%_ if (plan?.hasAfterHookAsync) { _%>
|
|
239
244
|
// ── Asynchronous After Hooks ──
|
|
240
245
|
<%_ plan.afterHooks.filter(h => h?.generatedCodeConfig?.invocationType === 'ownTopic').forEach(hook => { _%>
|
|
241
|
-
<%_ if (hook.
|
|
242
|
-
if (returnValue.requestParams?.objType?.objectType === '<%= hook.
|
|
246
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length === 1) { _%>
|
|
247
|
+
if (returnValue.requestParams?.objType?.objectType === '<%= hook.targetObjectTypes[0] %>') {
|
|
248
|
+
<%_ } else if (hook.targetObjectTypes && hook.targetObjectTypes.length > 1) { _%>
|
|
249
|
+
if (<%- JSON.stringify(hook.targetObjectTypes) %>.includes(returnValue.requestParams?.objType?.objectType)) {
|
|
243
250
|
<%_ } _%>
|
|
251
|
+
let hookPayload_<%= hook.flowTag %> = {
|
|
252
|
+
objType: returnValue.requestParams.objType,
|
|
253
|
+
objInstanceFull: node.objInstanceFull,
|
|
254
|
+
relationships: node.relationships || [],
|
|
255
|
+
targetIdentifiers: requestParams.targetIdentifiers,
|
|
256
|
+
submittedByUserId
|
|
257
|
+
};
|
|
258
|
+
//(<beforeSendHook_<%= hook.flowTag %>>)
|
|
259
|
+
//(</beforeSendHook_<%= hook.flowTag %>>)
|
|
244
260
|
const hookMsg_<%= hook.flowTag %> = callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
|
|
245
|
-
|
|
246
|
-
objType: returnValue.requestParams.objType,
|
|
247
|
-
objInstanceFull: node.objInstanceFull,
|
|
248
|
-
relationships: node.relationships || [],
|
|
249
|
-
targetIdentifiers: requestParams.targetIdentifiers,
|
|
250
|
-
submittedByUserId
|
|
251
|
-
},
|
|
261
|
+
hookPayload_<%= hook.flowTag %>,
|
|
252
262
|
callingFlowSharedLib.addParentCallingFlowConfig(
|
|
253
263
|
callingFlowConfig,
|
|
254
264
|
callingFlowSharedLib.createCallingFlowConfig(
|
|
@@ -272,7 +282,7 @@ export default async function CreateNodeCallbackMain(
|
|
|
272
282
|
Message: JSON.stringify(hookMsg_<%= hook.flowTag %>),
|
|
273
283
|
MessageAttributes: sns.createStringMessageAttributes(_izContext, {})
|
|
274
284
|
});
|
|
275
|
-
<%_ if (hook.
|
|
285
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length > 0) { _%>
|
|
276
286
|
}
|
|
277
287
|
<%_ } _%>
|
|
278
288
|
<%_ }) _%>
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (C) 2026 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 asyncFlowSharedLib from '@izara_project/izara-core-library-asynchronous-flow';
|
|
19
|
+
import callingFlowSharedLib from '@izara_project/izara-core-library-calling-flow';
|
|
20
|
+
import snsSharedLib from '@izara_project/izara-core-library-sns';
|
|
21
|
+
import { sns } from '@izara_project/izara-core-library-external-request';
|
|
22
|
+
import { consts } from '@izara_project/izara-core-library-service-schemas';
|
|
23
|
+
|
|
24
|
+
//(<optionalRequire>)
|
|
25
|
+
//(</optionalRequire>)
|
|
26
|
+
|
|
27
|
+
const { TOPIC_NAME_GENERATE_CODE } = consts;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Handles callback after async AfterHook completion for Delete
|
|
31
|
+
* @param {Object} _izContext - Izara context object
|
|
32
|
+
* @param {Object} requestParams - Callback request parameters
|
|
33
|
+
* @param {Object} passBackProperties - Pass-back properties
|
|
34
|
+
* @returns {Promise<Object>} Result object
|
|
35
|
+
*/
|
|
36
|
+
export default async function DeleteAfterHookCallbackMain(
|
|
37
|
+
_izContext,
|
|
38
|
+
requestParams,
|
|
39
|
+
passBackProperties
|
|
40
|
+
//(<additionalParams>)
|
|
41
|
+
//(</additionalParams>)
|
|
42
|
+
) {
|
|
43
|
+
try {
|
|
44
|
+
_izContext.logger.debug('[DeleteAfterHookCallback] started', {
|
|
45
|
+
requestParams,
|
|
46
|
+
passBackProperties
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const {
|
|
50
|
+
status,
|
|
51
|
+
errorsFound = [],
|
|
52
|
+
returnValue,
|
|
53
|
+
parentFlowId
|
|
54
|
+
} = requestParams;
|
|
55
|
+
|
|
56
|
+
const mergedErrors = Array.isArray(errorsFound) ? [...errorsFound] : [];
|
|
57
|
+
if (status === 'error' && mergedErrors.length === 0) {
|
|
58
|
+
mergedErrors.push('AfterHook execution reported error');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const callingFlowConfig =
|
|
62
|
+
passBackProperties?.callingFlowConfig ||
|
|
63
|
+
requestParams?.passBackProperties?.callingFlowConfig ||
|
|
64
|
+
passBackProperties;
|
|
65
|
+
|
|
66
|
+
const actionData =
|
|
67
|
+
passBackProperties?.actionData ||
|
|
68
|
+
requestParams?.passBackProperties?.actionData ||
|
|
69
|
+
{
|
|
70
|
+
objType: returnValue?.objType || requestParams?.objType,
|
|
71
|
+
identifiers:
|
|
72
|
+
returnValue?.identifiers || requestParams?.identifiers || {},
|
|
73
|
+
targetIdentifiers: requestParams?.targetIdentifiers,
|
|
74
|
+
parentFlowId: parentFlowId || returnValue?.parentFlowId,
|
|
75
|
+
status: mergedErrors.length > 0 ? 'error' : 'complete',
|
|
76
|
+
errorsFound: mergedErrors
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const topicArn = snsSharedLib.snsTopicArnByFlowSchema(
|
|
80
|
+
_izContext,
|
|
81
|
+
TOPIC_NAME_GENERATE_CODE.outDeleteNodeComplete
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const completionPayload =
|
|
85
|
+
callingFlowSharedLib.addParentPassBackPropertiesToSnsResponseMessageObject(
|
|
86
|
+
callingFlowConfig,
|
|
87
|
+
{
|
|
88
|
+
...actionData,
|
|
89
|
+
status: mergedErrors.length > 0 ? 'error' : 'complete',
|
|
90
|
+
errorsFound: mergedErrors
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
await sns.publishAsync(_izContext, {
|
|
95
|
+
TopicArn: topicArn,
|
|
96
|
+
Message: JSON.stringify(completionPayload),
|
|
97
|
+
MessageAttributes: sns.createStringMessageAttributes(
|
|
98
|
+
_izContext,
|
|
99
|
+
callingFlowSharedLib.addParentPassBackCallingFlowToSnsResponseMessageAttributes(
|
|
100
|
+
callingFlowConfig,
|
|
101
|
+
{}
|
|
102
|
+
)
|
|
103
|
+
)
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
//(<afterProcessCallback>)
|
|
107
|
+
//(</afterProcessCallback>)
|
|
108
|
+
|
|
109
|
+
return {
|
|
110
|
+
returnValue,
|
|
111
|
+
status: mergedErrors.length > 0 ? 'error' : 'complete',
|
|
112
|
+
errorsFound: mergedErrors
|
|
113
|
+
};
|
|
114
|
+
} catch (error) {
|
|
115
|
+
_izContext.logger.error('[DeleteAfterHookCallback] error:', error);
|
|
116
|
+
throw error;
|
|
117
|
+
}
|
|
118
|
+
}
|