@izara_project/izara-core-generate-service-code 1.0.86 → 1.0.88

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/package.json +1 -1
  2. package/src/compile/loadSchemas.js +45 -10
  3. package/src/emit/coreFunction/emitCoreFunctionArtifacts.js +1 -1
  4. package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +22 -15
  5. package/src/emit/crud/crudActionPlan.js +47 -6
  6. package/src/emit/crud/emitCrudApplicationArtifacts.js +63 -3
  7. package/src/emit/crud/emitDynamicCrudFlowSchemas.js +6 -4
  8. package/src/emit/crud/templates/CreateAfterHookCallback_Main.ejs +121 -0
  9. package/src/emit/crud/templates/CreateBeforeHookCallback_Main.ejs +108 -0
  10. package/src/emit/crud/templates/CreateEndpoint_Main.ejs +138 -335
  11. package/src/emit/crud/templates/CreateLogicalLib.ejs +205 -42
  12. package/src/emit/crud/templates/CreateNodeCallback_Main.ejs +80 -0
  13. package/src/emit/crud/templates/DeleteBeforeHookCallback_Main.ejs +99 -0
  14. package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +153 -182
  15. package/src/emit/crud/templates/DeleteLogicalLib.ejs +132 -26
  16. package/src/emit/crud/templates/UpdateBeforeHookCallback_Main.ejs +112 -0
  17. package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +166 -188
  18. package/src/emit/crud/templates/UpdateLogicalLib.ejs +2 -2
  19. package/src/emit/custom/customFlows.js +3 -1
  20. package/src/emit/function/functionYamlArtifact.js +4 -2
  21. package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +0 -3
  22. package/src/emit/rbac/emitRbacApplicationArtifacts.js +1 -116
  23. package/src/emit/rbac/templates/CancelUsage_Main.ejs +14 -10
  24. package/src/emit/rbac/templates/ConfirmUsage_Main.ejs +14 -10
  25. package/src/emit/rbac/templates/CreateTargetRole_Main.ejs +22 -12
  26. package/src/emit/rbac/templates/GetMyPermissions_Main.ejs +14 -10
  27. package/src/emit/rbac/templates/ReservedDynamicUsage_Main.ejs +76 -34
  28. package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +12 -9
  29. package/src/emit/resource/emitResourceArtifacts.js +141 -62
  30. package/src/emit/resource/templates/SystemDynamoDB_Yaml.ejs +14 -18
  31. package/src/emit/system/templates/WebSocketComplete_Yaml.ejs +4 -2
  32. package/test/createTargetRoleHandler.test.js +1 -15
  33. package/test/crudApplicationArtifacts.test.js +540 -3
  34. package/test/customFlowApplicationArtifacts.test.js +3 -5
  35. package/test/dynamicCrudFlowSchemas.test.js +5 -17
  36. package/test/dynamicRbacFlowSchemas.test.js +0 -3
  37. package/test/functionYamlArtifact.test.js +4 -2
  38. package/test/resourceArtifacts.test.js +203 -14
@@ -83,12 +83,14 @@ test('filters all SQS functions by their calling flow', () => {
83
83
  /#<#CreateCompleteHdrSqsFilterPatterns#>[\s\S]*filterPatterns:[\s\S]*\$\{self:custom\.iz_resourcePrefix\}CreateCompleteHdrSqs/
84
84
  );
85
85
  assert.match(completion, /#<#\/CreateCompleteHdrSqsFilterPatterns#>/);
86
- assert.match(completion, /exists: false/);
86
+ assert.match(completion, /callingFlow:\s*\n\s*- exists: false/);
87
+ assert.match(completion, /MessageAttributes:\s*\n\s*- exists: false/);
87
88
  assert.match(
88
89
  ordinary,
89
90
  /#<#CreateHdrSqsFilterPatterns#>[\s\S]*filterPatterns:[\s\S]*\$\{self:custom\.iz_resourcePrefix\}CreateHdrSqs/
90
91
  );
91
92
  assert.match(ordinary, /#<#\/CreateHdrSqsFilterPatterns#>/);
92
- assert.match(ordinary, /exists: false/);
93
+ assert.match(ordinary, /callingFlow:\s*\n\s*- exists: false/);
94
+ assert.match(ordinary, /MessageAttributes:\s*\n\s*- exists: false/);
93
95
  });
94
96
 
@@ -76,10 +76,23 @@ test('emits queues, topics, tables, and IAM roles from schema data', async () =>
76
76
  assert.match(dynamoYaml, /OrdersTable:/);
77
77
  assert.match(dynamoYaml, /#<#OrdersTableSetting#>/);
78
78
  assert.match(dynamoYaml, /#<#\/OrdersTableSetting#>/);
79
- assert.match(dynamoYaml, /TargetRolesTable:\s+Type: 'AWS::DynamoDB::Table'[\s\S]+AttributeName: identifiersConcat/);
80
- assert.match(dynamoYaml, /RoleLimitTable:\s+Type: 'AWS::DynamoDB::Table'[\s\S]+TableName: \${self:custom\.iz_resourcePrefix}RoleLimit/);
81
- assert.match(dynamoYaml, /RunningTotalUsageTable:\s+Type: 'AWS::DynamoDB::Table'[\s\S]+TableName: \${self:custom\.iz_resourcePrefix}RunningTotalUsage/);
82
- assert.match(dynamoYaml, /RunningTotalReservedUsageTable:\s+Type: 'AWS::DynamoDB::Table'[\s\S]+TableName: \${self:custom\.iz_resourcePrefix}RunningTotalReservedUsage/);
79
+ assert.match(
80
+ dynamoYaml,
81
+ /RolesTable:\s+Type: 'AWS::DynamoDB::Table'[\s\S]+TableName: \${self:custom\.iz_resourcePrefix}Roles/
82
+ );
83
+ assert.match(
84
+ dynamoYaml,
85
+ /TargetRolesTable:\s+Type: 'AWS::DynamoDB::Table'[\s\S]+AttributeName: identifiersConcat/
86
+ );
87
+ assert.doesNotMatch(dynamoYaml, /RoleLimitTable:/);
88
+ assert.match(
89
+ dynamoYaml,
90
+ /RunningTotalUsageTable:\s+Type: 'AWS::DynamoDB::Table'[\s\S]+TableName: \${self:custom\.iz_resourcePrefix}RunningTotalUsage/
91
+ );
92
+ assert.match(
93
+ dynamoYaml,
94
+ /RunningTotalReservedUsageTable:\s+Type: 'AWS::DynamoDB::Table'[\s\S]+TableName: \${self:custom\.iz_resourcePrefix}RunningTotalReservedUsage/
95
+ );
83
96
  const iam = await readFile(
84
97
  join(
85
98
  rootPath,
@@ -108,9 +121,9 @@ test('emits queues, topics, tables, and IAM roles from schema data', async () =>
108
121
  roleBlock(iam, 'FlowRbacRole'),
109
122
  /RolePermissions|ProcessCreateTargetRoleHdrSqs/
110
123
  );
111
- assert.match(roleBlock(iam, 'FlowRbacRole'), /RoleLimit/);
124
+ assert.doesNotMatch(roleBlock(iam, 'FlowRbacRole'), /RoleLimit/);
112
125
  assert.match(roleBlock(iam, 'FlowRbacRole'), /RunningTotalUsage/);
113
- assert.match(roleBlock(iam, 'FlowObjectsRole'), /RoleLimit/);
126
+ assert.doesNotMatch(roleBlock(iam, 'FlowObjectsRole'), /RoleLimit/);
114
127
  // Per-object RBAC flow queue (e.g. ValidatorRbacHdrSqs from Order with rbac add-on)
115
128
  assert.match(roleBlock(iam, 'FlowRbacRole'), /ValidatorRbacHdrSqs/);
116
129
 
@@ -150,6 +163,7 @@ test('emits queues, topics, tables, and IAM roles from schema data', async () =>
150
163
  const procFindDataRole = roleBlock(iam, 'ProcFindDataRole');
151
164
  assert.match(procFindDataRole, /dynamodb:UpdateItem/);
152
165
  assert.match(procFindDataRole, /dynamodb:GetItem/);
166
+ assert.match(procFindDataRole, /dynamodb:PutItem/);
153
167
  assert.match(procFindDataRole, /dynamodb:Query/);
154
168
  assert.match(procFindDataRole, /sns:Publish/);
155
169
  assert.match(procFindDataRole, /FindData_Out/);
@@ -289,21 +303,21 @@ test('emits DynamoDB table with number sortKey attribute type when field type is
289
303
  const rootPath = await createProject();
290
304
  await writeFile(
291
305
  join(rootPath, 'app/src/schemas/ObjectSchemas/CartOrder.js'),
292
- "export default { " +
306
+ 'export default { ' +
293
307
  "objectType: 'cartOrder', " +
294
308
  "generatedBy: 'user', " +
295
- "fieldNames: { " +
309
+ 'fieldNames: { ' +
296
310
  " cartId: { type: 'string' }, " +
297
311
  " sortId: { type: 'number' } " +
298
- "}, " +
299
- "identifiers: [ " +
312
+ '}, ' +
313
+ 'identifiers: [ ' +
300
314
  " { type: 'partitionKey', fieldName: 'cartId' }, " +
301
315
  " { type: 'sortKey', fieldName: 'sortId' } " +
302
- "], " +
303
- "storageResources: { " +
316
+ '], ' +
317
+ 'storageResources: { ' +
304
318
  " main: { storageType: 'dynamoDB', tableName: 'CartOrders' } " +
305
- "} " +
306
- "};\n"
319
+ '} ' +
320
+ '};\n'
307
321
  );
308
322
 
309
323
  await generateResourceArtifacts(rootPath);
@@ -370,6 +384,181 @@ test('emits CreateNodeCallbackHdrSqs in FlowObjectsRole when object has graph an
370
384
  assert.match(role, /Rbac_\$\{self:custom\.iz_stage\}_ValidatorRbac_In/);
371
385
  });
372
386
 
387
+ test('emits CreateAfterHookCallbackHdrSqs in SQS resources and FlowObjectsRole when flow has after hook with ownTopic', async () => {
388
+ const rootPath = await createProject();
389
+ const schemas = join(rootPath, 'app/src/schemas');
390
+ await writeFile(
391
+ join(schemas, 'FlowSchemas/NotifyAfterCreate.js'),
392
+ "export default { flowTag: 'notifyAfterCreate', event: ['ownTopic'], generatedCodeConfig: { generateCodeTag: 'create', codeHookTag: 'after', invocationType: 'ownTopic', objType: { objectType: 'order' } } };\n"
393
+ );
394
+ await generateResourceArtifacts(rootPath);
395
+
396
+ const crudResources = await readFile(
397
+ join(
398
+ rootPath,
399
+ 'resource/sls_yaml/generatedCode/source/generated-sns-sqs-crud.yml'
400
+ ),
401
+ 'utf8'
402
+ );
403
+ assert.match(crudResources, /^ CreateAfterHookCallbackHdrSqs:/m);
404
+ assert.match(crudResources, /^ CreateAfterHookCallbackHdrSqsDLQ:/m);
405
+
406
+ const iam = await readFile(
407
+ join(
408
+ rootPath,
409
+ 'app/sls_yaml/generatedCode/source/generate-shared-resource.yml'
410
+ ),
411
+ 'utf8'
412
+ );
413
+ const role = roleBlock(iam, 'FlowObjectsRole');
414
+ assert.match(role, /CreateAfterHookCallbackHdrSqs/);
415
+ assert.match(role, /CreateAfterHookCallbackHdrSqsDLQ/);
416
+ assert.match(role, /NotifyAfterCreate_In/);
417
+ });
418
+
419
+ test('emits CreateBeforeHookCallbackHdrSqs in SQS resources and FlowObjectsRole when flow has before hook with ownTopic', async () => {
420
+ const rootPath = await createProject();
421
+ const schemas = join(rootPath, 'app/src/schemas');
422
+ await writeFile(
423
+ join(schemas, 'FlowSchemas/ValidateBeforeCreate.js'),
424
+ "export default { flowTag: 'validateBeforeCreate', event: ['ownTopic'], generatedCodeConfig: { generateCodeTag: 'create', codeHookTag: 'before', invocationType: 'ownTopic' }, objType: { objectType: 'order' } };\n"
425
+ );
426
+ await generateResourceArtifacts(rootPath);
427
+
428
+ const crudResources = await readFile(
429
+ join(
430
+ rootPath,
431
+ 'resource/sls_yaml/generatedCode/source/generated-sns-sqs-crud.yml'
432
+ ),
433
+ 'utf8'
434
+ );
435
+ assert.match(crudResources, /^ CreateBeforeHookCallbackHdrSqs:/m);
436
+ assert.match(crudResources, /^ CreateBeforeHookCallbackHdrSqsDLQ:/m);
437
+
438
+ const iam = await readFile(
439
+ join(
440
+ rootPath,
441
+ 'app/sls_yaml/generatedCode/source/generate-shared-resource.yml'
442
+ ),
443
+ 'utf8'
444
+ );
445
+ const role = roleBlock(iam, 'FlowObjectsRole');
446
+ assert.match(role, /CreateBeforeHookCallbackHdrSqs/);
447
+ assert.match(role, /CreateBeforeHookCallbackHdrSqsDLQ/);
448
+ assert.match(role, /ValidateBeforeCreate_In/);
449
+ });
450
+
451
+ test('emits UpdateBeforeHookCallbackHdrSqs in SQS resources and FlowObjectsRole when flow has before hook with ownTopic', async () => {
452
+ const rootPath = await createProject();
453
+ const schemas = join(rootPath, 'app/src/schemas');
454
+ await writeFile(
455
+ join(schemas, 'FlowSchemas/ValidateBeforeUpdate.js'),
456
+ "export default { flowTag: 'validateBeforeUpdate', event: ['ownTopic'], generatedCodeConfig: { generateCodeTag: 'update', codeHookTag: 'before', invocationType: 'ownTopic' }, objType: { objectType: 'order' } };\n"
457
+ );
458
+ await generateResourceArtifacts(rootPath);
459
+
460
+ const crudResources = await readFile(
461
+ join(
462
+ rootPath,
463
+ 'resource/sls_yaml/generatedCode/source/generated-sns-sqs-crud.yml'
464
+ ),
465
+ 'utf8'
466
+ );
467
+ assert.match(crudResources, /^ UpdateBeforeHookCallbackHdrSqs:/m);
468
+ assert.match(crudResources, /^ UpdateBeforeHookCallbackHdrSqsDLQ:/m);
469
+
470
+ const iam = await readFile(
471
+ join(
472
+ rootPath,
473
+ 'app/sls_yaml/generatedCode/source/generate-shared-resource.yml'
474
+ ),
475
+ 'utf8'
476
+ );
477
+ const role = roleBlock(iam, 'FlowObjectsRole');
478
+ assert.match(role, /UpdateBeforeHookCallbackHdrSqs/);
479
+ assert.match(role, /UpdateBeforeHookCallbackHdrSqsDLQ/);
480
+ assert.match(role, /ValidateBeforeUpdate_In/);
481
+ });
482
+
483
+ test('emits DeleteBeforeHookCallbackHdrSqs in SQS resources and FlowObjectsRole when flow has before hook with ownTopic', async () => {
484
+ const rootPath = await createProject();
485
+ const schemas = join(rootPath, 'app/src/schemas');
486
+ await writeFile(
487
+ join(schemas, 'FlowSchemas/ValidateBeforeDelete.js'),
488
+ "export default { flowTag: 'validateBeforeDelete', event: ['ownTopic'], generatedCodeConfig: { generateCodeTag: 'delete', codeHookTag: 'before', invocationType: 'ownTopic' }, objType: { objectType: 'order' } };\n"
489
+ );
490
+ await generateResourceArtifacts(rootPath);
491
+
492
+ const crudResources = await readFile(
493
+ join(
494
+ rootPath,
495
+ 'resource/sls_yaml/generatedCode/source/generated-sns-sqs-crud.yml'
496
+ ),
497
+ 'utf8'
498
+ );
499
+ assert.match(crudResources, /^ DeleteBeforeHookCallbackHdrSqs:/m);
500
+ assert.match(crudResources, /^ DeleteBeforeHookCallbackHdrSqsDLQ:/m);
501
+
502
+ const iam = await readFile(
503
+ join(
504
+ rootPath,
505
+ 'app/sls_yaml/generatedCode/source/generate-shared-resource.yml'
506
+ ),
507
+ 'utf8'
508
+ );
509
+ const role = roleBlock(iam, 'FlowObjectsRole');
510
+ assert.match(role, /DeleteBeforeHookCallbackHdrSqs/);
511
+ assert.match(role, /DeleteBeforeHookCallbackHdrSqsDLQ/);
512
+ assert.match(role, /ValidateBeforeDelete_In/);
513
+ });
514
+
515
+ test('emits lambda:InvokeFunction in FlowObjectsRole when flow has before hook with lambdaSyncInv for update and delete', async () => {
516
+ const rootPath = await createProject();
517
+ const schemas = join(rootPath, 'app/src/schemas');
518
+ await writeFile(
519
+ join(schemas, 'FlowSchemas/CheckBeforeUpdate.js'),
520
+ "export default { flowTag: 'checkBeforeUpdate', event: ['lambdaSyncInv'], generatedCodeConfig: { generateCodeTag: 'update', codeHookTag: 'before', invocationType: 'lambdaSyncInv' }, objType: { objectType: 'order' } };\n"
521
+ );
522
+ await writeFile(
523
+ join(schemas, 'FlowSchemas/CheckBeforeDelete.js'),
524
+ "export default { flowTag: 'checkBeforeDelete', event: ['lambdaSyncInv'], generatedCodeConfig: { generateCodeTag: 'delete', codeHookTag: 'before', invocationType: 'lambdaSyncInv' }, objType: { objectType: 'order' } };\n"
525
+ );
526
+ await generateResourceArtifacts(rootPath);
527
+
528
+ const iam = await readFile(
529
+ join(
530
+ rootPath,
531
+ 'app/sls_yaml/generatedCode/source/generate-shared-resource.yml'
532
+ ),
533
+ 'utf8'
534
+ );
535
+ const role = roleBlock(iam, 'FlowObjectsRole');
536
+ assert.match(role, /lambda:InvokeFunction/);
537
+ assert.match(role, /CheckBeforeUpdate/);
538
+ assert.match(role, /CheckBeforeDelete/);
539
+ });
540
+
541
+ test('emits lambda:InvokeFunction in FlowObjectsRole when flow has after hook with lambdaSyncInv', async () => {
542
+ const rootPath = await createProject();
543
+ const schemas = join(rootPath, 'app/src/schemas');
544
+ await writeFile(
545
+ join(schemas, 'FlowSchemas/AuditAfterCreate.js'),
546
+ "export default { flowTag: 'auditAfterCreate', event: ['lambdaSyncInv'], generatedCodeConfig: { generateCodeTag: 'create', codeHookTag: 'after', invocationType: 'lambdaSyncInv', objType: { objectType: 'order' } } };\n"
547
+ );
548
+ await generateResourceArtifacts(rootPath);
549
+
550
+ const iam = await readFile(
551
+ join(
552
+ rootPath,
553
+ 'app/sls_yaml/generatedCode/source/generate-shared-resource.yml'
554
+ ),
555
+ 'utf8'
556
+ );
557
+ const role = roleBlock(iam, 'FlowObjectsRole');
558
+ assert.match(role, /lambda:InvokeFunction/);
559
+ assert.match(role, /AuditAfterCreate/);
560
+ });
561
+
373
562
  function roleBlock(iam, roleName) {
374
563
  const match = iam.match(
375
564
  new RegExp(