@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
|
@@ -200,11 +200,15 @@ export default async function <%- flowTag %>(
|
|
|
200
200
|
|
|
201
201
|
// ── Optional phase extension point ────────────────────────────────────────
|
|
202
202
|
<%_
|
|
203
|
+
const allCrudObjectTypes = (objects || []).filter(isCrudObject).map(o => o.objectType);
|
|
203
204
|
const beforeHooksByObjType = (plan?.beforeHooks || []).reduce((acc, hook) => {
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
205
|
+
const targets = (hook?.targetObjectTypes && hook.targetObjectTypes.length > 0)
|
|
206
|
+
? hook.targetObjectTypes
|
|
207
|
+
: allCrudObjectTypes;
|
|
208
|
+
for (const key of targets) {
|
|
209
|
+
if (!acc[key]) acc[key] = [];
|
|
210
|
+
acc[key].push(hook);
|
|
211
|
+
}
|
|
208
212
|
return acc;
|
|
209
213
|
}, {});
|
|
210
214
|
_%>
|
|
@@ -218,6 +222,18 @@ export default async function <%- flowTag %>(
|
|
|
218
222
|
const lambdaSyncInvResults = [];
|
|
219
223
|
<%_ for (const config of configs.filter(c => c?.generatedCodeConfig?.invocationType === 'lambdaSyncInv' || c?.event?.includes('lambdaSyncInv'))) { _%>
|
|
220
224
|
try {
|
|
225
|
+
let hookPayload_<%= config.flowTag %> = {
|
|
226
|
+
objType,
|
|
227
|
+
objInstanceFull: requestParams.objInstanceFull,
|
|
228
|
+
identifiers: requestParams.objInstanceFull?.identifiers,
|
|
229
|
+
fieldNames:
|
|
230
|
+
requestParams.objInstanceFull?.fields || requestParams.fieldNames,
|
|
231
|
+
relationships: requestParams.relationships || [],
|
|
232
|
+
targetIdentifiers,
|
|
233
|
+
submittedByUserId: requestParams.submittedByUserId
|
|
234
|
+
};
|
|
235
|
+
//(<beforeSendHook_<%= config.flowTag %>>)
|
|
236
|
+
//(</beforeSendHook_<%= config.flowTag %>>)
|
|
221
237
|
const returnValue = await lambda.invokeSync(
|
|
222
238
|
_izContext,
|
|
223
239
|
await lambdaSharedLib.lambdaFunctionName(
|
|
@@ -225,15 +241,7 @@ export default async function <%- flowTag %>(
|
|
|
225
241
|
'<%= config.flowTag %>'
|
|
226
242
|
),
|
|
227
243
|
{
|
|
228
|
-
requestParams:
|
|
229
|
-
objType,
|
|
230
|
-
objInstanceFull: requestParams.objInstanceFull,
|
|
231
|
-
identifiers: requestParams.objInstanceFull?.identifiers,
|
|
232
|
-
fieldNames: requestParams.objInstanceFull?.fields || requestParams.fieldNames,
|
|
233
|
-
relationships: requestParams.relationships || [],
|
|
234
|
-
targetIdentifiers,
|
|
235
|
-
submittedByUserId: requestParams.submittedByUserId
|
|
236
|
-
},
|
|
244
|
+
requestParams: hookPayload_<%= config.flowTag %>,
|
|
237
245
|
callingFlowConfig
|
|
238
246
|
}
|
|
239
247
|
);
|
|
@@ -282,17 +290,21 @@ export default async function <%- flowTag %>(
|
|
|
282
290
|
<%_ if (hasOwnTopic) { _%>
|
|
283
291
|
// ── ownTopic (async — dispatch to before-hook and await callback) ──────────
|
|
284
292
|
<%_ configs.filter(c => c?.generatedCodeConfig?.invocationType === 'ownTopic' || c?.event?.includes('ownTopic')).forEach(config => { _%>
|
|
293
|
+
let hookPayload_<%= config.flowTag %> = {
|
|
294
|
+
objType,
|
|
295
|
+
objInstanceFull: requestParams.objInstanceFull,
|
|
296
|
+
identifiers: requestParams.objInstanceFull?.identifiers,
|
|
297
|
+
fieldNames:
|
|
298
|
+
requestParams.objInstanceFull?.fields || requestParams.fieldNames,
|
|
299
|
+
relationships: requestParams.relationships || [],
|
|
300
|
+
targetIdentifiers,
|
|
301
|
+
submittedByUserId: requestParams.submittedByUserId
|
|
302
|
+
};
|
|
303
|
+
//(<beforeSendHook_<%= config.flowTag %>>)
|
|
304
|
+
//(</beforeSendHook_<%= config.flowTag %>>)
|
|
285
305
|
const hookMsg_<%= config.flowTag %> =
|
|
286
306
|
callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
|
|
287
|
-
|
|
288
|
-
objType,
|
|
289
|
-
objInstanceFull: requestParams.objInstanceFull,
|
|
290
|
-
identifiers: requestParams.objInstanceFull?.identifiers,
|
|
291
|
-
fieldNames: requestParams.objInstanceFull?.fields || requestParams.fieldNames,
|
|
292
|
-
relationships: requestParams.relationships || [],
|
|
293
|
-
targetIdentifiers,
|
|
294
|
-
submittedByUserId: requestParams.submittedByUserId
|
|
295
|
-
},
|
|
307
|
+
hookPayload_<%= config.flowTag %>,
|
|
296
308
|
callingFlowSharedLib.addParentCallingFlowConfig(
|
|
297
309
|
callingFlowConfig,
|
|
298
310
|
callingFlowSharedLib.createCallingFlowConfig(
|
|
@@ -852,12 +852,132 @@ export async function <%- flowTag %>LogicalLib(
|
|
|
852
852
|
|
|
853
853
|
// 5. If no graph storage, complete immediately
|
|
854
854
|
if (!hasGraphStorage) {
|
|
855
|
+
<%_ if (plan?.hasAfterHookSync) { _%>
|
|
856
|
+
// ── Synchronous After Hooks ──
|
|
857
|
+
<%_ plan.afterHooks.filter(h => h?.generatedCodeConfig?.invocationType === 'lambdaSyncInv').forEach(hook => { _%>
|
|
858
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length === 1) { _%>
|
|
859
|
+
if (objType?.objectType === '<%= hook.targetObjectTypes[0] %>') {
|
|
860
|
+
<%_ } else if (hook.targetObjectTypes && hook.targetObjectTypes.length > 1) { _%>
|
|
861
|
+
if (<%- JSON.stringify(hook.targetObjectTypes) %>.includes(objType?.objectType)) {
|
|
862
|
+
<%_ } _%>
|
|
863
|
+
try {
|
|
864
|
+
let hookPayload_<%= hook.flowTag %> = {
|
|
865
|
+
objType,
|
|
866
|
+
objInstanceFull: createObjInstanceFullFromParams(
|
|
867
|
+
updateItem,
|
|
868
|
+
requestParams
|
|
869
|
+
),
|
|
870
|
+
relationships: requestParams.relationships || [],
|
|
871
|
+
targetIdentifiers: requestParams.targetIdentifiers,
|
|
872
|
+
submittedByUserId: requestParams.submittedByUserId
|
|
873
|
+
};
|
|
874
|
+
//(<beforeSendHook_<%= hook.flowTag %>>)
|
|
875
|
+
//(</beforeSendHook_<%= hook.flowTag %>>)
|
|
876
|
+
const hookResult = await lambda.invokeSync(
|
|
877
|
+
_izContext,
|
|
878
|
+
await lambdaSharedLib.lambdaFunctionName(
|
|
879
|
+
_izContext,
|
|
880
|
+
'<%= hook.flowTag %>'
|
|
881
|
+
),
|
|
882
|
+
{
|
|
883
|
+
requestParams: hookPayload_<%= hook.flowTag %>,
|
|
884
|
+
callingFlowConfig
|
|
885
|
+
}
|
|
886
|
+
);
|
|
887
|
+
if (
|
|
888
|
+
hookResult?.errorsFound?.length > 0 ||
|
|
889
|
+
hookResult?.status === 'error'
|
|
890
|
+
) {
|
|
891
|
+
errorsFound.push(
|
|
892
|
+
...(hookResult.errorsFound || ['Hook <%= hook.flowTag %> failed'])
|
|
893
|
+
);
|
|
894
|
+
}
|
|
895
|
+
} catch (hookErr) {
|
|
896
|
+
_izContext.logger.error(
|
|
897
|
+
'[<%- flowTag %>LogicalLib] Sync hook <%= hook.flowTag %> error:',
|
|
898
|
+
hookErr
|
|
899
|
+
);
|
|
900
|
+
errorsFound.push(hookErr.message || 'Hook <%= hook.flowTag %> failed');
|
|
901
|
+
}
|
|
902
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length > 0) { _%>
|
|
903
|
+
}
|
|
904
|
+
<%_ } _%>
|
|
905
|
+
<%_ }) _%>
|
|
906
|
+
<%_ } _%>
|
|
907
|
+
|
|
908
|
+
<%_ if (plan?.hasAfterHookAsync) { _%>
|
|
909
|
+
// ── Asynchronous After Hooks ──
|
|
910
|
+
<%_ plan.afterHooks.filter(h => h?.generatedCodeConfig?.invocationType === 'ownTopic').forEach(hook => { _%>
|
|
911
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length === 1) { _%>
|
|
912
|
+
if (objType?.objectType === '<%= hook.targetObjectTypes[0] %>') {
|
|
913
|
+
<%_ } else if (hook.targetObjectTypes && hook.targetObjectTypes.length > 1) { _%>
|
|
914
|
+
if (<%- JSON.stringify(hook.targetObjectTypes) %>.includes(objType?.objectType)) {
|
|
915
|
+
<%_ } _%>
|
|
916
|
+
let hookPayload_<%= hook.flowTag %> = {
|
|
917
|
+
objType,
|
|
918
|
+
objInstanceFull: createObjInstanceFullFromParams(
|
|
919
|
+
updateItem,
|
|
920
|
+
requestParams
|
|
921
|
+
),
|
|
922
|
+
relationships: requestParams.relationships || [],
|
|
923
|
+
targetIdentifiers: requestParams.targetIdentifiers,
|
|
924
|
+
submittedByUserId: requestParams.submittedByUserId
|
|
925
|
+
};
|
|
926
|
+
//(<beforeSendHook_<%= hook.flowTag %>>)
|
|
927
|
+
//(</beforeSendHook_<%= hook.flowTag %>>)
|
|
928
|
+
const hookMsg_<%= hook.flowTag %> =
|
|
929
|
+
callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
|
|
930
|
+
hookPayload_<%= hook.flowTag %>,
|
|
931
|
+
callingFlowSharedLib.addParentCallingFlowConfig(
|
|
932
|
+
callingFlowConfig,
|
|
933
|
+
callingFlowSharedLib.createCallingFlowConfig(
|
|
934
|
+
await lambdaSharedLib.lambdaFunctionName(
|
|
935
|
+
_izContext,
|
|
936
|
+
'UpdateAfterHookCallbackHdrSqs'
|
|
937
|
+
),
|
|
938
|
+
{
|
|
939
|
+
actionData: {
|
|
940
|
+
objType,
|
|
941
|
+
objInstanceFull: createObjInstanceFullFromParams(
|
|
942
|
+
updateItem,
|
|
943
|
+
requestParams
|
|
944
|
+
),
|
|
945
|
+
relationships: requestParams.relationships || [],
|
|
946
|
+
targetIdentifiers: requestParams.targetIdentifiers,
|
|
947
|
+
parentFlowId: requestParams.parentFlowId,
|
|
948
|
+
status: 'complete',
|
|
949
|
+
errorsFound
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
)
|
|
953
|
+
)
|
|
954
|
+
);
|
|
955
|
+
|
|
956
|
+
await sns.publishAsync(_izContext, {
|
|
957
|
+
TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
|
|
958
|
+
_izContext,
|
|
959
|
+
'<%= hook.flowTag %>_In'
|
|
960
|
+
),
|
|
961
|
+
Message: JSON.stringify(hookMsg_<%= hook.flowTag %>),
|
|
962
|
+
MessageAttributes: sns.createStringMessageAttributes(_izContext, {})
|
|
963
|
+
});
|
|
964
|
+
<%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length > 0) { _%>
|
|
965
|
+
}
|
|
966
|
+
<%_ } _%>
|
|
967
|
+
<%_ }) _%>
|
|
968
|
+
<%_ } else { _%>
|
|
855
969
|
await handleDynamoDbOnlyComplete(_izContext, {
|
|
856
970
|
objType,
|
|
857
971
|
updateItem,
|
|
858
972
|
requestParams,
|
|
859
973
|
callingFlowConfig
|
|
860
974
|
});
|
|
975
|
+
<%_ } _%>
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
let resultStatus = 'complete';
|
|
979
|
+
if (errorsFound.length > 0) {
|
|
980
|
+
resultStatus = 'error';
|
|
861
981
|
}
|
|
862
982
|
|
|
863
983
|
return {
|
|
@@ -866,7 +986,7 @@ export async function <%- flowTag %>LogicalLib(
|
|
|
866
986
|
objInstanceFull: { identifiers, fields },
|
|
867
987
|
versionedDataIds
|
|
868
988
|
},
|
|
869
|
-
status:
|
|
989
|
+
status: resultStatus,
|
|
870
990
|
errorsFound
|
|
871
991
|
};
|
|
872
992
|
} catch (err) {
|
|
@@ -19,8 +19,14 @@ const RBAC_CORE_FLOW_DEFINITIONS = [
|
|
|
19
19
|
|
|
20
20
|
const LIMIT_FLOW_DEFINITIONS = [
|
|
21
21
|
{ flowTag: 'ReservedDynamicUsage', event: ['ownTopic'] },
|
|
22
|
-
{
|
|
23
|
-
|
|
22
|
+
{
|
|
23
|
+
flowTag: 'ConfirmUsage',
|
|
24
|
+
event: ['ownTopic', 'lambdaSyncInv', 'lambdaSyncApi']
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
flowTag: 'CancelUsage',
|
|
28
|
+
event: ['ownTopic', 'lambdaSyncInv', 'lambdaSyncApi']
|
|
29
|
+
}
|
|
24
30
|
];
|
|
25
31
|
|
|
26
32
|
const RBAC_FLOW_DEFINITIONS = [
|
|
@@ -146,20 +146,40 @@ export default async function CancelUsage(_izContext, requestParams) {
|
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
149
|
+
const returnResult = {
|
|
150
|
+
status: true,
|
|
151
|
+
uniqueIdentify: usedTimestampId,
|
|
152
|
+
usedTimestampId,
|
|
153
|
+
runningTotalReservedId
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const eventSourceTag =
|
|
157
|
+
_izContext.izEventSource?.eventSourceTag ||
|
|
158
|
+
requestParams?.izEventSource?.eventSourceTag;
|
|
159
|
+
|
|
160
|
+
let isSync = false;
|
|
161
|
+
if (
|
|
162
|
+
eventSourceTag === 'DirectInvoke' ||
|
|
163
|
+
eventSourceTag === 'ApiGateway' ||
|
|
164
|
+
eventSourceTag === 'ApiGatewayV2' ||
|
|
165
|
+
requestParams?.hasOwnProperty('__context__')
|
|
166
|
+
) {
|
|
167
|
+
isSync = true;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (!isSync) {
|
|
171
|
+
await sns.publishMessage(_izContext, {
|
|
172
|
+
message: {
|
|
173
|
+
returnResult
|
|
174
|
+
},
|
|
175
|
+
TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
|
|
176
|
+
_izContext,
|
|
177
|
+
'CancelUsage_Out'
|
|
178
|
+
)
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return returnResult;
|
|
163
183
|
} catch (error) {
|
|
164
184
|
_izContext.logger.error(`[${process.env.iz_serviceTag}:CancelUsage] error:`, error);
|
|
165
185
|
throw error;
|
|
@@ -170,20 +170,40 @@ export default async function ConfirmUsage(_izContext, requestParams) {
|
|
|
170
170
|
).catch(() => null);
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
173
|
+
const returnResult = {
|
|
174
|
+
status: true,
|
|
175
|
+
uniqueIdentify: usedTimestampId,
|
|
176
|
+
usedTimestampId,
|
|
177
|
+
runningTotalReservedId
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const eventSourceTag =
|
|
181
|
+
_izContext.izEventSource?.eventSourceTag ||
|
|
182
|
+
requestParams?.izEventSource?.eventSourceTag;
|
|
183
|
+
|
|
184
|
+
let isSync = false;
|
|
185
|
+
if (
|
|
186
|
+
eventSourceTag === 'DirectInvoke' ||
|
|
187
|
+
eventSourceTag === 'ApiGateway' ||
|
|
188
|
+
eventSourceTag === 'ApiGatewayV2' ||
|
|
189
|
+
requestParams?.hasOwnProperty('__context__')
|
|
190
|
+
) {
|
|
191
|
+
isSync = true;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (!isSync) {
|
|
195
|
+
await sns.publishMessage(_izContext, {
|
|
196
|
+
message: {
|
|
197
|
+
returnResult
|
|
198
|
+
},
|
|
199
|
+
TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
|
|
200
|
+
_izContext,
|
|
201
|
+
'ConfirmUsage_Out'
|
|
202
|
+
)
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return returnResult;
|
|
187
207
|
} catch (error) {
|
|
188
208
|
_izContext.logger.error(`[${process.env.iz_serviceTag}:ConfirmUsage] error:`, error);
|
|
189
209
|
throw error;
|
|
@@ -958,7 +958,7 @@ function roleTopicNames(state, roleName) {
|
|
|
958
958
|
}
|
|
959
959
|
}
|
|
960
960
|
}
|
|
961
|
-
return topics;
|
|
961
|
+
return [...new Set(topics)];
|
|
962
962
|
}
|
|
963
963
|
if (roleName === 'FlowRelationshipRole') {
|
|
964
964
|
const actions = state.outTopics.filter((topic) =>
|
|
@@ -1102,8 +1102,15 @@ function roleExternalLambdaArns(state, roleName) {
|
|
|
1102
1102
|
(tag) =>
|
|
1103
1103
|
`arn:aws:lambda:\${self:custom.iz_region}:\${self:custom.iz_accountId}:function:${tag}\${self:custom.iz_stage}ValidatorRbacHdrInv`
|
|
1104
1104
|
);
|
|
1105
|
+
if (roleName === 'FlowObjectsRole') {
|
|
1106
|
+
return [
|
|
1107
|
+
`arn:aws:lambda:\${self:custom.iz_region}:\${self:custom.iz_accountId}:function:Rbac\${self:custom.iz_stage}ValidatorRbacHdrInv`,
|
|
1108
|
+
`arn:aws:lambda:\${self:custom.iz_region}:\${self:custom.iz_accountId}:function:Rbac\${self:custom.iz_stage}ConfirmUsageHdrInv`,
|
|
1109
|
+
`arn:aws:lambda:\${self:custom.iz_region}:\${self:custom.iz_accountId}:function:Rbac\${self:custom.iz_stage}CancelUsageHdrInv`,
|
|
1110
|
+
...extraLambdas
|
|
1111
|
+
];
|
|
1112
|
+
}
|
|
1105
1113
|
if (
|
|
1106
|
-
roleName === 'FlowObjectsRole' ||
|
|
1107
1114
|
roleName === 'FlowRbacRole' ||
|
|
1108
1115
|
roleName === 'FlowRelationshipRole'
|
|
1109
1116
|
) {
|