@izara_project/izara-core-generate-service-code 1.0.88 → 1.0.90
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 +1 -1
- package/src/compile/flowValidator.js +25 -0
- package/src/compile/loadSchemas.js +154 -0
- package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +3 -7
- package/src/emit/crud/crudActionPlan.js +67 -9
- package/src/emit/crud/emitDynamicCrudFlowSchemas.js +15 -32
- package/src/emit/crud/templates/CreateComplete_Main.ejs +135 -10
- package/src/emit/crud/templates/CreateEndpoint_Main.ejs +33 -27
- package/src/emit/crud/templates/CreateLogicalLib.ejs +282 -95
- package/src/emit/crud/templates/CreateNodeCallback_Main.ejs +38 -21
- package/src/emit/crud/templates/DeleteAfterHookCallback_Main.ejs +118 -0
- package/src/emit/crud/templates/DeleteComplete_Main.ejs +124 -10
- package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +26 -16
- package/src/emit/crud/templates/DeleteLogicalLib.ejs +113 -4
- package/src/emit/crud/templates/UpdateAfterHookCallback_Main.ejs +120 -0
- package/src/emit/crud/templates/UpdateComplete_Main.ejs +104 -10
- package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +34 -22
- package/src/emit/crud/templates/UpdateLogicalLib.ejs +121 -4
- package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +8 -2
- package/src/emit/rbac/templates/CancelUsage_Main.ejs +34 -14
- package/src/emit/rbac/templates/ConfirmUsage_Main.ejs +34 -14
- package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +20 -13
- package/src/emit/resource/emitResourceArtifacts.js +55 -14
- package/test/createTargetRoleHandler.test.js +11 -8
- package/test/crudApplicationArtifacts.test.js +440 -0
- package/test/dynamicCrudFlowSchemas.test.js +10 -5
- package/test/dynamicRbacFlowSchemas.test.js +24 -2
- package/test/graphDrivenFlowSchema.test.js +36 -0
- package/test/resourceArtifacts.test.js +113 -0
|
@@ -204,6 +204,38 @@ test('rejects deprecated FlowHook schemas', async () => {
|
|
|
204
204
|
);
|
|
205
205
|
});
|
|
206
206
|
|
|
207
|
+
test('rejects invalid generateCodeTag configuration', async () => {
|
|
208
|
+
const rootPath = await createProject();
|
|
209
|
+
const flowDirectory = join(rootPath, 'app/src/schemas/FlowSchemas');
|
|
210
|
+
await writeFile(
|
|
211
|
+
join(flowDirectory, 'InvalidTag.js'),
|
|
212
|
+
"export default { flowTag: 'invalidHook', event: ['ownTopic'], " +
|
|
213
|
+
"generatedCodeConfig: { generateCodeTag: ['invalidAction'], " +
|
|
214
|
+
"codeHookTag: 'before' } };\n"
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
await assert.rejects(
|
|
218
|
+
generateResourceArtifacts(rootPath),
|
|
219
|
+
/generatedCodeConfig\.generateCodeTag contains invalid tag 'invalidAction'/
|
|
220
|
+
);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
test('rejects empty generateCodeTag array configuration', async () => {
|
|
224
|
+
const rootPath = await createProject();
|
|
225
|
+
const flowDirectory = join(rootPath, 'app/src/schemas/FlowSchemas');
|
|
226
|
+
await writeFile(
|
|
227
|
+
join(flowDirectory, 'EmptyTag.js'),
|
|
228
|
+
"export default { flowTag: 'emptyHook', event: ['ownTopic'], " +
|
|
229
|
+
"generatedCodeConfig: { generateCodeTag: [], " +
|
|
230
|
+
"codeHookTag: 'before' } };\n"
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
await assert.rejects(
|
|
234
|
+
generateResourceArtifacts(rootPath),
|
|
235
|
+
/generatedCodeConfig\.generateCodeTag array must not be empty/
|
|
236
|
+
);
|
|
237
|
+
});
|
|
238
|
+
|
|
207
239
|
test('emits the shared WebSocket completion queue and output-topic subscriptions', async () => {
|
|
208
240
|
const rootPath = await createProject();
|
|
209
241
|
await generateResourceArtifacts(rootPath);
|
|
@@ -382,6 +414,50 @@ test('emits CreateNodeCallbackHdrSqs in FlowObjectsRole when object has graph an
|
|
|
382
414
|
assert.match(role, /RolePermissions/);
|
|
383
415
|
assert.match(role, /ValidatorRbac_In/);
|
|
384
416
|
assert.match(role, /Rbac_\$\{self:custom\.iz_stage\}_ValidatorRbac_In/);
|
|
417
|
+
assert.match(role, /ConfirmUsageHdrInv/);
|
|
418
|
+
assert.match(role, /CancelUsageHdrInv/);
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
test('emits correct permissions in FlowObjectsRole when object is child RBAC node with graph', async () => {
|
|
422
|
+
const rootPath = await createProject();
|
|
423
|
+
const schemas = join(rootPath, 'app/src/schemas');
|
|
424
|
+
await rm(join(schemas, 'ObjectSchemas/Order.js'));
|
|
425
|
+
await writeFile(
|
|
426
|
+
join(schemas, 'ObjectSchemas/ChildNode.js'),
|
|
427
|
+
"export default { objectType: 'childNode', generatedBy: 'user', belongTo: [{ serviceTag: 'UserAccount', objectType: 'user' }], identifiers: [{ type: 'partitionKey', fieldName: 'childId' }], storageResources: { main: { storageType: 'graph', tableName: 'ChildNodes' } } };\n"
|
|
428
|
+
);
|
|
429
|
+
await generateResourceArtifacts(rootPath);
|
|
430
|
+
|
|
431
|
+
const iam = await readFile(
|
|
432
|
+
join(
|
|
433
|
+
rootPath,
|
|
434
|
+
'app/sls_yaml/generatedCode/source/generate-shared-resource.yml'
|
|
435
|
+
),
|
|
436
|
+
'utf8'
|
|
437
|
+
);
|
|
438
|
+
const role = roleBlock(iam, 'FlowObjectsRole');
|
|
439
|
+
assert.match(role, /CreateNodeCallbackHdrSqs/);
|
|
440
|
+
assert.match(role, /CreateNodeCallbackHdrSqsDLQ/);
|
|
441
|
+
assert.match(role, /ValidatorRbac_In/);
|
|
442
|
+
assert.match(role, /Rbac_\$\{self:custom\.iz_stage\}_ValidatorRbac_In/);
|
|
443
|
+
assert.match(role, /UserAccount_\$\{self:custom\.iz_stage\}_ValidatorRbac_In/);
|
|
444
|
+
assert.match(role, /ConfirmUsageHdrInv/);
|
|
445
|
+
assert.match(role, /CancelUsageHdrInv/);
|
|
446
|
+
assert.match(role, /UserAccount\$\{self:custom\.iz_stage\}ValidatorRbacHdrInv/);
|
|
447
|
+
// Child node service is not RBAC provider: no TargetRoles or Roles table in DynamoDB permissions
|
|
448
|
+
assert.doesNotMatch(role, /TargetRoles/);
|
|
449
|
+
assert.doesNotMatch(role, /RolePermissions/);
|
|
450
|
+
assert.doesNotMatch(iam, /FlowRbacRole:/);
|
|
451
|
+
|
|
452
|
+
const dynamo = await readFile(
|
|
453
|
+
join(
|
|
454
|
+
rootPath,
|
|
455
|
+
'resource/sls_yaml/generatedCode/source/generated-dynamoDB-table.yml'
|
|
456
|
+
),
|
|
457
|
+
'utf8'
|
|
458
|
+
);
|
|
459
|
+
assert.doesNotMatch(dynamo, /TargetRolesTable:/);
|
|
460
|
+
assert.doesNotMatch(dynamo, /RolesTable:/);
|
|
385
461
|
});
|
|
386
462
|
|
|
387
463
|
test('emits CreateAfterHookCallbackHdrSqs in SQS resources and FlowObjectsRole when flow has after hook with ownTopic', async () => {
|
|
@@ -559,6 +635,43 @@ test('emits lambda:InvokeFunction in FlowObjectsRole when flow has after hook wi
|
|
|
559
635
|
assert.match(role, /AuditAfterCreate/);
|
|
560
636
|
});
|
|
561
637
|
|
|
638
|
+
test('emits SQS queues and deduplicated IAM policies when generateCodeTag is an array for multiple actions', async () => {
|
|
639
|
+
const rootPath = await createProject();
|
|
640
|
+
const schemas = join(rootPath, 'app/src/schemas');
|
|
641
|
+
await writeFile(
|
|
642
|
+
join(schemas, 'FlowSchemas/NotifyMultiAfter.js'),
|
|
643
|
+
"export default { flowTag: 'notifyMultiAfter', event: ['ownTopic'], " +
|
|
644
|
+
"generatedCodeConfig: { generateCodeTag: ['create', 'update'], " +
|
|
645
|
+
"codeHookTag: 'after', invocationType: 'ownTopic', " +
|
|
646
|
+
"objType: { objectType: 'order' } } };\n"
|
|
647
|
+
);
|
|
648
|
+
await generateResourceArtifacts(rootPath);
|
|
649
|
+
|
|
650
|
+
const crudResources = await readFile(
|
|
651
|
+
join(
|
|
652
|
+
rootPath,
|
|
653
|
+
'resource/sls_yaml/generatedCode/source/generated-sns-sqs-crud.yml'
|
|
654
|
+
),
|
|
655
|
+
'utf8'
|
|
656
|
+
);
|
|
657
|
+
assert.match(crudResources, /^ CreateAfterHookCallbackHdrSqs:/m);
|
|
658
|
+
assert.match(crudResources, /^ UpdateAfterHookCallbackHdrSqs:/m);
|
|
659
|
+
|
|
660
|
+
const iam = await readFile(
|
|
661
|
+
join(
|
|
662
|
+
rootPath,
|
|
663
|
+
'app/sls_yaml/generatedCode/source/generate-shared-resource.yml'
|
|
664
|
+
),
|
|
665
|
+
'utf8'
|
|
666
|
+
);
|
|
667
|
+
const role = roleBlock(iam, 'FlowObjectsRole');
|
|
668
|
+
assert.match(role, /CreateAfterHookCallbackHdrSqs/);
|
|
669
|
+
assert.match(role, /UpdateAfterHookCallbackHdrSqs/);
|
|
670
|
+
|
|
671
|
+
const notifyTopicMatches = role.match(/NotifyMultiAfter_In/g);
|
|
672
|
+
assert.strictEqual(notifyTopicMatches?.length, 1);
|
|
673
|
+
});
|
|
674
|
+
|
|
562
675
|
function roleBlock(iam, roleName) {
|
|
563
676
|
const match = iam.match(
|
|
564
677
|
new RegExp(
|