@kapeta/local-cluster-service 0.54.11 → 0.55.0
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/CHANGELOG.md +21 -0
- package/definitions.d.ts +11 -0
- package/dist/cjs/src/storm/archetype.d.ts +12 -0
- package/dist/cjs/src/storm/archetype.js +98 -0
- package/dist/cjs/src/storm/codegen.d.ts +2 -0
- package/dist/cjs/src/storm/codegen.js +28 -4
- package/dist/cjs/src/storm/event-parser.d.ts +7 -4
- package/dist/cjs/src/storm/event-parser.js +190 -160
- package/dist/cjs/src/storm/events.d.ts +1 -0
- package/dist/cjs/src/storm/predefined.d.ts +27 -0
- package/dist/cjs/src/storm/predefined.js +64 -0
- package/dist/cjs/src/storm/routes.js +23 -15
- package/dist/cjs/test/storm/codegen.test.d.ts +5 -0
- package/dist/cjs/test/storm/codegen.test.js +41 -0
- package/dist/cjs/test/storm/event-parser.test.d.ts +25 -1
- package/dist/cjs/test/storm/event-parser.test.js +34 -15
- package/dist/cjs/test/storm/predefined-user-events.json +13 -0
- package/dist/esm/src/storm/archetype.d.ts +12 -0
- package/dist/esm/src/storm/archetype.js +98 -0
- package/dist/esm/src/storm/codegen.d.ts +2 -0
- package/dist/esm/src/storm/codegen.js +28 -4
- package/dist/esm/src/storm/event-parser.d.ts +7 -4
- package/dist/esm/src/storm/event-parser.js +190 -160
- package/dist/esm/src/storm/events.d.ts +1 -0
- package/dist/esm/src/storm/predefined.d.ts +27 -0
- package/dist/esm/src/storm/predefined.js +64 -0
- package/dist/esm/src/storm/routes.js +23 -15
- package/dist/esm/test/storm/codegen.test.d.ts +5 -0
- package/dist/esm/test/storm/codegen.test.js +41 -0
- package/dist/esm/test/storm/event-parser.test.d.ts +25 -1
- package/dist/esm/test/storm/event-parser.test.js +34 -15
- package/dist/esm/test/storm/predefined-user-events.json +13 -0
- package/package.json +6 -1
- package/src/storm/archetype.ts +85 -0
- package/src/storm/codegen.ts +34 -4
- package/src/storm/event-parser.ts +200 -159
- package/src/storm/events.ts +1 -0
- package/src/storm/predefined.ts +52 -0
- package/src/storm/routes.ts +25 -18
- package/test/storm/codegen.test.ts +46 -0
- package/test/storm/event-parser.test.ts +32 -10
- package/test/storm/predefined-user-events.json +13 -0
@@ -36,11 +36,15 @@ import {
|
|
36
36
|
} from '@kapeta/kaplang-core';
|
37
37
|
import { v5 as uuid } from 'uuid';
|
38
38
|
import { definitionsManager } from '../definitionsManager';
|
39
|
+
import { PREDEFINED_BLOCKS } from './predefined';
|
40
|
+
|
41
|
+
import _ from 'lodash';
|
39
42
|
|
40
43
|
export interface BlockDefinitionInfo {
|
41
44
|
uri: string;
|
42
45
|
content: BlockDefinition;
|
43
46
|
aiName: string;
|
47
|
+
archetype?: string;
|
44
48
|
}
|
45
49
|
|
46
50
|
export interface StormDefinitions {
|
@@ -268,7 +272,7 @@ export class StormEventParser {
|
|
268
272
|
/**
|
269
273
|
* Builds plan and block definitions - and enriches events with relevant refs and ids
|
270
274
|
*/
|
271
|
-
public processEvent(handle: string, evt: StormEvent): StormDefinitions {
|
275
|
+
public async processEvent(handle: string, evt: StormEvent): Promise<StormDefinitions> {
|
272
276
|
let blockInfo;
|
273
277
|
this.events.push(evt);
|
274
278
|
switch (evt.type) {
|
@@ -338,7 +342,7 @@ export class StormEventParser {
|
|
338
342
|
break;
|
339
343
|
}
|
340
344
|
|
341
|
-
return this.toResult(handle);
|
345
|
+
return await this.toResult(handle);
|
342
346
|
}
|
343
347
|
|
344
348
|
public getEvents(): StormEvent[] {
|
@@ -356,9 +360,9 @@ export class StormEventParser {
|
|
356
360
|
return this.error;
|
357
361
|
}
|
358
362
|
|
359
|
-
public toResult(handle: string): StormDefinitions {
|
363
|
+
public async toResult(handle: string): Promise<StormDefinitions> {
|
360
364
|
const planRef = StormEventParser.toRef(handle, this.planName || 'undefined');
|
361
|
-
const blockDefinitions = this.toBlockDefinitions(handle);
|
365
|
+
const blockDefinitions = await this.toBlockDefinitions(handle);
|
362
366
|
const refIdMap: { [key: string]: string } = {};
|
363
367
|
const blocks = Object.entries(blockDefinitions).map(([ref, block]) => {
|
364
368
|
// Create a deterministic uuid
|
@@ -504,163 +508,182 @@ export class StormEventParser {
|
|
504
508
|
};
|
505
509
|
}
|
506
510
|
|
507
|
-
public toBlockDefinitions(handle: string): { [key: string]: BlockDefinitionInfo } {
|
511
|
+
public async toBlockDefinitions(handle: string): Promise<{ [key: string]: BlockDefinitionInfo }> {
|
508
512
|
const result: { [key: string]: BlockDefinitionInfo } = {};
|
509
513
|
|
510
|
-
Object.entries(this.blocks)
|
514
|
+
for (const [, blockInfo] of Object.entries(this.blocks)) {
|
511
515
|
const blockRef = StormEventParser.toRef(handle, blockInfo.name);
|
512
516
|
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
517
|
+
let blockDefinitionInfo: BlockDefinitionInfo;
|
518
|
+
|
519
|
+
if (blockInfo.archetype) {
|
520
|
+
blockDefinitionInfo = await this.resolveArchetypeBlockDefinition(blockRef, blockInfo);
|
521
|
+
} else {
|
522
|
+
blockDefinitionInfo = this.createBlockDefinitionInfo(blockRef, blockInfo, handle);
|
523
|
+
}
|
524
|
+
|
525
|
+
result[blockRef.toNormalizedString()] = blockDefinitionInfo;
|
526
|
+
}
|
527
|
+
|
528
|
+
return result;
|
529
|
+
}
|
530
|
+
|
531
|
+
private createBlockDefinitionInfo(
|
532
|
+
blockRef: KapetaURI,
|
533
|
+
blockInfo: StormBlockInfoFilled,
|
534
|
+
handle: string
|
535
|
+
): BlockDefinitionInfo {
|
536
|
+
const blockDefinitionInfo: BlockDefinitionInfo = {
|
537
|
+
uri: blockRef.toNormalizedString(),
|
538
|
+
aiName: blockInfo.name,
|
539
|
+
content: {
|
540
|
+
kind: this.toBlockKind(blockInfo.type),
|
541
|
+
metadata: {
|
542
|
+
title: blockInfo.name,
|
543
|
+
name: blockRef.fullName,
|
544
|
+
description: blockInfo.description,
|
545
|
+
},
|
546
|
+
spec: {
|
547
|
+
entities: {
|
548
|
+
types: [],
|
549
|
+
source: {
|
550
|
+
type: KAPLANG_ID,
|
551
|
+
version: KAPLANG_VERSION,
|
552
|
+
value: '',
|
531
553
|
},
|
532
|
-
target: this.toBlockTarget(handle, blockInfo.type),
|
533
|
-
providers: [],
|
534
|
-
consumers: [],
|
535
554
|
},
|
555
|
+
target: this.toBlockTarget(handle, blockInfo.type),
|
556
|
+
providers: [],
|
557
|
+
consumers: [],
|
536
558
|
},
|
537
|
-
}
|
559
|
+
},
|
560
|
+
};
|
538
561
|
|
539
|
-
|
562
|
+
const blockSpec = blockDefinitionInfo.content.spec;
|
540
563
|
|
541
|
-
|
542
|
-
|
564
|
+
const apiResources: { [key: string]: Resource | undefined } = {};
|
565
|
+
let dbResource: Resource | undefined = undefined;
|
543
566
|
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
567
|
+
(blockInfo.resources || []).forEach((resource) => {
|
568
|
+
const port = {
|
569
|
+
type: this.toPortType(resource.type),
|
570
|
+
};
|
571
|
+
switch (resource.type) {
|
572
|
+
case 'API': {
|
573
|
+
const apiResource = {
|
574
|
+
kind: this.toResourceKind(resource.type),
|
575
|
+
metadata: {
|
576
|
+
name: resource.name,
|
577
|
+
description: resource.description,
|
578
|
+
},
|
579
|
+
spec: {
|
580
|
+
port,
|
581
|
+
methods: {},
|
582
|
+
source: {
|
583
|
+
type: KAPLANG_ID,
|
584
|
+
version: KAPLANG_VERSION,
|
585
|
+
value: '',
|
586
|
+
} satisfies SourceCode,
|
587
|
+
},
|
588
|
+
};
|
589
|
+
apiResources[resource.name] = apiResource;
|
590
|
+
blockSpec.providers!.push(apiResource);
|
591
|
+
break;
|
592
|
+
}
|
593
|
+
case 'CLIENT':
|
594
|
+
blockSpec.consumers!.push({
|
595
|
+
kind: this.toResourceKind(resource.type),
|
596
|
+
metadata: {
|
597
|
+
name: resource.name,
|
598
|
+
description: resource.description,
|
599
|
+
},
|
600
|
+
spec: {
|
601
|
+
port,
|
602
|
+
methods: {},
|
603
|
+
source: {
|
604
|
+
type: KAPLANG_ID,
|
605
|
+
version: KAPLANG_VERSION,
|
606
|
+
value: '',
|
607
|
+
} satisfies SourceCode,
|
608
|
+
},
|
609
|
+
});
|
610
|
+
break;
|
611
|
+
case 'EXTERNAL_API':
|
612
|
+
break;
|
613
|
+
case 'EXCHANGE':
|
614
|
+
break;
|
615
|
+
case 'PUBLISHER':
|
616
|
+
break;
|
617
|
+
case 'QUEUE':
|
618
|
+
break;
|
619
|
+
case 'SUBSCRIBER':
|
620
|
+
break;
|
621
|
+
case 'JWTPROVIDER':
|
622
|
+
case 'WEBPAGE':
|
623
|
+
blockSpec.providers!.push({
|
624
|
+
kind: this.toResourceKind(resource.type),
|
625
|
+
metadata: {
|
626
|
+
name: resource.name,
|
627
|
+
description: resource.description,
|
628
|
+
},
|
629
|
+
spec: {
|
630
|
+
port,
|
631
|
+
},
|
632
|
+
});
|
633
|
+
break;
|
634
|
+
case 'DATABASE':
|
635
|
+
if (dbResource) {
|
568
636
|
break;
|
569
637
|
}
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
name: resource.name,
|
604
|
-
description: resource.description,
|
605
|
-
},
|
606
|
-
spec: {
|
607
|
-
port,
|
608
|
-
},
|
609
|
-
});
|
610
|
-
break;
|
611
|
-
case 'DATABASE':
|
612
|
-
if (dbResource) {
|
613
|
-
break;
|
614
|
-
}
|
615
|
-
dbResource = {
|
616
|
-
kind: this.toResourceKind(resource.type),
|
617
|
-
metadata: {
|
618
|
-
name: resource.name,
|
619
|
-
description: resource.description,
|
620
|
-
},
|
621
|
-
spec: {
|
622
|
-
port,
|
623
|
-
models: [],
|
624
|
-
source: {
|
625
|
-
type: KAPLANG_ID,
|
626
|
-
version: KAPLANG_VERSION,
|
627
|
-
value: '',
|
628
|
-
} satisfies SourceCode,
|
629
|
-
},
|
630
|
-
};
|
631
|
-
blockSpec.consumers!.push(dbResource);
|
632
|
-
break;
|
633
|
-
case 'JWTCONSUMER':
|
634
|
-
case 'WEBFRAGMENT':
|
635
|
-
case 'SMTPCLIENT':
|
636
|
-
blockSpec.consumers!.push({
|
637
|
-
kind: this.toResourceKind(resource.type),
|
638
|
-
metadata: {
|
639
|
-
name: resource.name,
|
640
|
-
description: resource.description,
|
641
|
-
},
|
642
|
-
spec: {
|
643
|
-
port,
|
644
|
-
},
|
645
|
-
});
|
646
|
-
}
|
647
|
-
});
|
638
|
+
dbResource = {
|
639
|
+
kind: this.toResourceKind(resource.type),
|
640
|
+
metadata: {
|
641
|
+
name: resource.name,
|
642
|
+
description: resource.description,
|
643
|
+
},
|
644
|
+
spec: {
|
645
|
+
port,
|
646
|
+
models: [],
|
647
|
+
source: {
|
648
|
+
type: KAPLANG_ID,
|
649
|
+
version: KAPLANG_VERSION,
|
650
|
+
value: '',
|
651
|
+
} satisfies SourceCode,
|
652
|
+
},
|
653
|
+
};
|
654
|
+
blockSpec.consumers!.push(dbResource);
|
655
|
+
break;
|
656
|
+
case 'JWTCONSUMER':
|
657
|
+
case 'WEBFRAGMENT':
|
658
|
+
case 'SMTPCLIENT':
|
659
|
+
blockSpec.consumers!.push({
|
660
|
+
kind: this.toResourceKind(resource.type),
|
661
|
+
metadata: {
|
662
|
+
name: resource.name,
|
663
|
+
description: resource.description,
|
664
|
+
},
|
665
|
+
spec: {
|
666
|
+
port,
|
667
|
+
},
|
668
|
+
});
|
669
|
+
}
|
670
|
+
});
|
648
671
|
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
}
|
672
|
+
blockInfo.apis.forEach((api) => {
|
673
|
+
const dslApi = DSLAPIParser.parse(api, {
|
674
|
+
ignoreSemantics: true,
|
675
|
+
}) as (DSLMethod | DSLController)[];
|
676
|
+
|
677
|
+
let exactMatch = false;
|
678
|
+
if (dslApi[0] && dslApi[0].type == DSLEntityType.CONTROLLER) {
|
679
|
+
const name = dslApi[0].name.toLowerCase();
|
680
|
+
const apiResourceName = Object.keys(apiResources).find((key) => key.indexOf(name) > -1);
|
681
|
+
if (apiResourceName) {
|
682
|
+
const exactResource = apiResources[apiResourceName];
|
683
|
+
exactResource!.spec.source.value += api + '\n\n';
|
684
|
+
exactMatch = true;
|
663
685
|
}
|
686
|
+
}
|
664
687
|
|
665
688
|
if (!exactMatch) {
|
666
689
|
// if we couldn't place the given api on the exact resource we just park it on the first
|
@@ -675,20 +698,17 @@ export class StormEventParser {
|
|
675
698
|
}
|
676
699
|
});
|
677
700
|
|
678
|
-
|
679
|
-
|
680
|
-
});
|
681
|
-
|
682
|
-
if (dbResource) {
|
683
|
-
blockInfo.models.forEach((model) => {
|
684
|
-
dbResource!.spec.source.value += model + '\n';
|
685
|
-
});
|
686
|
-
}
|
687
|
-
|
688
|
-
result[blockRef.toNormalizedString()] = blockDefinitionInfo;
|
701
|
+
blockInfo.types.forEach((type) => {
|
702
|
+
blockSpec.entities!.source!.value += type + '\n';
|
689
703
|
});
|
690
704
|
|
691
|
-
|
705
|
+
if (dbResource) {
|
706
|
+
blockInfo.models.forEach((model) => {
|
707
|
+
dbResource!.spec.source.value += model + '\n';
|
708
|
+
});
|
709
|
+
}
|
710
|
+
|
711
|
+
return blockDefinitionInfo;
|
692
712
|
}
|
693
713
|
|
694
714
|
private toResourceKind(type: StormResourceType) {
|
@@ -861,4 +881,25 @@ export class StormEventParser {
|
|
861
881
|
}
|
862
882
|
return undefined;
|
863
883
|
}
|
884
|
+
|
885
|
+
private async resolveArchetypeBlockDefinition(
|
886
|
+
blockRef: KapetaURI,
|
887
|
+
blockInfo: StormBlockInfoFilled
|
888
|
+
): Promise<BlockDefinitionInfo> {
|
889
|
+
const predefinedBlock = PREDEFINED_BLOCKS.get(blockInfo.archetype!);
|
890
|
+
if (!predefinedBlock) {
|
891
|
+
throw new Error('Predefined block not found for archetype [' + blockInfo.archetype + ']');
|
892
|
+
}
|
893
|
+
|
894
|
+
const blockDefinition = await predefinedBlock.getBlockDefinition();
|
895
|
+
_.set(blockDefinition!, ['metadata', 'name'], blockRef.fullName);
|
896
|
+
_.set(blockDefinition!, ['metadata', 'title'], blockRef.name);
|
897
|
+
|
898
|
+
return {
|
899
|
+
uri: blockRef.toNormalizedString(),
|
900
|
+
aiName: blockInfo.name,
|
901
|
+
content: blockDefinition,
|
902
|
+
archetype: blockInfo.archetype,
|
903
|
+
} as BlockDefinitionInfo;
|
904
|
+
}
|
864
905
|
}
|
package/src/storm/events.ts
CHANGED
@@ -0,0 +1,52 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright 2023 Kapeta Inc.
|
3
|
+
* SPDX-License-Identifier: BUSL-1.1
|
4
|
+
*/
|
5
|
+
|
6
|
+
import { BlockDefinition } from '@kapeta/schemas';
|
7
|
+
import * as yaml from 'js-yaml';
|
8
|
+
|
9
|
+
export class PredefinedBlock {
|
10
|
+
constructor(
|
11
|
+
public archetype: string,
|
12
|
+
public kapetaYml: string,
|
13
|
+
public gitRepo: {
|
14
|
+
owner: string;
|
15
|
+
repo: string;
|
16
|
+
path: string;
|
17
|
+
}
|
18
|
+
) {}
|
19
|
+
|
20
|
+
public getGitRepo(): { owner: string; repo: string; path: string } {
|
21
|
+
return this.gitRepo;
|
22
|
+
}
|
23
|
+
|
24
|
+
private async getKapetaYML(): Promise<string> {
|
25
|
+
const response = await fetch(this.kapetaYml);
|
26
|
+
if (!response.ok) {
|
27
|
+
throw new Error(`HTTP error! Status: ${response.status}`);
|
28
|
+
}
|
29
|
+
return await response.text();
|
30
|
+
}
|
31
|
+
|
32
|
+
public async getBlockDefinition(): Promise<BlockDefinition> {
|
33
|
+
const kapetaYml = await this.getKapetaYML();
|
34
|
+
return yaml.load(kapetaYml) as BlockDefinition;
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
const predefinedBlocks: PredefinedBlock[] = [
|
39
|
+
new PredefinedBlock(
|
40
|
+
'USER_SERVICE',
|
41
|
+
'https://raw.githubusercontent.com/kapetacom/everything/master/blocks/everything-user/kapeta.yml',
|
42
|
+
{
|
43
|
+
owner: 'kapetacom',
|
44
|
+
repo: 'everything',
|
45
|
+
path: 'blocks/everything-user',
|
46
|
+
}
|
47
|
+
),
|
48
|
+
];
|
49
|
+
|
50
|
+
export const PREDEFINED_BLOCKS = new Map<string, PredefinedBlock>(
|
51
|
+
predefinedBlocks.map((block) => [block.archetype, block])
|
52
|
+
);
|
package/src/storm/routes.ts
CHANGED
@@ -22,6 +22,7 @@ import {
|
|
22
22
|
import { StormCodegen } from './codegen';
|
23
23
|
import { assetManager } from '../assetManager';
|
24
24
|
import Path from 'path';
|
25
|
+
import _ from 'lodash';
|
25
26
|
|
26
27
|
const router = Router();
|
27
28
|
|
@@ -29,7 +30,7 @@ router.use('/', corsHandler);
|
|
29
30
|
router.use('/', stringBody);
|
30
31
|
|
31
32
|
router.post('/:handle/all', async (req: KapetaBodyRequest, res: Response) => {
|
32
|
-
const handle = req.params.handle;
|
33
|
+
const handle = req.params.handle as string;
|
33
34
|
|
34
35
|
try {
|
35
36
|
const stormOptions = await resolveOptions();
|
@@ -51,23 +52,29 @@ router.post('/:handle/all', async (req: KapetaBodyRequest, res: Response) => {
|
|
51
52
|
|
52
53
|
let currentPhase = StormEventPhaseType.META;
|
53
54
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
55
|
+
// Helper to avoid sending the plan multiple times in a row
|
56
|
+
const sendUpdatedPlan = _.debounce(sendDefinitions, 50, { maxWait: 200 });
|
57
|
+
metaStream.on('data', async (data: StormEvent) => {
|
58
|
+
try {
|
59
|
+
const result = await eventParser.processEvent(handle, data);
|
60
|
+
|
61
|
+
switch (data.type) {
|
62
|
+
case 'CREATE_API':
|
63
|
+
case 'CREATE_MODEL':
|
64
|
+
case 'CREATE_TYPE':
|
65
|
+
if (currentPhase !== StormEventPhaseType.DEFINITIONS) {
|
66
|
+
sendEvent(res, createPhaseEndEvent(StormEventPhaseType.META));
|
67
|
+
currentPhase = StormEventPhaseType.DEFINITIONS;
|
68
|
+
sendEvent(res, createPhaseStartEvent(StormEventPhaseType.DEFINITIONS));
|
69
|
+
}
|
70
|
+
break;
|
71
|
+
}
|
68
72
|
|
69
|
-
|
70
|
-
|
73
|
+
sendEvent(res, data);
|
74
|
+
sendUpdatedPlan(res, result);
|
75
|
+
} catch (e) {
|
76
|
+
console.error('Failed to process event', e);
|
77
|
+
}
|
71
78
|
});
|
72
79
|
|
73
80
|
try {
|
@@ -96,7 +103,7 @@ router.post('/:handle/all', async (req: KapetaBodyRequest, res: Response) => {
|
|
96
103
|
return;
|
97
104
|
}
|
98
105
|
|
99
|
-
const result = eventParser.toResult(handle);
|
106
|
+
const result = await eventParser.toResult(handle);
|
100
107
|
|
101
108
|
if (metaStream.isAborted()) {
|
102
109
|
return;
|
@@ -0,0 +1,46 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright 2023 Kapeta Inc.
|
3
|
+
* SPDX-License-Identifier: BUSL-1.1
|
4
|
+
*/
|
5
|
+
|
6
|
+
import predefinedUserEvents from './predefined-user-events.json';
|
7
|
+
import { StormEventParser } from '../../src/storm/event-parser';
|
8
|
+
import { parserOptions } from './event-parser.test';
|
9
|
+
import { StormEvent } from '../../src/storm/events';
|
10
|
+
import { StormCodegen } from '../../src/storm/codegen';
|
11
|
+
import uuid from 'node-uuid';
|
12
|
+
import { StormStream } from '../../src/storm/stream';
|
13
|
+
|
14
|
+
describe('codegen', () => {
|
15
|
+
it('predefined components', async () => {
|
16
|
+
const events = predefinedUserEvents as StormEvent[];
|
17
|
+
const parser = new StormEventParser(parserOptions);
|
18
|
+
for (const event of events) {
|
19
|
+
await parser.processEvent('kapeta', event);
|
20
|
+
}
|
21
|
+
|
22
|
+
const result = await parser.toResult('kapeta');
|
23
|
+
|
24
|
+
const conversationId = uuid.v4().toString();
|
25
|
+
|
26
|
+
let codegen = new StormCodegen(conversationId, '', result.blocks, parser.getEvents());
|
27
|
+
let codegenPromise = consumeStream(codegen.getStream());
|
28
|
+
await codegen.process();
|
29
|
+
|
30
|
+
const stormEvents = await codegenPromise;
|
31
|
+
expect(stormEvents[0].type).toBe('FILE_DONE');
|
32
|
+
expect(stormEvents[stormEvents.length - 1].type).toBe('BLOCK_READY');
|
33
|
+
});
|
34
|
+
});
|
35
|
+
|
36
|
+
async function consumeStream(stream: StormStream): Promise<StormEvent[]> {
|
37
|
+
const events: StormEvent[] = [];
|
38
|
+
return new Promise<StormEvent[]>((resolve) => {
|
39
|
+
stream.on('data', (data) => {
|
40
|
+
events.push(data);
|
41
|
+
});
|
42
|
+
|
43
|
+
stream.waitForDone();
|
44
|
+
resolve(events);
|
45
|
+
});
|
46
|
+
}
|