@izara_project/izara-core-generate-service-code 1.0.68 → 1.0.69

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.
Files changed (81) hide show
  1. package/package.json +1 -1
  2. package/scripts/format-ejs.js +1 -2
  3. package/src/compile/compileProject.js +26 -10
  4. package/src/compile/loadSchemas.js +47 -23
  5. package/src/emit/crud/emitCrudApplicationArtifacts.js +188 -41
  6. package/src/emit/crud/emitDynamicCrudFlowSchemas.js +34 -17
  7. package/src/emit/crud/generateCrudApplicationArtifacts.js +14 -6
  8. package/src/emit/crud/generateDynamicCrudFlowSchemas.js +4 -1
  9. package/src/emit/crud/templates/GetEndpoint_Main.ejs +1 -1
  10. package/src/emit/custom/customFlows.js +23 -13
  11. package/src/emit/custom/emitCustomFlowApplicationArtifacts.js +515 -113
  12. package/src/emit/custom/generateCustomFlowApplicationArtifacts.js +28 -8
  13. package/src/emit/custom/templates/s3/FlowHandler_HdrS3.ejs +2 -2
  14. package/src/emit/custom/templates/s3/ReservedLimit_HdrSqs.ejs +1 -1
  15. package/src/emit/function/functionYamlArtifact.js +270 -97
  16. package/src/emit/function/templates/ApiFunction_Yaml.ejs +7 -0
  17. package/src/emit/function/templates/EventBridgeFunction_Yaml.ejs +6 -0
  18. package/src/emit/function/templates/InvFunction_Yaml.ejs +5 -0
  19. package/src/emit/function/templates/S3Function_Yaml.ejs +16 -0
  20. package/src/emit/function/templates/SqsFunction_Yaml.ejs +10 -0
  21. package/src/emit/function/templates/WbsFunction_Yaml.ejs +10 -0
  22. package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +28 -30
  23. package/src/emit/rbac/emitRbacApplicationArtifacts.js +6 -6
  24. package/src/emit/rbac/generateCreateTargetRoleHandler.js +6 -4
  25. package/src/emit/rbac/generateDynamicRbacFlowSchemas.js +8 -2
  26. package/src/emit/rbac/rbacFlowTag.js +3 -1
  27. package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +1 -1
  28. package/src/emit/relationship/emitDynamicRelationshipFlowSchemas.js +26 -10
  29. package/src/emit/relationship/emitRelationshipApplicationArtifacts.js +179 -37
  30. package/src/emit/relationship/generateDynamicRelationshipFlowSchemas.js +8 -2
  31. package/src/emit/relationship/generateRelationshipApplicationArtifacts.js +15 -6
  32. package/src/emit/resource/emitResourceArtifacts.js +187 -114
  33. package/src/emit/resource/generateResourceArtifacts.js +15 -6
  34. package/src/emit/resource/templates/DynamoDBTable_Yaml.ejs +18 -18
  35. package/src/emit/resource/templates/FlowOut_Yaml.ejs +5 -5
  36. package/src/emit/resource/templates/GeneratedLambdaRoleServiceConfig.ejs +10 -9
  37. package/src/emit/resource/templates/ResourceBeforeLogicalYaml.ejs +44 -44
  38. package/src/emit/resource/templates/ResourceSqsYaml.ejs +36 -36
  39. package/src/emit/resource/templates/ResourceYaml.ejs +48 -48
  40. package/src/emit/resource/templates/S3Subscription_Yaml.ejs +7 -0
  41. package/src/emit/resource/templates/SharedResource_Yaml.ejs +11 -11
  42. package/src/emit/resource/templates/SystemDynamoDB_Yaml.ejs +105 -105
  43. package/src/emit/resource/templates/WebSocketSubscription_Yaml.ejs +7 -0
  44. package/src/emit/system/emitSystemWebSocketArtifacts.js +61 -165
  45. package/src/emit/system/templates/WebSocketComplete_HdrSqs.ejs +32 -0
  46. package/src/emit/system/templates/WebSocketComplete_Main.ejs +46 -0
  47. package/src/emit/system/templates/WebSocketComplete_Yaml.ejs +19 -0
  48. package/src/emit/system/templates/WebSocketConnect.ejs +25 -0
  49. package/src/emit/system/templates/WebSocketConnect_Yaml.ejs +11 -0
  50. package/src/generate.js +136 -33
  51. package/src/generateIntTest.js +76 -28
  52. package/src/generateResourceIntTest.js +35 -12
  53. package/src/generateResources/IntTest/generateResources/generateResources.js +5 -2
  54. package/src/generateResources/IntTest/generateResources/templateResources.ejs +18 -30
  55. package/src/generateResources/IntTest/generateTests/events/events.js +1 -1
  56. package/src/generateResources/IntTest/generateTests/events/templateEvents.ejs +13 -10
  57. package/src/generateResources/IntTest/generateTests/generateTemplate.js +2 -2
  58. package/src/generateResources/IntTest/generateTests/pathIntTest/pathIntTest.js +2 -1
  59. package/src/generateResources/IntTest/generateTests/pathIntTest/template.ejs +1 -3
  60. package/src/generateResources/IntTest/generateTests/tests/templateTests.ejs +1 -1
  61. package/src/generateResources/IntTest/generateTests/tests/tests.js +7 -3
  62. package/src/generateResources/IntTest/libs/{libs.js → IntTestGenerateLib.js} +34 -23
  63. package/src/generateResources/IntTest/upload/uploadIntTest.js +33 -19
  64. package/src/intTestGeneratorShared.js +15 -10
  65. package/src/output/commitArtifacts.js +99 -39
  66. package/src/output/mergeHooks.js +24 -10
  67. package/src/output/validateArtifacts.js +37 -27
  68. package/src/plan/buildGenerationPlan.js +24 -13
  69. package/test/core.test.js +116 -49
  70. package/test/createTargetRoleHandler.test.js +1 -1
  71. package/test/crudApplicationArtifacts.test.js +128 -23
  72. package/test/customFlowApplicationArtifacts.test.js +353 -71
  73. package/test/dynamicCrudFlowSchemas.test.js +74 -26
  74. package/test/dynamicRbacFlowSchemas.test.js +61 -14
  75. package/test/dynamicRelationshipFlowSchemas.test.js +65 -18
  76. package/test/functionYamlArtifact.test.js +67 -10
  77. package/test/intTestApi.test.js +9 -10
  78. package/test/publicApi.test.js +176 -34
  79. package/test/relationshipApplicationArtifacts.test.js +90 -19
  80. package/test/resourceArtifacts.test.js +172 -32
  81. package/src/emit/relationship/dynamicRelationshipFlowSchemaTemplate.js +0 -11
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@izara_project/izara-core-generate-service-code",
3
- "version": "1.0.68",
3
+ "version": "1.0.69",
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": {
@@ -34,8 +34,7 @@ export async function formatEjsFiles(targetDir = 'src/emit') {
34
34
  const id = placeholders.length;
35
35
  const isExpr = match.startsWith('<%=') || match.startsWith('<%-');
36
36
  const isConditionalComma =
37
- match.includes('?') &&
38
- (match.includes("','") || match.includes('","'));
37
+ match.includes('?') && (match.includes("','") || match.includes('","'));
39
38
 
40
39
  let replacement;
41
40
  if (isYaml) {
@@ -1,17 +1,24 @@
1
+ import Logger from '@izara_project/izara-core-library-logger';
1
2
  import { join, resolve } from 'node:path';
2
3
  import { readFileSync, existsSync } from 'node:fs';
3
4
  import { parse as parseYaml } from 'yaml';
4
5
 
5
6
  export function compileProject(request = {}) {
6
- if (!isNonEmptyString(request.rootPath)) {
7
- throw new TypeError('GenerationRequest.rootPath must be a non-empty string');
7
+ if (!_isNonEmptyString(request.rootPath)) {
8
+ throw new TypeError(
9
+ 'GenerationRequest.rootPath must be a non-empty string'
10
+ );
8
11
  }
9
12
 
10
13
  const rootPath = resolve(request.rootPath);
11
- const outputPath = resolve(request.outputPath ?? rootPath);
12
- const configPath = resolve(
13
- request.configPath ?? join(rootPath, 'config', 'serverless.config.yml')
14
- );
14
+ let outputPath = rootPath;
15
+ if (request.outputPath) {
16
+ outputPath = resolve(request.outputPath);
17
+ }
18
+ let configPath = join(rootPath, 'config', 'serverless.config.yml');
19
+ if (request.configPath) {
20
+ configPath = resolve(request.configPath);
21
+ }
15
22
 
16
23
  let serviceTag = request.serviceTag;
17
24
  if (!serviceTag && existsSync(configPath)) {
@@ -19,23 +26,32 @@ export function compileProject(request = {}) {
19
26
  const configContent = readFileSync(configPath, 'utf8');
20
27
  const parsedConfig = parseYaml(configContent);
21
28
  if (parsedConfig && parsedConfig.main_config) {
22
- serviceTag = parsedConfig.main_config.iz_serviceTag || parsedConfig.main_config.iz_serviceName;
29
+ if (parsedConfig.main_config.iz_serviceTag) {
30
+ serviceTag = parsedConfig.main_config.iz_serviceTag;
31
+ } else if (parsedConfig.main_config.iz_serviceName) {
32
+ serviceTag = parsedConfig.main_config.iz_serviceName;
33
+ }
23
34
  }
24
35
  } catch (err) {
25
- // Ignore configuration read error
36
+ Logger?.debug?.('Could not read serverless.config.yml', err);
26
37
  }
27
38
  }
28
39
 
40
+ let schemaTemplateConfig = [];
41
+ if (request.schemaTemplateConfig) {
42
+ schemaTemplateConfig = request.schemaTemplateConfig;
43
+ }
44
+
29
45
  return Object.freeze({
30
46
  rootPath,
31
47
  outputPath,
32
48
  configPath,
33
49
  schemaRoot: join(rootPath, 'app', 'src', 'schemas'),
34
50
  serviceTag,
35
- schemaTemplateConfig: request.schemaTemplateConfig ?? []
51
+ schemaTemplateConfig
36
52
  });
37
53
  }
38
54
 
39
- function isNonEmptyString(value) {
55
+ function _isNonEmptyString(value) {
40
56
  return typeof value === 'string' && value.trim() !== '';
41
57
  }
@@ -1,7 +1,10 @@
1
1
  import { readdir, stat } from 'node:fs/promises';
2
2
  import { join } from 'node:path';
3
3
  import { pathToFileURL } from 'node:url';
4
- import { getObjectSchema, utils } from '@izara_project/izara-core-library-service-schemas';
4
+ import {
5
+ getObjectSchema,
6
+ utils
7
+ } from '@izara_project/izara-core-library-service-schemas';
5
8
  import Logger from '@izara_project/izara-core-library-logger';
6
9
 
7
10
  export async function loadLocalSchemaDirectory(project, directoryName) {
@@ -16,35 +19,61 @@ export async function loadLocalSchemaDirectory(project, directoryName) {
16
19
  throw error;
17
20
  }
18
21
 
22
+ const validEntries = entries.filter(
23
+ (entry) => entry.isFile() && entry.name.endsWith('.js')
24
+ );
25
+ validEntries.sort((a, b) => a.name.localeCompare(b.name));
26
+
19
27
  const schemas = [];
20
- for (const entry of entries.filter(entry => entry.isFile() && entry.name.endsWith('.js')).sort((a, b) => a.name.localeCompare(b.name))) {
28
+ for (const entry of validEntries) {
21
29
  const filePath = join(directoryPath, entry.name);
22
30
  const details = await stat(filePath);
23
- const module = await import(`${pathToFileURL(filePath).href}?schemaVersion=${details.mtimeMs}-${details.size}`);
31
+ const module = await import(
32
+ `${pathToFileURL(filePath).href}?schemaVersion=${details.mtimeMs}-${details.size}`
33
+ );
24
34
  if (!module.default || typeof module.default !== 'object') {
25
- throw new TypeError(`Schema module must default-export an object or array: ${filePath}`);
35
+ throw new TypeError(
36
+ `Schema module must default-export an object or array: ${filePath}`
37
+ );
38
+ }
39
+ let loadedSchemas = [module.default];
40
+ if (Array.isArray(module.default)) {
41
+ loadedSchemas = module.default;
26
42
  }
27
- const loadedSchemas = Array.isArray(module.default) ? module.default : [module.default];
28
43
 
29
- if (process.env.NODE_ENV !== 'test') {
44
+ if (process.env.NODE_ENV && process.env.NODE_ENV !== 'test') {
30
45
  for (const schema of loadedSchemas) {
31
46
  let status = true;
32
47
  let errors = [];
33
-
48
+
34
49
  if (directoryName === 'ObjectSchemas') {
35
- [status, errors] = utils.validateObjectSchema({ logger: Logger }, schema);
50
+ [status, errors] = utils.validateObjectSchema(
51
+ { logger: Logger },
52
+ schema
53
+ );
36
54
  } else if (directoryName === 'RelationshipSchemas') {
37
55
  if (entry.name.toLowerCase() === 'refobjectrelationships.js') {
38
- [status, errors] = utils.validateRefRelationshipSchema({ logger: Logger }, schema);
56
+ [status, errors] = utils.validateRefRelationshipSchema(
57
+ { logger: Logger },
58
+ schema
59
+ );
39
60
  } else {
40
- [status, errors] = utils.validateRelationshipSchema({ logger: Logger }, schema);
61
+ [status, errors] = utils.validateRelationshipSchema(
62
+ { logger: Logger },
63
+ schema
64
+ );
41
65
  }
42
66
  } else if (directoryName === 'FlowSchemas') {
43
- [status, errors] = utils.validateBasicFlowSchema({ logger: Logger }, schema);
67
+ [status, errors] = utils.validateBasicFlowSchema(
68
+ { logger: Logger },
69
+ schema
70
+ );
44
71
  }
45
72
 
46
73
  if (!status) {
47
- throw new Error(`Schema validation failed for ${entry.name}:\n${errors.join('\n')}`);
74
+ throw new Error(
75
+ `Schema validation failed for ${entry.name}:\n${errors.join('\n')}`
76
+ );
48
77
  }
49
78
  }
50
79
  }
@@ -68,10 +97,7 @@ export async function loadLocalSchemaDirectory(project, directoryName) {
68
97
  * @returns {Promise<Object[]>} The same array with extended storageResources
69
98
  * merged in.
70
99
  */
71
- export async function resolveExtendedObjectSchemas(
72
- objectSchemas,
73
- bucketName
74
- ) {
100
+ export async function resolveExtendedObjectSchemas(objectSchemas, bucketName) {
75
101
  if (!Array.isArray(objectSchemas)) {
76
102
  throw new TypeError('objectSchemas must be an array');
77
103
  }
@@ -83,9 +109,8 @@ export async function resolveExtendedObjectSchemas(
83
109
  }
84
110
  try {
85
111
  // Track which storageResource keys existed in the child before merge
86
- const childStorageResourceKeys = new Set(
87
- Object.keys(schema.storageResources ?? {})
88
- );
112
+ const initialResources = schema.storageResources || {};
113
+ const childStorageResourceKeys = new Set(Object.keys(initialResources));
89
114
  const parentServiceTag = schema.extendObjType.serviceTag;
90
115
 
91
116
  const mergedSchema = await getObjectSchema.mergeExtendObjSchema(
@@ -100,9 +125,8 @@ export async function resolveExtendedObjectSchemas(
100
125
  // emitResourceArtifacts can add cross-service ARNs to IAM roles.
101
126
  const externalDynamoResources = [];
102
127
  const ownStorageResources = {};
103
- for (const [key, resource] of Object.entries(
104
- mergedSchema.storageResources ?? {}
105
- )) {
128
+ const mergedStorageResources = mergedSchema.storageResources || {};
129
+ for (const [key, resource] of Object.entries(mergedStorageResources)) {
106
130
  if (
107
131
  resource?.storageType === 'dynamoDB' &&
108
132
  !childStorageResourceKeys.has(key)
@@ -125,7 +149,7 @@ export async function resolveExtendedObjectSchemas(
125
149
  } catch (error) {
126
150
  Logger.error(
127
151
  `resolveExtendedObjectSchemas: failed to merge extendObjType` +
128
- ` for objectType=${schema.objectType}`,
152
+ ` for objectType=${schema.objectType}`,
129
153
  { error }
130
154
  );
131
155
  throw error;
@@ -1,4 +1,4 @@
1
- import ejs from 'ejs';
1
+ import ejsLib from 'ejs';
2
2
  import { readFile } from 'node:fs/promises';
3
3
 
4
4
  import {
@@ -12,30 +12,42 @@ const ACTIONS = ['Create', 'Update', 'Delete', 'Get'];
12
12
  const YAML_PATH = 'app/sls_yaml/generatedCode/source/flow-objects.yml';
13
13
  const TEMPLATE_URL = new URL('./templates/', import.meta.url);
14
14
 
15
- export async function emitCrudApplicationArtifacts({ objects, flows = [], serviceTag }) {
15
+ export async function emitCrudApplicationArtifacts({
16
+ objects,
17
+ flows = [],
18
+ serviceTag
19
+ }) {
16
20
  if (!Array.isArray(objects) || !Array.isArray(flows)) {
17
21
  throw new TypeError('objects and flows must be arrays');
18
22
  }
19
23
  if (!objects.some(isCrudObject)) return [];
20
24
 
21
- const handlers = await Promise.all(ACTIONS.map(action => emitAction(action, objects, flows, serviceTag)));
25
+ const handlers = await Promise.all(
26
+ ACTIONS.map((action) => emitAction(action, objects, flows, serviceTag))
27
+ );
22
28
  return [
23
- ...handlers.flatMap(handler => handler.artifacts),
29
+ ...handlers.flatMap((handler) => handler.artifacts),
24
30
  {
25
31
  path: YAML_PATH,
26
- content: handlers.flatMap(handler => handler.functions).map(renderFunction).join('\n')
32
+ content: handlers
33
+ .flatMap((handler) => handler.functions)
34
+ .map(renderFunction)
35
+ .join('\n')
27
36
  }
28
37
  ];
29
38
  }
30
39
 
31
40
  export function crudApplicationManagedPaths() {
32
41
  return [
33
- ...ACTIONS.flatMap(action => {
42
+ ...ACTIONS.flatMap((action) => {
34
43
  const source = `app/src/generatedCode/FlowObjects/${action}/source`;
35
44
  const paths = [`${source}/${action}_Main.js`];
36
45
  if (action === 'Get') {
37
46
  paths.push(`${source}/Get_HdrInv.js`, `${source}/Get_HdrApi.js`);
38
- paths.push(`${source}/GetRange_Main.js`, `${source}/GetRange_HdrApi.js`);
47
+ paths.push(
48
+ `${source}/GetRange_Main.js`,
49
+ `${source}/GetRange_HdrApi.js`
50
+ );
39
51
  } else {
40
52
  paths.push(
41
53
  `${source}/${action}_HdrSqs.js`,
@@ -44,7 +56,10 @@ export function crudApplicationManagedPaths() {
44
56
  `${source}/${action}BeforeLogical_Main.js`,
45
57
  `${source}/${action}BeforeLogical_HdrSqs.js`
46
58
  );
47
- paths.push(`${source}/${action}Complete_Main.js`, `${source}/${action}Complete_HdrSqs.js`);
59
+ paths.push(
60
+ `${source}/${action}Complete_Main.js`,
61
+ `${source}/${action}Complete_HdrSqs.js`
62
+ );
48
63
  }
49
64
  return paths;
50
65
  }),
@@ -56,8 +71,12 @@ async function emitAction(action, objects, flows, serviceTag) {
56
71
  const source = `app/src/generatedCode/FlowObjects/${action}/source`;
57
72
  const handlerRoot = `src/generatedCode/FlowObjects/${action}/source`;
58
73
  const generateCode = flows
59
- .filter(flow => flow?.generatedCodeConfig?.generatedCodeTag?.toLowerCase() === action.toLowerCase())
60
- .map(flow => ({ ...flow.generatedCodeConfig, flowTag: flow.flowTag }));
74
+ .filter(
75
+ (flow) =>
76
+ flow?.generatedCodeConfig?.generatedCodeTag?.toLowerCase() ===
77
+ action.toLowerCase()
78
+ )
79
+ .map((flow) => ({ ...flow.generatedCodeConfig, flowTag: flow.flowTag }));
61
80
  const mainFileName = `${action}_Main`;
62
81
  const shared = {
63
82
  flowTag: action,
@@ -68,22 +87,66 @@ async function emitAction(action, objects, flows, serviceTag) {
68
87
  flowStepName: '',
69
88
  startConfig: null
70
89
  };
71
- const artifacts = [{
72
- path: `${source}/${mainFileName}.js`,
73
- content: await render(`${action}Endpoint_Main.ejs`, shared)
74
- }];
90
+ const artifacts = [
91
+ {
92
+ path: `${source}/${mainFileName}.js`,
93
+ content: await render(`${action}Endpoint_Main.ejs`, shared)
94
+ }
95
+ ];
75
96
 
97
+ let targetServiceTag = '${self:custom.iz_serviceName}';
98
+ if (serviceTag) {
99
+ targetServiceTag = serviceTag;
100
+ }
76
101
  if (action === 'Get') {
77
102
  artifacts.push(
78
- { path: `${source}/Get_HdrInv.js`, content: await render('FlowHandler_HdrInv.ejs', { ...shared, mainFileName, functionName: 'Get', queueName: 'GetHdrInv' }) },
79
- { path: `${source}/Get_HdrApi.js`, content: await render('FlowHandler_HdrApi.ejs', { ...shared, mainFileName, functionName: 'Get', queueName: 'GetHdrApi' }) },
80
- { path: `${source}/GetRange_Main.js`, content: await render('GetRangeEndpoint_Main.ejs', { ...shared, mainFileName: 'GetRange_Main', functionName: 'GetRange' }) },
81
- { path: `${source}/GetRange_HdrApi.js`, content: await render('FlowHandler_HdrApi.ejs', { ...shared, mainFileName: 'GetRange_Main', functionName: 'GetRange', queueName: 'GetRangeHdrApi' }) }
103
+ {
104
+ path: `${source}/Get_HdrInv.js`,
105
+ content: await render('FlowHandler_HdrInv.ejs', {
106
+ ...shared,
107
+ mainFileName,
108
+ functionName: 'Get',
109
+ queueName: 'GetHdrInv'
110
+ })
111
+ },
112
+ {
113
+ path: `${source}/Get_HdrApi.js`,
114
+ content: await render('FlowHandler_HdrApi.ejs', {
115
+ ...shared,
116
+ mainFileName,
117
+ functionName: 'Get',
118
+ queueName: 'GetHdrApi'
119
+ })
120
+ },
121
+ {
122
+ path: `${source}/GetRange_Main.js`,
123
+ content: await render('GetRangeEndpoint_Main.ejs', {
124
+ ...shared,
125
+ mainFileName: 'GetRange_Main',
126
+ functionName: 'GetRange'
127
+ })
128
+ },
129
+ {
130
+ path: `${source}/GetRange_HdrApi.js`,
131
+ content: await render('FlowHandler_HdrApi.ejs', {
132
+ ...shared,
133
+ mainFileName: 'GetRange_Main',
134
+ functionName: 'GetRange',
135
+ queueName: 'GetRangeHdrApi'
136
+ })
137
+ }
82
138
  );
83
139
  return {
84
140
  artifacts,
85
141
  functions: [
86
- { type: 'inv', functionName: 'GetHdrInv', handlerPath: `${handlerRoot}/Get_HdrInv.main`, roleName: 'FlowObjectsRole', flowTag: action, flowStepName: '' },
142
+ {
143
+ type: 'inv',
144
+ functionName: 'GetHdrInv',
145
+ handlerPath: `${handlerRoot}/Get_HdrInv.main`,
146
+ roleName: 'FlowObjectsRole',
147
+ flowTag: action,
148
+ flowStepName: ''
149
+ },
87
150
  {
88
151
  type: 'api',
89
152
  functionName: 'GetHdrApi',
@@ -91,8 +154,8 @@ async function emitAction(action, objects, flows, serviceTag) {
91
154
  roleName: 'FlowObjectsRole',
92
155
  flowTag: action,
93
156
  flowStepName: '',
94
- routes: objects.filter(isCrudObject).map(object => ({
95
- path: `/${serviceTag ?? '${self:custom.iz_serviceName}'}/${object.objectType}/get`,
157
+ routes: objects.filter(isCrudObject).map((object) => ({
158
+ path: `/${targetServiceTag}/${object.objectType}/get`,
96
159
  upperName: upperFirst(object.objectType)
97
160
  }))
98
161
  },
@@ -103,45 +166,129 @@ async function emitAction(action, objects, flows, serviceTag) {
103
166
  roleName: 'FlowObjectsRole',
104
167
  flowTag: 'GetRange',
105
168
  flowStepName: '',
106
- routes: objects.filter(isCrudObject)
107
- .filter(object => object.identifiers && object.identifiers.some(i => i.type === 'sortKey'))
108
- .map(object => ({
109
- path: `/${serviceTag ?? '${self:custom.iz_serviceName}'}/${object.objectType}/getRange`,
110
- upperName: upperFirst(object.objectType)
111
- }))
169
+ routes: objects
170
+ .filter(isCrudObject)
171
+ .filter(
172
+ (object) =>
173
+ object.identifiers &&
174
+ object.identifiers.some((i) => i.type === 'sortKey')
175
+ )
176
+ .map((object) => ({
177
+ path: `/${targetServiceTag}/${object.objectType}/getRange`,
178
+ upperName: upperFirst(object.objectType)
179
+ }))
112
180
  }
113
181
  ]
114
182
  };
115
183
  }
116
184
 
117
185
  artifacts.push(
118
- { path: `${source}/${action}_HdrSqs.js`, content: await render('FlowHandler_HdrSqs.ejs', { ...shared, mainFileName, functionName: action, queueName: `${action}HdrSqs` }) },
119
- { path: `${source}/${action}_WbsMain.js`, content: await render('FlowMain_Wbs.ejs', { ...shared, functionName: action }) },
120
- { path: `${source}/${action}_HdrWbs.js`, content: await render('FlowEndpoint_HdrWbs.ejs', { ...shared, mainFileName: `${action}_WbsMain`, functionName: action, route: action }) }
186
+ {
187
+ path: `${source}/${action}_HdrSqs.js`,
188
+ content: await render('FlowHandler_HdrSqs.ejs', {
189
+ ...shared,
190
+ mainFileName,
191
+ functionName: action,
192
+ queueName: `${action}HdrSqs`
193
+ })
194
+ },
195
+ {
196
+ path: `${source}/${action}_WbsMain.js`,
197
+ content: await render('FlowMain_Wbs.ejs', {
198
+ ...shared,
199
+ functionName: action
200
+ })
201
+ },
202
+ {
203
+ path: `${source}/${action}_HdrWbs.js`,
204
+ content: await render('FlowEndpoint_HdrWbs.ejs', {
205
+ ...shared,
206
+ mainFileName: `${action}_WbsMain`,
207
+ functionName: action,
208
+ route: action
209
+ })
210
+ }
121
211
  );
122
212
  const functions = [
123
- { type: 'wbs', functionName: `${action}HdrWbs`, handlerPath: `${handlerRoot}/${action}_HdrWbs.main`, roleName: 'FlowObjectsRole', routeName: action, flowTag: action, flowStepName: '' },
124
- { type: 'sqs', functionName: `${action}HdrSqs`, handlerPath: `${handlerRoot}/${action}_HdrSqs.main`, roleName: 'FlowObjectsRole', queueName: `${action}HdrSqs`, flowTag: action, flowStepName: '' }
213
+ {
214
+ type: 'wbs',
215
+ functionName: `${action}HdrWbs`,
216
+ handlerPath: `${handlerRoot}/${action}_HdrWbs.main`,
217
+ roleName: 'FlowObjectsRole',
218
+ routeName: action,
219
+ flowTag: action,
220
+ flowStepName: ''
221
+ },
222
+ {
223
+ type: 'sqs',
224
+ functionName: `${action}HdrSqs`,
225
+ handlerPath: `${handlerRoot}/${action}_HdrSqs.main`,
226
+ roleName: 'FlowObjectsRole',
227
+ queueName: `${action}HdrSqs`,
228
+ flowTag: action,
229
+ flowStepName: ''
230
+ }
125
231
  ];
126
232
  const complete = `${action}Complete`;
127
233
  artifacts.push(
128
- { path: `${source}/${complete}_Main.js`, content: await render('FlowEndpointComplete_Main.ejs', { action }) },
129
- { path: `${source}/${complete}_HdrSqs.js`, content: await render('FlowHandler_HdrSqs.ejs', { ...shared, mainFileName: `${complete}_Main`, functionName: complete, queueName: `${action}CompleteHdrSqs` }) }
234
+ {
235
+ path: `${source}/${complete}_Main.js`,
236
+ content: await render('FlowEndpointComplete_Main.ejs', { action })
237
+ },
238
+ {
239
+ path: `${source}/${complete}_HdrSqs.js`,
240
+ content: await render('FlowHandler_HdrSqs.ejs', {
241
+ ...shared,
242
+ mainFileName: `${complete}_Main`,
243
+ functionName: complete,
244
+ queueName: `${action}CompleteHdrSqs`
245
+ })
246
+ }
130
247
  );
131
- functions.push({ type: 'sqs', functionName: `${action}CompleteHdrSqs`, handlerPath: `${handlerRoot}/${complete}_HdrSqs.main`, roleName: 'FlowObjectsRole', queueName: `${action}CompleteHdrSqs`, flowTag: action, flowStepName: 'Complete' });
132
- if (generateCode.some(config => config.codeHookTag === 'beforeLogical')) {
248
+ functions.push({
249
+ type: 'sqs',
250
+ functionName: `${action}CompleteHdrSqs`,
251
+ handlerPath: `${handlerRoot}/${complete}_HdrSqs.main`,
252
+ roleName: 'FlowObjectsRole',
253
+ queueName: `${action}CompleteHdrSqs`,
254
+ flowTag: action,
255
+ flowStepName: 'Complete'
256
+ });
257
+ if (generateCode.some((config) => config.codeHookTag === 'beforeLogical')) {
133
258
  const beforeMain = `${action}BeforeLogical_Main`;
134
259
  artifacts.push(
135
- { path: `${source}/${beforeMain}.js`, content: await render('FlowEndpointBeforeLogical_Main.ejs', shared) },
136
- { path: `${source}/${action}BeforeLogical_HdrSqs.js`, content: await render('FlowHandler_HdrSqs.ejs', { ...shared, mainFileName: beforeMain, functionName: `${action}BeforeLogicalMain`, queueName: `${action}BeforeLogicalHdrSqs` }) }
260
+ {
261
+ path: `${source}/${beforeMain}.js`,
262
+ content: await render('FlowEndpointBeforeLogical_Main.ejs', shared)
263
+ },
264
+ {
265
+ path: `${source}/${action}BeforeLogical_HdrSqs.js`,
266
+ content: await render('FlowHandler_HdrSqs.ejs', {
267
+ ...shared,
268
+ mainFileName: beforeMain,
269
+ functionName: `${action}BeforeLogicalMain`,
270
+ queueName: `${action}BeforeLogicalHdrSqs`
271
+ })
272
+ }
137
273
  );
138
- functions.push({ type: 'sqs', functionName: `${action}BeforeLogicalHdrSqs`, handlerPath: `${handlerRoot}/${action}BeforeLogical_HdrSqs.main`, roleName: 'FlowObjectsRole', queueName: `${action}BeforeLogicalHdrSqs`, flowTag: action, flowStepName: 'BeforeLogical' });
274
+ functions.push({
275
+ type: 'sqs',
276
+ functionName: `${action}BeforeLogicalHdrSqs`,
277
+ handlerPath: `${handlerRoot}/${action}BeforeLogical_HdrSqs.main`,
278
+ roleName: 'FlowObjectsRole',
279
+ queueName: `${action}BeforeLogicalHdrSqs`,
280
+ flowTag: action,
281
+ flowStepName: 'BeforeLogical'
282
+ });
139
283
  }
140
284
  return { artifacts, functions };
141
285
  }
142
286
 
143
287
  function isCrudObject(object) {
144
- return object?.generatedBy === 'userGenerated' || object?.generatedBy === 'systemGenerated';
288
+ return (
289
+ object?.generatedBy === 'userGenerated' ||
290
+ object?.generatedBy === 'systemGenerated'
291
+ );
145
292
  }
146
293
 
147
294
  function upperFirst(value) {
@@ -150,7 +297,7 @@ function upperFirst(value) {
150
297
 
151
298
  async function render(templateName, data) {
152
299
  const template = await readFile(new URL(templateName, TEMPLATE_URL), 'utf8');
153
- return ejs.render(template, data);
300
+ return ejsLib.render(template, data);
154
301
  }
155
302
 
156
303
  function renderFunction(descriptor) {
@@ -4,19 +4,26 @@ const ACTIONS = ['Create', 'Update', 'Delete', 'Get'];
4
4
  const MESSAGE_ATTRIBUTES = ['userId', 'correlationId'];
5
5
 
6
6
  export const dynamicCrudFlowSchemaPaths = ACTIONS.map(
7
- action => `app/src/schemas/FlowSchemas/generateCode/FlowObjects/${action}.js`
7
+ (action) =>
8
+ `app/src/schemas/FlowSchemas/generateCode/FlowObjects/${action}.js`
8
9
  );
9
10
 
10
11
  export function emitDynamicCrudFlowSchemas({ objects, flows = [] }) {
11
12
  if (!Array.isArray(objects) || !Array.isArray(flows)) {
12
13
  throw new TypeError('objects and flows must be arrays');
13
14
  }
14
- if (!objects.some(object => object?.generatedBy === 'userGenerated' || object?.generatedBy === 'systemGenerated')) {
15
+ if (
16
+ !objects.some(
17
+ (object) =>
18
+ object?.generatedBy === 'userGenerated' ||
19
+ object?.generatedBy === 'systemGenerated'
20
+ )
21
+ ) {
15
22
  return [];
16
23
  }
17
24
 
18
25
  return ACTIONS.map((action, index) => {
19
- const flow = createDynamicFlow(action, hasBeforeLogicalStep(flows, action));
26
+ const flow = _createDynamicFlow(action, _hasBeforeLogicalStep(flows, action));
20
27
  return {
21
28
  path: dynamicCrudFlowSchemaPaths[index],
22
29
  content: renderDynamicCrudFlowSchema(action, flow)
@@ -24,19 +31,21 @@ export function emitDynamicCrudFlowSchemas({ objects, flows = [] }) {
24
31
  });
25
32
  }
26
33
 
27
- function createDynamicFlow(action, hasBeforeLogicalStep) {
34
+ function _createDynamicFlow(action, hasBeforeLogicalStep) {
28
35
  const outputTopic = action !== 'Get';
29
36
  const flowSteps = [
30
37
  {
31
38
  stepName: 'start',
32
39
  properties: [],
33
40
  messageAttributes: MESSAGE_ATTRIBUTES,
34
- ...(outputTopic ? {
35
- returnValues: {
36
- properties: [],
37
- messageAttributes: MESSAGE_ATTRIBUTES
38
- }
39
- } : {})
41
+ ...(outputTopic
42
+ ? {
43
+ returnValues: {
44
+ properties: [],
45
+ messageAttributes: MESSAGE_ATTRIBUTES
46
+ }
47
+ }
48
+ : {})
40
49
  }
41
50
  ];
42
51
 
@@ -48,6 +57,7 @@ function createDynamicFlow(action, hasBeforeLogicalStep) {
48
57
  messageAttributes: MESSAGE_ATTRIBUTES
49
58
  });
50
59
  }
60
+
51
61
  if (action !== 'Get') {
52
62
  flowSteps.push({
53
63
  stepName: 'Complete',
@@ -57,12 +67,17 @@ function createDynamicFlow(action, hasBeforeLogicalStep) {
57
67
  });
58
68
  }
59
69
 
70
+ let eventTypes = ['lambdaSyncInv', 'lambdaSyncApi'];
71
+ if (outputTopic) {
72
+ eventTypes = ['ownTopic'];
73
+ }
74
+
60
75
  return {
61
76
  flowTag: action,
62
77
  initiateBy: 'system',
63
78
  handleObj: 'one',
64
79
  statusType: 'none',
65
- event: outputTopic ? ['ownTopic'] : ['lambdaSyncInv', 'lambdaSyncApi'],
80
+ event: eventTypes,
66
81
  outputTopic,
67
82
  stepMessageAttributes: {
68
83
  userId: { propertyName: 'x-correlation-base-user-id', type: 'string' },
@@ -72,12 +87,14 @@ function createDynamicFlow(action, hasBeforeLogicalStep) {
72
87
  };
73
88
  }
74
89
 
75
- function hasBeforeLogicalStep(flows, action) {
76
- return flows.some(flow => {
90
+ function _hasBeforeLogicalStep(flows, action) {
91
+ return flows.some((flow) => {
77
92
  const config = flow?.generatedCodeConfig;
78
- return config?.generatedCodeTag === action.toLowerCase()
79
- && config.codeHookTag === 'beforeLogical'
80
- && Array.isArray(flow.event)
81
- && flow.event.includes(config.invocationType);
93
+ return (
94
+ config?.generatedCodeTag === action.toLowerCase() &&
95
+ config.codeHookTag === 'beforeLogical' &&
96
+ Array.isArray(flow.event) &&
97
+ flow.event.includes(config.invocationType)
98
+ );
82
99
  });
83
100
  }