@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.
@@ -21,14 +21,10 @@ import {
21
21
  objectHash as hash,
22
22
  identifierUuid
23
23
  } from '@izara_project/izara-shared-core';
24
- import {
25
- consts as coreConsts,
26
- NoRetryError
27
- } from '@izara_project/izara-core-library-core';
24
+ import { NoRetryError } from '@izara_project/izara-core-library-core';
28
25
 
29
26
  // ==================== Core Service Schemas ====================
30
27
  import {
31
- getObjectSchema,
32
28
  consts,
33
29
  utils,
34
30
  identifiersObject,
@@ -53,7 +49,10 @@ import {
53
49
  lambda
54
50
  } from '@izara_project/izara-core-library-external-request';
55
51
 
56
- import { <%- flowTag %>LogicalLib } from './<%- upperCaseFlowTag %>LogicalLib.js';
52
+ import {
53
+ <%- flowTag %>LogicalLib,
54
+ resolveSchemaAndIdentity
55
+ } from './<%- upperCaseFlowTag %>LogicalLib.js';
57
56
 
58
57
  //(<optionalRequire>)
59
58
  //(</optionalRequire>)
@@ -79,88 +78,44 @@ export default async function <%- flowTag %>(
79
78
  });
80
79
 
81
80
  const errorsFound = [];
82
- const objType = createObjType(requestParams.objectType);
83
-
84
- // ── Load schema ───────────────────────────────────────────────────────────
85
- const objectSchema = await getObjectSchema.getObjSchemaS3WithHierarchy(
86
- _izContext,
87
- objType
88
- );
89
- _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] objectSchema:`, objectSchema);
90
-
91
- // ── Resolve submittedByUserId / targetIdentifiers ─────────────────────────
92
- let submittedByUserId, targetIdentifiers;
93
- if (
94
- objectSchema.generatedBy === 'user' ||
95
- objectSchema.generatedBy === 'systemWithUser'
96
- ) {
97
- submittedByUserId =
98
- requestParams.submittedByUserId ||
99
- _izContext.correlationIds?.get(coreConsts.SUBMITTED_BY_USER_ID);
100
-
101
- targetIdentifiers = requestParams.targetIdentifiers;
102
- delete requestParams.targetIdentifiers;
103
-
104
- if (!targetIdentifiers && objectSchema.belongTo?.objectType === 'user' && submittedByUserId) {
105
- targetIdentifiers = { submittedByUserId };
106
- }
107
81
 
108
- if (!submittedByUserId) errorsFound.push('Not have submittedByUserId');
109
- if (objectSchema.hasOwnProperty('belongTo') && !targetIdentifiers)
110
- errorsFound.push('not have targetIdentifiers');
111
-
112
- requestParams.submittedByUserId = submittedByUserId;
113
- if (targetIdentifiers) {
114
- if (!targetIdentifiers.submittedByUserId && submittedByUserId) {
115
- targetIdentifiers.submittedByUserId = submittedByUserId;
116
- }
117
- }
118
-
119
- _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] Identity & Target Context Resolved:`, {
120
- submittedByUserId: requestParams.submittedByUserId,
121
- targetIdentifiers,
122
- belongTo: objectSchema.belongTo,
123
- generatedBy: objectSchema.generatedBy
124
- });
125
- } else if (objectSchema.generatedBy === 'searchResultGenerated') {
126
- throw new NoRetryError(
127
- 'error searchResultGenerated should not happen here'
128
- );
129
- }
82
+ // ── Resolve Schema & Identity ─────────────────────────────────────────────
83
+ const { objType, objectSchema, targetIdentifiers } =
84
+ await resolveSchemaAndIdentity(_izContext, requestParams, errorsFound);
130
85
 
131
86
  // ── Build identifiers used by asynchronous processing ────────────────────
132
87
  const identifiers = requestParams.objInstanceFull?.identifiers;
133
88
 
134
- if (!objectSchema.hasOwnProperty('belongTo')) {
135
- if (!targetIdentifiers && identifiers) {
136
- targetIdentifiers = { ...identifiers };
137
- } else if (targetIdentifiers && identifiers) {
138
- for (const [key, value] of Object.entries(identifiers)) {
139
- if (targetIdentifiers[key] === undefined && value !== undefined) {
140
- targetIdentifiers[key] = value;
141
- }
142
- }
143
- }
144
- if (targetIdentifiers) {
145
- if (!targetIdentifiers.submittedByUserId && submittedByUserId) {
146
- targetIdentifiers.submittedByUserId = submittedByUserId;
147
- }
148
- }
149
- }
150
-
151
- if (targetIdentifiers && identifiers) {
152
- for (const [key, value] of Object.entries(identifiers)) {
153
- if (
154
- targetIdentifiers[key] !== undefined &&
155
- value !== undefined &&
156
- targetIdentifiers[key] !== value
157
- ) {
158
- errorsFound.push(
159
- `targetIdentifiers.${key} must match objInstanceFull.identifiers.${key}`
160
- );
161
- }
162
- }
163
- }
89
+ // if (!objectSchema.hasOwnProperty('belongTo')) {
90
+ // if (!targetIdentifiers && identifiers) {
91
+ // targetIdentifiers = { ...identifiers };
92
+ // } else if (targetIdentifiers && identifiers) {
93
+ // for (const [key, value] of Object.entries(identifiers)) {
94
+ // if (targetIdentifiers[key] === undefined && value !== undefined) {
95
+ // targetIdentifiers[key] = value;
96
+ // }
97
+ // }
98
+ // }
99
+ // if (targetIdentifiers) {
100
+ // if (!targetIdentifiers.submittedByUserId && submittedByUserId) {
101
+ // targetIdentifiers.submittedByUserId = submittedByUserId;
102
+ // }
103
+ // }
104
+ // }
105
+
106
+ // if (targetIdentifiers && identifiers) {
107
+ // for (const [key, value] of Object.entries(identifiers)) {
108
+ // if (
109
+ // targetIdentifiers[key] !== undefined &&
110
+ // value !== undefined &&
111
+ // targetIdentifiers[key] !== value
112
+ // ) {
113
+ // errorsFound.push(
114
+ // `targetIdentifiers.${key} must match objInstanceFull.identifiers.${key}`
115
+ // );
116
+ // }
117
+ // }
118
+ // }
164
119
 
165
120
  //(<validateBeforeUpdate>)
166
121
  //(</validateBeforeUpdate>)
@@ -245,110 +200,120 @@ export default async function <%- flowTag %>(
245
200
 
246
201
  // ── Optional phase extension point ────────────────────────────────────────
247
202
  <%_
248
- const groupedByObjType = [];
203
+ 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);
208
+ return acc;
209
+ }, {});
249
210
  _%>
250
- <%_ Object.entries(groupedByObjType).forEach(([objectType, configs]) => { _%>
211
+ <%_ Object.entries(beforeHooksByObjType).forEach(([objectType, configs]) => { _%>
251
212
  <%_
252
- const hasOwnTopic = configs.some(c => c.invocationType === 'ownTopic');
253
- const hasLambdaSyncInv = configs.some(c => c.invocationType === 'lambdaSyncInv');
254
- _%>
213
+ const hasOwnTopic = configs.some(c => c?.generatedCodeConfig?.invocationType === 'ownTopic' || c?.event?.includes('ownTopic'));
214
+ const hasLambdaSyncInv = configs.some(c => c?.generatedCodeConfig?.invocationType === 'lambdaSyncInv' || c?.event?.includes('lambdaSyncInv'));
215
+ _%>
255
216
  if (requestParams.objectType === '<%= objectType %>') {
256
217
  <%_ if (hasLambdaSyncInv) { _%>
257
- const lambdaSyncInvResults = await Promise.all([
258
- <%_ configs.filter(c => c.invocationType === 'lambdaSyncInv').forEach((config, index, arr) => { _%>
259
- // lambdaSyncInv <%= config.flowTag %>
260
- lambda
261
- .invokeSync(
218
+ const lambdaSyncInvResults = [];
219
+ <%_ for (const config of configs.filter(c => c?.generatedCodeConfig?.invocationType === 'lambdaSyncInv' || c?.event?.includes('lambdaSyncInv'))) { _%>
220
+ try {
221
+ const returnValue = await lambda.invokeSync(
222
+ _izContext,
223
+ await lambdaSharedLib.lambdaFunctionName(
262
224
  _izContext,
263
- await lambdaSharedLib.lambdaFunctionName(
264
- _izContext,
265
- 'Process<%= config.flowTag %>HdrInv'
266
- ),
267
- { requestParams, callingFlowConfig }
268
- )
269
- .then((returnValue) => ({
270
- flowTag: '<%= config.flowTag %>',
271
- returnValue
272
- })) /*__EJS_COMMA_14__*/
273
- // lambdaSyncInv <%= config.flowTag %>
274
- <%_ }) _%>
275
- ]);
225
+ '<%= config.flowTag %>'
226
+ ),
227
+ {
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
+ },
237
+ callingFlowConfig
238
+ }
239
+ );
240
+ lambdaSyncInvResults.push({
241
+ flowTag: '<%= config.flowTag %>',
242
+ returnValue
243
+ });
244
+ if (returnValue?.errorsFound?.length > 0) {
245
+ errorsFound.push(...returnValue.errorsFound);
246
+ } else if (returnValue?.status === 'error') {
247
+ errorsFound.push('Error from <%= config.flowTag %>');
248
+ } else {
249
+ if (returnValue?.fields && requestParams?.objInstanceFull?.fields) {
250
+ Object.assign(requestParams.objInstanceFull.fields, returnValue.fields);
251
+ } else if (returnValue?.fieldNames && requestParams?.objInstanceFull?.fields) {
252
+ Object.assign(requestParams.objInstanceFull.fields, returnValue.fieldNames);
253
+ } else if (returnValue?.fieldNames && requestParams?.fieldNames) {
254
+ Object.assign(requestParams.fieldNames, returnValue.fieldNames);
255
+ }
256
+ if (returnValue?.relationships && requestParams) {
257
+ requestParams.relationships = returnValue.relationships;
258
+ }
259
+ }
260
+ } catch (hookErr) {
261
+ _izContext.logger.error(
262
+ '[<%- flowTag %>] Sync hook <%= config.flowTag %> error:',
263
+ hookErr
264
+ );
265
+ errorsFound.push(hookErr.message || 'Hook <%= config.flowTag %> failed');
266
+ }
267
+ <%_ } _%>
268
+
269
+ if (errorsFound.length > 0) {
270
+ return await <%- flowTag %>LogicalLib(
271
+ _izContext,
272
+ requestParams,
273
+ callingFlowConfig,
274
+ errorsFound
275
+ );
276
+ }
276
277
  <%_ } _%>
277
278
 
278
279
  //(<afterBeforeLogical_<%= objectType %>>)
279
280
  //(</afterBeforeLogical_<%= objectType %>>)
280
281
 
281
282
  <%_ if (hasOwnTopic) { _%>
282
- // ── ownTopic (async — create awaitingSteps and then publish) ──────────
283
- const awaitingMultipleStepIds = [];
284
- const recordMsgs = [];
285
-
286
- <%_ configs.filter(c => c.invocationType === 'ownTopic').forEach(config => { _%>
287
- // ownTopic <%= config.flowTag %>
288
- awaitingMultipleStepIds.push({
289
- awaitingStepId: await asyncFlowSharedLib.createAwaitingStepId(
290
- hash(identifiers),
291
- 'logical_<%= objectType %>_<%= config.flowTag.charAt(0).toUpperCase() + config.flowTag.slice(1) %>'
292
- ),
293
- additionalAttributes: {}
294
- });
295
-
296
- recordMsgs.push({
297
- msg: callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
298
- requestParams,
283
+ // ── ownTopic (async — dispatch to before-hook and await callback) ──────────
284
+ <%_ configs.filter(c => c?.generatedCodeConfig?.invocationType === 'ownTopic' || c?.event?.includes('ownTopic')).forEach(config => { _%>
285
+ const hookMsg_<%= config.flowTag %> =
286
+ 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
+ },
299
296
  callingFlowSharedLib.addParentCallingFlowConfig(
300
297
  callingFlowConfig,
301
298
  callingFlowSharedLib.createCallingFlowConfig(
302
- //(<callingFlowProperties_<%= config.flowTag %>>)
303
299
  await lambdaSharedLib.lambdaFunctionName(
304
300
  _izContext,
305
- '<%= flowTag.toLowerCase() %>Complete'
301
+ '<%- flowTag %>BeforeHookCallbackHdrSqs'
306
302
  ),
307
- {}
308
- //(</callingFlowProperties_<%= config.flowTag %>>)
303
+ {
304
+ originalRequestParams: {
305
+ ...requestParams,
306
+ objType,
307
+ targetIdentifiers
308
+ },
309
+ callingFlowConfig
310
+ }
309
311
  )
310
312
  )
311
- ),
312
- flowTag: '<%= config.flowTag.charAt(0).toUpperCase() + config.flowTag.slice(1) %>'
313
- });
314
- <%_ }) _%>
315
-
316
- <%_ if (hasLambdaSyncInv) { _%>
317
- // ── Add lambdaSyncInv results to awaitingSteps ────────────────────────
318
- for (const syncResult of lambdaSyncInvResults) {
319
- awaitingMultipleStepIds.push({
320
- awaitingStepId: await asyncFlowSharedLib.createAwaitingStepId(
321
- hash(identifiers),
322
- 'logical_<%= objectType %>_' + syncResult.flowTag
323
- ),
324
- additionalAttributes: {
325
- complete: true,
326
- errorsFound: [],
327
- returnValue: syncResult.returnValue
328
- }
329
- });
330
- }
331
- <%_ } _%>
332
-
333
- await asyncFlowSharedLib.createAwaitingMultipleSteps(
334
- _izContext,
335
- asyncFlowSharedLib.createPendingStepId(
336
- _izContext.uniqueRequestId,
337
- 'logical_<%= objectType %>'
338
- ),
339
- awaitingMultipleStepIds,
340
- {
341
- additionalAttributes: {
342
- callingFlowConfig
343
- }
344
- }
345
- );
346
-
347
- //(<beforePublish_<%= objectType %>>)
348
- //(</beforePublish_<%= objectType %>>)
313
+ );
349
314
 
350
- for (const recordMsg of recordMsgs) {
351
- const messageAttributes = sns.createStringMessageAttributes(
315
+ const messageAttributes_<%= config.flowTag %> =
316
+ sns.createStringMessageAttributes(
352
317
  _izContext,
353
318
  callingFlowSharedLib.addCallingFlowToSnsResponseMessageAttributes(
354
319
  callingFlowConfig,
@@ -356,32 +321,36 @@ export default async function <%- flowTag %>(
356
321
  )
357
322
  );
358
323
 
359
- const topicArn = snsSharedLib.snsTopicArnByFlowSchema(
360
- _izContext,
361
- `${recordMsg.flowTag}_In`
362
- );
324
+ const topicArn_<%= config.flowTag %> = snsSharedLib.snsTopicArnByFlowSchema(
325
+ _izContext,
326
+ '<%= config.flowTag %>_In'
327
+ );
363
328
 
364
- await sns.publishAsync(_izContext, {
365
- Message: JSON.stringify(recordMsg.msg),
366
- MessageAttributes: messageAttributes,
367
- TopicArn: topicArn
368
- });
369
- }
329
+ _izContext.logger.debug(
330
+ `[${process.env.iz_serviceTag}:<%- flowTag %>] Dispatching to BeforeHook:`,
331
+ {
332
+ topicArn: topicArn_<%= config.flowTag %>,
333
+ flowTag: '<%= config.flowTag %>'
334
+ }
335
+ );
370
336
 
371
- return 'complete logical <%= objectType %>';
337
+ await sns.publishAsync(_izContext, {
338
+ Message: JSON.stringify(hookMsg_<%= config.flowTag %>),
339
+ MessageAttributes: messageAttributes_<%= config.flowTag %>,
340
+ TopicArn: topicArn_<%= config.flowTag %>
341
+ });
342
+ <%_ }) _%>
372
343
 
344
+ return {
345
+ status: 'pending',
346
+ message: 'Dispatched to BeforeHook'
347
+ };
373
348
  <%_ } else { _%>
374
- // ── lambdaSyncInv only — collect results and proceed to updateLogicalLib
375
- const phaseResults = Object.fromEntries(
376
- lambdaSyncInvResults.map(({ flowTag: tag, returnValue }) => [tag, returnValue])
377
- );
378
-
379
349
  return await <%- flowTag %>LogicalLib(
380
350
  _izContext,
381
351
  requestParams,
382
352
  callingFlowConfig,
383
- errorsFound,
384
- phaseResults
353
+ errorsFound
385
354
  );
386
355
  <%_ } _%>
387
356
  }
@@ -108,7 +108,7 @@ export async function resolveSchemaAndIdentity(_izContext, requestParams, errors
108
108
  if (!targetIdentifiers.submittedByUserId && submittedByUserId) {
109
109
  targetIdentifiers.submittedByUserId = submittedByUserId;
110
110
  }
111
- requestParams.targetIdentifiers = targetIdentifiers;
111
+ // requestParams.targetIdentifiers = targetIdentifiers;
112
112
  }
113
113
 
114
114
  _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] Identity & Target Context Resolved:`, {
@@ -124,7 +124,7 @@ export async function resolveSchemaAndIdentity(_izContext, requestParams, errors
124
124
  }
125
125
 
126
126
  requestParams.submittedByUserId = submittedByUserId;
127
- return { objType, objectSchema };
127
+ return { objType, objectSchema, targetIdentifiers };
128
128
  }
129
129
 
130
130
  // ── 2. UpdateRbacCallback_Main Helpers ────────────────────────────────────────
@@ -16,7 +16,9 @@ export function supportedCustomFlows(flows) {
16
16
  (flow) =>
17
17
  typeof flow?.flowTag === 'string' &&
18
18
  flow.flowTag !== '' &&
19
- !flow.generatedCodeConfig &&
19
+ (!flow.generatedCodeConfig ||
20
+ (flow.generatedCodeConfig.codeHookTag &&
21
+ !flow.event.includes('ownTopic'))) &&
20
22
  Array.isArray(flow.event) &&
21
23
  flow.event.some((event) => SUPPORTED_EVENTS.has(event))
22
24
  );