@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.
Files changed (29) hide show
  1. package/package.json +1 -1
  2. package/src/compile/flowValidator.js +25 -0
  3. package/src/compile/loadSchemas.js +154 -0
  4. package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +3 -7
  5. package/src/emit/crud/crudActionPlan.js +67 -9
  6. package/src/emit/crud/emitDynamicCrudFlowSchemas.js +15 -32
  7. package/src/emit/crud/templates/CreateComplete_Main.ejs +135 -10
  8. package/src/emit/crud/templates/CreateEndpoint_Main.ejs +33 -27
  9. package/src/emit/crud/templates/CreateLogicalLib.ejs +282 -95
  10. package/src/emit/crud/templates/CreateNodeCallback_Main.ejs +38 -21
  11. package/src/emit/crud/templates/DeleteAfterHookCallback_Main.ejs +118 -0
  12. package/src/emit/crud/templates/DeleteComplete_Main.ejs +124 -10
  13. package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +26 -16
  14. package/src/emit/crud/templates/DeleteLogicalLib.ejs +113 -4
  15. package/src/emit/crud/templates/UpdateAfterHookCallback_Main.ejs +120 -0
  16. package/src/emit/crud/templates/UpdateComplete_Main.ejs +104 -10
  17. package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +34 -22
  18. package/src/emit/crud/templates/UpdateLogicalLib.ejs +121 -4
  19. package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +8 -2
  20. package/src/emit/rbac/templates/CancelUsage_Main.ejs +34 -14
  21. package/src/emit/rbac/templates/ConfirmUsage_Main.ejs +34 -14
  22. package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +20 -13
  23. package/src/emit/resource/emitResourceArtifacts.js +55 -14
  24. package/test/createTargetRoleHandler.test.js +11 -8
  25. package/test/crudApplicationArtifacts.test.js +440 -0
  26. package/test/dynamicCrudFlowSchemas.test.js +10 -5
  27. package/test/dynamicRbacFlowSchemas.test.js +24 -2
  28. package/test/graphDrivenFlowSchema.test.js +36 -0
  29. package/test/resourceArtifacts.test.js +113 -0
@@ -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 { sns } from '@izara_project/izara-core-library-external-request';
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
  }
@@ -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 key = hook?.objType?.objectType;
205
- if (!key) return acc;
206
- if (!acc[key]) acc[key] = [];
207
- acc[key].push(hook);
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(
@@ -105,9 +105,6 @@ export async function resolveSchemaAndIdentity(_izContext, requestParams, errors
105
105
 
106
106
  requestParams.submittedByUserId = submittedByUserId;
107
107
  if (targetIdentifiers) {
108
- if (!targetIdentifiers.submittedByUserId && submittedByUserId) {
109
- targetIdentifiers.submittedByUserId = submittedByUserId;
110
- }
111
108
  // requestParams.targetIdentifiers = targetIdentifiers;
112
109
  }
113
110
 
@@ -852,12 +849,132 @@ export async function <%- flowTag %>LogicalLib(
852
849
 
853
850
  // 5. If no graph storage, complete immediately
854
851
  if (!hasGraphStorage) {
852
+ <%_ if (plan?.hasAfterHookSync) { _%>
853
+ // ── Synchronous After Hooks ──
854
+ <%_ plan.afterHooks.filter(h => h?.generatedCodeConfig?.invocationType === 'lambdaSyncInv').forEach(hook => { _%>
855
+ <%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length === 1) { _%>
856
+ if (objType?.objectType === '<%= hook.targetObjectTypes[0] %>') {
857
+ <%_ } else if (hook.targetObjectTypes && hook.targetObjectTypes.length > 1) { _%>
858
+ if (<%- JSON.stringify(hook.targetObjectTypes) %>.includes(objType?.objectType)) {
859
+ <%_ } _%>
860
+ try {
861
+ let hookPayload_<%= hook.flowTag %> = {
862
+ objType,
863
+ objInstanceFull: createObjInstanceFullFromParams(
864
+ updateItem,
865
+ requestParams
866
+ ),
867
+ relationships: requestParams.relationships || [],
868
+ targetIdentifiers: requestParams.targetIdentifiers,
869
+ submittedByUserId: requestParams.submittedByUserId
870
+ };
871
+ //(<beforeSendHook_<%= hook.flowTag %>>)
872
+ //(</beforeSendHook_<%= hook.flowTag %>>)
873
+ const hookResult = await lambda.invokeSync(
874
+ _izContext,
875
+ await lambdaSharedLib.lambdaFunctionName(
876
+ _izContext,
877
+ '<%= hook.flowTag %>'
878
+ ),
879
+ {
880
+ requestParams: hookPayload_<%= hook.flowTag %>,
881
+ callingFlowConfig
882
+ }
883
+ );
884
+ if (
885
+ hookResult?.errorsFound?.length > 0 ||
886
+ hookResult?.status === 'error'
887
+ ) {
888
+ errorsFound.push(
889
+ ...(hookResult.errorsFound || ['Hook <%= hook.flowTag %> failed'])
890
+ );
891
+ }
892
+ } catch (hookErr) {
893
+ _izContext.logger.error(
894
+ '[<%- flowTag %>LogicalLib] Sync hook <%= hook.flowTag %> error:',
895
+ hookErr
896
+ );
897
+ errorsFound.push(hookErr.message || 'Hook <%= hook.flowTag %> failed');
898
+ }
899
+ <%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length > 0) { _%>
900
+ }
901
+ <%_ } _%>
902
+ <%_ }) _%>
903
+ <%_ } _%>
904
+
905
+ <%_ if (plan?.hasAfterHookAsync) { _%>
906
+ // ── Asynchronous After Hooks ──
907
+ <%_ plan.afterHooks.filter(h => h?.generatedCodeConfig?.invocationType === 'ownTopic').forEach(hook => { _%>
908
+ <%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length === 1) { _%>
909
+ if (objType?.objectType === '<%= hook.targetObjectTypes[0] %>') {
910
+ <%_ } else if (hook.targetObjectTypes && hook.targetObjectTypes.length > 1) { _%>
911
+ if (<%- JSON.stringify(hook.targetObjectTypes) %>.includes(objType?.objectType)) {
912
+ <%_ } _%>
913
+ let hookPayload_<%= hook.flowTag %> = {
914
+ objType,
915
+ objInstanceFull: createObjInstanceFullFromParams(
916
+ updateItem,
917
+ requestParams
918
+ ),
919
+ relationships: requestParams.relationships || [],
920
+ targetIdentifiers: requestParams.targetIdentifiers,
921
+ submittedByUserId: requestParams.submittedByUserId
922
+ };
923
+ //(<beforeSendHook_<%= hook.flowTag %>>)
924
+ //(</beforeSendHook_<%= hook.flowTag %>>)
925
+ const hookMsg_<%= hook.flowTag %> =
926
+ callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
927
+ hookPayload_<%= hook.flowTag %>,
928
+ callingFlowSharedLib.addParentCallingFlowConfig(
929
+ callingFlowConfig,
930
+ callingFlowSharedLib.createCallingFlowConfig(
931
+ await lambdaSharedLib.lambdaFunctionName(
932
+ _izContext,
933
+ 'UpdateAfterHookCallbackHdrSqs'
934
+ ),
935
+ {
936
+ actionData: {
937
+ objType,
938
+ objInstanceFull: createObjInstanceFullFromParams(
939
+ updateItem,
940
+ requestParams
941
+ ),
942
+ relationships: requestParams.relationships || [],
943
+ targetIdentifiers: requestParams.targetIdentifiers,
944
+ parentFlowId: requestParams.parentFlowId,
945
+ status: 'complete',
946
+ errorsFound
947
+ }
948
+ }
949
+ )
950
+ )
951
+ );
952
+
953
+ await sns.publishAsync(_izContext, {
954
+ TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
955
+ _izContext,
956
+ '<%= hook.flowTag %>_In'
957
+ ),
958
+ Message: JSON.stringify(hookMsg_<%= hook.flowTag %>),
959
+ MessageAttributes: sns.createStringMessageAttributes(_izContext, {})
960
+ });
961
+ <%_ if (hook.targetObjectTypes && hook.targetObjectTypes.length > 0) { _%>
962
+ }
963
+ <%_ } _%>
964
+ <%_ }) _%>
965
+ <%_ } else { _%>
855
966
  await handleDynamoDbOnlyComplete(_izContext, {
856
967
  objType,
857
968
  updateItem,
858
969
  requestParams,
859
970
  callingFlowConfig
860
971
  });
972
+ <%_ } _%>
973
+ }
974
+
975
+ let resultStatus = 'complete';
976
+ if (errorsFound.length > 0) {
977
+ resultStatus = 'error';
861
978
  }
862
979
 
863
980
  return {
@@ -866,7 +983,7 @@ export async function <%- flowTag %>LogicalLib(
866
983
  objInstanceFull: { identifiers, fields },
867
984
  versionedDataIds
868
985
  },
869
- status: 'complete',
986
+ status: resultStatus,
870
987
  errorsFound
871
988
  };
872
989
  } 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
- { flowTag: 'ConfirmUsage', event: ['ownTopic'] },
23
- { flowTag: 'CancelUsage', event: ['ownTopic'] }
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
- await sns.publishMessage(_izContext, {
150
- message: {
151
- returnResult: {
152
- status: true,
153
- uniqueIdentify: usedTimestampId,
154
- usedTimestampId,
155
- runningTotalReservedId
156
- }
157
- },
158
- TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
159
- _izContext,
160
- 'CancelUsage_Out'
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
- await sns.publishMessage(_izContext, {
174
- message: {
175
- returnResult: {
176
- status: true,
177
- uniqueIdentify: usedTimestampId,
178
- usedTimestampId,
179
- runningTotalReservedId
180
- }
181
- },
182
- TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
183
- _izContext,
184
- 'ConfirmUsage_Out'
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;