@izara_project/izara-core-generate-service-code 1.0.75 → 1.0.76

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@izara_project/izara-core-generate-service-code",
3
- "version": "1.0.75",
3
+ "version": "1.0.76",
4
4
  "description": "Code for locally generating per service files",
5
5
  "homepage": "https://bitbucket.org/izara-core-support-services/izara-core-support-services-generate-service-code#readme",
6
6
  "repository": {
@@ -159,41 +159,47 @@ export async function resolveExtendedObjectSchemas(
159
159
  }
160
160
  }
161
161
 
162
- /*
163
162
  if (
164
163
  currentSchema.hasOwnProperty('belongTo') &&
165
- currentSchema.belongTo &&
166
- currentSchema.belongTo.serviceTag &&
167
- currentSchema.belongTo.objectType
164
+ currentSchema.belongTo
168
165
  ) {
169
- try {
170
- Logger.debug(
171
- `[DEBUG] [resolveExtendedObjectSchemas] Fetching belongTo schema for objectType=${currentSchema.objectType}`,
172
- { belongTo: currentSchema.belongTo }
173
- );
174
- const belongToObjType = {
175
- serviceTag: currentSchema.belongTo.serviceTag,
176
- objectType: currentSchema.belongTo.objectType
177
- };
178
- const belongToSchema = await getObjectSchema.getObjSchemaS3(
179
- { logger: Logger },
180
- belongToObjType,
181
- false,
182
- bucketName
183
- );
184
- currentSchema.belongToSchema = belongToSchema;
185
- Logger.debug(
186
- `[DEBUG] [resolveExtendedObjectSchemas] Successfully fetched belongTo schema for objectType=${currentSchema.objectType}`,
187
- { belongToObjectType: belongToSchema?.objectType }
188
- );
189
- } catch (error) {
190
- Logger.warn(
191
- `[WARN] [resolveExtendedObjectSchemas] Failed to fetch belongTo schema for objectType=${currentSchema.objectType}`,
192
- { error }
193
- );
166
+ const belongToTarget = Array.isArray(currentSchema.belongTo)
167
+ ? currentSchema.belongTo[0]
168
+ : currentSchema.belongTo;
169
+
170
+ if (
171
+ belongToTarget &&
172
+ belongToTarget.serviceTag &&
173
+ belongToTarget.objectType
174
+ ) {
175
+ try {
176
+ Logger.debug(
177
+ `[DEBUG] [resolveExtendedObjectSchemas] Fetching belongTo schema for objectType=${currentSchema.objectType}`,
178
+ { belongTo: belongToTarget }
179
+ );
180
+ const belongToObjType = {
181
+ serviceTag: belongToTarget.serviceTag,
182
+ objectType: belongToTarget.objectType
183
+ };
184
+ const belongToSchema = await getObjectSchema.getObjSchemaS3(
185
+ { logger: Logger },
186
+ belongToObjType,
187
+ false,
188
+ bucketName
189
+ );
190
+ currentSchema.belongToSchema = belongToSchema;
191
+ Logger.debug(
192
+ `[DEBUG] [resolveExtendedObjectSchemas] Successfully fetched belongTo schema for objectType=${currentSchema.objectType}`,
193
+ { belongToObjectType: belongToSchema?.objectType }
194
+ );
195
+ } catch (error) {
196
+ Logger.warn(
197
+ `[WARN] [resolveExtendedObjectSchemas] Failed to fetch belongTo schema for objectType=${currentSchema.objectType}`,
198
+ { error }
199
+ );
200
+ }
194
201
  }
195
202
  }
196
- */
197
203
 
198
204
  resolvedSchemas.push(currentSchema);
199
205
  }
@@ -210,13 +210,11 @@ export async function emitCoreFunctionArtifacts({ project, objects = [], relatio
210
210
  },
211
211
  {
212
212
  path: `${SRC_ROOT}/InitialSetupConfig.js`,
213
- content: initialSetupConfig,
214
- writeWhenFileExist: false
213
+ content: initialSetupConfig
215
214
  },
216
215
  {
217
216
  path: `${INITIAL_SETUP_ROOT}/InitialSetupConfig.js`,
218
- content: initialSetupConfig,
219
- writeWhenFileExist: false // Don't overwrite the file that dev modifies
217
+ content: initialSetupConfig
220
218
  },
221
219
  {
222
220
  path: `${INITIAL_SETUP_ROOT}/runner.js`,
@@ -49,21 +49,31 @@ const externalServices = {
49
49
  -%>
50
50
  const tableConfigs = {
51
51
  prod: {
52
- Config: {},
52
+ Config: {
53
+ // <#InitialSetupConfig_Prod_Config_TableConfig#>
54
+ // <#/InitialSetupConfig_Prod_Config_TableConfig#>
55
+ },
53
56
  <% dynamoTableNames.forEach(tableName => { -%>
54
- <%= tableName %>: {},
57
+ <%= tableName %>: {
58
+ // <#InitialSetupConfig_Prod_<%= tableName %>_TableConfig#>
59
+ // <#/InitialSetupConfig_Prod_<%= tableName %>_TableConfig#>
60
+ },
55
61
  <% }); -%>
56
62
  // <#InitialSetupConfig_ExtraProdTableConfigs#>
57
63
  // <#/InitialSetupConfig_ExtraProdTableConfigs#>
58
64
  },
59
65
  test: {
60
66
  Config: {
67
+ // <#InitialSetupConfig_Test_Config_TableConfig#>
61
68
  clearDataWhenRefresh: true,
62
69
  rawSource: false
70
+ // <#/InitialSetupConfig_Test_Config_TableConfig#>
63
71
  },
64
72
  <% dynamoTableNames.forEach(tableName => { -%>
65
73
  <%= tableName %>: {
74
+ // <#InitialSetupConfig_Test_<%= tableName %>_TableConfig#>
66
75
  clearDataWhenRefresh: true
76
+ // <#/InitialSetupConfig_Test_<%= tableName %>_TableConfig#>
67
77
  },
68
78
  <% }); -%>
69
79
  // <#InitialSetupConfig_ExtraTestTableConfigs#>
@@ -40,6 +40,8 @@ if (fs.existsSync(configPath)) {
40
40
  );
41
41
  }
42
42
 
43
+ process.env.LOG_LEVEL = process.env.LOG_LEVEL || 'INFO';
44
+
43
45
  // 2. Dynamic import to ensure SDKs use the injected process.env
44
46
  const { default: initialSetupSharedLib } =
45
47
  await import('@izara_project/izara-core-library-initial-setup');
@@ -96,15 +98,15 @@ const commands = {
96
98
  },
97
99
  uploadSchema: async (_izContext) => {
98
100
  const { default: fn } = await import('./commands/uploadSchema.js');
99
- await fn(_izContext);
101
+ await fn(_izContext, initialSetupSharedLib);
100
102
  },
101
103
  'uploadSchema:test': async (_izContext) => {
102
104
  const { default: fn } = await import('./commands/uploadSchema.js');
103
- await fn(_izContext);
105
+ await fn(_izContext, initialSetupSharedLib);
104
106
  },
105
107
  'uploadSchema:prod': async (_izContext) => {
106
108
  const { default: fn } = await import('./commands/uploadSchema.js');
107
- await fn(_izContext);
109
+ await fn(_izContext, initialSetupSharedLib);
108
110
  }
109
111
  };
110
112
 
@@ -1,4 +1,4 @@
1
- import { uploadObjSchema } from '@izara_project/izara-core-library-service-schemas';
1
+ import initialSetupLib from '@izara_project/izara-core-library-initial-setup';
2
2
 
3
3
  const SERVICE_TAG = {
4
4
  TRANSLATIONS: 'Translations',
@@ -18,18 +18,25 @@ const ignoreExternalServices = {
18
18
  };
19
19
  //(</ignoreExternalServices>)
20
20
 
21
- export default async function uploadSchema(_izContext) {
21
+ export default async function uploadSchema(_izContext, initialSetupSharedLib = initialSetupLib) {
22
22
  console.log('======== UploadSchema ========');
23
23
  try {
24
- _izContext.logger.debug('uploadSchema _izContext: ', _izContext);
25
-
26
- await uploadObjSchema.uploadObjectSchemaByUseCase(_izContext, {
24
+ const libToUse = initialSetupSharedLib || initialSetupLib;
25
+ await libToUse.uploadObjectSchema(_izContext, {
27
26
  ignoreExternalServices: ignoreExternalServices
28
27
  });
29
28
  console.log('-------- Finish UploadSchema --------');
30
29
  return 'upload successfully';
31
30
  } catch (err) {
32
- _izContext.logger.error('error LambdaFunction: ', err);
31
+ let errorDetails = err.message || String(err);
32
+ if (errorDetails.includes('errorMessage:')) {
33
+ const match = errorDetails.match(/functionName:\s*([^,]+),errorMessage:(.*)/);
34
+ if (match) {
35
+ errorDetails = `Lambda [${match[1].trim()}] failed: ${match[2].trim()}`;
36
+ }
37
+ }
38
+ _izContext.logger.error(`[uploadSchema] ❌ ${errorDetails}`);
33
39
  throw err;
34
40
  }
35
41
  }
42
+
@@ -1,4 +1,4 @@
1
- import middlewareHandler from '@izara_project/izara-core-library-middleware';
1
+ import { middlewareHandler } from '@izara_project/izara-middleware';
2
2
  import mainHandler from './InitialSetup_Main.js';
3
3
 
4
4
  export const main = middlewareHandler.wrap(
@@ -29,7 +29,9 @@ export function rbacFlowSchemaManagedPaths(objects = []) {
29
29
  (object) =>
30
30
  `app/src/schemas/FlowSchemas/generateCode/FlowRbac/${rbacFlowTag(object)}.js`
31
31
  );
32
- return [...dynamicRbacFlowSchemaPaths, ...rbacPaths];
32
+ const hasSelfRbac = objects.some(_hasSelfRbacAddOn);
33
+ const dynamicPaths = hasSelfRbac ? dynamicRbacFlowSchemaPaths : [];
34
+ return [...dynamicPaths, ...rbacPaths];
33
35
  }
34
36
 
35
37
  export async function emitDynamicRbacFlowSchemas({ objects, serviceTag }) {
@@ -47,9 +49,12 @@ export async function emitDynamicRbacFlowSchemas({ objects, serviceTag }) {
47
49
  );
48
50
  }
49
51
 
50
- const sharedArtifacts = RBAC_FLOW_DEFINITIONS.map(({ flowTag, event }) =>
51
- _artifact(flowTag, _createSharedRbacFlow(flowTag, event))
52
- );
52
+ const hasSelfRbac = objects.some(_hasSelfRbacAddOn);
53
+ const sharedArtifacts = hasSelfRbac
54
+ ? RBAC_FLOW_DEFINITIONS.map(({ flowTag, event }) =>
55
+ _artifact(flowTag, _createSharedRbacFlow(flowTag, event))
56
+ )
57
+ : [];
53
58
  const userArtifacts = rbacObjects.map((object) => {
54
59
  const flowTag = rbacFlowTag(object);
55
60
  return _artifact(
@@ -61,13 +66,23 @@ export async function emitDynamicRbacFlowSchemas({ objects, serviceTag }) {
61
66
  return Promise.all([...sharedArtifacts, ...userArtifacts]);
62
67
  }
63
68
 
64
- function _hasRbacAddOn(object) {
69
+ function _hasSelfRbacAddOn(object) {
65
70
  return (
66
71
  Array.isArray(object?.addOnDataStructure) &&
67
72
  object.addOnDataStructure.some((addOn) => addOn?.type === 'rbac')
68
73
  );
69
74
  }
70
75
 
76
+ function _hasRbacAddOn(object) {
77
+ const selfHasRbac = _hasSelfRbacAddOn(object);
78
+ const belongToHasRbac =
79
+ Array.isArray(object?.belongToSchema?.addOnDataStructure) &&
80
+ object.belongToSchema.addOnDataStructure.some(
81
+ (addOn) => addOn?.type === 'rbac'
82
+ );
83
+ return selfHasRbac || belongToHasRbac;
84
+ }
85
+
71
86
  async function _artifact(flowTag, flow) {
72
87
  return {
73
88
  path: `app/src/schemas/FlowSchemas/generateCode/FlowRbac/${flowTag}.js`,
@@ -21,11 +21,16 @@ export async function emitRbacApplicationArtifacts(objects) {
21
21
  return [];
22
22
  }
23
23
 
24
+ const hasSelfRbac = objects.some(hasSelfRbacAddOn);
24
25
  const handlers = await Promise.all([
25
- createTargetRoleHandler(),
26
- ...LIST_DEFINITIONS.map(createListHandler),
27
- ...MUTATION_DEFINITIONS.map(createMutationHandler),
28
- ...USER_ROLE_MUTATIONS.map(createUserRoleMutationHandler),
26
+ ...(hasSelfRbac
27
+ ? [
28
+ createTargetRoleHandler(),
29
+ ...LIST_DEFINITIONS.map(createListHandler),
30
+ ...MUTATION_DEFINITIONS.map(createMutationHandler),
31
+ ...USER_ROLE_MUTATIONS.map(createUserRoleMutationHandler)
32
+ ]
33
+ : []),
29
34
  ...objects.filter(hasRbacAddOn).map(createUserRbacFlowHandler)
30
35
  ]);
31
36
  return [
@@ -83,49 +88,42 @@ const USER_ROLE_MUTATIONS = [
83
88
  { flowTag: 'DeleteUserFromRole', operation: 'Delete' }
84
89
  ];
85
90
 
91
+ const STATIC_RBAC_APPLICATION_PATHS = [
92
+ 'app/src/generatedCode/FlowRbac/CreateTargetRole/source/CreateTargetRole_Main.js',
93
+ 'app/src/generatedCode/FlowRbac/CreateTargetRole/source/CreateTargetRole_HdrSqs.js',
94
+ 'app/src/generatedCode/FlowRbac/CreateTargetRole/source/CreateTargetRole_WbsMain.js',
95
+ 'app/src/generatedCode/FlowRbac/CreateTargetRole/source/CreateTargetRole_HdrWbs.js',
96
+ ...LIST_DEFINITIONS.flatMap(({ flowTag }) => [
97
+ `app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_Main.js`,
98
+ `app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_HdrSqs.js`,
99
+ `app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_HdrApi.js`
100
+ ]),
101
+ ...MUTATION_DEFINITIONS.flatMap(({ flowTag }) => [
102
+ `app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_Main.js`,
103
+ `app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_HdrSqs.js`,
104
+ `app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_WbsMain.js`,
105
+ `app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_HdrWbs.js`
106
+ ]),
107
+ ...USER_ROLE_MUTATIONS.flatMap(({ flowTag }) => [
108
+ `app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_Main.js`,
109
+ `app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_HdrSqs.js`,
110
+ `app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_WbsMain.js`,
111
+ `app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_HdrWbs.js`
112
+ ]),
113
+ FLOW_RBAC_YAML_PATH
114
+ ];
115
+
86
116
  export function rbacApplicationManagedPaths(objects = []) {
87
117
  if (!Array.isArray(objects)) {
88
118
  throw new TypeError('objects must be an array');
89
119
  }
90
- return [
91
- 'app/src/generatedCode/FlowRbac/CreateTargetRole/source/CreateTargetRole_Main.js',
92
- 'app/src/generatedCode/FlowRbac/CreateTargetRole/source/CreateTargetRole_HdrSqs.js',
93
- 'app/src/generatedCode/FlowRbac/CreateTargetRole/source/CreateTargetRole_WbsMain.js',
94
- 'app/src/generatedCode/FlowRbac/CreateTargetRole/source/CreateTargetRole_HdrWbs.js',
95
- ...LIST_DEFINITIONS.flatMap(({ flowTag }) => [
96
- `app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_Main.js`,
97
- `app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_HdrSqs.js`,
98
- `app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_HdrApi.js`
99
- ]),
100
- ...MUTATION_DEFINITIONS.flatMap(({ flowTag }) => [
101
- `app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_Main.js`,
102
- `app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_HdrSqs.js`,
103
- `app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_WbsMain.js`,
104
- `app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_HdrWbs.js`
105
- ]),
106
- ...USER_ROLE_MUTATIONS.flatMap(({ flowTag }) => [
107
- `app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_Main.js`,
108
- `app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_HdrSqs.js`,
109
- `app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_WbsMain.js`,
110
- `app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_HdrWbs.js`
111
- ]),
112
- ...objects.filter(hasRbacAddOn).flatMap((object) => {
113
- const flowTag = rbacFlowTag(object);
114
- const sourcePath = `app/src/generatedCode/FlowRbac/${flowTag}/source`;
115
- return [
116
- `${sourcePath}/${flowTag}_Main.js`,
117
- `${sourcePath}/${flowTag}_HdrSqs.js`
118
- ];
119
- }),
120
- FLOW_RBAC_YAML_PATH
121
- ];
122
- }
123
-
124
- function hasRbacAddOn(object) {
125
- return (
126
- Array.isArray(object?.addOnDataStructure) &&
127
- object.addOnDataStructure.some((addOn) => addOn?.type === 'rbac')
128
- );
120
+ const rbacObjects = objects.filter(hasRbacAddOn);
121
+ const sourcePaths = rbacObjects.flatMap((object) => {
122
+ const flowTag = rbacFlowTag(object);
123
+ const sourcePath = `app/src/generatedCode/FlowRbac/${flowTag}/source`;
124
+ return [`${sourcePath}/${flowTag}_Main.js`, `${sourcePath}/${flowTag}_HdrSqs.js`];
125
+ });
126
+ return [...STATIC_RBAC_APPLICATION_PATHS, ...sourcePaths];
129
127
  }
130
128
 
131
129
  async function createTargetRoleHandler() {
@@ -367,3 +365,20 @@ async function renderTemplate(templateUrl, templateName, data) {
367
365
  data
368
366
  );
369
367
  }
368
+
369
+ function hasSelfRbacAddOn(object) {
370
+ return (
371
+ Array.isArray(object?.addOnDataStructure) &&
372
+ object.addOnDataStructure.some((addOn) => addOn?.type === 'rbac')
373
+ );
374
+ }
375
+
376
+ function hasRbacAddOn(object) {
377
+ const selfHasRbac = hasSelfRbacAddOn(object);
378
+ const belongToHasRbac =
379
+ Array.isArray(object?.belongToSchema?.addOnDataStructure) &&
380
+ object.belongToSchema.addOnDataStructure.some(
381
+ (addOn) => addOn?.type === 'rbac'
382
+ );
383
+ return selfHasRbac || belongToHasRbac;
384
+ }
@@ -15,33 +15,81 @@ You should have received a copy of the GNU Affero General Public License
15
15
  along with this program. If not, see <http://www.gnu.org/licenses/>.
16
16
  */
17
17
 
18
- import { middlewareHandler as middleware } from '@izara_project/izara-middleware';
18
+ import {
19
+ middlewareHandler as middleware,
20
+ validatorSchema
21
+ } from '@izara_project/izara-middleware';
19
22
  import { recordHandlerSharedLib } from '@izara_project/izara-core-library-record-handler';
23
+ import Logger from '@izara_project/izara-core-library-logger';
20
24
  import callingFlowSharedLib from '@izara_project/izara-core-library-calling-flow';
25
+
21
26
  import CreateTargetRole from './CreateTargetRole_Main.js';
22
27
 
28
+ // validate event properties in body.Message of sqs event
23
29
  middleware.setValidatorSchema(recordHandlerSharedLib.baseValidatorSchema());
24
30
 
25
- export const main = middleware.wrap(async (event) =>
26
- Promise.all(
27
- event.Records.map(async (record) => {
28
- await recordHandlerSharedLib.validateRecord(
29
- record,
30
- 'CreateTargetRoleHdrSqs',
31
- {},
32
- null
33
- );
34
- return recordHandlerSharedLib.recordHandler(
35
- record,
36
- CreateTargetRole,
37
- 'CreateTargetRoleHdrSqs',
38
- [
39
- record.body.Message,
31
+ let perRecordsValidatorSchema = {
32
+ type: 'object',
33
+ properties: {}
34
+ };
35
+
36
+ export const main = middleware.wrap(async (event, context) => {
37
+ try {
38
+ let recordPromises = [];
39
+
40
+ // loop each record and send to mainFunction
41
+ await Promise.all(
42
+ event.Records.map(async (record) => {
43
+ // promise.all for map() function
44
+
45
+ let passOnProperties = [];
46
+ record._izContext.logger.debug('record ReceiveMsgOutHdrSqs', record);
47
+
48
+ // validate message (and MessageAttributes)
49
+ await recordHandlerSharedLib.validateRecord(
50
+ record, // one record will send to mainFunction
51
+ 'CreateTargetRoleHdrSqs', // queue name that need to retry or send to dlq
52
+ perRecordsValidatorSchema // schema for record.Message
53
+ );
54
+
55
+ // add argument (to invoke lambda) to passOnProperties[]
56
+ passOnProperties.push(record.body.Message);
57
+ passOnProperties.push(
40
58
  callingFlowSharedLib.addCallingFlowToPassOnProperties(
41
59
  record.body.Message
42
60
  )
43
- ]
61
+ );
62
+ record._izContext.logger.debug(
63
+ 'passOnProperties in handler',
64
+ passOnProperties
65
+ );
66
+
67
+ // call recordHandlerSharedLib.recordHandler with 3 parameters and return promise(resolve)
68
+ let recordPromise = recordHandlerSharedLib.recordHandler(
69
+ record, // one record will send to mainFunction
70
+ CreateTargetRole, // mainFunction that need to invoke.
71
+ 'CreateTargetRoleHdrSqs', // queue name that need to retry or send to dlq
72
+ passOnProperties // all parameters that mainFunction needed.
73
+ );
74
+ record._izContext.logger.debug('after recordPromise in handler');
75
+ recordPromises.push(recordPromise); // push promise to recordPromises
76
+ })
77
+ );
78
+
79
+ Logger.debug('before Promise.all(recordPromises) in handler');
80
+ try {
81
+ // --- main await all promises
82
+ await Promise.all(recordPromises); // await all promises
83
+
84
+ return event.Records; // return all for local testing
85
+ } catch {
86
+ Logger.debug(
87
+ 'Promise.all(recordPromises) in handler threw error (at least one record did no resolve)'
44
88
  );
45
- })
46
- )
47
- );
89
+ }
90
+ Logger.debug('after Promise.all(recordPromises) in handler');
91
+ } catch (err) {
92
+ Logger.error('Unhandled Error, LambdaFunctionHdrSqs: ', err);
93
+ throw err;
94
+ }
95
+ });
@@ -15,32 +15,81 @@ You should have received a copy of the GNU Affero General Public License
15
15
  along with this program. If not, see <http://www.gnu.org/licenses/>.
16
16
  */
17
17
 
18
- import { middlewareHandler as middleware } from '@izara_project/izara-middleware';
18
+ import {
19
+ middlewareHandler as middleware,
20
+ validatorSchema
21
+ } from '@izara_project/izara-middleware';
19
22
  import { recordHandlerSharedLib } from '@izara_project/izara-core-library-record-handler';
23
+ import Logger from '@izara_project/izara-core-library-logger';
20
24
  import callingFlowSharedLib from '@izara_project/izara-core-library-calling-flow';
25
+
21
26
  import <%- flowTag %> from './<%- flowTag %>_Main.js';
22
27
 
28
+ // validate event properties in body.Message of sqs event
23
29
  middleware.setValidatorSchema(recordHandlerSharedLib.baseValidatorSchema());
24
- export const main = middleware.wrap(async (event) =>
25
- Promise.all(
26
- event.Records.map(async (record) => {
27
- await recordHandlerSharedLib.validateRecord(
28
- record,
29
- '<%- flowTag %>HdrSqs',
30
- {},
31
- null
32
- );
33
- return recordHandlerSharedLib.recordHandler(
34
- record,
35
- <%- flowTag %>,
36
- '<%- flowTag %>HdrSqs',
37
- [
38
- record.body.Message,
30
+
31
+ let perRecordsValidatorSchema = {
32
+ type: 'object',
33
+ properties: {}
34
+ };
35
+
36
+ export const main = middleware.wrap(async (event, context) => {
37
+ try {
38
+ let recordPromises = [];
39
+
40
+ // loop each record and send to mainFunction
41
+ await Promise.all(
42
+ event.Records.map(async (record) => {
43
+ // promise.all for map() function
44
+
45
+ let passOnProperties = [];
46
+ record._izContext.logger.debug('record ReceiveMsgOutHdrSqs', record);
47
+
48
+ // validate message (and MessageAttributes)
49
+ await recordHandlerSharedLib.validateRecord(
50
+ record, // one record will send to mainFunction
51
+ '<%- flowTag %>HdrSqs', // queue name that need to retry or send to dlq
52
+ perRecordsValidatorSchema // schema for record.Message
53
+ );
54
+
55
+ // add argument (to invoke lambda) to passOnProperties[]
56
+ passOnProperties.push(record.body.Message);
57
+ passOnProperties.push(
39
58
  callingFlowSharedLib.addCallingFlowToPassOnProperties(
40
59
  record.body.Message
41
60
  )
42
- ]
61
+ );
62
+ record._izContext.logger.debug(
63
+ 'passOnProperties in handler',
64
+ passOnProperties
65
+ );
66
+
67
+ // call recordHandlerSharedLib.recordHandler with 3 parameters and return promise(resolve)
68
+ let recordPromise = recordHandlerSharedLib.recordHandler(
69
+ record, // one record will send to mainFunction
70
+ <%- flowTag %>, // mainFunction that need to invoke.
71
+ '<%- flowTag %>HdrSqs', // queue name that need to retry or send to dlq
72
+ passOnProperties // all parameters that mainFunction needed.
73
+ );
74
+ record._izContext.logger.debug('after recordPromise in handler');
75
+ recordPromises.push(recordPromise); // push promise to recordPromises
76
+ })
77
+ );
78
+
79
+ Logger.debug('before Promise.all(recordPromises) in handler');
80
+ try {
81
+ // --- main await all promises
82
+ await Promise.all(recordPromises); // await all promises
83
+
84
+ return event.Records; // return all for local testing
85
+ } catch {
86
+ Logger.debug(
87
+ 'Promise.all(recordPromises) in handler threw error (at least one record did no resolve)'
43
88
  );
44
- })
45
- )
46
- );
89
+ }
90
+ Logger.debug('after Promise.all(recordPromises) in handler');
91
+ } catch (err) {
92
+ Logger.error('Unhandled Error, LambdaFunctionHdrSqs: ', err);
93
+ throw err;
94
+ }
95
+ });
@@ -15,32 +15,81 @@ You should have received a copy of the GNU Affero General Public License
15
15
  along with this program. If not, see <http://www.gnu.org/licenses/>.
16
16
  */
17
17
 
18
- import { middlewareHandler as middleware } from '@izara_project/izara-middleware';
18
+ import {
19
+ middlewareHandler as middleware,
20
+ validatorSchema
21
+ } from '@izara_project/izara-middleware';
19
22
  import { recordHandlerSharedLib } from '@izara_project/izara-core-library-record-handler';
23
+ import Logger from '@izara_project/izara-core-library-logger';
20
24
  import callingFlowSharedLib from '@izara_project/izara-core-library-calling-flow';
25
+
21
26
  import <%- flowTag %> from './<%- flowTag %>_Main.js';
22
27
 
28
+ // validate event properties in body.Message of sqs event
23
29
  middleware.setValidatorSchema(recordHandlerSharedLib.baseValidatorSchema());
24
- export const main = middleware.wrap(async (event) =>
25
- Promise.all(
26
- event.Records.map(async (record) => {
27
- await recordHandlerSharedLib.validateRecord(
28
- record,
29
- '<%- flowTag %>HdrSqs',
30
- {},
31
- null
32
- );
33
- return recordHandlerSharedLib.recordHandler(
34
- record,
35
- <%- flowTag %>,
36
- '<%- flowTag %>HdrSqs',
37
- [
38
- record.body.Message,
30
+
31
+ let perRecordsValidatorSchema = {
32
+ type: 'object',
33
+ properties: {}
34
+ };
35
+
36
+ export const main = middleware.wrap(async (event, context) => {
37
+ try {
38
+ let recordPromises = [];
39
+
40
+ // loop each record and send to mainFunction
41
+ await Promise.all(
42
+ event.Records.map(async (record) => {
43
+ // promise.all for map() function
44
+
45
+ let passOnProperties = [];
46
+ record._izContext.logger.debug('record ReceiveMsgOutHdrSqs', record);
47
+
48
+ // validate message (and MessageAttributes)
49
+ await recordHandlerSharedLib.validateRecord(
50
+ record, // one record will send to mainFunction
51
+ '<%- flowTag %>HdrSqs', // queue name that need to retry or send to dlq
52
+ perRecordsValidatorSchema // schema for record.Message
53
+ );
54
+
55
+ // add argument (to invoke lambda) to passOnProperties[]
56
+ passOnProperties.push(record.body.Message);
57
+ passOnProperties.push(
39
58
  callingFlowSharedLib.addCallingFlowToPassOnProperties(
40
59
  record.body.Message
41
60
  )
42
- ]
61
+ );
62
+ record._izContext.logger.debug(
63
+ 'passOnProperties in handler',
64
+ passOnProperties
65
+ );
66
+
67
+ // call recordHandlerSharedLib.recordHandler with 3 parameters and return promise(resolve)
68
+ let recordPromise = recordHandlerSharedLib.recordHandler(
69
+ record, // one record will send to mainFunction
70
+ <%- flowTag %>, // mainFunction that need to invoke.
71
+ '<%- flowTag %>HdrSqs', // queue name that need to retry or send to dlq
72
+ passOnProperties // all parameters that mainFunction needed.
73
+ );
74
+ record._izContext.logger.debug('after recordPromise in handler');
75
+ recordPromises.push(recordPromise); // push promise to recordPromises
76
+ })
77
+ );
78
+
79
+ Logger.debug('before Promise.all(recordPromises) in handler');
80
+ try {
81
+ // --- main await all promises
82
+ await Promise.all(recordPromises); // await all promises
83
+
84
+ return event.Records; // return all for local testing
85
+ } catch {
86
+ Logger.debug(
87
+ 'Promise.all(recordPromises) in handler threw error (at least one record did no resolve)'
43
88
  );
44
- })
45
- )
46
- );
89
+ }
90
+ Logger.debug('after Promise.all(recordPromises) in handler');
91
+ } catch (err) {
92
+ Logger.error('Unhandled Error, LambdaFunctionHdrSqs: ', err);
93
+ throw err;
94
+ }
95
+ });
@@ -148,6 +148,7 @@ export const resourceArtifactPaths = [
148
148
 
149
149
  function createResourceState({ objects, relationships, flows }) {
150
150
  const crud = objects.some(isCrudObject);
151
+ const selfRbac = objects.some(hasSelfRbacAddOn);
151
152
  const rbac = objects.some(hasRbacAddOn);
152
153
  const ownTopics = new Set([
153
154
  'ProcessLogical',
@@ -195,11 +196,13 @@ function createResourceState({ objects, relationships, flows }) {
195
196
  }
196
197
  dsqQueues.add('GetRelationshipHdrDsq');
197
198
  }
198
- if (rbac) {
199
+ if (selfRbac) {
199
200
  for (const action of RBAC_ACTIONS) {
200
201
  ownTopics.add(action);
201
202
  sqsQueues.add(`Process${action}HdrSqs`);
202
203
  }
204
+ }
205
+ if (rbac) {
203
206
  for (const object of objects.filter(hasRbacAddOn)) {
204
207
  const flowTag = upperFirst(object.objectType) + 'RbacFlow';
205
208
  ownTopics.add(flowTag);
@@ -816,13 +819,21 @@ function isCrudObject(object) {
816
819
  object?.generatedBy === 'systemGenerated'
817
820
  );
818
821
  }
819
- function hasRbacAddOn(object) {
822
+ function hasSelfRbacAddOn(object) {
820
823
  return (
821
824
  Array.isArray(object?.addOnDataStructure) &&
822
825
  object.addOnDataStructure.some((addOn) => addOn?.type === 'rbac')
823
826
  );
824
827
  }
825
828
 
829
+ function hasRbacAddOn(object) {
830
+ const selfHasRbac = hasSelfRbacAddOn(object);
831
+ const belongToHasRbac =
832
+ Array.isArray(object?.belongToSchema?.addOnDataStructure) &&
833
+ object.belongToSchema.addOnDataStructure.some((addOn) => addOn?.type === 'rbac');
834
+ return selfHasRbac || belongToHasRbac;
835
+ }
836
+
826
837
  /**
827
838
  * Returns the per-object RBAC flow queues (e.g. UserRbacFlowHdrSqs)
828
839
  * created for objects with an 'rbac' add-on. These are consumed by the
@@ -39,7 +39,8 @@ async function mergeHook(outputRoot, artifact) {
39
39
 
40
40
  return artifact.content.replace(
41
41
  matchers.anyTag,
42
- (_match, tagName) => {
42
+ (_match, p1, _body1, p2) => {
43
+ const tagName = p1 || p2;
43
44
  const hookBlock = sourceContent.match(matchers.tagPattern(tagName))?.[0];
44
45
  return hookBlock ?? _match;
45
46
  }
@@ -49,10 +50,10 @@ async function mergeHook(outputRoot, artifact) {
49
50
  function hookMatchers(filePath) {
50
51
  if (filePath.endsWith('.js')) {
51
52
  return {
52
- anyTag: /\/\/\(<(\w+)>\)([\s\S]*?)\/\/\(<\/\1>\)/gm,
53
+ anyTag: /(?:\/\/\(<(\w+)>\)([\s\S]*?)\/\/\(<\/\1>\)|\/\/\s*<#(\w+)#>([\s\S]*?)\/\/\s*<#\/\3#>)/gm,
53
54
  tagPattern: (name) =>
54
55
  new RegExp(
55
- `\\/\\/\\(<${name}>\\)([\\s\\S]*?)\\/\\/\\(<\\/${name}>\\)`,
56
+ `(?:\\/\\/\\(<${name}>\\)([\\s\\S]*?)\\/\\/\\(<\\/${name}>\\)|\\/\\/\\s*<#${name}#>([\\s\\S]*?)\\/\\/\\s*<#\\/${name}#>)`,
56
57
  'gm'
57
58
  )
58
59
  };