@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
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import asyncFlowSharedLib from '@izara_project/izara-core-library-asynchronous-flow';
|
|
2
2
|
import callingFlowSharedLib from '@izara_project/izara-core-library-calling-flow';
|
|
3
3
|
import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
|
|
4
|
+
import lambdaSharedLib from '@izara_project/izara-core-library-lambda';
|
|
4
5
|
import snsSharedLib from '@izara_project/izara-core-library-sns';
|
|
5
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
sns,
|
|
8
|
+
lambda
|
|
9
|
+
} from '@izara_project/izara-core-library-external-request';
|
|
6
10
|
import { consts } from '@izara_project/izara-core-library-service-schemas';
|
|
7
11
|
import { NoRetryError } from '@izara_project/izara-core-library-core';
|
|
8
12
|
|
|
@@ -142,18 +146,127 @@ export default async function DeleteComplete(
|
|
|
142
146
|
const callingFlowConfig =
|
|
143
147
|
result?.additionalAttributes?.callingFlowConfig ||
|
|
144
148
|
passBackProperties;
|
|
149
|
+
const actionData = {
|
|
150
|
+
objType: returnValue.requestParams.objType,
|
|
151
|
+
objInstanceFull: node.objInstanceFull,
|
|
152
|
+
identifiers:
|
|
153
|
+
node.objInstanceFull?.identifiers ||
|
|
154
|
+
requestParams?.targetIdentifiers ||
|
|
155
|
+
{},
|
|
156
|
+
relationships: node.relationships,
|
|
157
|
+
parentFlowId: parentFlowId || returnValue?.parentFlowId,
|
|
158
|
+
existsNode,
|
|
159
|
+
status,
|
|
160
|
+
errorsFound
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
<%_ if (plan?.hasAfterHookSync) { _%>
|
|
164
|
+
// ── Synchronous After Hooks ──
|
|
165
|
+
<%_ plan.afterHooks.filter(h => h?.generatedCodeConfig?.invocationType === 'lambdaSyncInv').forEach(hook => { _%>
|
|
166
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length === 1) { _%>
|
|
167
|
+
if (returnValue.requestParams?.objType?.objectType === '<%= hook.targetObjectTypes[0] %>') {
|
|
168
|
+
<%_ } else if (hook.targetObjectTypes && hook.targetObjectTypes.length > 1) { _%>
|
|
169
|
+
if (<%- JSON.stringify(hook.targetObjectTypes) %>.includes(returnValue.requestParams?.objType?.objectType)) {
|
|
170
|
+
<%_ } _%>
|
|
171
|
+
try {
|
|
172
|
+
let hookPayload_<%= hook.flowTag %> = {
|
|
173
|
+
objType: returnValue.requestParams.objType,
|
|
174
|
+
identifiers:
|
|
175
|
+
node.objInstanceFull?.identifiers ||
|
|
176
|
+
requestParams.targetIdentifiers ||
|
|
177
|
+
{},
|
|
178
|
+
objInstanceFull: node.objInstanceFull,
|
|
179
|
+
relationships: node.relationships || [],
|
|
180
|
+
targetIdentifiers: requestParams.targetIdentifiers
|
|
181
|
+
};
|
|
182
|
+
//(<beforeSendHook_<%= hook.flowTag %>>)
|
|
183
|
+
//(</beforeSendHook_<%= hook.flowTag %>>)
|
|
184
|
+
const hookResult = await lambda.invokeSync(
|
|
185
|
+
_izContext,
|
|
186
|
+
await lambdaSharedLib.lambdaFunctionName(
|
|
187
|
+
_izContext,
|
|
188
|
+
'<%= hook.flowTag %>'
|
|
189
|
+
),
|
|
190
|
+
{
|
|
191
|
+
requestParams: hookPayload_<%= hook.flowTag %>,
|
|
192
|
+
callingFlowConfig
|
|
193
|
+
}
|
|
194
|
+
);
|
|
195
|
+
if (
|
|
196
|
+
hookResult?.errorsFound?.length > 0 ||
|
|
197
|
+
hookResult?.status === 'error'
|
|
198
|
+
) {
|
|
199
|
+
errorsFound.push(
|
|
200
|
+
...(hookResult.errorsFound || ['Hook <%= hook.flowTag %> failed'])
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
} catch (hookErr) {
|
|
204
|
+
_izContext.logger.error(
|
|
205
|
+
'[DeleteComplete] Sync hook <%= hook.flowTag %> error:',
|
|
206
|
+
hookErr
|
|
207
|
+
);
|
|
208
|
+
errorsFound.push(hookErr.message || 'Hook <%= hook.flowTag %> failed');
|
|
209
|
+
}
|
|
210
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length > 0) { _%>
|
|
211
|
+
}
|
|
212
|
+
<%_ } _%>
|
|
213
|
+
<%_ }) _%>
|
|
214
|
+
<%_ } _%>
|
|
215
|
+
|
|
216
|
+
<%_ if (plan?.hasAfterHookAsync) { _%>
|
|
217
|
+
// ── Asynchronous After Hooks ──
|
|
218
|
+
<%_ plan.afterHooks.filter(h => h?.generatedCodeConfig?.invocationType === 'ownTopic').forEach(hook => { _%>
|
|
219
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length === 1) { _%>
|
|
220
|
+
if (returnValue.requestParams?.objType?.objectType === '<%= hook.targetObjectTypes[0] %>') {
|
|
221
|
+
<%_ } else if (hook.targetObjectTypes && hook.targetObjectTypes.length > 1) { _%>
|
|
222
|
+
if (<%- JSON.stringify(hook.targetObjectTypes) %>.includes(returnValue.requestParams?.objType?.objectType)) {
|
|
223
|
+
<%_ } _%>
|
|
224
|
+
let hookPayload_<%= hook.flowTag %> = {
|
|
225
|
+
objType: returnValue.requestParams.objType,
|
|
226
|
+
identifiers:
|
|
227
|
+
node.objInstanceFull?.identifiers ||
|
|
228
|
+
requestParams.targetIdentifiers ||
|
|
229
|
+
{},
|
|
230
|
+
objInstanceFull: node.objInstanceFull,
|
|
231
|
+
relationships: node.relationships || [],
|
|
232
|
+
targetIdentifiers: requestParams.targetIdentifiers
|
|
233
|
+
};
|
|
234
|
+
//(<beforeSendHook_<%= hook.flowTag %>>)
|
|
235
|
+
//(</beforeSendHook_<%= hook.flowTag %>>)
|
|
236
|
+
const hookMsg_<%= hook.flowTag %> =
|
|
237
|
+
callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
|
|
238
|
+
hookPayload_<%= hook.flowTag %>,
|
|
239
|
+
callingFlowSharedLib.addParentCallingFlowConfig(
|
|
240
|
+
callingFlowConfig,
|
|
241
|
+
callingFlowSharedLib.createCallingFlowConfig(
|
|
242
|
+
await lambdaSharedLib.lambdaFunctionName(
|
|
243
|
+
_izContext,
|
|
244
|
+
'DeleteAfterHookCallbackHdrSqs'
|
|
245
|
+
),
|
|
246
|
+
{
|
|
247
|
+
actionData
|
|
248
|
+
}
|
|
249
|
+
)
|
|
250
|
+
)
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
await sns.publishAsync(_izContext, {
|
|
254
|
+
TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
|
|
255
|
+
_izContext,
|
|
256
|
+
'<%= hook.flowTag %>_In'
|
|
257
|
+
),
|
|
258
|
+
Message: JSON.stringify(hookMsg_<%= hook.flowTag %>),
|
|
259
|
+
MessageAttributes: sns.createStringMessageAttributes(_izContext, {})
|
|
260
|
+
});
|
|
261
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length > 0) { _%>
|
|
262
|
+
}
|
|
263
|
+
<%_ } _%>
|
|
264
|
+
<%_ }) _%>
|
|
265
|
+
<%_ } else { _%>
|
|
145
266
|
const message =
|
|
146
267
|
callingFlowSharedLib.addParentPassBackPropertiesToSnsResponseMessageObject(
|
|
147
268
|
callingFlowConfig,
|
|
148
|
-
|
|
149
|
-
objType: returnValue.requestParams.objType,
|
|
150
|
-
objInstanceFull: node.objInstanceFull,
|
|
151
|
-
relationships: node.relationships,
|
|
152
|
-
parentFlowId: parentFlowId || returnValue?.parentFlowId,
|
|
153
|
-
existsNode,
|
|
154
|
-
status,
|
|
155
|
-
errorsFound
|
|
156
|
-
}
|
|
269
|
+
actionData
|
|
157
270
|
);
|
|
158
271
|
const messageAttributes =
|
|
159
272
|
callingFlowSharedLib.addParentPassBackCallingFlowToSnsResponseMessageAttributes(
|
|
@@ -176,6 +289,7 @@ export default async function DeleteComplete(
|
|
|
176
289
|
),
|
|
177
290
|
TopicArn: topicArn
|
|
178
291
|
});
|
|
292
|
+
<%_ } _%>
|
|
179
293
|
//(<afterSendMessage>)
|
|
180
294
|
//(</afterSendMessage>)
|
|
181
295
|
}
|
|
@@ -188,11 +188,15 @@ export default async function <%- flowTag %>(
|
|
|
188
188
|
|
|
189
189
|
// ── Optional phase extension point ────────────────────────────────────────
|
|
190
190
|
<%_
|
|
191
|
+
const allCrudObjectTypes = (objects || []).filter(isCrudObject).map(o => o.objectType);
|
|
191
192
|
const beforeHooksByObjType = (plan?.beforeHooks || []).reduce((acc, hook) => {
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
193
|
+
const targets = (hook?.targetObjectTypes && hook.targetObjectTypes.length > 0)
|
|
194
|
+
? hook.targetObjectTypes
|
|
195
|
+
: allCrudObjectTypes;
|
|
196
|
+
for (const key of targets) {
|
|
197
|
+
if (!acc[key]) acc[key] = [];
|
|
198
|
+
acc[key].push(hook);
|
|
199
|
+
}
|
|
196
200
|
return acc;
|
|
197
201
|
}, {});
|
|
198
202
|
_%>
|
|
@@ -206,6 +210,14 @@ export default async function <%- flowTag %>(
|
|
|
206
210
|
const lambdaSyncInvResults = [];
|
|
207
211
|
<%_ for (const config of configs.filter(c => c?.generatedCodeConfig?.invocationType === 'lambdaSyncInv' || c?.event?.includes('lambdaSyncInv'))) { _%>
|
|
208
212
|
try {
|
|
213
|
+
let hookPayload_<%= config.flowTag %> = {
|
|
214
|
+
objType,
|
|
215
|
+
identifiers: requestParams.identifiers,
|
|
216
|
+
targetIdentifiers,
|
|
217
|
+
submittedByUserId: requestParams.submittedByUserId
|
|
218
|
+
};
|
|
219
|
+
//(<beforeSendHook_<%= config.flowTag %>>)
|
|
220
|
+
//(</beforeSendHook_<%= config.flowTag %>>)
|
|
209
221
|
const returnValue = await lambda.invokeSync(
|
|
210
222
|
_izContext,
|
|
211
223
|
await lambdaSharedLib.lambdaFunctionName(
|
|
@@ -213,12 +225,7 @@ export default async function <%- flowTag %>(
|
|
|
213
225
|
'<%= config.flowTag %>'
|
|
214
226
|
),
|
|
215
227
|
{
|
|
216
|
-
requestParams:
|
|
217
|
-
objType,
|
|
218
|
-
identifiers: requestParams.identifiers,
|
|
219
|
-
targetIdentifiers,
|
|
220
|
-
submittedByUserId: requestParams.submittedByUserId
|
|
221
|
-
},
|
|
228
|
+
requestParams: hookPayload_<%= config.flowTag %>,
|
|
222
229
|
callingFlowConfig
|
|
223
230
|
}
|
|
224
231
|
);
|
|
@@ -260,14 +267,17 @@ export default async function <%- flowTag %>(
|
|
|
260
267
|
<%_ if (hasOwnTopic) { _%>
|
|
261
268
|
// ── ownTopic (async — dispatch to before-hook and await callback) ──────────
|
|
262
269
|
<%_ configs.filter(c => c?.generatedCodeConfig?.invocationType === 'ownTopic' || c?.event?.includes('ownTopic')).forEach(config => { _%>
|
|
270
|
+
let hookPayload_<%= config.flowTag %> = {
|
|
271
|
+
objType,
|
|
272
|
+
identifiers: requestParams.identifiers,
|
|
273
|
+
targetIdentifiers,
|
|
274
|
+
submittedByUserId: requestParams.submittedByUserId
|
|
275
|
+
};
|
|
276
|
+
//(<beforeSendHook_<%= config.flowTag %>>)
|
|
277
|
+
//(</beforeSendHook_<%= config.flowTag %>>)
|
|
263
278
|
const hookMsg_<%= config.flowTag %> =
|
|
264
279
|
callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
|
|
265
|
-
|
|
266
|
-
objType,
|
|
267
|
-
identifiers: requestParams.identifiers,
|
|
268
|
-
targetIdentifiers,
|
|
269
|
-
submittedByUserId: requestParams.submittedByUserId
|
|
270
|
-
},
|
|
280
|
+
hookPayload_<%= config.flowTag %>,
|
|
271
281
|
callingFlowSharedLib.addParentCallingFlowConfig(
|
|
272
282
|
callingFlowConfig,
|
|
273
283
|
callingFlowSharedLib.createCallingFlowConfig(
|
|
@@ -274,6 +274,111 @@ export async function <%- flowTag %>LogicalLib(
|
|
|
274
274
|
}
|
|
275
275
|
|
|
276
276
|
// ── Complete ──────────────────────────────────────────────────────────────
|
|
277
|
+
<%_ if (plan?.hasAfterHookSync) { _%>
|
|
278
|
+
// ── Synchronous After Hooks ──
|
|
279
|
+
<%_ plan.afterHooks.filter(h => h?.generatedCodeConfig?.invocationType === 'lambdaSyncInv').forEach(hook => { _%>
|
|
280
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length === 1) { _%>
|
|
281
|
+
if (objType?.objectType === '<%= hook.targetObjectTypes[0] %>') {
|
|
282
|
+
<%_ } else if (hook.targetObjectTypes && hook.targetObjectTypes.length > 1) { _%>
|
|
283
|
+
if (<%- JSON.stringify(hook.targetObjectTypes) %>.includes(objType?.objectType)) {
|
|
284
|
+
<%_ } _%>
|
|
285
|
+
try {
|
|
286
|
+
let hookPayload_<%= hook.flowTag %> = {
|
|
287
|
+
objType,
|
|
288
|
+
identifiers: requestParams.identifiers,
|
|
289
|
+
relationships: requestParams.relationships || [],
|
|
290
|
+
targetIdentifiers: requestParams.targetIdentifiers,
|
|
291
|
+
submittedByUserId: requestParams.submittedByUserId
|
|
292
|
+
};
|
|
293
|
+
//(<beforeSendHook_<%= hook.flowTag %>>)
|
|
294
|
+
//(</beforeSendHook_<%= hook.flowTag %>>)
|
|
295
|
+
const hookResult = await lambda.invokeSync(
|
|
296
|
+
_izContext,
|
|
297
|
+
await lambdaSharedLib.lambdaFunctionName(
|
|
298
|
+
_izContext,
|
|
299
|
+
'<%= hook.flowTag %>'
|
|
300
|
+
),
|
|
301
|
+
{
|
|
302
|
+
requestParams: hookPayload_<%= hook.flowTag %>,
|
|
303
|
+
callingFlowConfig
|
|
304
|
+
}
|
|
305
|
+
);
|
|
306
|
+
if (
|
|
307
|
+
hookResult?.errorsFound?.length > 0 ||
|
|
308
|
+
hookResult?.status === 'error'
|
|
309
|
+
) {
|
|
310
|
+
errorsFound.push(
|
|
311
|
+
...(hookResult.errorsFound || ['Hook <%= hook.flowTag %> failed'])
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
} catch (hookErr) {
|
|
315
|
+
_izContext.logger.error(
|
|
316
|
+
'[<%- flowTag %>LogicalLib] Sync hook <%= hook.flowTag %> error:',
|
|
317
|
+
hookErr
|
|
318
|
+
);
|
|
319
|
+
errorsFound.push(hookErr.message || 'Hook <%= hook.flowTag %> failed');
|
|
320
|
+
}
|
|
321
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length > 0) { _%>
|
|
322
|
+
}
|
|
323
|
+
<%_ } _%>
|
|
324
|
+
<%_ }) _%>
|
|
325
|
+
<%_ } _%>
|
|
326
|
+
|
|
327
|
+
<%_ if (plan?.hasAfterHookAsync) { _%>
|
|
328
|
+
// ── Asynchronous After Hooks ──
|
|
329
|
+
<%_ plan.afterHooks.filter(h => h?.generatedCodeConfig?.invocationType === 'ownTopic').forEach(hook => { _%>
|
|
330
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length === 1) { _%>
|
|
331
|
+
if (objType?.objectType === '<%= hook.targetObjectTypes[0] %>') {
|
|
332
|
+
<%_ } else if (hook.targetObjectTypes && hook.targetObjectTypes.length > 1) { _%>
|
|
333
|
+
if (<%- JSON.stringify(hook.targetObjectTypes) %>.includes(objType?.objectType)) {
|
|
334
|
+
<%_ } _%>
|
|
335
|
+
let hookPayload_<%= hook.flowTag %> = {
|
|
336
|
+
objType,
|
|
337
|
+
identifiers: requestParams.identifiers,
|
|
338
|
+
relationships: requestParams.relationships || [],
|
|
339
|
+
targetIdentifiers: requestParams.targetIdentifiers,
|
|
340
|
+
submittedByUserId: requestParams.submittedByUserId
|
|
341
|
+
};
|
|
342
|
+
//(<beforeSendHook_<%= hook.flowTag %>>)
|
|
343
|
+
//(</beforeSendHook_<%= hook.flowTag %>>)
|
|
344
|
+
const hookMsg_<%= hook.flowTag %> =
|
|
345
|
+
callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
|
|
346
|
+
hookPayload_<%= hook.flowTag %>,
|
|
347
|
+
callingFlowSharedLib.addParentCallingFlowConfig(
|
|
348
|
+
callingFlowConfig,
|
|
349
|
+
callingFlowSharedLib.createCallingFlowConfig(
|
|
350
|
+
await lambdaSharedLib.lambdaFunctionName(
|
|
351
|
+
_izContext,
|
|
352
|
+
'DeleteAfterHookCallbackHdrSqs'
|
|
353
|
+
),
|
|
354
|
+
{
|
|
355
|
+
actionData: {
|
|
356
|
+
objType,
|
|
357
|
+
identifiers: requestParams.identifiers,
|
|
358
|
+
relationships: requestParams.relationships || [],
|
|
359
|
+
targetIdentifiers: requestParams.targetIdentifiers,
|
|
360
|
+
parentFlowId: requestParams.parentFlowId,
|
|
361
|
+
status: 'complete',
|
|
362
|
+
errorsFound
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
)
|
|
366
|
+
)
|
|
367
|
+
);
|
|
368
|
+
|
|
369
|
+
await sns.publishAsync(_izContext, {
|
|
370
|
+
TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
|
|
371
|
+
_izContext,
|
|
372
|
+
'<%= hook.flowTag %>_In'
|
|
373
|
+
),
|
|
374
|
+
Message: JSON.stringify(hookMsg_<%= hook.flowTag %>),
|
|
375
|
+
MessageAttributes: sns.createStringMessageAttributes(_izContext, {})
|
|
376
|
+
});
|
|
377
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length > 0) { _%>
|
|
378
|
+
}
|
|
379
|
+
<%_ } _%>
|
|
380
|
+
<%_ }) _%>
|
|
381
|
+
<%_ } else { _%>
|
|
277
382
|
const outMessage =
|
|
278
383
|
callingFlowSharedLib.addPassBackPropertiesToSnsResponseMessageObject(
|
|
279
384
|
callingFlowConfig,
|
|
@@ -304,12 +409,18 @@ export async function <%- flowTag %>LogicalLib(
|
|
|
304
409
|
)
|
|
305
410
|
});
|
|
306
411
|
}
|
|
412
|
+
<%_ } _%>
|
|
413
|
+
|
|
414
|
+
let resultStatus = 'complete';
|
|
415
|
+
if (errorsFound.length > 0) {
|
|
416
|
+
resultStatus = 'error';
|
|
417
|
+
}
|
|
307
418
|
|
|
308
419
|
return {
|
|
309
420
|
objType,
|
|
310
421
|
identifiers: requestParams.identifiers,
|
|
311
422
|
targetIdentifiers: requestParams.targetIdentifiers,
|
|
312
|
-
status:
|
|
423
|
+
status: resultStatus,
|
|
313
424
|
errorsFound
|
|
314
425
|
};
|
|
315
426
|
} catch (err) {
|
|
@@ -0,0 +1,120 @@
|
|
|
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 Update
|
|
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 UpdateAfterHookCallbackMain(
|
|
37
|
+
_izContext,
|
|
38
|
+
requestParams,
|
|
39
|
+
passBackProperties
|
|
40
|
+
//(<additionalParams>)
|
|
41
|
+
//(</additionalParams>)
|
|
42
|
+
) {
|
|
43
|
+
try {
|
|
44
|
+
_izContext.logger.debug('[UpdateAfterHookCallback] 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
|
+
objInstanceFull:
|
|
72
|
+
returnValue?.objInstanceFull || requestParams?.objInstanceFull,
|
|
73
|
+
relationships:
|
|
74
|
+
returnValue?.relationships || requestParams?.relationships || [],
|
|
75
|
+
targetIdentifiers: requestParams?.targetIdentifiers,
|
|
76
|
+
parentFlowId: parentFlowId || returnValue?.parentFlowId,
|
|
77
|
+
status: mergedErrors.length > 0 ? 'error' : 'complete',
|
|
78
|
+
errorsFound: mergedErrors
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const topicArn = snsSharedLib.snsTopicArnByFlowSchema(
|
|
82
|
+
_izContext,
|
|
83
|
+
TOPIC_NAME_GENERATE_CODE.outUpdateNodeComplete
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const completionPayload =
|
|
87
|
+
callingFlowSharedLib.addParentPassBackPropertiesToSnsResponseMessageObject(
|
|
88
|
+
callingFlowConfig,
|
|
89
|
+
{
|
|
90
|
+
...actionData,
|
|
91
|
+
status: mergedErrors.length > 0 ? 'error' : 'complete',
|
|
92
|
+
errorsFound: mergedErrors
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
await sns.publishAsync(_izContext, {
|
|
97
|
+
TopicArn: topicArn,
|
|
98
|
+
Message: JSON.stringify(completionPayload),
|
|
99
|
+
MessageAttributes: sns.createStringMessageAttributes(
|
|
100
|
+
_izContext,
|
|
101
|
+
callingFlowSharedLib.addParentPassBackCallingFlowToSnsResponseMessageAttributes(
|
|
102
|
+
callingFlowConfig,
|
|
103
|
+
{}
|
|
104
|
+
)
|
|
105
|
+
)
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
//(<afterProcessCallback>)
|
|
109
|
+
//(</afterProcessCallback>)
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
returnValue,
|
|
113
|
+
status: mergedErrors.length > 0 ? 'error' : 'complete',
|
|
114
|
+
errorsFound: mergedErrors
|
|
115
|
+
};
|
|
116
|
+
} catch (error) {
|
|
117
|
+
_izContext.logger.error('[UpdateAfterHookCallback] error:', error);
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import asyncFlowSharedLib from '@izara_project/izara-core-library-asynchronous-flow';
|
|
2
2
|
import callingFlowSharedLib from '@izara_project/izara-core-library-calling-flow';
|
|
3
3
|
import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
|
|
4
|
+
import lambdaSharedLib from '@izara_project/izara-core-library-lambda';
|
|
4
5
|
import snsSharedLib from '@izara_project/izara-core-library-sns';
|
|
5
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
sns,
|
|
8
|
+
lambda
|
|
9
|
+
} from '@izara_project/izara-core-library-external-request';
|
|
6
10
|
import { consts } from '@izara_project/izara-core-library-service-schemas';
|
|
7
11
|
import { NoRetryError } from '@izara_project/izara-core-library-core';
|
|
8
12
|
|
|
@@ -142,18 +146,107 @@ export default async function UpdateComplete(
|
|
|
142
146
|
const callingFlowConfig =
|
|
143
147
|
result?.additionalAttributes?.callingFlowConfig ||
|
|
144
148
|
passBackProperties;
|
|
149
|
+
|
|
150
|
+
const actionData = {
|
|
151
|
+
objType: returnValue.requestParams.objType,
|
|
152
|
+
objInstanceFull: node.objInstanceFull,
|
|
153
|
+
relationships: node.relationships,
|
|
154
|
+
parentFlowId: parentFlowId || returnValue?.parentFlowId,
|
|
155
|
+
existsNode,
|
|
156
|
+
status,
|
|
157
|
+
errorsFound
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
<%_ if (plan?.hasAfterHookSync) { _%>
|
|
161
|
+
// ── Synchronous After Hooks ──
|
|
162
|
+
<%_ plan.afterHooks.filter(h => h?.generatedCodeConfig?.invocationType === 'lambdaSyncInv').forEach(hook => { _%>
|
|
163
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length === 1) { _%>
|
|
164
|
+
if (returnValue.requestParams?.objType?.objectType === '<%= hook.targetObjectTypes[0] %>') {
|
|
165
|
+
<%_ } else if (hook.targetObjectTypes && hook.targetObjectTypes.length > 1) { _%>
|
|
166
|
+
if (<%- JSON.stringify(hook.targetObjectTypes) %>.includes(returnValue.requestParams?.objType?.objectType)) {
|
|
167
|
+
<%_ } _%>
|
|
168
|
+
try {
|
|
169
|
+
let hookPayload_<%= hook.flowTag %> = {
|
|
170
|
+
objType: returnValue.requestParams.objType,
|
|
171
|
+
objInstanceFull: node.objInstanceFull,
|
|
172
|
+
relationships: node.relationships || [],
|
|
173
|
+
targetIdentifiers: requestParams.targetIdentifiers
|
|
174
|
+
};
|
|
175
|
+
//(<beforeSendHook_<%= hook.flowTag %>>)
|
|
176
|
+
//(</beforeSendHook_<%= hook.flowTag %>>)
|
|
177
|
+
const hookResult = await lambda.invokeSync(
|
|
178
|
+
_izContext,
|
|
179
|
+
await lambdaSharedLib.lambdaFunctionName(
|
|
180
|
+
_izContext,
|
|
181
|
+
'<%= hook.flowTag %>'
|
|
182
|
+
),
|
|
183
|
+
{
|
|
184
|
+
requestParams: hookPayload_<%= hook.flowTag %>,
|
|
185
|
+
callingFlowConfig
|
|
186
|
+
}
|
|
187
|
+
);
|
|
188
|
+
if (hookResult?.errorsFound?.length > 0 || hookResult?.status === 'error') {
|
|
189
|
+
errorsFound.push(...(hookResult.errorsFound || ['Hook <%= hook.flowTag %> failed']));
|
|
190
|
+
}
|
|
191
|
+
} catch (hookErr) {
|
|
192
|
+
_izContext.logger.error('[UpdateComplete] Sync hook <%= hook.flowTag %> error:', hookErr);
|
|
193
|
+
errorsFound.push(hookErr.message || 'Hook <%= hook.flowTag %> failed');
|
|
194
|
+
}
|
|
195
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length > 0) { _%>
|
|
196
|
+
}
|
|
197
|
+
<%_ } _%>
|
|
198
|
+
<%_ }) _%>
|
|
199
|
+
<%_ } _%>
|
|
200
|
+
|
|
201
|
+
<%_ if (plan?.hasAfterHookAsync) { _%>
|
|
202
|
+
// ── Asynchronous After Hooks ──
|
|
203
|
+
<%_ plan.afterHooks.filter(h => h?.generatedCodeConfig?.invocationType === 'ownTopic').forEach(hook => { _%>
|
|
204
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length === 1) { _%>
|
|
205
|
+
if (returnValue.requestParams?.objType?.objectType === '<%= hook.targetObjectTypes[0] %>') {
|
|
206
|
+
<%_ } else if (hook.targetObjectTypes && hook.targetObjectTypes.length > 1) { _%>
|
|
207
|
+
if (<%- JSON.stringify(hook.targetObjectTypes) %>.includes(returnValue.requestParams?.objType?.objectType)) {
|
|
208
|
+
<%_ } _%>
|
|
209
|
+
let hookPayload_<%= hook.flowTag %> = {
|
|
210
|
+
objType: returnValue.requestParams.objType,
|
|
211
|
+
objInstanceFull: node.objInstanceFull,
|
|
212
|
+
relationships: node.relationships || [],
|
|
213
|
+
targetIdentifiers: requestParams.targetIdentifiers
|
|
214
|
+
};
|
|
215
|
+
//(<beforeSendHook_<%= hook.flowTag %>>)
|
|
216
|
+
//(</beforeSendHook_<%= hook.flowTag %>>)
|
|
217
|
+
const hookMsg_<%= hook.flowTag %> = callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
|
|
218
|
+
hookPayload_<%= hook.flowTag %>,
|
|
219
|
+
callingFlowSharedLib.addParentCallingFlowConfig(
|
|
220
|
+
callingFlowConfig,
|
|
221
|
+
callingFlowSharedLib.createCallingFlowConfig(
|
|
222
|
+
await lambdaSharedLib.lambdaFunctionName(
|
|
223
|
+
_izContext,
|
|
224
|
+
'UpdateAfterHookCallbackHdrSqs'
|
|
225
|
+
),
|
|
226
|
+
{
|
|
227
|
+
actionData
|
|
228
|
+
}
|
|
229
|
+
)
|
|
230
|
+
)
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
await sns.publishAsync(_izContext, {
|
|
234
|
+
TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
|
|
235
|
+
_izContext,
|
|
236
|
+
'<%= hook.flowTag %>_In'
|
|
237
|
+
),
|
|
238
|
+
Message: JSON.stringify(hookMsg_<%= hook.flowTag %>),
|
|
239
|
+
MessageAttributes: sns.createStringMessageAttributes(_izContext, {})
|
|
240
|
+
});
|
|
241
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length > 0) { _%>
|
|
242
|
+
}
|
|
243
|
+
<%_ } _%>
|
|
244
|
+
<%_ }) _%>
|
|
245
|
+
<%_ } else { _%>
|
|
145
246
|
const message =
|
|
146
247
|
callingFlowSharedLib.addParentPassBackPropertiesToSnsResponseMessageObject(
|
|
147
248
|
callingFlowConfig,
|
|
148
|
-
|
|
149
|
-
objType: returnValue.requestParams.objType,
|
|
150
|
-
objInstanceFull: node.objInstanceFull,
|
|
151
|
-
relationships: node.relationships,
|
|
152
|
-
parentFlowId: parentFlowId || returnValue?.parentFlowId,
|
|
153
|
-
existsNode,
|
|
154
|
-
status,
|
|
155
|
-
errorsFound
|
|
156
|
-
}
|
|
249
|
+
actionData
|
|
157
250
|
);
|
|
158
251
|
const messageAttributes =
|
|
159
252
|
callingFlowSharedLib.addParentPassBackCallingFlowToSnsResponseMessageAttributes(
|
|
@@ -176,6 +269,7 @@ export default async function UpdateComplete(
|
|
|
176
269
|
),
|
|
177
270
|
TopicArn: topicArn
|
|
178
271
|
});
|
|
272
|
+
<%_ } _%>
|
|
179
273
|
//(<afterSendMessage>)
|
|
180
274
|
//(</afterSendMessage>)
|
|
181
275
|
}
|