@izara_project/izara-core-generate-service-code 1.0.72 → 1.0.73

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.72",
3
+ "version": "1.0.73",
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": {
@@ -26,12 +26,13 @@
26
26
  "@izara_project/izara-shared-core": "^1.0.13",
27
27
  "ejs": "^6.0.1",
28
28
  "js-beautify": "^2.0.3",
29
+ "ws": "^8.21.2",
29
30
  "yaml": "^2.9.0"
30
31
  },
31
32
  "devDependencies": {
32
33
  "@izara_project/izara-core-library-logger": "^1.0.11",
33
34
  "@izara_project/izara-core-library-service-schemas": "1.0.161",
34
- "@izara_project/izara-shared-service-schemas": "^1.0.69",
35
+ "@izara_project/izara-shared-service-schemas": "^1.0.70",
35
36
  "jest": "^30.4.2",
36
37
  "prettier": "^3.9.6",
37
38
  "prettier-plugin-ejs": "^1.0.3"
@@ -27,6 +27,8 @@ if (fs.existsSync(configPath)) {
27
27
  process.env.iz_accountId = izConfig.iz_accountId || process.env.iz_accountId;
28
28
  process.env.iz_serviceTag =
29
29
  izConfig.iz_serviceTag || process.env.iz_serviceTag;
30
+ process.env.iz_serviceSchemaBucketName =
31
+ izConfig.iz_serviceSchemaBucketName || process.env.iz_serviceSchemaBucketName;
30
32
  process.env.iz_resourcePrefix =
31
33
  izConfig.iz_resourcePrefix ||
32
34
  process.env.iz_resourcePrefix ||
@@ -53,11 +55,11 @@ function _createContext() {
53
55
  _izContext.correlationIds = new CorrelationIds();
54
56
  _izContext.correlationIds.set(
55
57
  consts.BASE_USER_ID,
56
- process.env.iz_userId || ''
58
+ process.env.iz_userId || 'system'
57
59
  );
58
60
  _izContext.correlationIds.set(
59
61
  consts.RESOURCE_USE_USER_ID,
60
- process.env.iz_userId || ''
62
+ process.env.iz_userId || 'system'
61
63
  );
62
64
  _izContext.logger = Logger;
63
65
  return _izContext;
@@ -657,11 +657,28 @@ function stepConfig(flow, step) {
657
657
  };
658
658
  }
659
659
 
660
- function mapFields(names = [], definitions = {}) {
661
- return names.map((name) => ({
662
- propertyName: name,
663
- ...(definitions?.[name] ?? {})
664
- }));
660
+ function mapFields(items = [], definitions = {}) {
661
+ return items.map((item) => {
662
+ if (typeof item === 'string') {
663
+ const def = definitions?.[item] ?? {};
664
+ return {
665
+ propertyName: item,
666
+ required: def.required ?? false,
667
+ ...def
668
+ };
669
+ }
670
+ if (typeof item === 'object' && item !== null) {
671
+ const name = item.key ?? item.propertyName;
672
+ const def = definitions?.[name] ?? {};
673
+ return {
674
+ propertyName: name,
675
+ required: item.required ?? def.required ?? false,
676
+ ...def,
677
+ ...item
678
+ };
679
+ }
680
+ return item;
681
+ });
665
682
  }
666
683
 
667
684
  function isS3Only(flow) {
@@ -6,33 +6,37 @@ import callingFlowSharedLib from '@izara_project/izara-core-library-calling-flow
6
6
  import <%- functionName %> from './<%- functionName %>_Main.js';
7
7
 
8
8
  let perRecordsValidatorSchema = {
9
- <% if (typeof startConfig !== 'undefined' && startConfig !== null && startConfig.properties && startConfig.properties.length > 0) { -%>
9
+ <%_ if (typeof startConfig !== 'undefined' && startConfig !== null && startConfig.properties && startConfig.properties.length > 0) { _%>
10
10
  type: 'object',
11
11
  properties: {
12
- <% startConfig.properties.forEach((prop, index) => { %> <%- prop.propertyName %>: {
12
+ <%_ startConfig.properties.forEach((prop, index) => { _%>
13
+ <%- /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(prop.propertyName) ? prop.propertyName : `'${prop.propertyName}'` %>: {
13
14
  type: '<%- prop.type || 'string' %>'
14
- }
15
- <% }) %>
15
+ }<%- index < startConfig.properties.length - 1 ? ',' : '' %>
16
+ <%_ }) _%>
16
17
  },
17
18
  required: [<%- startConfig.properties.filter(p => p.required === true).map(p => `'${p.propertyName}'`).join(', ') %>]
18
- <% } -%>
19
+ <%_ } _%>
19
20
  };
20
21
 
21
- <% if (typeof startConfig !== 'undefined' && startConfig !== null && startConfig.messageAttributes && startConfig.messageAttributes.length > 0) { -%>
22
+ <%_ if (typeof startConfig !== 'undefined' && startConfig !== null && startConfig.messageAttributes && startConfig.messageAttributes.length > 0) { _%>
22
23
  let messageAttributeValidatorSchema = {
23
24
  type: 'object',
24
25
  properties: {
25
- <% startConfig.messageAttributes.forEach((prop, index) => { %> <%- prop.propertyName %>: {
26
+ <%_ startConfig.messageAttributes.forEach((prop, index) => { _%>
27
+ <%- /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(prop.propertyName) ? prop.propertyName : `'${prop.propertyName}'` %>: {
26
28
  type: 'object',
27
29
  properties: {
28
30
  Type: { type: 'string' },
29
31
  Value: { type: '<%- prop.type || 'string' %>' }
30
32
  },
31
33
  required: ['Type', 'Value']
32
- }
33
- <% }) %>
34
+ }<%- index < startConfig.messageAttributes.length - 1 ? ',' : '' %>
35
+ <%_ }) _%>
34
36
  },
35
37
  required: [<%- startConfig.messageAttributes.filter(p => p.required === true).map(p => `'${p.propertyName}'`).join(', ') %>]
38
+ //(<messageAttributeValidatorSchema>)
39
+ //(</messageAttributeValidatorSchema>)
36
40
  };
37
41
  <% } else { -%>
38
42
  let messageAttributeValidatorSchema = null;
@@ -9,16 +9,16 @@ import <%= functionName %> from './<%= mainFileName %>.js';
9
9
  //(</optionalRequire>)
10
10
 
11
11
  const validatorSchema = {
12
- //(<validatorSchema>)
13
- <% if (typeof startConfig !== 'undefined' && startConfig !== null && startConfig.properties && startConfig.properties.length > 0) { -%>
12
+ <%_ if (typeof startConfig !== 'undefined' && startConfig !== null && startConfig.properties && startConfig.properties.length > 0) { _%>
14
13
  type: 'object',
15
14
  properties: {
16
- <% startConfig.properties.forEach(prop => { -%>
17
- <%- prop.propertyName %>: { type: '<%- prop.type || 'string' %>' }
18
- <% }) -%>
15
+ <%_ startConfig.properties.forEach((prop, index) => { _%>
16
+ <%- /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(prop.propertyName) ? prop.propertyName : `'${prop.propertyName}'` %>: { type: '<%- prop.type || 'string' %>' }<%- index < startConfig.properties.length - 1 ? ',' : '' %>
17
+ <%_ }) _%>
19
18
  },
20
19
  required: [<%- startConfig.properties.filter(p => p.required === true).map(p => `'${p.propertyName}'`).join(', ') %>]
21
- <% } -%>
20
+ <%_ } _%>
21
+ //(<validatorSchema>)
22
22
  //(</validatorSchema>)
23
23
  };
24
24
 
@@ -26,39 +26,43 @@ import <%= functionName %> from './<%= mainFileName %>.js';
26
26
 
27
27
  // validate event properties in body.Message of sqs event
28
28
  let perRecordsValidatorSchema = {
29
- //(<validatorSchema>)
30
- <% if (typeof startConfig !== 'undefined' && startConfig !== null && startConfig.properties && startConfig.properties.length > 0) { -%>
29
+ <%_ if (typeof startConfig !== 'undefined' && startConfig !== null && startConfig.properties && startConfig.properties.length > 0) { _%>
31
30
  type: 'object',
32
31
  properties: {
33
- <% startConfig.properties.forEach((prop, index) => { %> <%- prop.propertyName %>: {
32
+ <%_ startConfig.properties.forEach((prop, index) => { _%>
33
+ <%- /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(prop.propertyName) ? prop.propertyName : `'${prop.propertyName}'` %>: {
34
34
  type: '<%- prop.type || 'string' %>'
35
- }
36
- <% }) %>
35
+ }<%- index < startConfig.properties.length - 1 ? ',' : '' %>
36
+ <%_ }) _%>
37
37
  },
38
38
  required: [<%- startConfig.properties.filter(p => p.required === true).map(p => `'${p.propertyName}'`).join(', ') %>]
39
- <% } -%>
39
+ <%_ } _%>
40
+ //(<validatorSchema>)
40
41
  //(</validatorSchema>)
41
42
  };
42
43
 
43
- <% if (typeof startConfig !== 'undefined' && startConfig !== null && startConfig.messageAttributes && startConfig.messageAttributes.length > 0) { -%>
44
+ <%_ if (typeof startConfig !== 'undefined' && startConfig !== null && startConfig.messageAttributes && startConfig.messageAttributes.length > 0) { _%>
44
45
  let messageAttributeValidatorSchema = {
45
46
  type: 'object',
46
47
  properties: {
47
- <% startConfig.messageAttributes.forEach((prop, index) => { %> <%- prop.propertyName %>: {
48
+ <%_ startConfig.messageAttributes.forEach((prop, index) => { _%>
49
+ <%- /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(prop.propertyName) ? prop.propertyName : `'${prop.propertyName}'` %>: {
48
50
  type: 'object',
49
51
  properties: {
50
52
  Type: { type: 'string' },
51
53
  Value: { type: '<%- prop.type || 'string' %>' }
52
54
  },
53
55
  required: ['Type', 'Value']
54
- }
55
- <% }) %>
56
+ }<%- index < startConfig.messageAttributes.length - 1 ? ',' : '' %>
57
+ <%_ }) _%>
56
58
  },
57
59
  required: [<%- startConfig.messageAttributes.filter(p => p.required === true).map(p => `'${p.propertyName}'`).join(', ') %>]
60
+ //(<messageAttributeValidatorSchema>)
61
+ //(</messageAttributeValidatorSchema>)
58
62
  };
59
- <% } else { -%>
63
+ <%_ } else { _%>
60
64
  let messageAttributeValidatorSchema = null;
61
- <% } -%>
65
+ <%_ } _%>
62
66
 
63
67
  middleware.setValidatorSchema(
64
68
  recordHandlerSharedLib.baseValidatorSchema({
@@ -6,16 +6,16 @@ import <%= functionName %> from './<%= mainFileName %>.js';
6
6
  //(</optionalRequire>)
7
7
 
8
8
  const validatorSchema = {
9
- //(<validatorSchema>)
10
- <% if (typeof startConfig !== 'undefined' && startConfig !== null && startConfig.properties && startConfig.properties.length > 0) { -%>
9
+ <%_ if (typeof startConfig !== 'undefined' && startConfig !== null && startConfig.properties && startConfig.properties.length > 0) { _%>
11
10
  type: 'object',
12
11
  properties: {
13
- <% startConfig.properties.forEach(prop => { -%>
14
- <%- prop.propertyName %>: { type: '<%- prop.type || 'string' %>' }
15
- <% }) -%>
12
+ <%_ startConfig.properties.forEach((prop, index) => { _%>
13
+ <%- /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(prop.propertyName) ? prop.propertyName : `'${prop.propertyName}'` %>: { type: '<%- prop.type || 'string' %>' }<%- index < startConfig.properties.length - 1 ? ',' : '' %>
14
+ <%_ }) _%>
16
15
  },
17
16
  required: [<%- startConfig.properties.filter(p => p.required === true).map(p => `'${p.propertyName}'`).join(', ') %>]
18
- <% } -%>
17
+ <%_ } _%>
18
+ //(<validatorSchema>)
19
19
  //(</validatorSchema>)
20
20
  };
21
21
 
@@ -26,39 +26,43 @@ import <%= functionName %> from './<%= mainFileName %>.js';
26
26
 
27
27
  // validate event properties in body.Message of sqs event
28
28
  let perRecordsValidatorSchema = {
29
- //(<validatorSchema>)
30
- <% if (typeof startConfig !== 'undefined' && startConfig !== null && startConfig.properties && startConfig.properties.length > 0) { -%>
29
+ <%_ if (typeof startConfig !== 'undefined' && startConfig !== null && startConfig.properties && startConfig.properties.length > 0) { _%>
31
30
  type: 'object',
32
31
  properties: {
33
- <% startConfig.properties.forEach((prop, index) => { %> <%- prop.propertyName %>: {
32
+ <%_ startConfig.properties.forEach((prop, index) => { _%>
33
+ <%- /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(prop.propertyName) ? prop.propertyName : `'${prop.propertyName}'` %>: {
34
34
  type: '<%- prop.type || 'string' %>'
35
- }
36
- <% }) %>
35
+ }<%- index < startConfig.properties.length - 1 ? ',' : '' %>
36
+ <%_ }) _%>
37
37
  },
38
38
  required: [<%- startConfig.properties.filter(p => p.required === true).map(p => `'${p.propertyName}'`).join(', ') %>]
39
- <% } -%>
39
+ <%_ } _%>
40
+ //(<validatorSchema>)
40
41
  //(</validatorSchema>)
41
42
  };
42
43
 
43
- <% if (typeof startConfig !== 'undefined' && startConfig !== null && startConfig.messageAttributes && startConfig.messageAttributes.length > 0) { -%>
44
+ <%_ if (typeof startConfig !== 'undefined' && startConfig !== null && startConfig.messageAttributes && startConfig.messageAttributes.length > 0) { _%>
44
45
  let messageAttributeValidatorSchema = {
45
46
  type: 'object',
46
47
  properties: {
47
- <% startConfig.messageAttributes.forEach((prop, index) => { %> <%- prop.propertyName %>: {
48
+ <%_ startConfig.messageAttributes.forEach((prop, index) => { _%>
49
+ <%- /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(prop.propertyName) ? prop.propertyName : `'${prop.propertyName}'` %>: {
48
50
  type: 'object',
49
51
  properties: {
50
52
  Type: { type: 'string' },
51
53
  Value: { type: '<%- prop.type || 'string' %>' }
52
54
  },
53
55
  required: ['Type', 'Value']
54
- }
55
- <% }) %>
56
+ }<%- index < startConfig.messageAttributes.length - 1 ? ',' : '' %>
57
+ <%_ }) _%>
56
58
  },
57
59
  required: [<%- startConfig.messageAttributes.filter(p => p.required === true).map(p => `'${p.propertyName}'`).join(', ') %>]
60
+ //(<messageAttributeValidatorSchema>)
61
+ //(</messageAttributeValidatorSchema>)
58
62
  };
59
- <% } else { -%>
63
+ <%_ } else { _%>
60
64
  let messageAttributeValidatorSchema = null;
61
- <% } -%>
65
+ <%_ } _%>
62
66
  middleware.setValidatorSchema(recordHandlerSharedLib.baseValidatorSchema());
63
67
 
64
68
  export const main = middleware.wrap(async (event, context) => {
@@ -602,3 +602,74 @@ async function createTriggerCacheProject(triggerFlowTypes) {
602
602
  );
603
603
  return rootPath;
604
604
  }
605
+
606
+ test('supports step-level required overrides in flowSteps properties and messageAttributes', async () => {
607
+ const rootPath = await mkdtemp(
608
+ join(tmpdir(), 'generate-service-code-v2-step-required-')
609
+ );
610
+ roots.add(rootPath);
611
+ const schemaRoot = join(rootPath, 'app/src/schemas/FlowSchemas');
612
+ await mkdir(schemaRoot, { recursive: true });
613
+
614
+ await writeFile(
615
+ join(schemaRoot, 'Reservations.js'),
616
+ `export default {
617
+ flowTag: 'Reservations',
618
+ event: ['ownTopic'],
619
+ stepProperties: {
620
+ reservationItems: { propertyName: 'reservationItems', type: 'array' }
621
+ },
622
+ stepMessageAttributes: {
623
+ userId: { propertyName: 'x-correlation-base-user-id', type: 'string' }
624
+ },
625
+ flowSteps: [
626
+ {
627
+ stepName: 'Start',
628
+ properties: [{ key: 'reservationItems', required: true }],
629
+ messageAttributes: [{ key: 'userId', required: true }]
630
+ },
631
+ {
632
+ stepName: 'Complete',
633
+ event: ['extTopic'],
634
+ properties: ['reservationItems'],
635
+ messageAttributes: ['userId']
636
+ }
637
+ ]
638
+ };\n`
639
+ );
640
+
641
+ const result = await generateCustomFlowApplicationArtifacts(rootPath);
642
+ assert.ok(result);
643
+
644
+ const startHdrContent = await readFile(
645
+ join(
646
+ rootPath,
647
+ 'app/src/generatedCode/FlowSchemas/Reservations/source/Reservations_HdrSqs.js'
648
+ ),
649
+ 'utf8'
650
+ );
651
+ assert.match(
652
+ startHdrContent,
653
+ /perRecordsValidatorSchema = {[\s\S]*required: \['reservationItems'\]/
654
+ );
655
+ assert.match(
656
+ startHdrContent,
657
+ /messageAttributeValidatorSchema = {[\s\S]*required: \['x-correlation-base-user-id'\]/
658
+ );
659
+
660
+ const completeHdrContent = await readFile(
661
+ join(
662
+ rootPath,
663
+ 'app/src/generatedCode/FlowSchemas/Reservations/source/ReservationsComplete_HdrSqs.js'
664
+ ),
665
+ 'utf8'
666
+ );
667
+ assert.match(
668
+ completeHdrContent,
669
+ /perRecordsValidatorSchema = {[\s\S]*required: \[\]/
670
+ );
671
+ assert.match(
672
+ completeHdrContent,
673
+ /messageAttributeValidatorSchema = {[\s\S]*required: \[\]/
674
+ );
675
+ });