@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.
@@ -12,10 +12,7 @@ import {
12
12
  } from '../custom/customFlows.js';
13
13
  import { hasSystemWebSocket } from '../system/emitSystemWebSocketArtifacts.js';
14
14
  import { rbacFlowTag } from '../rbac/rbacFlowTag.js';
15
- import {
16
- CRUD_ACTIONS,
17
- createCrudActionPlans
18
- } from '../crud/crudActionPlan.js';
15
+ import { CRUD_ACTIONS, createCrudActionPlans } from '../crud/crudActionPlan.js';
19
16
 
20
17
  const TEMPLATE_URL = new URL('./templates/', import.meta.url);
21
18
  const RESOURCE_ROOT = 'resource/sls_yaml/generatedCode/source';
@@ -208,7 +205,7 @@ function createResourceState({ objects, relationships, flows }) {
208
205
  const crud = objects.some(isCrudObject);
209
206
  const selfRbac = objects.some(hasSelfRbacAddOn);
210
207
  const rbac = objects.some(hasSelfRbacAddOn);
211
- const crudActionPlans = createCrudActionPlans(objects);
208
+ const crudActionPlans = createCrudActionPlans(objects, flows);
212
209
 
213
210
  const crudOwnTopics = crud ? [...CRUD_ACTIONS] : [];
214
211
  const crudSqsQueues = [];
@@ -218,21 +215,26 @@ function createResourceState({ objects, relationships, flows }) {
218
215
  if (plan.hasCreateNodeCallback) {
219
216
  crudSqsQueues.push(`${action}NodeCallbackHdrSqs`);
220
217
  }
218
+ if (plan.hasBeforeHookCallback) {
219
+ crudSqsQueues.push(`${action}BeforeHookCallbackHdrSqs`);
220
+ }
221
+ if (plan.hasAfterHookCallback) {
222
+ crudSqsQueues.push(`${action}AfterHookCallbackHdrSqs`);
223
+ }
221
224
  if (plan.hasComplete) {
222
225
  crudSqsQueues.push(`${action}CompleteHdrSqs`);
223
226
  }
224
227
  }
225
228
  }
226
229
 
227
- const relationshipOwnTopics = relationships.length > 0
228
- ? [...RELATIONSHIP_ACTIONS]
229
- : [];
230
- const relationshipSqsQueues = relationships.length > 0
231
- ? RELATIONSHIP_ACTIONS.map((action) => `${action}CompleteHdrSqs`)
232
- : [];
233
- const relationshipDsqQueues = relationships.length > 0
234
- ? ['GetRelationshipHdrDsq']
235
- : [];
230
+ const relationshipOwnTopics =
231
+ relationships.length > 0 ? [...RELATIONSHIP_ACTIONS] : [];
232
+ const relationshipSqsQueues =
233
+ relationships.length > 0
234
+ ? RELATIONSHIP_ACTIONS.map((action) => `${action}CompleteHdrSqs`)
235
+ : [];
236
+ const relationshipDsqQueues =
237
+ relationships.length > 0 ? ['GetRelationshipHdrDsq'] : [];
236
238
 
237
239
  const rbacOwnTopics = [];
238
240
  const rbacSqsQueues = [];
@@ -308,9 +310,7 @@ function createResourceState({ objects, relationships, flows }) {
308
310
  const systemOwnTopics = ['ProcessLogical', 'FindData'];
309
311
  const systemSqsQueues = [
310
312
  'PaginateProcessLogicalHdrSqs',
311
- ...(websocket
312
- ? ['WebSocketCompleteHdrSqs', 'RegisterCompleteHdrSqs']
313
- : [])
313
+ ...(websocket ? ['WebSocketCompleteHdrSqs', 'RegisterCompleteHdrSqs'] : [])
314
314
  ];
315
315
  const systemDsqQueues = ['PaginateProcessLogicalHdrDsq'];
316
316
 
@@ -348,9 +348,7 @@ function createResourceState({ objects, relationships, flows }) {
348
348
  ...flowExtTopicSteps(flows).map(({ flow }) =>
349
349
  customFlowRoleName(flow.flowTag)
350
350
  ),
351
- ...flowDsqSteps(flows).map(({ flow }) =>
352
- customFlowRoleName(flow.flowTag)
353
- )
351
+ ...flowDsqSteps(flows).map(({ flow }) => customFlowRoleName(flow.flowTag))
354
352
  ])
355
353
  ];
356
354
  const webSocketRoles = new Set();
@@ -400,9 +398,9 @@ function createResourceState({ objects, relationships, flows }) {
400
398
  const outputTopicStr =
401
399
  typeof flow.outputTopic === 'string' ? flow.outputTopic : null;
402
400
  const topicName = outputTopicStr
403
- ? (outputTopicStr.startsWith('Out')
401
+ ? outputTopicStr.startsWith('Out')
404
402
  ? outputTopicStr
405
- : `Out${upperFirst(outputTopicStr)}`)
403
+ : `Out${upperFirst(outputTopicStr)}`
406
404
  : flow.s3Subscription?.topicName || 'OutCreate';
407
405
  const queueName =
408
406
  flow.s3Subscription?.queueName || `${tag}ReservedLimitHdrSqs`;
@@ -555,9 +553,7 @@ async function renderResourceGroup({
555
553
  if (!hasResources) return '';
556
554
 
557
555
  const chunks = await Promise.all([
558
- ...ownTopics.map((queueName) =>
559
- render('ResourceYaml.ejs', { queueName })
560
- ),
556
+ ...ownTopics.map((queueName) => render('ResourceYaml.ejs', { queueName })),
561
557
  ...sqsQueues.map((queueName) =>
562
558
  render('ResourceSqsYaml.ejs', { queueName })
563
559
  ),
@@ -571,13 +567,12 @@ async function renderResourceGroup({
571
567
  )
572
568
  );
573
569
  const s3Subs = await Promise.all(
574
- s3Subscriptions.map(
575
- ({ subscriptionName, topicName, queueName }) =>
576
- render('S3Subscription_Yaml.ejs', {
577
- subscriptionName,
578
- topicName,
579
- queueName
580
- })
570
+ s3Subscriptions.map(({ subscriptionName, topicName, queueName }) =>
571
+ render('S3Subscription_Yaml.ejs', {
572
+ subscriptionName,
573
+ topicName,
574
+ queueName
575
+ })
581
576
  )
582
577
  );
583
578
  const parts = [chunks.join('\n')];
@@ -631,7 +626,9 @@ async function renderSystemInSqs(state) {
631
626
  async function renderOut(state) {
632
627
  const body = (
633
628
  await Promise.all(
634
- state.outTopics.map((topicName) => render('FlowOut_Yaml.ejs', { topicName }))
629
+ state.outTopics.map((topicName) =>
630
+ render('FlowOut_Yaml.ejs', { topicName })
631
+ )
635
632
  )
636
633
  ).join('\n');
637
634
  return `Resources:\n${indentYaml(body, 2)}`;
@@ -700,15 +697,11 @@ function roleStatements(state, roleName) {
700
697
  if (roleNeedsSchemaRead(state, roleName)) {
701
698
  statements.push({
702
699
  action: ['s3:GetObject'],
703
- resource: [
704
- 'arn:aws:s3:::${self:custom.iz_serviceSchemaBucketName}/*'
705
- ]
700
+ resource: ['arn:aws:s3:::${self:custom.iz_serviceSchemaBucketName}/*']
706
701
  });
707
702
  statements.push({
708
703
  action: ['s3:ListBucket'],
709
- resource: [
710
- 'arn:aws:s3:::${self:custom.iz_serviceSchemaBucketName}'
711
- ]
704
+ resource: ['arn:aws:s3:::${self:custom.iz_serviceSchemaBucketName}']
712
705
  });
713
706
  }
714
707
  addStatement(statements, dynamoActionsForRole(roleName), [
@@ -736,7 +729,10 @@ function roleStatements(state, roleName) {
736
729
  addStatement(
737
730
  statements,
738
731
  ['lambda:InvokeFunction'],
739
- roleExternalLambdaArns(state, roleName)
732
+ [
733
+ ...roleExternalLambdaArns(state, roleName),
734
+ ...roleHookLambdaArns(state, roleName)
735
+ ]
740
736
  );
741
737
  if (state.webSocketRoles.has(roleName)) {
742
738
  statements.push({
@@ -807,7 +803,8 @@ function roleTableNames(state, roleName) {
807
803
  const tables = [];
808
804
  if (includesEvent(flow, 'ownTopic') || includesEvent(flow, 's3'))
809
805
  tables.push('WebSocketTask');
810
- if (includesEvent(flow, 's3')) tables.push('UserUploadRecords', 'ReservedDataMain');
806
+ if (includesEvent(flow, 's3'))
807
+ tables.push('UserUploadRecords', 'ReservedDataMain');
811
808
  if (flow.statusType === 'storedCache') {
812
809
  const object = state.objectTablesByType.get(flow.objType?.objectType);
813
810
  if (object) tables.push(object);
@@ -817,7 +814,12 @@ function roleTableNames(state, roleName) {
817
814
 
818
815
  function dynamoActionsForRole(roleName) {
819
816
  if (roleName === 'ProcFindDataRole')
820
- return ['dynamodb:GetItem', 'dynamodb:Query', 'dynamodb:UpdateItem'];
817
+ return [
818
+ 'dynamodb:GetItem',
819
+ 'dynamodb:PutItem',
820
+ 'dynamodb:Query',
821
+ 'dynamodb:UpdateItem'
822
+ ];
821
823
  if (roleName === 'WebSocketMainRole')
822
824
  return ['dynamodb:DeleteItem', 'dynamodb:PutItem', 'dynamodb:Query'];
823
825
  if (roleName === 'FlowRbacRole' || roleName === 'FlowObjectsRole')
@@ -847,12 +849,10 @@ function roleQueueNames(state, roleName) {
847
849
  if (!plan.outputTopic) return [];
848
850
  return [
849
851
  `${action}HdrSqs`,
850
- ...(plan.hasCreateNodeCallback
851
- ? [`${action}NodeCallbackHdrSqs`]
852
- : []),
853
- ...(plan.hasRbacCallback
854
- ? [`${action}RbacCallbackHdrSqs`]
855
- : []),
852
+ ...(plan.hasCreateNodeCallback ? [`${action}NodeCallbackHdrSqs`] : []),
853
+ ...(plan.hasBeforeHookCallback ? [`${action}BeforeHookCallbackHdrSqs`] : []),
854
+ ...(plan.hasAfterHookCallback ? [`${action}AfterHookCallbackHdrSqs`] : []),
855
+ ...(plan.hasRbacCallback ? [`${action}RbacCallbackHdrSqs`] : []),
856
856
  ...(plan.hasComplete ? [`${action}CompleteHdrSqs`] : [])
857
857
  ];
858
858
  });
@@ -923,9 +923,13 @@ function roleDlqQueueNames(state, roleName) {
923
923
 
924
924
  function roleTopicNames(state, roleName) {
925
925
  if (roleName === 'ProcFindDataRole')
926
- return state.outTopics.filter((topic) => topic === 'FindData').map((t) => `${t}_Out`);
926
+ return state.outTopics
927
+ .filter((topic) => topic === 'FindData')
928
+ .map((t) => `${t}_Out`);
927
929
  if (roleName === 'FlowObjectsRole') {
928
- const actions = state.outTopics.filter((topic) => CRUD_ACTIONS.includes(topic));
930
+ const actions = state.outTopics.filter((topic) =>
931
+ CRUD_ACTIONS.includes(topic)
932
+ );
929
933
  const topics = [];
930
934
  for (const action of actions) {
931
935
  if (action === 'Get') {
@@ -937,10 +941,29 @@ function roleTopicNames(state, roleName) {
937
941
  if (state.rbac) {
938
942
  topics.push('ValidatorRbac_In');
939
943
  }
944
+ for (const action of ['Create', 'Update', 'Delete']) {
945
+ const plan = state.crudActionPlans?.[action];
946
+ if (plan?.hasBeforeHookAsync) {
947
+ for (const hook of plan.beforeHooks) {
948
+ if (hook?.generatedCodeConfig?.invocationType === 'ownTopic') {
949
+ topics.push(`${upperFirst(hook.flowTag)}_In`);
950
+ }
951
+ }
952
+ }
953
+ if (plan?.hasAfterHookAsync) {
954
+ for (const hook of plan.afterHooks) {
955
+ if (hook?.generatedCodeConfig?.invocationType === 'ownTopic') {
956
+ topics.push(`${upperFirst(hook.flowTag)}_In`);
957
+ }
958
+ }
959
+ }
960
+ }
940
961
  return topics;
941
962
  }
942
963
  if (roleName === 'FlowRelationshipRole') {
943
- const actions = state.outTopics.filter((topic) => RELATIONSHIP_ACTIONS.includes(topic));
964
+ const actions = state.outTopics.filter((topic) =>
965
+ RELATIONSHIP_ACTIONS.includes(topic)
966
+ );
944
967
  const topics = [];
945
968
  for (const action of actions) {
946
969
  if (action === 'GetRelationship') {
@@ -955,7 +978,9 @@ function roleTopicNames(state, roleName) {
955
978
  return topics;
956
979
  }
957
980
  if (roleName === 'FlowRbacRole') {
958
- const actions = state.outTopics.filter((topic) => RBAC_ACTIONS.includes(topic));
981
+ const actions = state.outTopics.filter((topic) =>
982
+ RBAC_ACTIONS.includes(topic)
983
+ );
959
984
  const topics = [];
960
985
  for (const action of actions) {
961
986
  if (action.startsWith('List')) {
@@ -1090,6 +1115,37 @@ function roleExternalLambdaArns(state, roleName) {
1090
1115
  return [];
1091
1116
  }
1092
1117
 
1118
+ function roleHookLambdaArns(state, roleName) {
1119
+ if (roleName !== 'FlowObjectsRole') {
1120
+ return [];
1121
+ }
1122
+ const hookLambdas = [];
1123
+ for (const action of ['Create', 'Update', 'Delete']) {
1124
+ const plan = state.crudActionPlans?.[action];
1125
+ if (plan?.hasBeforeHookSync) {
1126
+ for (const hook of plan.beforeHooks) {
1127
+ if (hook?.generatedCodeConfig?.invocationType === 'lambdaSyncInv') {
1128
+ const hookTag = upperFirst(hook.flowTag);
1129
+ hookLambdas.push(
1130
+ `arn:aws:lambda:\${self:custom.iz_region}:\${self:custom.iz_accountId}:function:\${self:custom.iz_resourcePrefix}${hookTag}*`
1131
+ );
1132
+ }
1133
+ }
1134
+ }
1135
+ if (plan?.hasAfterHookSync) {
1136
+ for (const hook of plan.afterHooks) {
1137
+ if (hook?.generatedCodeConfig?.invocationType === 'lambdaSyncInv') {
1138
+ const hookTag = upperFirst(hook.flowTag);
1139
+ hookLambdas.push(
1140
+ `arn:aws:lambda:\${self:custom.iz_region}:\${self:custom.iz_accountId}:function:\${self:custom.iz_resourcePrefix}${hookTag}*`
1141
+ );
1142
+ }
1143
+ }
1144
+ }
1145
+ }
1146
+ return [...new Set(hookLambdas)];
1147
+ }
1148
+
1093
1149
  function queueArns(queueNames) {
1094
1150
  return [...new Set(queueNames)]
1095
1151
  .sort()
@@ -1121,8 +1177,7 @@ function collectTables(schemas) {
1121
1177
  : [];
1122
1178
  const pkIdentifier = identifiers.find(
1123
1179
  (identifier) =>
1124
- identifier.type === 'partitionKey' ||
1125
- identifier.type === 'identifier'
1180
+ identifier.type === 'partitionKey' || identifier.type === 'identifier'
1126
1181
  );
1127
1182
  const skIdentifier = identifiers.find(
1128
1183
  (identifier) => identifier.type === 'sortKey'
@@ -1237,9 +1292,7 @@ function hasRbacAddOn(object) {
1237
1292
  */
1238
1293
  function rbacFlowQueueNames(state) {
1239
1294
  const flowTags = [
1240
- ...new Set(
1241
- (state.objects ?? []).filter(hasRbacAddOn).map(rbacFlowTag)
1242
- )
1295
+ ...new Set((state.objects ?? []).filter(hasRbacAddOn).map(rbacFlowTag))
1243
1296
  ];
1244
1297
  return flowTags.map((flowTag) => `${flowTag}HdrSqs`);
1245
1298
  }