@izara_project/izara-core-generate-service-code 1.0.88 → 1.0.90
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/CreateComplete_Main.ejs +135 -10
- package/src/emit/crud/templates/CreateEndpoint_Main.ejs +33 -27
- package/src/emit/crud/templates/CreateLogicalLib.ejs +282 -95
- package/src/emit/crud/templates/CreateNodeCallback_Main.ejs +38 -21
- 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 +113 -4
- 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 -4
- 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/rbac/templates/UserRbacFlow_Main.ejs +20 -13
- package/src/emit/resource/emitResourceArtifacts.js +55 -14
- package/test/createTargetRoleHandler.test.js +11 -8
- package/test/crudApplicationArtifacts.test.js +440 -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 +113 -0
|
@@ -167,18 +167,36 @@ export default async function CreateNodeCallbackMain(
|
|
|
167
167
|
_izContext.correlationIds?.get(coreConsts.SUBMITTED_BY_USER_ID) ||
|
|
168
168
|
_izContext.correlationIds?.get('submittedByUserId');
|
|
169
169
|
|
|
170
|
+
<%_ const rootRbacObjs = (objects || []).filter(obj => {
|
|
171
|
+
const hasSelfRbac = Array.isArray(obj?.addOnDataStructure) && obj.addOnDataStructure.some(addOn => addOn?.type === 'rbac');
|
|
172
|
+
return hasSelfRbac && !obj?.belongTo && obj?.objectType !== 'user' && obj?.generatedBy !== 'systemNoUser';
|
|
173
|
+
}); _%>
|
|
174
|
+
<%_ if (rootRbacObjs.length > 0) { _%>
|
|
170
175
|
await autoProvisionOwnerTargetRole(_izContext, {
|
|
171
176
|
node,
|
|
172
|
-
submittedByUserId
|
|
177
|
+
submittedByUserId,
|
|
178
|
+
objType: returnValue?.requestParams?.objType
|
|
173
179
|
});
|
|
180
|
+
<%_ } _%>
|
|
174
181
|
|
|
175
182
|
<%_ if (plan?.hasAfterHookSync) { _%>
|
|
176
183
|
// ── Synchronous After Hooks ──
|
|
177
184
|
<%_ plan.afterHooks.filter(h => h?.generatedCodeConfig?.invocationType === 'lambdaSyncInv').forEach(hook => { _%>
|
|
178
|
-
<%_ if (hook.
|
|
179
|
-
if (returnValue.requestParams?.objType?.objectType === '<%= hook.
|
|
185
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length === 1) { _%>
|
|
186
|
+
if (returnValue.requestParams?.objType?.objectType === '<%= hook.targetObjectTypes[0] %>') {
|
|
187
|
+
<%_ } else if (hook.targetObjectTypes && hook.targetObjectTypes.length > 1) { _%>
|
|
188
|
+
if (<%- JSON.stringify(hook.targetObjectTypes) %>.includes(returnValue.requestParams?.objType?.objectType)) {
|
|
180
189
|
<%_ } _%>
|
|
181
190
|
try {
|
|
191
|
+
let hookPayload_<%= hook.flowTag %> = {
|
|
192
|
+
objType: returnValue.requestParams.objType,
|
|
193
|
+
objInstanceFull: node.objInstanceFull,
|
|
194
|
+
relationships: node.relationships || [],
|
|
195
|
+
targetIdentifiers: requestParams.targetIdentifiers,
|
|
196
|
+
submittedByUserId
|
|
197
|
+
};
|
|
198
|
+
//(<beforeSendHook_<%= hook.flowTag %>>)
|
|
199
|
+
//(</beforeSendHook_<%= hook.flowTag %>>)
|
|
182
200
|
const hookResult = await lambda.invokeSync(
|
|
183
201
|
_izContext,
|
|
184
202
|
await lambdaSharedLib.lambdaFunctionName(
|
|
@@ -186,13 +204,7 @@ export default async function CreateNodeCallbackMain(
|
|
|
186
204
|
'<%= hook.flowTag %>'
|
|
187
205
|
),
|
|
188
206
|
{
|
|
189
|
-
requestParams:
|
|
190
|
-
objType: returnValue.requestParams.objType,
|
|
191
|
-
objInstanceFull: node.objInstanceFull,
|
|
192
|
-
relationships: node.relationships || [],
|
|
193
|
-
targetIdentifiers: requestParams.targetIdentifiers,
|
|
194
|
-
submittedByUserId
|
|
195
|
-
},
|
|
207
|
+
requestParams: hookPayload_<%= hook.flowTag %>,
|
|
196
208
|
callingFlowConfig
|
|
197
209
|
}
|
|
198
210
|
);
|
|
@@ -203,7 +215,7 @@ export default async function CreateNodeCallbackMain(
|
|
|
203
215
|
_izContext.logger.error('[CreateNodeCallback] Sync hook <%= hook.flowTag %> error:', hookErr);
|
|
204
216
|
errorsFound.push(hookErr.message || 'Hook <%= hook.flowTag %> failed');
|
|
205
217
|
}
|
|
206
|
-
<%_ if (hook.
|
|
218
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length > 0) { _%>
|
|
207
219
|
}
|
|
208
220
|
<%_ } _%>
|
|
209
221
|
<%_ }) _%>
|
|
@@ -238,17 +250,22 @@ export default async function CreateNodeCallbackMain(
|
|
|
238
250
|
<%_ if (plan?.hasAfterHookAsync) { _%>
|
|
239
251
|
// ── Asynchronous After Hooks ──
|
|
240
252
|
<%_ plan.afterHooks.filter(h => h?.generatedCodeConfig?.invocationType === 'ownTopic').forEach(hook => { _%>
|
|
241
|
-
<%_ if (hook.
|
|
242
|
-
if (returnValue.requestParams?.objType?.objectType === '<%= hook.
|
|
253
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length === 1) { _%>
|
|
254
|
+
if (returnValue.requestParams?.objType?.objectType === '<%= hook.targetObjectTypes[0] %>') {
|
|
255
|
+
<%_ } else if (hook.targetObjectTypes && hook.targetObjectTypes.length > 1) { _%>
|
|
256
|
+
if (<%- JSON.stringify(hook.targetObjectTypes) %>.includes(returnValue.requestParams?.objType?.objectType)) {
|
|
243
257
|
<%_ } _%>
|
|
258
|
+
let hookPayload_<%= hook.flowTag %> = {
|
|
259
|
+
objType: returnValue.requestParams.objType,
|
|
260
|
+
objInstanceFull: node.objInstanceFull,
|
|
261
|
+
relationships: node.relationships || [],
|
|
262
|
+
targetIdentifiers: requestParams.targetIdentifiers,
|
|
263
|
+
submittedByUserId
|
|
264
|
+
};
|
|
265
|
+
//(<beforeSendHook_<%= hook.flowTag %>>)
|
|
266
|
+
//(</beforeSendHook_<%= hook.flowTag %>>)
|
|
244
267
|
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
|
-
},
|
|
268
|
+
hookPayload_<%= hook.flowTag %>,
|
|
252
269
|
callingFlowSharedLib.addParentCallingFlowConfig(
|
|
253
270
|
callingFlowConfig,
|
|
254
271
|
callingFlowSharedLib.createCallingFlowConfig(
|
|
@@ -272,7 +289,7 @@ export default async function CreateNodeCallbackMain(
|
|
|
272
289
|
Message: JSON.stringify(hookMsg_<%= hook.flowTag %>),
|
|
273
290
|
MessageAttributes: sns.createStringMessageAttributes(_izContext, {})
|
|
274
291
|
});
|
|
275
|
-
<%_ if (hook.
|
|
292
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length > 0) { _%>
|
|
276
293
|
}
|
|
277
294
|
<%_ } _%>
|
|
278
295
|
<%_ }) _%>
|
|
@@ -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
|
+
}
|
|
@@ -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(
|
|
@@ -100,9 +100,7 @@ export async function resolveSchemaAndIdentity(
|
|
|
100
100
|
|
|
101
101
|
requestParams.submittedByUserId = submittedByUserId;
|
|
102
102
|
if (targetIdentifiers) {
|
|
103
|
-
|
|
104
|
-
targetIdentifiers.submittedByUserId = submittedByUserId;
|
|
105
|
-
}
|
|
103
|
+
requestParams.targetIdentifiers = targetIdentifiers;
|
|
106
104
|
}
|
|
107
105
|
|
|
108
106
|
_izContext.logger.debug(
|
|
@@ -274,6 +272,111 @@ export async function <%- flowTag %>LogicalLib(
|
|
|
274
272
|
}
|
|
275
273
|
|
|
276
274
|
// ── Complete ──────────────────────────────────────────────────────────────
|
|
275
|
+
<%_ if (plan?.hasAfterHookSync) { _%>
|
|
276
|
+
// ── Synchronous After Hooks ──
|
|
277
|
+
<%_ plan.afterHooks.filter(h => h?.generatedCodeConfig?.invocationType === 'lambdaSyncInv').forEach(hook => { _%>
|
|
278
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length === 1) { _%>
|
|
279
|
+
if (objType?.objectType === '<%= hook.targetObjectTypes[0] %>') {
|
|
280
|
+
<%_ } else if (hook.targetObjectTypes && hook.targetObjectTypes.length > 1) { _%>
|
|
281
|
+
if (<%- JSON.stringify(hook.targetObjectTypes) %>.includes(objType?.objectType)) {
|
|
282
|
+
<%_ } _%>
|
|
283
|
+
try {
|
|
284
|
+
let hookPayload_<%= hook.flowTag %> = {
|
|
285
|
+
objType,
|
|
286
|
+
identifiers: requestParams.identifiers,
|
|
287
|
+
relationships: requestParams.relationships || [],
|
|
288
|
+
targetIdentifiers: requestParams.targetIdentifiers,
|
|
289
|
+
submittedByUserId: requestParams.submittedByUserId
|
|
290
|
+
};
|
|
291
|
+
//(<beforeSendHook_<%= hook.flowTag %>>)
|
|
292
|
+
//(</beforeSendHook_<%= hook.flowTag %>>)
|
|
293
|
+
const hookResult = await lambda.invokeSync(
|
|
294
|
+
_izContext,
|
|
295
|
+
await lambdaSharedLib.lambdaFunctionName(
|
|
296
|
+
_izContext,
|
|
297
|
+
'<%= hook.flowTag %>'
|
|
298
|
+
),
|
|
299
|
+
{
|
|
300
|
+
requestParams: hookPayload_<%= hook.flowTag %>,
|
|
301
|
+
callingFlowConfig
|
|
302
|
+
}
|
|
303
|
+
);
|
|
304
|
+
if (
|
|
305
|
+
hookResult?.errorsFound?.length > 0 ||
|
|
306
|
+
hookResult?.status === 'error'
|
|
307
|
+
) {
|
|
308
|
+
errorsFound.push(
|
|
309
|
+
...(hookResult.errorsFound || ['Hook <%= hook.flowTag %> failed'])
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
} catch (hookErr) {
|
|
313
|
+
_izContext.logger.error(
|
|
314
|
+
'[<%- flowTag %>LogicalLib] Sync hook <%= hook.flowTag %> error:',
|
|
315
|
+
hookErr
|
|
316
|
+
);
|
|
317
|
+
errorsFound.push(hookErr.message || 'Hook <%= hook.flowTag %> failed');
|
|
318
|
+
}
|
|
319
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length > 0) { _%>
|
|
320
|
+
}
|
|
321
|
+
<%_ } _%>
|
|
322
|
+
<%_ }) _%>
|
|
323
|
+
<%_ } _%>
|
|
324
|
+
|
|
325
|
+
<%_ if (plan?.hasAfterHookAsync) { _%>
|
|
326
|
+
// ── Asynchronous After Hooks ──
|
|
327
|
+
<%_ plan.afterHooks.filter(h => h?.generatedCodeConfig?.invocationType === 'ownTopic').forEach(hook => { _%>
|
|
328
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length === 1) { _%>
|
|
329
|
+
if (objType?.objectType === '<%= hook.targetObjectTypes[0] %>') {
|
|
330
|
+
<%_ } else if (hook.targetObjectTypes && hook.targetObjectTypes.length > 1) { _%>
|
|
331
|
+
if (<%- JSON.stringify(hook.targetObjectTypes) %>.includes(objType?.objectType)) {
|
|
332
|
+
<%_ } _%>
|
|
333
|
+
let hookPayload_<%= hook.flowTag %> = {
|
|
334
|
+
objType,
|
|
335
|
+
identifiers: requestParams.identifiers,
|
|
336
|
+
relationships: requestParams.relationships || [],
|
|
337
|
+
targetIdentifiers: requestParams.targetIdentifiers,
|
|
338
|
+
submittedByUserId: requestParams.submittedByUserId
|
|
339
|
+
};
|
|
340
|
+
//(<beforeSendHook_<%= hook.flowTag %>>)
|
|
341
|
+
//(</beforeSendHook_<%= hook.flowTag %>>)
|
|
342
|
+
const hookMsg_<%= hook.flowTag %> =
|
|
343
|
+
callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
|
|
344
|
+
hookPayload_<%= hook.flowTag %>,
|
|
345
|
+
callingFlowSharedLib.addParentCallingFlowConfig(
|
|
346
|
+
callingFlowConfig,
|
|
347
|
+
callingFlowSharedLib.createCallingFlowConfig(
|
|
348
|
+
await lambdaSharedLib.lambdaFunctionName(
|
|
349
|
+
_izContext,
|
|
350
|
+
'DeleteAfterHookCallbackHdrSqs'
|
|
351
|
+
),
|
|
352
|
+
{
|
|
353
|
+
actionData: {
|
|
354
|
+
objType,
|
|
355
|
+
identifiers: requestParams.identifiers,
|
|
356
|
+
relationships: requestParams.relationships || [],
|
|
357
|
+
targetIdentifiers: requestParams.targetIdentifiers,
|
|
358
|
+
parentFlowId: requestParams.parentFlowId,
|
|
359
|
+
status: 'complete',
|
|
360
|
+
errorsFound
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
)
|
|
364
|
+
)
|
|
365
|
+
);
|
|
366
|
+
|
|
367
|
+
await sns.publishAsync(_izContext, {
|
|
368
|
+
TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
|
|
369
|
+
_izContext,
|
|
370
|
+
'<%= hook.flowTag %>_In'
|
|
371
|
+
),
|
|
372
|
+
Message: JSON.stringify(hookMsg_<%= hook.flowTag %>),
|
|
373
|
+
MessageAttributes: sns.createStringMessageAttributes(_izContext, {})
|
|
374
|
+
});
|
|
375
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length > 0) { _%>
|
|
376
|
+
}
|
|
377
|
+
<%_ } _%>
|
|
378
|
+
<%_ }) _%>
|
|
379
|
+
<%_ } else { _%>
|
|
277
380
|
const outMessage =
|
|
278
381
|
callingFlowSharedLib.addPassBackPropertiesToSnsResponseMessageObject(
|
|
279
382
|
callingFlowConfig,
|
|
@@ -304,12 +407,18 @@ export async function <%- flowTag %>LogicalLib(
|
|
|
304
407
|
)
|
|
305
408
|
});
|
|
306
409
|
}
|
|
410
|
+
<%_ } _%>
|
|
411
|
+
|
|
412
|
+
let resultStatus = 'complete';
|
|
413
|
+
if (errorsFound.length > 0) {
|
|
414
|
+
resultStatus = 'error';
|
|
415
|
+
}
|
|
307
416
|
|
|
308
417
|
return {
|
|
309
418
|
objType,
|
|
310
419
|
identifiers: requestParams.identifiers,
|
|
311
420
|
targetIdentifiers: requestParams.targetIdentifiers,
|
|
312
|
-
status:
|
|
421
|
+
status: resultStatus,
|
|
313
422
|
errorsFound
|
|
314
423
|
};
|
|
315
424
|
} catch (err) {
|