@kapeta/local-cluster-service 0.55.2 → 0.55.3

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.
@@ -26,8 +26,8 @@ describe('codegen', () => {
26
26
  await codegen.process();
27
27
  const stormEvents = await codegenPromise;
28
28
  expect(stormEvents.filter((event) => event.type === 'FILE_DONE').length).toBeGreaterThan(1);
29
- expect(stormEvents.filter((event) => event.type === 'FILE_DONE' && event.payload.filename.endsWith('UserDTO.java')).length)
30
- .toBe(1);
29
+ expect(stormEvents.filter((event) => event.type === 'FILE_DONE' && event.payload.filename.endsWith('UserDTO.java'))
30
+ .length).toBe(1);
31
31
  expect(stormEvents.at(-1).type).toBe('BLOCK_READY');
32
32
  });
33
33
  });
@@ -11,9 +11,10 @@ exports.parserOptions = void 0;
11
11
  const event_parser_1 = require("../../src/storm/event-parser");
12
12
  const simple_blog_events_json_1 = __importDefault(require("./simple-blog-events.json"));
13
13
  const predefined_user_events_json_1 = __importDefault(require("./predefined-user-events.json"));
14
+ const blog_events_json_1 = __importDefault(require("./blog-events.json"));
14
15
  exports.parserOptions = {
15
16
  serviceKind: 'kapeta/block-service:local',
16
- serviceLanguage: 'kapeta/language-target-nodejs-ts:local',
17
+ serviceLanguage: 'kapeta/language-target-java-spring-boot:local',
17
18
  frontendKind: 'kapeta/block-type-frontend:local',
18
19
  frontendLanguage: 'kapeta/language-target-react-ts:local',
19
20
  cliKind: 'kapeta/block-type-cli:local',
@@ -27,7 +28,7 @@ exports.parserOptions = {
27
28
  publisherKind: 'kapeta/resource-type-publisher:local',
28
29
  subscriberKind: 'kapeta/resource-type-subscriber:local',
29
30
  databaseKind: 'kapeta/block-type-database:local',
30
- apiKind: 'kapeta/block-type-api:local',
31
+ apiKind: 'kapeta/resource-type-rest-api:local',
31
32
  clientKind: 'kapeta/block-type-client:local',
32
33
  webPageKind: 'kapeta/block-type-web-page:local',
33
34
  webFragmentKind: 'kapeta/block-type-web-fragment:local',
@@ -176,7 +177,7 @@ describe('event-parser', () => {
176
177
  const blogService = result.blocks.find((block) => block.aiName === 'blog-service');
177
178
  expect(blogService).toBeDefined();
178
179
  expect(blogService?.content).toBeDefined();
179
- const apiProviders = blogService?.content?.spec?.providers?.filter((provider) => provider.kind === 'kapeta/block-type-api:local');
180
+ const apiProviders = blogService?.content?.spec?.providers?.filter((provider) => provider.kind === 'kapeta/resource-type-rest-api:local');
180
181
  expect(apiProviders).toBeDefined();
181
182
  expect(apiProviders.length).toBe(2);
182
183
  expect(apiProviders['0'].spec.source.value).not.toBe('');
@@ -190,9 +191,26 @@ describe('event-parser', () => {
190
191
  }
191
192
  const result = await parser.toResult('kapeta');
192
193
  expect(result.blocks.length).toBe(1);
193
- expect(result.blocks[0].content.metadata.title).toBe('user-service');
194
- expect(result.blocks[0].content.metadata.title).toBe('user-service');
195
- expect(result.blocks[0].content.metadata.name).toBe('kapeta/user-service');
196
- expect(result.blocks[0].archetype).toBeDefined();
194
+ const block = result.blocks[0];
195
+ expect(block.content.metadata.title).toBe('user-service');
196
+ expect(block.content.metadata.title).toBe('user-service');
197
+ expect(block.content.metadata.name).toBe('kapeta/user-service');
198
+ expect(block.archetype).toBeDefined();
199
+ expect(block.content.spec.target?.options).toBeDefined();
200
+ expect(block.content.spec.target?.options.groupId).toBe('ai.kapeta');
201
+ expect(block.content.spec.target?.options.artifactId).toBe('blogplatform');
202
+ expect(block.content.spec.target?.options.basePackage).toBe('ai.kapeta.blogplatform');
203
+ });
204
+ it('ensure post-service has api', async () => {
205
+ const events = blog_events_json_1.default;
206
+ const parser = new event_parser_1.StormEventParser(exports.parserOptions);
207
+ for (const event of events) {
208
+ await parser.processEvent('kapeta', event);
209
+ }
210
+ const result = await parser.toResult('kapeta', true);
211
+ const postService = result.blocks.find((block) => block.aiName === 'post-service');
212
+ expect(postService).toBeDefined();
213
+ expect(postService?.content?.spec?.providers?.length).toBe(1);
214
+ expect(postService?.content?.spec?.providers[0].spec.source.value.startsWith('controller')).toBeTruthy();
197
215
  });
198
216
  });
@@ -1,4 +1,13 @@
1
1
  [
2
+ {
3
+ "type": "CREATE_PLAN_PROPERTIES",
4
+ "reason": "Define the properties for the plan itself",
5
+ "payload": {
6
+ "description": "A blogging platform with user management, post management, and comment management functionalities.",
7
+ "name": "Blog Platform"
8
+ },
9
+ "created": 1720768973436
10
+ },
2
11
  {
3
12
  "type": "CREATE_BLOCK",
4
13
  "reason": "Handles user registration, authentication, and authorization.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kapeta/local-cluster-service",
3
- "version": "0.55.2",
3
+ "version": "0.55.3",
4
4
  "description": "Manages configuration, ports and service discovery for locally running Kapeta systems",
5
5
  "type": "commonjs",
6
6
  "exports": {
@@ -76,6 +76,7 @@ export interface StormOptions {
76
76
  desktopKind: string;
77
77
  desktopLanguage: string;
78
78
  gatewayKind: string;
79
+ [key: string]: string;
79
80
  }
80
81
 
81
82
  function prettifyKaplang(source: string) {
@@ -288,7 +289,7 @@ export class StormEventParser {
288
289
  this.blocks[evt.payload.name] = {
289
290
  ...evt.payload,
290
291
  apis: apis ?? [],
291
- models: models ??[],
292
+ models: models ?? [],
292
293
  types: types ?? [],
293
294
  };
294
295
  evt.payload.blockRef = StormEventParser.toRef(handle, evt.payload.name).toNormalizedString();
@@ -364,7 +365,7 @@ export class StormEventParser {
364
365
  return this.error;
365
366
  }
366
367
 
367
- public async toResult(handle: string): Promise<StormDefinitions> {
368
+ public async toResult(handle: string, warn: boolean = false): Promise<StormDefinitions> {
368
369
  const planRef = StormEventParser.toRef(handle, this.planName || 'undefined');
369
370
  const blockDefinitions = await this.toBlockDefinitions(handle);
370
371
  const refIdMap: { [key: string]: string } = {};
@@ -409,12 +410,14 @@ export class StormEventParser {
409
410
  );
410
411
 
411
412
  if (!apiResource) {
412
- console.warn(
413
- 'API resource not found: %s on %s',
414
- apiConnection.fromResource,
415
- apiProviderRef.toNormalizedString(),
416
- apiConnection
417
- );
413
+ if (warn) {
414
+ console.warn(
415
+ 'API resource not found: %s on %s',
416
+ apiConnection.fromResource,
417
+ apiProviderRef.toNormalizedString(),
418
+ apiConnection
419
+ );
420
+ }
418
421
  return;
419
422
  }
420
423
 
@@ -428,12 +431,14 @@ export class StormEventParser {
428
431
  });
429
432
 
430
433
  if (!clientResource) {
431
- console.warn(
432
- 'Client resource not found: %s on %s',
433
- apiConnection.toResource,
434
- clientConsumerRef.toNormalizedString(),
435
- apiConnection
436
- );
434
+ if (warn) {
435
+ console.warn(
436
+ 'Client resource not found: %s on %s',
437
+ apiConnection.toResource,
438
+ clientConsumerRef.toNormalizedString(),
439
+ apiConnection
440
+ );
441
+ }
437
442
  return;
438
443
  }
439
444
 
@@ -487,7 +492,7 @@ export class StormEventParser {
487
492
  blockId: refIdMap[fromRef.toNormalizedString()],
488
493
  resourceName: connection.fromResource,
489
494
  },
490
- mapping: this.toConnectionMapping(handle, connection, blockDefinitions),
495
+ mapping: this.toConnectionMapping(handle, connection, blockDefinitions, warn),
491
496
  } satisfies Connection;
492
497
  });
493
498
 
@@ -521,7 +526,7 @@ export class StormEventParser {
521
526
  let blockDefinitionInfo: BlockDefinitionInfo;
522
527
 
523
528
  if (blockInfo.archetype) {
524
- blockDefinitionInfo = await this.resolveArchetypeBlockDefinition(blockRef, blockInfo);
529
+ blockDefinitionInfo = await this.resolveArchetypeBlockDefinition(blockRef, blockInfo, handle);
525
530
  } else {
526
531
  blockDefinitionInfo = this.createBlockDefinitionInfo(blockRef, blockInfo, handle);
527
532
  }
@@ -697,7 +702,7 @@ export class StormEventParser {
697
702
  if (firstEntry) {
698
703
  firstEntry.spec.source.value += api + '\n\n';
699
704
  } else {
700
- console.warn('Unable to find resource for API', api);
705
+ // this might be ok as we might receive api and types before resources from the ai-service
701
706
  }
702
707
  }
703
708
  });
@@ -770,7 +775,8 @@ export class StormEventParser {
770
775
  private toConnectionMapping(
771
776
  handle: string,
772
777
  connection: StormConnection,
773
- blockDefinitions: { [key: string]: BlockDefinitionInfo }
778
+ blockDefinitions: { [key: string]: BlockDefinitionInfo },
779
+ warn: boolean
774
780
  ): any {
775
781
  if (connection.fromResourceType !== 'API') {
776
782
  return;
@@ -789,12 +795,14 @@ export class StormEventParser {
789
795
  );
790
796
 
791
797
  if (!apiResource) {
792
- console.warn(
793
- 'API resource not found: %s on %s',
794
- connection.fromResource,
795
- fromRef.toNormalizedString(),
796
- connection
797
- );
798
+ if (warn) {
799
+ console.warn(
800
+ 'API resource not found: %s on %s',
801
+ connection.fromResource,
802
+ fromRef.toNormalizedString(),
803
+ connection
804
+ );
805
+ }
798
806
  return;
799
807
  }
800
808
 
@@ -888,16 +896,43 @@ export class StormEventParser {
888
896
 
889
897
  private async resolveArchetypeBlockDefinition(
890
898
  blockRef: KapetaURI,
891
- blockInfo: StormBlockInfoFilled
899
+ blockInfo: StormBlockInfoFilled,
900
+ handle: string
892
901
  ): Promise<BlockDefinitionInfo> {
893
902
  const predefinedBlock = PREDEFINED_BLOCKS.get(blockInfo.archetype!);
894
903
  if (!predefinedBlock) {
895
904
  throw new Error('Predefined block not found for archetype [' + blockInfo.archetype + ']');
896
905
  }
897
906
 
907
+ const target = this.toBlockTarget(handle, blockInfo.type);
908
+
898
909
  const blockDefinition = await predefinedBlock.getBlockDefinition();
899
910
  _.set(blockDefinition!, ['metadata', 'name'], blockRef.fullName);
900
911
  _.set(blockDefinition!, ['metadata', 'title'], blockRef.name);
912
+ _.set(blockDefinition!, ['spec', 'target', 'options'], target?.options);
913
+
914
+ const options: StormOptions = this.options;
915
+
916
+ function getKind(kind: string): string | undefined {
917
+ for (const prop in options) {
918
+ if (options.hasOwnProperty(prop)) {
919
+ const value = options[prop];
920
+ if (value.startsWith(kind)) {
921
+ return value;
922
+ }
923
+ }
924
+ }
925
+ }
926
+
927
+ blockDefinition!.kind = getKind(parseKapetaUri(blockDefinition!.kind).fullName) ?? blockDefinition!.kind;
928
+ for (const provider of blockDefinition!.spec.providers ?? []) {
929
+ provider.kind = getKind(parseKapetaUri(provider.kind).fullName) ?? provider.kind;
930
+ }
931
+ for (const consumer of blockDefinition!.spec.consumers ?? []) {
932
+ consumer.kind = getKind(parseKapetaUri(consumer.kind).fullName) ?? consumer.kind;
933
+ }
934
+ blockDefinition!.spec.target!.kind =
935
+ getKind(parseKapetaUri(blockDefinition!.spec.target!.kind).fullName) ?? blockDefinition!.spec.target!.kind;
901
936
 
902
937
  return {
903
938
  uri: blockRef.toNormalizedString(),
@@ -103,7 +103,7 @@ router.post('/:handle/all', async (req: KapetaBodyRequest, res: Response) => {
103
103
  return;
104
104
  }
105
105
 
106
- const result = await eventParser.toResult(handle);
106
+ const result = await eventParser.toResult(handle, true);
107
107
 
108
108
  if (metaStream.isAborted()) {
109
109
  return;