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

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 (34) hide show
  1. package/package.json +3 -2
  2. package/src/emit/coreFunction/emitCoreFunctionArtifacts.js +3 -0
  3. package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +100 -28
  4. package/src/emit/coreFunction/templates/InitialSetupRunner.ejs +4 -2
  5. package/src/emit/coreFunction/templates/InitialSetupRunner_uploadSchema.ejs +2 -0
  6. package/src/emit/coreFunction/templates/UploadSchema_Main.ejs +2 -0
  7. package/src/emit/custom/customFlows.js +42 -0
  8. package/src/emit/custom/emitCustomFlowApplicationArtifacts.js +44 -14
  9. package/src/emit/custom/templates/triggerCache/CheckTriggerCache_HdrSqs.ejs +15 -10
  10. package/src/emit/function/functionYamlArtifact.js +8 -3
  11. package/src/emit/relationship/templates/ChangeRelationshipComplete_Main.ejs +8 -13
  12. package/src/emit/relationship/templates/ChangeRelationship_Main.ejs +5 -14
  13. package/src/emit/relationship/templates/CreateRelationshipComplete_Main.ejs +8 -13
  14. package/src/emit/relationship/templates/CreateRelationship_Main.ejs +7 -16
  15. package/src/emit/relationship/templates/DeleteRelationshipComplete_Main.ejs +8 -4
  16. package/src/emit/relationship/templates/DeleteRelationship_Main.ejs +6 -24
  17. package/src/emit/relationship/templates/GetRelationshipComplete_Main.ejs +8 -4
  18. package/src/emit/relationship/templates/MoveRelationshipComplete_Main.ejs +8 -15
  19. package/src/emit/relationship/templates/MoveRelationship_Main.ejs +6 -15
  20. package/src/emit/relationship/templates/UpdateRelationshipComplete_Main.ejs +9 -31
  21. package/src/emit/relationship/templates/UpdateRelationship_Main.ejs +6 -15
  22. package/src/emit/resource/emitResourceArtifacts.js +2 -1
  23. package/src/emit/resource/templates/DynamoDBTable_Yaml.ejs +3 -0
  24. package/src/emit/shared/templates/FlowHandler_HdrApi.ejs +6 -6
  25. package/src/emit/shared/templates/FlowHandler_HdrDsq.ejs +18 -13
  26. package/src/emit/shared/templates/FlowHandler_HdrInv.ejs +6 -6
  27. package/src/emit/shared/templates/FlowHandler_HdrSqs.ejs +18 -13
  28. package/src/emit/system/templates/WebSocketComplete_Yaml.ejs +2 -0
  29. package/test/crudApplicationArtifacts.test.js +22 -0
  30. package/test/customFlowApplicationArtifacts.test.js +206 -0
  31. package/test/functionYamlArtifact.test.js +5 -2
  32. package/test/publicApi.test.js +29 -0
  33. package/test/relationshipApplicationArtifacts.test.js +42 -8
  34. package/test/resourceArtifacts.test.js +34 -16
@@ -83,7 +83,7 @@ export default async function createRelationship(
83
83
  relationshipDirection,
84
84
  relationshipProperties,
85
85
  deepPathConditional,
86
- settings
86
+ settings = {}
87
87
  //(<requestParamCreateRel>)
88
88
  //(</requestParamCreateRel>)
89
89
  } = requestParams;
@@ -376,15 +376,6 @@ export default async function createRelationship(
376
376
  return createRelCompleteMsg;
377
377
  }
378
378
 
379
- // before create awaitingStepId per graph storageResource
380
- const linkTypeId = createLinkTypeId(
381
- _izContext,
382
- firstObject.objType,
383
- secondObject.objType,
384
- relType,
385
- relationshipDirection
386
- );
387
-
388
379
  let usedGraphServiceTag = []; // collect used graph serviceTag, use to check duplicate graph serviceTag across graph serverTag
389
380
  let targetGraphStorageResources = []; // collect used graph storageResources, filtered duplicate graphServiceTag from graphServerTag out
390
381
  let awaitingStepIds = [];
@@ -398,12 +389,12 @@ export default async function createRelationship(
398
389
  targetGraphStorageResources.push(targetStorageResource);
399
390
 
400
391
  // awaitingStepId per graphServiceTag
401
- awaitingStepIds.push(
402
- asyncFlowSharedLib.createAwaitingStepId(
392
+ awaitingStepIds.push({
393
+ awaitingStepId: asyncFlowSharedLib.createAwaitingStepId(
403
394
  parentFlowId, // hash id
404
395
  PREFIX.createRel // prefix, use constant further
405
396
  )
406
- );
397
+ });
407
398
  }
408
399
 
409
400
  // if have storageResource.storageType === "dynamoDB" will create relationship here
@@ -453,12 +444,12 @@ export default async function createRelationship(
453
444
  // save awaiting
454
445
  await asyncFlowSharedLib.createAwaitingMultipleSteps(
455
446
  _izContext,
456
- awaitingStepIds, // awaitingStepIds
457
447
  asyncFlowSharedLib.createPendingStepId(
458
- // pendingStepId
459
448
  _izContext.uniqueRequestId, // hash id
460
449
  PREFIX.createRel // prefix, use constant further
461
- )
450
+ ),
451
+ awaitingStepIds,
452
+ {}
462
453
  );
463
454
 
464
455
  // prepare message body
@@ -36,13 +36,17 @@ const { TOPIC_NAME_GENERATE_CODE, PREFIX } = consts;
36
36
 
37
37
  export default async function deleteRelationshipComplete(
38
38
  _izContext,
39
- returnValue,
40
- status,
41
- errorsFound,
42
- graphServiceTag,
39
+ requestParams,
43
40
  passBackProperties = {}
44
41
  ) {
45
42
  try {
43
+ const {
44
+ returnValue,
45
+ status,
46
+ errorsFound,
47
+ graphServiceTag
48
+ } = requestParams;
49
+
46
50
  _izContext.logger.debug('Function:deleteRelationshipComplete', {
47
51
  returnValue: returnValue,
48
52
  status: status,
@@ -262,24 +262,6 @@ export default async function deleteRelationship(
262
262
  return deleteRelCompleteMsg;
263
263
  }
264
264
 
265
- // before create awaitingStepId per graph storageResource
266
- let linkTypeId;
267
- if (
268
- secondObject &&
269
- secondObject.hasOwnProperty('objType') &&
270
- Object.values(secondObject.objType).length > 0
271
- ) {
272
- linkTypeId = createLinkTypeId(
273
- _izContext,
274
- firstObject.objType,
275
- secondObject.objType,
276
- relType,
277
- relationshipDirection
278
- );
279
- } else {
280
- linkTypeId = hash({ objType: firstObject.objType, relType: relType });
281
- }
282
-
283
265
  let usedGraphServiceTag = []; // collect used graph serviceTag, use to check duplicate graph serviceTag across graph serverTag
284
266
  let targetGraphStorageResources = []; // collect used graph storageResources, filtered duplicate graphServiceTag from graphServerTag out
285
267
  let awaitingStepIds = [];
@@ -293,12 +275,12 @@ export default async function deleteRelationship(
293
275
  targetGraphStorageResources.push(targetStorageResource);
294
276
 
295
277
  // awaitingStepId per graphServiceTag
296
- awaitingStepIds.push(
297
- asyncFlowSharedLib.createAwaitingStepId(
278
+ awaitingStepIds.push({
279
+ awaitingStepId: asyncFlowSharedLib.createAwaitingStepId(
298
280
  parentFlowId, // hash id
299
281
  PREFIX.deleteRel // prefix, use constant further
300
282
  )
301
- );
283
+ });
302
284
  } else if (
303
285
  targetStorageResource.storageType === consts.STORAGE_TYPES.dynamoDB
304
286
  ) {
@@ -345,12 +327,12 @@ export default async function deleteRelationship(
345
327
  // save awaiting
346
328
  await asyncFlowSharedLib.createAwaitingMultipleSteps(
347
329
  _izContext,
348
- awaitingStepIds, // awaitingStepIds
349
330
  asyncFlowSharedLib.createPendingStepId(
350
- // pendingStepId
351
331
  _izContext.uniqueRequestId, // hash id
352
332
  PREFIX.deleteRel // prefix, use constant further
353
- )
333
+ ),
334
+ awaitingStepIds,
335
+ {}
354
336
  );
355
337
 
356
338
  // prepare message body
@@ -36,13 +36,17 @@ const { TOPIC_NAME_GENERATE_CODE, PREFIX } = consts;
36
36
 
37
37
  export default async function getRelationshipComplete(
38
38
  _izContext,
39
- returnValue,
40
- status,
41
- errorsFound,
42
- graphServiceTag,
39
+ requestParams,
43
40
  passBackProperties = {}
44
41
  ) {
45
42
  try {
43
+ const {
44
+ returnValue,
45
+ status,
46
+ errorsFound,
47
+ graphServiceTag
48
+ } = requestParams;
49
+
46
50
  _izContext.logger.debug('Function:getRelationshipComplete', {
47
51
  returnValue: returnValue,
48
52
  status: status,
@@ -36,13 +36,17 @@ const { TOPIC_NAME_GENERATE_CODE, PREFIX } = consts;
36
36
 
37
37
  export default async function <%- functionName %>(
38
38
  _izContext,
39
- returnValue,
40
- status,
41
- errorsFound,
42
- graphServiceTag,
39
+ requestParams,
43
40
  passBackProperties = {}
44
41
  ) {
45
42
  try {
43
+ const {
44
+ returnValue,
45
+ status,
46
+ errorsFound,
47
+ graphServiceTag
48
+ } = requestParams;
49
+
46
50
  _izContext.logger.debug('Function:<%- functionName %>', {
47
51
  returnValue: returnValue,
48
52
  status: status,
@@ -51,17 +55,6 @@ export default async function <%- functionName %>(
51
55
  passBackProperties: passBackProperties
52
56
  });
53
57
 
54
- // start create awaitingStepId
55
- const linkTypeId = createLinkTypeId(
56
- _izContext,
57
- returnValue.requestParams.firstObject.objType,
58
- returnValue.requestParams.secondObject.objType,
59
- returnValue.requestParams.relType,
60
- returnValue.requestParams.relationshipProperties,
61
- returnValue.requestParams.relationshipDirection,
62
- returnValue.requestParams.moveObject
63
- );
64
-
65
58
  let awaitingStepId = asyncFlowSharedLib.createAwaitingStepId(
66
59
  returnValue.parentFlowId, // hash id
67
60
  PREFIX.changeRel // prefix, use constant further
@@ -382,15 +382,6 @@ export default async function moveRelationship(
382
382
  return moveRelCompleteMsg;
383
383
  }
384
384
 
385
- // before create awaitingStepId per graph storageResource
386
- const linkTypeId = createLinkTypeId(
387
- _izContext,
388
- firstObject.objType,
389
- secondObject.objType,
390
- relType,
391
- relationshipDirection
392
- );
393
-
394
385
  let usedGraphServiceTag = []; // collect used graph serviceTag, use to check duplicate graph serviceTag across graph serverTag
395
386
  let targetGraphStorageResources = []; // collect used graph storageResources, filtered duplicate graphServiceTag from graphServerTag out
396
387
  let awaitingStepIds = [];
@@ -404,12 +395,12 @@ export default async function moveRelationship(
404
395
  targetGraphStorageResources.push(targetStorageResource);
405
396
 
406
397
  // awaitingStepId per graphServiceTag
407
- awaitingStepIds.push(
408
- asyncFlowSharedLib.createAwaitingStepId(
398
+ awaitingStepIds.push({
399
+ awaitingStepId: asyncFlowSharedLib.createAwaitingStepId(
409
400
  parentFlowId, // hash id
410
401
  PREFIX.changeRel // prefix, use constant further
411
402
  )
412
- );
403
+ });
413
404
  }
414
405
  }
415
406
 
@@ -417,12 +408,12 @@ export default async function moveRelationship(
417
408
  // save awaiting
418
409
  await asyncFlowSharedLib.createAwaitingMultipleSteps(
419
410
  _izContext,
420
- awaitingStepIds, // awaitingStepIds
421
411
  asyncFlowSharedLib.createPendingStepId(
422
- // pendingStepId
423
412
  _izContext.uniqueRequestId, // hash id
424
413
  PREFIX.changeRel // prefix, use constant further
425
- )
414
+ ),
415
+ awaitingStepIds,
416
+ {}
426
417
  );
427
418
 
428
419
  // prepare message body
@@ -36,14 +36,18 @@ const { TOPIC_NAME_GENERATE_CODE, PREFIX } = consts;
36
36
 
37
37
  export default async function updateRelationshipComplete(
38
38
  _izContext,
39
- returnValue,
40
- status,
41
- errorsFound,
42
- graphServiceTag,
39
+ requestParams,
43
40
  passBackProperties = {}
44
41
  // callingFlowConfig = {}
45
42
  ) {
46
43
  try {
44
+ const {
45
+ returnValue,
46
+ status,
47
+ errorsFound,
48
+ graphServiceTag
49
+ } = requestParams;
50
+
47
51
  _izContext.logger.debug('Function:updateRelationshipComplete', {
48
52
  returnValue: returnValue,
49
53
  status: status,
@@ -53,34 +57,8 @@ export default async function updateRelationshipComplete(
53
57
  // callingFlowConfig: callingFlowConfig
54
58
  });
55
59
 
56
- let linkTypeId;
57
- // start create awaitingStepId
58
- if (
59
- returnValue.requestParams.hasOwnProperty('secondObject') &&
60
- Object.values(returnValue.requestParams.secondObject.objType).length > 0
61
- ) {
62
- linkTypeId = createLinkTypeId(
63
- _izContext,
64
- returnValue.requestParams.firstObject.objType,
65
- returnValue.requestParams.secondObject.objType,
66
- returnValue.requestParams.relType,
67
- returnValue.requestParams.relationshipDirection
68
- );
69
- } else {
70
- linkTypeId = hash({
71
- firstObject: returnValue.requestParams.firstObject.objType,
72
- relType: returnValue.requestParams.relType
73
- });
74
- }
75
-
76
60
  let awaitingStepId = asyncFlowSharedLib.createAwaitingStepId(
77
- hash({
78
- linkTypeId,
79
- relId: returnValue.requestParams.relId,
80
- relationshipProperties:
81
- returnValue.requestParams.relationshipProperties,
82
- graphServiceTag: graphServiceTag
83
- }), // hash id
61
+ returnValue.parentFlowId, // hash id
84
62
  PREFIX.updateRel // prefix, use constant further
85
63
  );
86
64
 
@@ -338,15 +338,6 @@ export default async function updateRelationship(
338
338
  return updateCompleteMsg;
339
339
  }
340
340
 
341
- // before create awaitingStepId per graph storageResource
342
- const linkTypeId = createLinkTypeId(
343
- _izContext,
344
- firstObject.objType,
345
- secondObject.objType,
346
- relType,
347
- relationshipDirection
348
- );
349
-
350
341
  let usedGraphServiceTag = []; // collect used graph serviceName, use to check duplicate graph serviceName across graph serverTag
351
342
  let targetGraphStorageResources = []; // collect used graph storageResources, filtered duplicate graphServiceTag from graphServerTag out
352
343
  let awaitingStepIds = [];
@@ -360,12 +351,12 @@ export default async function updateRelationship(
360
351
  targetGraphStorageResources.push(targetStorageResource);
361
352
 
362
353
  // awaitingStepId per graphServiceTag
363
- awaitingStepIds.push(
364
- asyncFlowSharedLib.createAwaitingStepId(
354
+ awaitingStepIds.push({
355
+ awaitingStepId: asyncFlowSharedLib.createAwaitingStepId(
365
356
  parentFlowId, // hash id
366
357
  PREFIX.updateRel // prefix, use constant further
367
358
  )
368
- );
359
+ });
369
360
  } else if (
370
361
  storageResource.storageType === consts.STORAGE_TYPES.dynamoDB
371
362
  ) {
@@ -411,12 +402,12 @@ export default async function updateRelationship(
411
402
  // save awaiting
412
403
  await asyncFlowSharedLib.createAwaitingMultipleSteps(
413
404
  _izContext,
414
- awaitingStepIds, // awaitingStepIds
415
405
  asyncFlowSharedLib.createPendingStepId(
416
- // pendingStepId
417
406
  _izContext.uniqueRequestId, // hash id
418
407
  PREFIX.updateRel // prefix, use constant further
419
- )
408
+ ),
409
+ awaitingStepIds,
410
+ {}
420
411
  );
421
412
 
422
413
  // prepare message body
@@ -255,7 +255,8 @@ function createResourceState({ objects, relationships, flows }) {
255
255
  const relationshipTableNames = [...collectTables(relationships).keys()];
256
256
  const tableMap = new Map([
257
257
  ...collectTables(objects),
258
- ...collectTables(relationships)
258
+ ...collectTables(relationships),
259
+ ...collectTables(flows)
259
260
  ]);
260
261
  const externalDynamoTables = objects.flatMap(
261
262
  (object) => object.externalDynamoResources ?? []
@@ -18,3 +18,6 @@
18
18
  - AttributeName: '<%- sk %>'
19
19
  KeyType: 'RANGE'
20
20
  <% } %>
21
+ #<#<%- tableName %>TableSetting#>
22
+ #<#/<%- tableName %>TableSetting#>
23
+
@@ -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' %>'<% if (typeof prop.default !== 'undefined') { %>, default: <%- typeof prop.default === 'string' ? `'${prop.default.replace(/'/g, "\\'")}'` : JSON.stringify(prop.default) %><% } %> }<%- 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,44 @@ 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 %>: {
34
- type: '<%- prop.type || 'string' %>'
35
- }
36
- <% }) %>
32
+ <%_ startConfig.properties.forEach((prop, index) => { _%>
33
+ <%- /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(prop.propertyName) ? prop.propertyName : `'${prop.propertyName}'` %>: {
34
+ type: '<%- prop.type || 'string' %>'<% if (typeof prop.default !== 'undefined') { %>,
35
+ default: <%- typeof prop.default === 'string' ? `'${prop.default.replace(/'/g, "\\'")}'` : JSON.stringify(prop.default) %><% } %>
36
+ }<%- index < startConfig.properties.length - 1 ? ',' : '' %>
37
+ <%_ }) _%>
37
38
  },
38
39
  required: [<%- startConfig.properties.filter(p => p.required === true).map(p => `'${p.propertyName}'`).join(', ') %>]
39
- <% } -%>
40
+ <%_ } _%>
41
+ //(<validatorSchema>)
40
42
  //(</validatorSchema>)
41
43
  };
42
44
 
43
- <% if (typeof startConfig !== 'undefined' && startConfig !== null && startConfig.messageAttributes && startConfig.messageAttributes.length > 0) { -%>
45
+ <%_ if (typeof startConfig !== 'undefined' && startConfig !== null && startConfig.messageAttributes && startConfig.messageAttributes.length > 0) { _%>
44
46
  let messageAttributeValidatorSchema = {
45
47
  type: 'object',
46
48
  properties: {
47
- <% startConfig.messageAttributes.forEach((prop, index) => { %> <%- prop.propertyName %>: {
49
+ <%_ startConfig.messageAttributes.forEach((prop, index) => { _%>
50
+ <%- /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(prop.propertyName) ? prop.propertyName : `'${prop.propertyName}'` %>: {
48
51
  type: 'object',
49
52
  properties: {
50
53
  Type: { type: 'string' },
51
54
  Value: { type: '<%- prop.type || 'string' %>' }
52
55
  },
53
56
  required: ['Type', 'Value']
54
- }
55
- <% }) %>
57
+ }<%- index < startConfig.messageAttributes.length - 1 ? ',' : '' %>
58
+ <%_ }) _%>
56
59
  },
57
60
  required: [<%- startConfig.messageAttributes.filter(p => p.required === true).map(p => `'${p.propertyName}'`).join(', ') %>]
61
+ //(<messageAttributeValidatorSchema>)
62
+ //(</messageAttributeValidatorSchema>)
58
63
  };
59
- <% } else { -%>
64
+ <%_ } else { _%>
60
65
  let messageAttributeValidatorSchema = null;
61
- <% } -%>
66
+ <%_ } _%>
62
67
 
63
68
  middleware.setValidatorSchema(
64
69
  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' %>'<% if (typeof prop.default !== 'undefined') { %>, default: <%- typeof prop.default === 'string' ? `'${prop.default.replace(/'/g, "\\'")}'` : JSON.stringify(prop.default) %><% } %> }<%- 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,44 @@ 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 %>: {
34
- type: '<%- prop.type || 'string' %>'
35
- }
36
- <% }) %>
32
+ <%_ startConfig.properties.forEach((prop, index) => { _%>
33
+ <%- /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(prop.propertyName) ? prop.propertyName : `'${prop.propertyName}'` %>: {
34
+ type: '<%- prop.type || 'string' %>'<% if (typeof prop.default !== 'undefined') { %>,
35
+ default: <%- typeof prop.default === 'string' ? `'${prop.default.replace(/'/g, "\\'")}'` : JSON.stringify(prop.default) %><% } %>
36
+ }<%- index < startConfig.properties.length - 1 ? ',' : '' %>
37
+ <%_ }) _%>
37
38
  },
38
39
  required: [<%- startConfig.properties.filter(p => p.required === true).map(p => `'${p.propertyName}'`).join(', ') %>]
39
- <% } -%>
40
+ <%_ } _%>
41
+ //(<validatorSchema>)
40
42
  //(</validatorSchema>)
41
43
  };
42
44
 
43
- <% if (typeof startConfig !== 'undefined' && startConfig !== null && startConfig.messageAttributes && startConfig.messageAttributes.length > 0) { -%>
45
+ <%_ if (typeof startConfig !== 'undefined' && startConfig !== null && startConfig.messageAttributes && startConfig.messageAttributes.length > 0) { _%>
44
46
  let messageAttributeValidatorSchema = {
45
47
  type: 'object',
46
48
  properties: {
47
- <% startConfig.messageAttributes.forEach((prop, index) => { %> <%- prop.propertyName %>: {
49
+ <%_ startConfig.messageAttributes.forEach((prop, index) => { _%>
50
+ <%- /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(prop.propertyName) ? prop.propertyName : `'${prop.propertyName}'` %>: {
48
51
  type: 'object',
49
52
  properties: {
50
53
  Type: { type: 'string' },
51
54
  Value: { type: '<%- prop.type || 'string' %>' }
52
55
  },
53
56
  required: ['Type', 'Value']
54
- }
55
- <% }) %>
57
+ }<%- index < startConfig.messageAttributes.length - 1 ? ',' : '' %>
58
+ <%_ }) _%>
56
59
  },
57
60
  required: [<%- startConfig.messageAttributes.filter(p => p.required === true).map(p => `'${p.propertyName}'`).join(', ') %>]
61
+ //(<messageAttributeValidatorSchema>)
62
+ //(</messageAttributeValidatorSchema>)
58
63
  };
59
- <% } else { -%>
64
+ <%_ } else { _%>
60
65
  let messageAttributeValidatorSchema = null;
61
- <% } -%>
66
+ <%_ } _%>
62
67
  middleware.setValidatorSchema(recordHandlerSharedLib.baseValidatorSchema());
63
68
 
64
69
  export const main = middleware.wrap(async (event, context) => {
@@ -6,6 +6,7 @@ WebSocketCompleteHdrSqs:
6
6
  - sqs:
7
7
  arn: arn:aws:sqs:${self:custom.iz_region}:${self:custom.iz_accountId}:${self:custom.iz_resourcePrefix}WebSocketCompleteHdrSqs
8
8
  batchSize: 10
9
+ #<#WebSocketCompleteHdrSqsFilterPatterns#>
9
10
  filterPatterns:
10
11
  - body:
11
12
  MessageAttributes:
@@ -17,3 +18,4 @@ WebSocketCompleteHdrSqs:
17
18
  callingFlow:
18
19
  Value:
19
20
  - exists: false
21
+ #<#/WebSocketCompleteHdrSqsFilterPatterns#>
@@ -137,6 +137,27 @@ test('preserves function-setting hooks across CRUD regeneration', async () => {
137
137
  /#<#CreateCompleteHdrSqsFunctionSetting#>\n memorySize: 512\n #<#\/CreateCompleteHdrSqsFunctionSetting#>/
138
138
  );
139
139
 
140
+ const customFilterHook =
141
+ ' #<#CreateCompleteHdrSqsFilterPatterns#>\n filterPatterns:\n - body: custom\n #<#/CreateCompleteHdrSqsFilterPatterns#>';
142
+ const withFilterHook = yaml.replace(
143
+ / #<#CreateCompleteHdrSqsFilterPatterns#>[\s\S]*?#<#\/CreateCompleteHdrSqsFilterPatterns#>/,
144
+ customFilterHook
145
+ );
146
+ assert.notEqual(
147
+ yaml,
148
+ withFilterHook,
149
+ 'filterPatterns hook placeholder must exist in generated YAML'
150
+ );
151
+ await writeFile(yamlPath, withFilterHook);
152
+
153
+ await generateCrudApplicationArtifacts(rootPath, { serviceTag: 'orders' });
154
+
155
+ yaml = await readFile(yamlPath, 'utf8');
156
+ assert.match(
157
+ yaml,
158
+ /#<#CreateCompleteHdrSqsFilterPatterns#>\n filterPatterns:\n - body: custom\n #<#\/CreateCompleteHdrSqsFilterPatterns#>/
159
+ );
160
+
140
161
  const conflictPath = join(
141
162
  rootPath,
142
163
  'app/src/generatedCode/FlowObjects/Create/source/Create_Main.js'
@@ -151,6 +172,7 @@ test('preserves function-setting hooks across CRUD regeneration', async () => {
151
172
  assert.equal(await readFile(yamlPath, 'utf8'), yaml);
152
173
  });
153
174
 
175
+
154
176
  test('removes managed CRUD artifacts when no applicable object remains', async () => {
155
177
  const rootPath = await createProject(true);
156
178
  await generateCrudApplicationArtifacts(rootPath, { serviceTag: 'orders' });