@izara_project/izara-core-generate-service-code 1.0.87 → 1.0.88

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.
@@ -102,27 +102,27 @@ export async function resolveSchemaAndIdentity(_izContext, requestParams, errors
102
102
  targetIdentifiers.submittedByUserId = submittedByUserId;
103
103
  }
104
104
 
105
- if (Array.isArray(objectSchema.identifiers)) {
106
- for (const identifier of objectSchema.identifiers) {
107
- if (identifier.fieldName) {
108
- if (targetIdentifiers[identifier.fieldName] === undefined) {
109
- targetIdentifiers[identifier.fieldName] = null;
110
- }
111
- } else if (Array.isArray(identifier.fieldNames)) {
112
- for (const fn of identifier.fieldNames) {
113
- if (targetIdentifiers[fn] === undefined) {
114
- targetIdentifiers[fn] = null;
115
- }
116
- }
117
- } else if (identifier.name) {
118
- if (targetIdentifiers[identifier.name] === undefined) {
119
- targetIdentifiers[identifier.name] = null;
120
- }
121
- }
122
- }
123
- }
124
-
125
- requestParams.targetIdentifiers = targetIdentifiers;
105
+ // if (Array.isArray(objectSchema.identifiers)) {
106
+ // for (const identifier of objectSchema.identifiers) {
107
+ // if (identifier.fieldName) {
108
+ // if (targetIdentifiers[identifier.fieldName] === undefined) {
109
+ // targetIdentifiers[identifier.fieldName] = null;
110
+ // }
111
+ // } else if (Array.isArray(identifier.fieldNames)) {
112
+ // for (const fn of identifier.fieldNames) {
113
+ // if (targetIdentifiers[fn] === undefined) {
114
+ // targetIdentifiers[fn] = null;
115
+ // }
116
+ // }
117
+ // } else if (identifier.name) {
118
+ // if (targetIdentifiers[identifier.name] === undefined) {
119
+ // targetIdentifiers[identifier.name] = null;
120
+ // }
121
+ // }
122
+ // }
123
+ // }
124
+
125
+ // requestParams.targetIdentifiers = targetIdentifiers;
126
126
  }
127
127
 
128
128
  _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] Identity & Target Context Resolved:`, {
@@ -136,7 +136,7 @@ export async function resolveSchemaAndIdentity(_izContext, requestParams, errors
136
136
  }
137
137
 
138
138
  requestParams.submittedByUserId = submittedByUserId;
139
- return { objType, objectSchema };
139
+ return { objType, objectSchema, targetIdentifiers };
140
140
  }
141
141
 
142
142
  /**
@@ -1344,6 +1344,7 @@ export async function <%- flowTag %>LogicalLib(
1344
1344
  }
1345
1345
  );
1346
1346
 
1347
+ const fieldsForHook = { ...objInstanceFullForDynamoDb.fields };
1347
1348
  objInstanceFullForDynamoDb.fields = {};
1348
1349
 
1349
1350
  // Auto-provision owner TargetRole for DynamoDB-only
@@ -1352,6 +1353,101 @@ export async function <%- flowTag %>LogicalLib(
1352
1353
  identifiersForCreateData,
1353
1354
  requestParams
1354
1355
  });
1356
+
1357
+ <%_ if (plan?.hasAfterHookSync) { _%>
1358
+ // ── Synchronous After Hooks ──
1359
+ <%_ plan.afterHooks.filter(h => h?.generatedCodeConfig?.invocationType === 'lambdaSyncInv').forEach(hook => { _%>
1360
+ <%_ if (hook.objType?.objectType) { _%>
1361
+ if (objType.objectType === '<%= hook.objType.objectType %>') {
1362
+ <%_ } _%>
1363
+ try {
1364
+ const hookResult = await lambda.invokeSync(
1365
+ _izContext,
1366
+ await lambdaSharedLib.lambdaFunctionName(
1367
+ _izContext,
1368
+ '<%= hook.flowTag %>'
1369
+ ),
1370
+ {
1371
+ requestParams: {
1372
+ objType,
1373
+ objInstanceFull: {
1374
+ identifiers: identifiersForCreateData,
1375
+ fields: fieldsForHook
1376
+ },
1377
+ relationships: requestParams.relationships || [],
1378
+ targetIdentifiers: requestParams.targetIdentifiers,
1379
+ submittedByUserId: requestParams.submittedByUserId
1380
+ },
1381
+ callingFlowConfig
1382
+ }
1383
+ );
1384
+ if (hookResult?.errorsFound?.length > 0 || hookResult?.status === 'error') {
1385
+ errorsFound.push(...(hookResult.errorsFound || ['Hook <%= hook.flowTag %> failed']));
1386
+ }
1387
+ } catch (hookErr) {
1388
+ _izContext.logger.error('[<%- flowTag %>LogicalLib] Sync hook <%= hook.flowTag %> error:', hookErr);
1389
+ errorsFound.push(hookErr.message || 'Hook <%= hook.flowTag %> failed');
1390
+ }
1391
+ <%_ if (hook.objType?.objectType) { _%>
1392
+ }
1393
+ <%_ } _%>
1394
+ <%_ }) _%>
1395
+ <%_ } _%>
1396
+
1397
+ <%_ if (plan?.hasAfterHookAsync) { _%>
1398
+ // ── Asynchronous After Hooks ──
1399
+ <%_ plan.afterHooks.filter(h => h?.generatedCodeConfig?.invocationType === 'ownTopic').forEach(hook => { _%>
1400
+ <%_ if (hook.objType?.objectType) { _%>
1401
+ if (objType.objectType === '<%= hook.objType.objectType %>') {
1402
+ <%_ } _%>
1403
+ const hookMsg_<%= hook.flowTag %> = callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
1404
+ {
1405
+ objType,
1406
+ objInstanceFull: {
1407
+ identifiers: identifiersForCreateData,
1408
+ fields: fieldsForHook
1409
+ },
1410
+ relationships: requestParams.relationships || [],
1411
+ targetIdentifiers: requestParams.targetIdentifiers,
1412
+ submittedByUserId: requestParams.submittedByUserId
1413
+ },
1414
+ callingFlowSharedLib.addParentCallingFlowConfig(
1415
+ callingFlowConfig,
1416
+ callingFlowSharedLib.createCallingFlowConfig(
1417
+ await lambdaSharedLib.lambdaFunctionName(
1418
+ _izContext,
1419
+ '<%- flowTag %>AfterHookCallbackHdrSqs'
1420
+ ),
1421
+ {
1422
+ actionData: {
1423
+ objType,
1424
+ objInstanceFull: {
1425
+ identifiers: identifiersForCreateData,
1426
+ fields: fieldsForHook
1427
+ },
1428
+ relationships: requestParams.relationships || [],
1429
+ targetIdentifiers: requestParams.targetIdentifiers,
1430
+ status: 'complete',
1431
+ errorsFound
1432
+ }
1433
+ }
1434
+ )
1435
+ )
1436
+ );
1437
+
1438
+ await sns.publishAsync(_izContext, {
1439
+ TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
1440
+ _izContext,
1441
+ '<%= hook.flowTag %>_In'
1442
+ ),
1443
+ Message: JSON.stringify(hookMsg_<%= hook.flowTag %>),
1444
+ MessageAttributes: sns.createStringMessageAttributes(_izContext, {})
1445
+ });
1446
+ <%_ if (hook.objType?.objectType) { _%>
1447
+ }
1448
+ <%_ } _%>
1449
+ <%_ }) _%>
1450
+ <%_ } _%>
1355
1451
  }
1356
1452
 
1357
1453
  //(<afterCreateRecordDynamo>)
@@ -1505,11 +1601,13 @@ export async function <%- flowTag %>LogicalLib(
1505
1601
 
1506
1602
  // 7. Handle DynamoDB-only Complete Path
1507
1603
  if (allAwaitingStepsId.length === 0 && listOfObjectForCreates.length === 0) {
1604
+ <%_ if (!plan?.hasAfterHookAsync) { _%>
1508
1605
  await handleDynamoDbOnlyComplete(_izContext, {
1509
1606
  objType,
1510
1607
  objInstanceFullForDynamoDb,
1511
1608
  callingFlowConfig
1512
1609
  });
1610
+ <%_ } _%>
1513
1611
  }
1514
1612
 
1515
1613
  return {
@@ -171,6 +171,43 @@ export default async function CreateNodeCallbackMain(
171
171
  node,
172
172
  submittedByUserId
173
173
  });
174
+
175
+ <%_ if (plan?.hasAfterHookSync) { _%>
176
+ // ── Synchronous After Hooks ──
177
+ <%_ plan.afterHooks.filter(h => h?.generatedCodeConfig?.invocationType === 'lambdaSyncInv').forEach(hook => { _%>
178
+ <%_ if (hook.objType?.objectType) { _%>
179
+ if (returnValue.requestParams?.objType?.objectType === '<%= hook.objType.objectType %>') {
180
+ <%_ } _%>
181
+ try {
182
+ const hookResult = await lambda.invokeSync(
183
+ _izContext,
184
+ await lambdaSharedLib.lambdaFunctionName(
185
+ _izContext,
186
+ '<%= hook.flowTag %>'
187
+ ),
188
+ {
189
+ requestParams: {
190
+ objType: returnValue.requestParams.objType,
191
+ objInstanceFull: node.objInstanceFull,
192
+ relationships: node.relationships || [],
193
+ targetIdentifiers: requestParams.targetIdentifiers,
194
+ submittedByUserId
195
+ },
196
+ callingFlowConfig
197
+ }
198
+ );
199
+ if (hookResult?.errorsFound?.length > 0 || hookResult?.status === 'error') {
200
+ errorsFound.push(...(hookResult.errorsFound || ['Hook <%= hook.flowTag %> failed']));
201
+ }
202
+ } catch (hookErr) {
203
+ _izContext.logger.error('[CreateNodeCallback] Sync hook <%= hook.flowTag %> error:', hookErr);
204
+ errorsFound.push(hookErr.message || 'Hook <%= hook.flowTag %> failed');
205
+ }
206
+ <%_ if (hook.objType?.objectType) { _%>
207
+ }
208
+ <%_ } _%>
209
+ <%_ }) _%>
210
+ <%_ } _%>
174
211
  }
175
212
 
176
213
  const callingFlowConfig =
@@ -198,6 +235,48 @@ export default async function CreateNodeCallbackMain(
198
235
  _izContext
199
236
  );
200
237
 
238
+ <%_ if (plan?.hasAfterHookAsync) { _%>
239
+ // ── Asynchronous After Hooks ──
240
+ <%_ plan.afterHooks.filter(h => h?.generatedCodeConfig?.invocationType === 'ownTopic').forEach(hook => { _%>
241
+ <%_ if (hook.objType?.objectType) { _%>
242
+ if (returnValue.requestParams?.objType?.objectType === '<%= hook.objType.objectType %>') {
243
+ <%_ } _%>
244
+ 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
+ },
252
+ callingFlowSharedLib.addParentCallingFlowConfig(
253
+ callingFlowConfig,
254
+ callingFlowSharedLib.createCallingFlowConfig(
255
+ await lambdaSharedLib.lambdaFunctionName(
256
+ _izContext,
257
+ 'CreateAfterHookCallbackHdrSqs'
258
+ ),
259
+ {
260
+ quotaKeys,
261
+ actionData
262
+ }
263
+ )
264
+ )
265
+ );
266
+
267
+ await sns.publishAsync(_izContext, {
268
+ TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
269
+ _izContext,
270
+ '<%= hook.flowTag %>_In'
271
+ ),
272
+ Message: JSON.stringify(hookMsg_<%= hook.flowTag %>),
273
+ MessageAttributes: sns.createStringMessageAttributes(_izContext, {})
274
+ });
275
+ <%_ if (hook.objType?.objectType) { _%>
276
+ }
277
+ <%_ } _%>
278
+ <%_ }) _%>
279
+ <%_ } else { _%>
201
280
  await forwardToQuotaConfirmation(_izContext, {
202
281
  status,
203
282
  errorsFound,
@@ -205,6 +284,7 @@ export default async function CreateNodeCallbackMain(
205
284
  actionData,
206
285
  callingFlowConfig
207
286
  });
287
+ <%_ } _%>
208
288
  }
209
289
 
210
290
  await asyncFlowSharedLib.removeAwaitingMultipleStep(
@@ -0,0 +1,99 @@
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 {
19
+ <%- flowTag %>LogicalLib,
20
+ handleDeleteError
21
+ } from './<%- upperCaseFlowTag %>LogicalLib.js';
22
+
23
+ //(<optionalRequire>)
24
+ //(</optionalRequire>)
25
+
26
+ /**
27
+ * Handles callback after async BeforeHook completion
28
+ * @param {Object} _izContext - Izara context object
29
+ * @param {Object} requestParams - Callback request parameters
30
+ * @param {Object} passBackProperties - Pass-back properties
31
+ * @returns {Promise<Object>} Result object
32
+ */
33
+ export default async function <%- upperCaseFlowTag %>BeforeHookCallbackMain(
34
+ _izContext,
35
+ requestParams,
36
+ passBackProperties
37
+ //(<additionalParams>)
38
+ //(</additionalParams>)
39
+ ) {
40
+ try {
41
+ _izContext.logger.debug('[<%- upperCaseFlowTag %>BeforeHookCallback] started', {
42
+ requestParams,
43
+ passBackProperties
44
+ });
45
+
46
+ const {
47
+ status,
48
+ errorsFound = [],
49
+ returnValue,
50
+ parentFlowId
51
+ } = requestParams;
52
+
53
+ const mergedErrors = Array.isArray(errorsFound) ? [...errorsFound] : [];
54
+ if (status === 'error' && mergedErrors.length === 0) {
55
+ mergedErrors.push('BeforeHook execution reported error');
56
+ }
57
+
58
+ const callingFlowConfig =
59
+ passBackProperties?.callingFlowConfig ||
60
+ requestParams?.passBackProperties?.callingFlowConfig ||
61
+ {};
62
+
63
+ const originalRequestParams =
64
+ passBackProperties?.originalRequestParams ||
65
+ requestParams?.passBackProperties?.originalRequestParams ||
66
+ passBackProperties?.requestParams ||
67
+ passBackProperties;
68
+
69
+ if (mergedErrors.length > 0) {
70
+ _izContext.logger.warn(
71
+ '[<%- upperCaseFlowTag %>BeforeHookCallback] BeforeHook reported errors:',
72
+ mergedErrors
73
+ );
74
+ return await handleDeleteError(_izContext, {
75
+ objType: originalRequestParams?.objType,
76
+ identifiers: originalRequestParams?.identifiers || {},
77
+ targetIdentifiers: originalRequestParams?.targetIdentifiers,
78
+ callingFlowConfig,
79
+ errorsFound: mergedErrors
80
+ });
81
+ }
82
+
83
+ if (returnValue?.identifiers && originalRequestParams?.identifiers) {
84
+ Object.assign(originalRequestParams.identifiers, returnValue.identifiers);
85
+ }
86
+
87
+ //(<beforeLogicalExecution>)
88
+ //(</beforeLogicalExecution>)
89
+
90
+ return await <%- flowTag %>LogicalLib(
91
+ _izContext,
92
+ originalRequestParams,
93
+ callingFlowConfig
94
+ );
95
+ } catch (error) {
96
+ _izContext.logger.error('[<%- upperCaseFlowTag %>BeforeHookCallback] error:', error);
97
+ throw error;
98
+ }
99
+ }