@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.
@@ -41,7 +41,12 @@ import {
41
41
  } from '@izara_project/izara-core-library-service-schemas';
42
42
  import snsSharedLib from '@izara_project/izara-core-library-sns';
43
43
 
44
- import { <%- flowTag %>LogicalLib } from './<%- upperCaseFlowTag %>LogicalLib.js';
44
+ import {
45
+ <%- flowTag %>LogicalLib,
46
+ resolveSchemaAndIdentity,
47
+ resolveAndGenerateIdentifiers,
48
+ validateFieldNames
49
+ } from './<%- upperCaseFlowTag %>LogicalLib.js';
45
50
 
46
51
  //(<optionalRequire>)
47
52
  //(</optionalRequire>)
@@ -50,228 +55,6 @@ const { createObjType, firstLetterUpperCase } = utils;
50
55
  const { createDataDetailsLib } = dataDetailsLib;
51
56
  const { createIdentifiersByUseCase } = identifiersObject;
52
57
 
53
- // ── Helper Functions ──────────────────────────────────────────────────────────
54
-
55
- /**
56
- * Loads Schema and resolves submittedByUserId and targetIdentifiers
57
- * @param {Object} _izContext - Izara context object
58
- * @param {Object} requestParams - Request parameters
59
- * @param {Array<string>} errorsFound - Error list
60
- * @returns {Promise<{ objType: Object, objectSchema: Object, targetIdentifiers?: Object }>}
61
- */
62
- async function resolveSchemaAndIdentity(_izContext, requestParams, errorsFound) {
63
- const objType = createObjType(requestParams.objectType);
64
- const objectSchema = await getObjectSchema.getObjSchemaS3WithHierarchy(
65
- _izContext,
66
- objType
67
- );
68
- _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] objectSchema:`, objectSchema);
69
-
70
- let submittedByUserId, targetIdentifiers;
71
- if (
72
- objectSchema.generatedBy === 'user' ||
73
- objectSchema.generatedBy === 'systemWithUser'
74
- ) {
75
- submittedByUserId =
76
- requestParams.submittedByUserId ||
77
- _izContext.correlationIds.get(coreConsts.SUBMITTED_BY_USER_ID);
78
-
79
- targetIdentifiers = requestParams.targetIdentifiers;
80
-
81
- if (!targetIdentifiers && submittedByUserId) {
82
- targetIdentifiers = { submittedByUserId };
83
- }
84
-
85
- if (!submittedByUserId) errorsFound.push('Not have submittedByUserId');
86
- if (objectSchema.hasOwnProperty('belongTo') && !targetIdentifiers)
87
- errorsFound.push('not have targetIdentifiers');
88
-
89
- if (targetIdentifiers) {
90
- if (!targetIdentifiers.submittedByUserId && submittedByUserId) {
91
- targetIdentifiers.submittedByUserId = submittedByUserId;
92
- }
93
-
94
- if (Array.isArray(objectSchema.identifiers)) {
95
- for (const identifier of objectSchema.identifiers) {
96
- if (identifier.fieldName) {
97
- if (targetIdentifiers[identifier.fieldName] === undefined) {
98
- targetIdentifiers[identifier.fieldName] = null;
99
- }
100
- } else if (Array.isArray(identifier.fieldNames)) {
101
- for (const fn of identifier.fieldNames) {
102
- if (targetIdentifiers[fn] === undefined) {
103
- targetIdentifiers[fn] = null;
104
- }
105
- }
106
- } else if (identifier.name) {
107
- if (targetIdentifiers[identifier.name] === undefined) {
108
- targetIdentifiers[identifier.name] = null;
109
- }
110
- }
111
- }
112
- }
113
-
114
- requestParams.targetIdentifiers = targetIdentifiers;
115
- }
116
-
117
- _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] Identity & Target Context Resolved:`, {
118
- submittedByUserId: requestParams.submittedByUserId,
119
- targetIdentifiers: requestParams.targetIdentifiers,
120
- belongTo: objectSchema.belongTo,
121
- generatedBy: objectSchema.generatedBy
122
- });
123
- } else if (objectSchema.generatedBy === 'searchResultGenerated') {
124
- throw new NoRetryError(
125
- 'error searchResultGenerated should not happen here'
126
- );
127
- }
128
-
129
- return { objType, objectSchema, targetIdentifiers };
130
- }
131
-
132
- /**
133
- * Resolves fromRequiredOnCreate fields and generates identifiers
134
- * @param {Object} _izContext - Izara context object
135
- * @param {Object} requestParams - Request parameters
136
- * @param {Object} objectSchema - Base object schema
137
- * @param {Object} objType - Object type
138
- * @param {Object} targetIdentifiers - Target identifiers
139
- * @param {Array<string>} errorsFound - Error list
140
- * @returns {Promise<{ objectSchemas: Object, createDataDetails: Object }>}
141
- */
142
- async function resolveAndGenerateIdentifiers(
143
- _izContext,
144
- requestParams,
145
- objectSchema,
146
- objType,
147
- targetIdentifiers,
148
- errorsFound
149
- ) {
150
- const objectSchemas =
151
- uploadUseCase.generateObjectSchemaForCombineFieldNames(
152
- _izContext,
153
- objectSchema
154
- );
155
- _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] objectSchemas:`, objectSchemas);
156
-
157
- const createDataDetails = await createDataDetailsLib(
158
- _izContext,
159
- objectSchemas
160
- );
161
- _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] createDataDetails:`, createDataDetails);
162
-
163
- if (requestParams.relationships?.length > 0) {
164
- //(<beforeValidateRelationships>)
165
- //(</beforeValidateRelationships>)
166
- }
167
-
168
- errorsFound.push(
169
- ...(await createNodeLib.validateRequiredOnCreateLinks(
170
- _izContext,
171
- objType,
172
- requestParams.relationships
173
- ))
174
- );
175
- _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] errorsFound:`, errorsFound);
176
-
177
- // ── Resolve fromRequiredOnCreate fields ──
178
- if (objectSchemas.fieldNames) {
179
- if (!requestParams.fieldNames) requestParams.fieldNames = {};
180
- for (const [fieldName, val] of Object.entries(objectSchemas.fieldNames)) {
181
- if (val.fromRequiredOnCreate && requestParams.fieldNames[fieldName] === undefined) {
182
- const fromConfig = val.fromRequiredOnCreate;
183
- const sourceField = fromConfig.fieldName || fieldName;
184
- if (fromConfig.belongToObjType === true && targetIdentifiers) {
185
- const targetValue =
186
- targetIdentifiers[sourceField] !== undefined
187
- ? targetIdentifiers[sourceField]
188
- : Object.values(targetIdentifiers)[0];
189
- requestParams.fieldNames[fieldName] = targetValue;
190
- } else if (fromConfig.relType && requestParams.relationships?.length > 0) {
191
- const matchedRel = requestParams.relationships.find(
192
- (rel) =>
193
- rel.relType?.serviceTag === fromConfig.relType.serviceTag &&
194
- rel.relType?.relationshipTag === fromConfig.relType.relationshipTag
195
- );
196
- if (matchedRel?.targetIdentifiers?.[sourceField] !== undefined) {
197
- requestParams.fieldNames[fieldName] = matchedRel.targetIdentifiers[sourceField];
198
- }
199
- }
200
- }
201
- }
202
- }
203
-
204
- // ── Resolve identifiers ──
205
- let errors;
206
- const identifiers = objectSchemas.identifiers;
207
- let optionalOnCreateIdentifiers;
208
-
209
- if (
210
- identifiers.length === 1 &&
211
- !identifiers[0].hasOwnProperty('fieldNames')
212
- ) {
213
- [requestParams, errors] = await createIdentifiersByUseCase(
214
- _izContext,
215
- requestParams,
216
- objectSchemas,
217
- identifiers[0],
218
- optionalOnCreateIdentifiers
219
- );
220
- errorsFound.push(...errors);
221
- } else if (identifiers.length > 1) {
222
- for (const identifier of identifiers) {
223
- [requestParams, errors] = await createIdentifiersByUseCase(
224
- _izContext,
225
- requestParams,
226
- objectSchemas,
227
- identifier,
228
- optionalOnCreateIdentifiers
229
- );
230
- errorsFound.push(...errors);
231
- }
232
- }
233
-
234
- return { objectSchemas, createDataDetails };
235
- }
236
-
237
- /**
238
- * Validates request field names against schema
239
- * @param {Object} requestParams - Request parameters
240
- * @param {Object} objectSchemas - Combined schema
241
- * @param {Array<string>} errorsFound - Error list
242
- */
243
- function validateFieldNames(requestParams, objectSchemas, errorsFound) {
244
- const listOfRequiredOnCreate = [];
245
- const listOfOptionalOnCreate = [];
246
-
247
- for (const [key, val] of Object.entries(objectSchemas.fieldNames)) {
248
- if (
249
- val.randomOnCreate === true ||
250
- val.requiredOnCreate === true ||
251
- val.fromRequiredOnCreate ||
252
- val.hashOnCreate?.length
253
- ) {
254
- listOfRequiredOnCreate.push(key);
255
- }
256
- if (val.requiredOnCreate === false && val.optionalOnCreate === true) {
257
- listOfOptionalOnCreate.push(key);
258
- }
259
- }
260
-
261
- for (const fieldName of Object.keys(requestParams.fieldNames)) {
262
- if (
263
- !listOfRequiredOnCreate.includes(fieldName) &&
264
- !listOfOptionalOnCreate.includes(fieldName)
265
- ) {
266
- errorsFound.push('[invalid] over fieldNames create object');
267
- }
268
- if (errorsFound.length > 0) {
269
- _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] HaveError:`, errorsFound);
270
- break;
271
- }
272
- }
273
- }
274
-
275
58
  // ── Main Entry Function ───────────────────────────────────────────────────────
276
59
 
277
60
  /**
@@ -284,15 +67,18 @@ function validateFieldNames(requestParams, objectSchemas, errorsFound) {
284
67
  export default async function <%- flowTag %>(
285
68
  _izContext,
286
69
  requestParams,
287
- callingFlowConfig = {},
70
+ callingFlowConfig = {}
288
71
  //(<additionalParams>)
289
72
  //(</additionalParams>)
290
73
  ) {
291
74
  try {
292
- _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] createMain:`, {
293
- requestParams,
294
- callingFlowConfig
295
- });
75
+ _izContext.logger.debug(
76
+ `[${process.env.iz_serviceTag}:<%- flowTag %>] createMain:`,
77
+ {
78
+ requestParams,
79
+ callingFlowConfig
80
+ }
81
+ );
296
82
 
297
83
  const errorsFound = [];
298
84
 
@@ -323,7 +109,7 @@ export default async function <%- flowTag %>(
323
109
  }
324
110
 
325
111
  // Step 3: Validate FieldNames
326
- validateFieldNames(requestParams, objectSchemas, errorsFound);
112
+ validateFieldNames(_izContext, requestParams, objectSchemas, errorsFound);
327
113
 
328
114
  if (errorsFound.length > 0) {
329
115
  return await <%- flowTag %>LogicalLib(
@@ -412,111 +198,112 @@ export default async function <%- flowTag %>(
412
198
 
413
199
  // ── Optional phase extension point ────────────────────────────────────────
414
200
  <%_
415
- const groupedByObjType = [];
201
+ const beforeHooksByObjType = (plan?.beforeHooks || []).reduce((acc, hook) => {
202
+ const key = hook?.objType?.objectType;
203
+ if (!key) return acc;
204
+ if (!acc[key]) acc[key] = [];
205
+ acc[key].push(hook);
206
+ return acc;
207
+ }, {});
416
208
  _%>
417
- <%_ Object.entries(groupedByObjType).forEach(([objectType, configs]) => { _%>
209
+ <%_ Object.entries(beforeHooksByObjType).forEach(([objectType, configs]) => { _%>
418
210
  <%_
419
- const hasOwnTopic = configs.some(c => c.invocationType === 'ownTopic');
420
- const hasLambdaSyncInv = configs.some(c => c.invocationType === 'lambdaSyncInv');
421
- _%>
211
+ const hasOwnTopic = configs.some(c => c?.generatedCodeConfig?.invocationType === 'ownTopic' || c?.event?.includes('ownTopic'));
212
+ const hasLambdaSyncInv = configs.some(c => c?.generatedCodeConfig?.invocationType === 'lambdaSyncInv' || c?.event?.includes('lambdaSyncInv'));
213
+ _%>
422
214
  if (requestParams.objectType === '<%= objectType %>') {
423
215
  <%_ if (hasLambdaSyncInv) { _%>
424
- const lambdaSyncInvResults = await Promise.all([
425
- <%_ configs.filter(c => c.invocationType === 'lambdaSyncInv').forEach((config, index, arr) => { _%>
426
- // lambdaSyncInv <%= config.flowTag %>
427
- lambda
428
- .invokeSync(
216
+ const lambdaSyncInvResults = [];
217
+ <%_ for (const config of configs.filter(c => c?.generatedCodeConfig?.invocationType === 'lambdaSyncInv' || c?.event?.includes('lambdaSyncInv'))) { _%>
218
+ try {
219
+ const returnValue = await lambda.invokeSync(
220
+ _izContext,
221
+ await lambdaSharedLib.lambdaFunctionName(
429
222
  _izContext,
430
- await lambdaSharedLib.lambdaFunctionName(
431
- _izContext,
432
- 'Process<%= config.flowTag %>HdrInv'
433
- ),
434
- { requestParams, callingFlowConfig }
435
- )
436
- .then((returnValue) => ({
437
- flowTag: '<%= config.flowTag %>',
438
- returnValue
439
- })) /*__EJS_COMMA_14__*/
440
- // lambdaSyncInv <%= config.flowTag %>
441
- <%_ }) _%>
442
- ]);
223
+ '<%= config.flowTag %>'
224
+ ),
225
+ {
226
+ requestParams: {
227
+ objType,
228
+ fieldNames: requestParams.fieldNames,
229
+ relationships: requestParams.relationships || [],
230
+ targetIdentifiers,
231
+ submittedByUserId: requestParams.submittedByUserId
232
+ },
233
+ callingFlowConfig
234
+ }
235
+ );
236
+ lambdaSyncInvResults.push({
237
+ flowTag: '<%= config.flowTag %>',
238
+ returnValue
239
+ });
240
+ if (returnValue?.errorsFound?.length > 0) {
241
+ errorsFound.push(...returnValue.errorsFound);
242
+ } else if (returnValue?.status === 'error') {
243
+ errorsFound.push('Error from <%= config.flowTag %>');
244
+ } else {
245
+ if (returnValue?.fieldNames && requestParams?.fieldNames) {
246
+ Object.assign(requestParams.fieldNames, returnValue.fieldNames);
247
+ }
248
+ if (returnValue?.relationships && requestParams) {
249
+ requestParams.relationships = returnValue.relationships;
250
+ }
251
+ }
252
+ } catch (hookErr) {
253
+ _izContext.logger.error(
254
+ '[<%- flowTag %>] Sync hook <%= config.flowTag %> error:',
255
+ hookErr
256
+ );
257
+ errorsFound.push(hookErr.message || 'Hook <%= config.flowTag %> failed');
258
+ }
259
+ <%_ } _%>
443
260
 
261
+ if (errorsFound.length > 0) {
262
+ return await <%- flowTag %>LogicalLib(
263
+ _izContext,
264
+ requestParams,
265
+ callingFlowConfig,
266
+ errorsFound
267
+ );
268
+ }
444
269
  <%_ } _%>
445
270
 
446
271
  //(<afterBeforeLogical_<%= objectType %>>)
447
272
  //(</afterBeforeLogical_<%= objectType %>>)
448
273
 
449
274
  <%_ if (hasOwnTopic) { _%>
450
- // ── ownTopic (async — create awaitingSteps and then publish) ──────────────
451
- const awaitingMultipleStepIds = [];
452
- const recordMsgs = [];
453
-
454
- <%_ configs.filter(c => c.invocationType === 'ownTopic').forEach(config => { _%>
455
- // ownTopic <%= config.flowTag %>
456
- awaitingMultipleStepIds.push({
457
- awaitingStepId: await asyncFlowSharedLib.createAwaitingStepId(
458
- hash(objInstanceFull.identifiers),
459
- 'logical_<%= objectType %>_<%= config.flowTag.charAt(0).toUpperCase() + config.flowTag.slice(1) %>'
460
- ),
461
- additionalAttributes: {}
462
- });
463
-
464
- recordMsgs.push({
465
- msg: callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
466
- requestParams,
275
+ // ── ownTopic (async — dispatch to before-hook and await callback) ──────────
276
+ <%_ configs.filter(c => c?.generatedCodeConfig?.invocationType === 'ownTopic' || c?.event?.includes('ownTopic')).forEach(config => { _%>
277
+ const hookMsg_<%= config.flowTag %> =
278
+ callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
279
+ {
280
+ objType,
281
+ fieldNames: requestParams.fieldNames,
282
+ relationships: requestParams.relationships || [],
283
+ targetIdentifiers,
284
+ submittedByUserId: requestParams.submittedByUserId
285
+ },
467
286
  callingFlowSharedLib.addParentCallingFlowConfig(
468
287
  callingFlowConfig,
469
288
  callingFlowSharedLib.createCallingFlowConfig(
470
- //(<callingFlowProperties_<%= config.flowTag %>>)
471
289
  await lambdaSharedLib.lambdaFunctionName(
472
290
  _izContext,
473
- '<%= flowTag.toLowerCase() %>Complete'
291
+ '<%- flowTag %>BeforeHookCallbackHdrSqs'
474
292
  ),
475
- {}
476
- //(</callingFlowProperties_<%= config.flowTag %>>)
293
+ {
294
+ originalRequestParams: {
295
+ ...requestParams,
296
+ objType,
297
+ targetIdentifiers
298
+ },
299
+ callingFlowConfig
300
+ }
477
301
  )
478
302
  )
479
- ),
480
- flowTag: '<%= config.flowTag.charAt(0).toUpperCase() + config.flowTag.slice(1) %>'
481
- });
482
- <%_ }) _%>
483
-
484
- <%_ if (hasLambdaSyncInv) { _%>
485
- // ── Add lambdaSyncInv results to awaitingSteps ────────────────────────
486
- for (const syncResult of lambdaSyncInvResults) {
487
- awaitingMultipleStepIds.push({
488
- awaitingStepId: await asyncFlowSharedLib.createAwaitingStepId(
489
- hash(objInstanceFull.identifiers),
490
- 'logical_<%= objectType %>_' + syncResult.flowTag
491
- ),
492
- additionalAttributes: {
493
- complete: true,
494
- errorsFound: [],
495
- returnValue: syncResult.returnValue
496
- }
497
- });
498
- }
499
- <%_ } _%>
500
-
501
- await asyncFlowSharedLib.createAwaitingMultipleSteps(
502
- _izContext,
503
- asyncFlowSharedLib.createPendingStepId(
504
- _izContext.uniqueRequestId,
505
- 'logical_<%= objectType %>'
506
- ),
507
- awaitingMultipleStepIds,
508
- {
509
- additionalAttributes: {
510
- callingFlowConfig
511
- }
512
- }
513
- );
514
-
515
- //(<beforePublish_<%= objectType %>>)
516
- //(</beforePublish_<%= objectType %>>)
303
+ );
517
304
 
518
- for (const recordMsg of recordMsgs) {
519
- const messageAttributes = sns.createStringMessageAttributes(
305
+ const messageAttributes_<%= config.flowTag %> =
306
+ sns.createStringMessageAttributes(
520
307
  _izContext,
521
308
  callingFlowSharedLib.addCallingFlowToSnsResponseMessageAttributes(
522
309
  callingFlowConfig,
@@ -524,32 +311,36 @@ export default async function <%- flowTag %>(
524
311
  )
525
312
  );
526
313
 
527
- const topicArn = snsSharedLib.snsTopicArnByFlowSchema(
528
- _izContext,
529
- `${recordMsg.flowTag}_In`
530
- );
314
+ const topicArn_<%= config.flowTag %> = snsSharedLib.snsTopicArnByFlowSchema(
315
+ _izContext,
316
+ '<%= config.flowTag %>_In'
317
+ );
531
318
 
532
- await sns.publishAsync(_izContext, {
533
- Message: JSON.stringify(recordMsg.msg),
534
- MessageAttributes: messageAttributes,
535
- TopicArn: topicArn
536
- });
537
- }
319
+ _izContext.logger.debug(
320
+ `[${process.env.iz_serviceTag}:<%- flowTag %>] Dispatching to BeforeHook:`,
321
+ {
322
+ topicArn: topicArn_<%= config.flowTag %>,
323
+ flowTag: '<%= config.flowTag %>'
324
+ }
325
+ );
538
326
 
539
- return 'complete logical <%= objectType %>';
327
+ await sns.publishAsync(_izContext, {
328
+ Message: JSON.stringify(hookMsg_<%= config.flowTag %>),
329
+ MessageAttributes: messageAttributes_<%= config.flowTag %>,
330
+ TopicArn: topicArn_<%= config.flowTag %>
331
+ });
332
+ <%_ }) _%>
540
333
 
334
+ return {
335
+ status: 'pending',
336
+ message: 'Dispatched to BeforeHook'
337
+ };
541
338
  <%_ } else { _%>
542
- // ── lambdaSyncInv only — collect results and proceed to createLogicalLib ────────────
543
- const phaseResults = Object.fromEntries(
544
- lambdaSyncInvResults.map(({ flowTag: tag, returnValue }) => [tag, returnValue])
545
- );
546
-
547
339
  return await <%- flowTag %>LogicalLib(
548
340
  _izContext,
549
341
  requestParams,
550
342
  callingFlowConfig,
551
- errorsFound,
552
- phaseResults
343
+ errorsFound
553
344
  );
554
345
  <%_ } _%>
555
346
  }
@@ -565,7 +356,10 @@ export default async function <%- flowTag %>(
565
356
  errorsFound
566
357
  );
567
358
  } catch (err) {
568
- _izContext.logger.error(`[${process.env.iz_serviceTag}:<%- flowTag %>] error:`, err);
359
+ _izContext.logger.error(
360
+ `[${process.env.iz_serviceTag}:<%- flowTag %>] error:`,
361
+ err
362
+ );
569
363
  throw err;
570
364
  }
571
365
  }