@kapeta/local-cluster-service 0.48.0 → 0.48.1

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 CHANGED
@@ -1,3 +1,10 @@
1
+ ## [0.48.1](https://github.com/kapetacom/local-cluster-service/compare/v0.48.0...v0.48.1) (2024-06-03)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * Enrich events with block refs and instance ids ([#156](https://github.com/kapetacom/local-cluster-service/issues/156)) ([c45d5d7](https://github.com/kapetacom/local-cluster-service/commit/c45d5d776760a51fb786582d74cb4d049e27f0db))
7
+
1
8
  # [0.48.0](https://github.com/kapetacom/local-cluster-service/compare/v0.47.4...v0.48.0) (2024-06-03)
2
9
 
3
10
 
@@ -51,10 +51,15 @@ export declare class StormEventParser {
51
51
  private options;
52
52
  constructor(options: StormOptions);
53
53
  private reset;
54
- addEvent(handle: string, evt: StormEvent): StormDefinitions;
54
+ /**
55
+ * Builds plan and block definitions - and enriches events with relevant refs and ids
56
+ */
57
+ processEvent(handle: string, evt: StormEvent): StormDefinitions;
55
58
  getEvents(): StormEvent[];
56
59
  isValid(): boolean;
57
60
  getError(): string;
61
+ private toInstanceId;
62
+ private toInstanceIdFromRef;
58
63
  toResult(handle: string): StormDefinitions;
59
64
  private toSafeName;
60
65
  private toRef;
@@ -122,9 +122,11 @@ class StormEventParser {
122
122
  this.blocks = {};
123
123
  this.connections = [];
124
124
  }
125
- addEvent(handle, evt) {
125
+ /**
126
+ * Builds plan and block definitions - and enriches events with relevant refs and ids
127
+ */
128
+ processEvent(handle, evt) {
126
129
  this.events.push(evt);
127
- console.log('evt', evt);
128
130
  switch (evt.type) {
129
131
  case 'CREATE_PLAN_PROPERTIES':
130
132
  this.planName = evt.payload.name;
@@ -137,6 +139,8 @@ class StormEventParser {
137
139
  models: [],
138
140
  types: [],
139
141
  };
142
+ evt.payload.blockRef = this.toRef(handle, evt.payload.name).toNormalizedString();
143
+ evt.payload.instanceId = this.toInstanceIdFromRef(evt.payload.blockRef);
140
144
  break;
141
145
  case 'PLAN_RETRY':
142
146
  this.reset();
@@ -147,14 +151,22 @@ class StormEventParser {
147
151
  break;
148
152
  case 'CREATE_API':
149
153
  this.blocks[evt.payload.blockName].apis.push(prettifyKaplang(evt.payload.content));
154
+ evt.payload.blockRef = this.toRef(handle, evt.payload.blockName).toNormalizedString();
155
+ evt.payload.instanceId = this.toInstanceIdFromRef(evt.payload.blockRef);
150
156
  break;
151
157
  case 'CREATE_TYPE':
152
158
  this.blocks[evt.payload.blockName].types.push(prettifyKaplang(evt.payload.content));
159
+ evt.payload.blockRef = this.toRef(handle, evt.payload.blockName).toNormalizedString();
160
+ evt.payload.instanceId = this.toInstanceIdFromRef(evt.payload.blockRef);
153
161
  break;
154
162
  case 'CREATE_MODEL':
155
163
  this.blocks[evt.payload.blockName].models.push(prettifyKaplang(evt.payload.content));
164
+ evt.payload.blockRef = this.toRef(handle, evt.payload.blockName).toNormalizedString();
165
+ evt.payload.instanceId = this.toInstanceIdFromRef(evt.payload.blockRef);
156
166
  break;
157
167
  case 'CREATE_CONNECTION':
168
+ evt.payload.fromBlockId = this.toInstanceId(handle, evt.payload.fromComponent);
169
+ evt.payload.toBlockId = this.toInstanceId(handle, evt.payload.toComponent);
158
170
  this.connections.push(evt.payload);
159
171
  break;
160
172
  default:
@@ -176,13 +188,20 @@ class StormEventParser {
176
188
  getError() {
177
189
  return this.error;
178
190
  }
191
+ toInstanceId(handle, blockName) {
192
+ const ref = this.toRef(handle, blockName);
193
+ return this.toInstanceIdFromRef(ref.toNormalizedString());
194
+ }
195
+ toInstanceIdFromRef(ref) {
196
+ return (0, uuid_1.v5)((0, nodejs_utils_1.normalizeKapetaUri)(ref), uuid_1.v5.URL);
197
+ }
179
198
  toResult(handle) {
180
199
  const planRef = this.toRef(handle, this.planName ?? 'undefined');
181
200
  const blockDefinitions = this.toBlockDefinitions(handle);
182
201
  const refIdMap = {};
183
202
  const blocks = Object.entries(blockDefinitions).map(([ref, block]) => {
184
203
  // Create a deterministic uuid
185
- const id = (0, uuid_1.v5)(ref, uuid_1.v5.URL);
204
+ const id = this.toInstanceIdFromRef(ref);
186
205
  refIdMap[ref] = id;
187
206
  return {
188
207
  id,
@@ -14,6 +14,8 @@ export interface StormBlockInfo {
14
14
  name: string;
15
15
  description: string;
16
16
  }[];
17
+ blockRef?: string;
18
+ instanceId?: string;
17
19
  }
18
20
  export interface StormBlockInfoFilled extends StormBlockInfo {
19
21
  apis: string[];
@@ -28,9 +30,11 @@ export interface StormEventCreateBlock {
28
30
  }
29
31
  export interface StormConnection {
30
32
  fromComponent: string;
33
+ fromBlockId?: string;
31
34
  fromResource: string;
32
35
  fromResourceType: StormResourceType;
33
36
  toComponent: string;
37
+ toBlockId?: string;
34
38
  toResource: string;
35
39
  toResourceType: StormResourceType;
36
40
  }
@@ -72,6 +76,8 @@ export interface StormEventCreateDSL {
72
76
  payload: {
73
77
  blockName: string;
74
78
  content: string;
79
+ blockRef?: string;
80
+ instanceId?: string;
75
81
  };
76
82
  }
77
83
  export interface StormEventError {
@@ -27,12 +27,12 @@ router.post('/:handle/all', async (req, res) => {
27
27
  res.set('Content-Type', 'application/x-ndjson');
28
28
  res.set('Access-Control-Expose-Headers', stormClient_1.ConversationIdHeader);
29
29
  res.set(stormClient_1.ConversationIdHeader, metaStream.getConversationId());
30
- console.log('metaStream.getConversationId()', metaStream.getConversationId());
31
30
  metaStream.on('data', (data) => {
32
- const result = eventParser.addEvent(req.params.handle, data);
31
+ const result = eventParser.processEvent(req.params.handle, data);
32
+ sendEvent(res, data);
33
33
  sendDefinitions(res, result);
34
34
  });
35
- await streamStormPartialResponse(metaStream, res);
35
+ await waitForStormStream(metaStream);
36
36
  if (!eventParser.isValid()) {
37
37
  // We can't continue if the meta stream is invalid
38
38
  sendEvent(res, {
@@ -88,6 +88,16 @@ function sendError(err, res) {
88
88
  res.status(400).send({ error: err.message });
89
89
  }
90
90
  }
91
+ function waitForStormStream(result) {
92
+ return new Promise((resolve, reject) => {
93
+ result.on('error', (err) => {
94
+ reject(err);
95
+ });
96
+ result.on('end', () => {
97
+ resolve();
98
+ });
99
+ });
100
+ }
91
101
  function streamStormPartialResponse(result, res) {
92
102
  return new Promise((resolve, reject) => {
93
103
  result.on('data', (data) => {
@@ -127,7 +127,7 @@ const events = [
127
127
  describe('event-parser', () => {
128
128
  it('it can parse events into a plan and blocks with proper layout', () => {
129
129
  const parser = new event_parser_1.StormEventParser(parserOptions);
130
- events.forEach((event) => parser.addEvent('kapeta', event));
130
+ events.forEach((event) => parser.processEvent('kapeta', event));
131
131
  const result = parser.toResult('kapeta');
132
132
  expect(result.plan.metadata.name).toBe('kapeta/my-plan');
133
133
  expect(result.plan.metadata.description).toBe('my plan description');
@@ -51,10 +51,15 @@ export declare class StormEventParser {
51
51
  private options;
52
52
  constructor(options: StormOptions);
53
53
  private reset;
54
- addEvent(handle: string, evt: StormEvent): StormDefinitions;
54
+ /**
55
+ * Builds plan and block definitions - and enriches events with relevant refs and ids
56
+ */
57
+ processEvent(handle: string, evt: StormEvent): StormDefinitions;
55
58
  getEvents(): StormEvent[];
56
59
  isValid(): boolean;
57
60
  getError(): string;
61
+ private toInstanceId;
62
+ private toInstanceIdFromRef;
58
63
  toResult(handle: string): StormDefinitions;
59
64
  private toSafeName;
60
65
  private toRef;
@@ -122,9 +122,11 @@ class StormEventParser {
122
122
  this.blocks = {};
123
123
  this.connections = [];
124
124
  }
125
- addEvent(handle, evt) {
125
+ /**
126
+ * Builds plan and block definitions - and enriches events with relevant refs and ids
127
+ */
128
+ processEvent(handle, evt) {
126
129
  this.events.push(evt);
127
- console.log('evt', evt);
128
130
  switch (evt.type) {
129
131
  case 'CREATE_PLAN_PROPERTIES':
130
132
  this.planName = evt.payload.name;
@@ -137,6 +139,8 @@ class StormEventParser {
137
139
  models: [],
138
140
  types: [],
139
141
  };
142
+ evt.payload.blockRef = this.toRef(handle, evt.payload.name).toNormalizedString();
143
+ evt.payload.instanceId = this.toInstanceIdFromRef(evt.payload.blockRef);
140
144
  break;
141
145
  case 'PLAN_RETRY':
142
146
  this.reset();
@@ -147,14 +151,22 @@ class StormEventParser {
147
151
  break;
148
152
  case 'CREATE_API':
149
153
  this.blocks[evt.payload.blockName].apis.push(prettifyKaplang(evt.payload.content));
154
+ evt.payload.blockRef = this.toRef(handle, evt.payload.blockName).toNormalizedString();
155
+ evt.payload.instanceId = this.toInstanceIdFromRef(evt.payload.blockRef);
150
156
  break;
151
157
  case 'CREATE_TYPE':
152
158
  this.blocks[evt.payload.blockName].types.push(prettifyKaplang(evt.payload.content));
159
+ evt.payload.blockRef = this.toRef(handle, evt.payload.blockName).toNormalizedString();
160
+ evt.payload.instanceId = this.toInstanceIdFromRef(evt.payload.blockRef);
153
161
  break;
154
162
  case 'CREATE_MODEL':
155
163
  this.blocks[evt.payload.blockName].models.push(prettifyKaplang(evt.payload.content));
164
+ evt.payload.blockRef = this.toRef(handle, evt.payload.blockName).toNormalizedString();
165
+ evt.payload.instanceId = this.toInstanceIdFromRef(evt.payload.blockRef);
156
166
  break;
157
167
  case 'CREATE_CONNECTION':
168
+ evt.payload.fromBlockId = this.toInstanceId(handle, evt.payload.fromComponent);
169
+ evt.payload.toBlockId = this.toInstanceId(handle, evt.payload.toComponent);
158
170
  this.connections.push(evt.payload);
159
171
  break;
160
172
  default:
@@ -176,13 +188,20 @@ class StormEventParser {
176
188
  getError() {
177
189
  return this.error;
178
190
  }
191
+ toInstanceId(handle, blockName) {
192
+ const ref = this.toRef(handle, blockName);
193
+ return this.toInstanceIdFromRef(ref.toNormalizedString());
194
+ }
195
+ toInstanceIdFromRef(ref) {
196
+ return (0, uuid_1.v5)((0, nodejs_utils_1.normalizeKapetaUri)(ref), uuid_1.v5.URL);
197
+ }
179
198
  toResult(handle) {
180
199
  const planRef = this.toRef(handle, this.planName ?? 'undefined');
181
200
  const blockDefinitions = this.toBlockDefinitions(handle);
182
201
  const refIdMap = {};
183
202
  const blocks = Object.entries(blockDefinitions).map(([ref, block]) => {
184
203
  // Create a deterministic uuid
185
- const id = (0, uuid_1.v5)(ref, uuid_1.v5.URL);
204
+ const id = this.toInstanceIdFromRef(ref);
186
205
  refIdMap[ref] = id;
187
206
  return {
188
207
  id,
@@ -14,6 +14,8 @@ export interface StormBlockInfo {
14
14
  name: string;
15
15
  description: string;
16
16
  }[];
17
+ blockRef?: string;
18
+ instanceId?: string;
17
19
  }
18
20
  export interface StormBlockInfoFilled extends StormBlockInfo {
19
21
  apis: string[];
@@ -28,9 +30,11 @@ export interface StormEventCreateBlock {
28
30
  }
29
31
  export interface StormConnection {
30
32
  fromComponent: string;
33
+ fromBlockId?: string;
31
34
  fromResource: string;
32
35
  fromResourceType: StormResourceType;
33
36
  toComponent: string;
37
+ toBlockId?: string;
34
38
  toResource: string;
35
39
  toResourceType: StormResourceType;
36
40
  }
@@ -72,6 +76,8 @@ export interface StormEventCreateDSL {
72
76
  payload: {
73
77
  blockName: string;
74
78
  content: string;
79
+ blockRef?: string;
80
+ instanceId?: string;
75
81
  };
76
82
  }
77
83
  export interface StormEventError {
@@ -27,12 +27,12 @@ router.post('/:handle/all', async (req, res) => {
27
27
  res.set('Content-Type', 'application/x-ndjson');
28
28
  res.set('Access-Control-Expose-Headers', stormClient_1.ConversationIdHeader);
29
29
  res.set(stormClient_1.ConversationIdHeader, metaStream.getConversationId());
30
- console.log('metaStream.getConversationId()', metaStream.getConversationId());
31
30
  metaStream.on('data', (data) => {
32
- const result = eventParser.addEvent(req.params.handle, data);
31
+ const result = eventParser.processEvent(req.params.handle, data);
32
+ sendEvent(res, data);
33
33
  sendDefinitions(res, result);
34
34
  });
35
- await streamStormPartialResponse(metaStream, res);
35
+ await waitForStormStream(metaStream);
36
36
  if (!eventParser.isValid()) {
37
37
  // We can't continue if the meta stream is invalid
38
38
  sendEvent(res, {
@@ -88,6 +88,16 @@ function sendError(err, res) {
88
88
  res.status(400).send({ error: err.message });
89
89
  }
90
90
  }
91
+ function waitForStormStream(result) {
92
+ return new Promise((resolve, reject) => {
93
+ result.on('error', (err) => {
94
+ reject(err);
95
+ });
96
+ result.on('end', () => {
97
+ resolve();
98
+ });
99
+ });
100
+ }
91
101
  function streamStormPartialResponse(result, res) {
92
102
  return new Promise((resolve, reject) => {
93
103
  result.on('data', (data) => {
@@ -127,7 +127,7 @@ const events = [
127
127
  describe('event-parser', () => {
128
128
  it('it can parse events into a plan and blocks with proper layout', () => {
129
129
  const parser = new event_parser_1.StormEventParser(parserOptions);
130
- events.forEach((event) => parser.addEvent('kapeta', event));
130
+ events.forEach((event) => parser.processEvent('kapeta', event));
131
131
  const result = parser.toResult('kapeta');
132
132
  expect(result.plan.metadata.name).toBe('kapeta/my-plan');
133
133
  expect(result.plan.metadata.description).toBe('my plan description');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kapeta/local-cluster-service",
3
- "version": "0.48.0",
3
+ "version": "0.48.1",
4
4
  "description": "Manages configuration, ports and service discovery for locally running Kapeta systems",
5
5
  "type": "commonjs",
6
6
  "exports": {
@@ -136,7 +136,7 @@ export class StormCodegen {
136
136
  }
137
137
 
138
138
  const basePath = path.join(os.tmpdir(), block.content.metadata.name);
139
-
139
+
140
140
  for (const serviceFile of serviceFiles) {
141
141
  const filePath = join(basePath, serviceFile.filename);
142
142
  await writeFile(filePath, serviceFile.content);
@@ -147,7 +147,7 @@ export class StormCodegen {
147
147
  await writeFile(filePath, serviceFile.content);
148
148
  }
149
149
 
150
- for(const uiFile of uiTemplates){
150
+ for (const uiFile of uiTemplates) {
151
151
  const filePath = join(basePath, uiFile.filename);
152
152
  await writeFile(filePath, uiFile.content);
153
153
  }
@@ -221,9 +221,11 @@ export class StormEventParser {
221
221
  this.connections = [];
222
222
  }
223
223
 
224
- public addEvent(handle: string, evt: StormEvent): StormDefinitions {
224
+ /**
225
+ * Builds plan and block definitions - and enriches events with relevant refs and ids
226
+ */
227
+ public processEvent(handle: string, evt: StormEvent): StormDefinitions {
225
228
  this.events.push(evt);
226
- console.log('evt', evt);
227
229
  switch (evt.type) {
228
230
  case 'CREATE_PLAN_PROPERTIES':
229
231
  this.planName = evt.payload.name;
@@ -236,6 +238,8 @@ export class StormEventParser {
236
238
  models: [],
237
239
  types: [],
238
240
  };
241
+ evt.payload.blockRef = this.toRef(handle, evt.payload.name).toNormalizedString();
242
+ evt.payload.instanceId = this.toInstanceIdFromRef(evt.payload.blockRef);
239
243
  break;
240
244
  case 'PLAN_RETRY':
241
245
  this.reset();
@@ -246,14 +250,22 @@ export class StormEventParser {
246
250
  break;
247
251
  case 'CREATE_API':
248
252
  this.blocks[evt.payload.blockName].apis.push(prettifyKaplang(evt.payload.content));
253
+ evt.payload.blockRef = this.toRef(handle, evt.payload.blockName).toNormalizedString();
254
+ evt.payload.instanceId = this.toInstanceIdFromRef(evt.payload.blockRef);
249
255
  break;
250
256
  case 'CREATE_TYPE':
251
257
  this.blocks[evt.payload.blockName].types.push(prettifyKaplang(evt.payload.content));
258
+ evt.payload.blockRef = this.toRef(handle, evt.payload.blockName).toNormalizedString();
259
+ evt.payload.instanceId = this.toInstanceIdFromRef(evt.payload.blockRef);
252
260
  break;
253
261
  case 'CREATE_MODEL':
254
262
  this.blocks[evt.payload.blockName].models.push(prettifyKaplang(evt.payload.content));
263
+ evt.payload.blockRef = this.toRef(handle, evt.payload.blockName).toNormalizedString();
264
+ evt.payload.instanceId = this.toInstanceIdFromRef(evt.payload.blockRef);
255
265
  break;
256
266
  case 'CREATE_CONNECTION':
267
+ evt.payload.fromBlockId = this.toInstanceId(handle, evt.payload.fromComponent);
268
+ evt.payload.toBlockId = this.toInstanceId(handle, evt.payload.toComponent);
257
269
  this.connections.push(evt.payload);
258
270
  break;
259
271
 
@@ -281,13 +293,22 @@ export class StormEventParser {
281
293
  return this.error;
282
294
  }
283
295
 
296
+ private toInstanceId(handle: string, blockName: string) {
297
+ const ref = this.toRef(handle, blockName);
298
+ return this.toInstanceIdFromRef(ref.toNormalizedString());
299
+ }
300
+
301
+ private toInstanceIdFromRef(ref: string) {
302
+ return uuid(normalizeKapetaUri(ref), uuid.URL);
303
+ }
304
+
284
305
  public toResult(handle: string): StormDefinitions {
285
306
  const planRef = this.toRef(handle, this.planName ?? 'undefined');
286
307
  const blockDefinitions = this.toBlockDefinitions(handle);
287
308
  const refIdMap: { [key: string]: string } = {};
288
309
  const blocks = Object.entries(blockDefinitions).map(([ref, block]) => {
289
310
  // Create a deterministic uuid
290
- const id = uuid(ref, uuid.URL);
311
+ const id = this.toInstanceIdFromRef(ref);
291
312
  refIdMap[ref] = id;
292
313
  return {
293
314
  id,
@@ -30,6 +30,8 @@ export interface StormBlockInfo {
30
30
  name: string;
31
31
  description: string;
32
32
  }[];
33
+ blockRef?: string;
34
+ instanceId?: string;
33
35
  }
34
36
 
35
37
  export interface StormBlockInfoFilled extends StormBlockInfo {
@@ -47,9 +49,11 @@ export interface StormEventCreateBlock {
47
49
 
48
50
  export interface StormConnection {
49
51
  fromComponent: string;
52
+ fromBlockId?: string;
50
53
  fromResource: string;
51
54
  fromResourceType: StormResourceType;
52
55
  toComponent: string;
56
+ toBlockId?: string;
53
57
  toResource: string;
54
58
  toResourceType: StormResourceType;
55
59
  }
@@ -96,6 +100,8 @@ export interface StormEventCreateDSL {
96
100
  payload: {
97
101
  blockName: string;
98
102
  content: string;
103
+ blockRef?: string;
104
+ instanceId?: string;
99
105
  };
100
106
  }
101
107
 
@@ -35,15 +35,15 @@ router.post('/:handle/all', async (req: KapetaBodyRequest, res: Response) => {
35
35
  res.set('Content-Type', 'application/x-ndjson');
36
36
  res.set('Access-Control-Expose-Headers', ConversationIdHeader);
37
37
  res.set(ConversationIdHeader, metaStream.getConversationId());
38
- console.log('metaStream.getConversationId()', metaStream.getConversationId());
39
38
 
40
39
  metaStream.on('data', (data: StormEvent) => {
41
- const result = eventParser.addEvent(req.params.handle, data);
40
+ const result = eventParser.processEvent(req.params.handle, data);
42
41
 
42
+ sendEvent(res, data);
43
43
  sendDefinitions(res, result);
44
44
  });
45
45
 
46
- await streamStormPartialResponse(metaStream, res);
46
+ await waitForStormStream(metaStream);
47
47
 
48
48
  if (!eventParser.isValid()) {
49
49
  // We can't continue if the meta stream is invalid
@@ -109,6 +109,17 @@ function sendError(err: Error, res: Response) {
109
109
  res.status(400).send({ error: err.message });
110
110
  }
111
111
  }
112
+ function waitForStormStream(result: StormStream) {
113
+ return new Promise<void>((resolve, reject) => {
114
+ result.on('error', (err) => {
115
+ reject(err);
116
+ });
117
+
118
+ result.on('end', () => {
119
+ resolve();
120
+ });
121
+ });
122
+ }
112
123
 
113
124
  function streamStormPartialResponse(result: StormStream, res: Response) {
114
125
  return new Promise<void>((resolve, reject) => {
@@ -139,7 +139,7 @@ const events: StormEvent[] = [
139
139
  describe('event-parser', () => {
140
140
  it('it can parse events into a plan and blocks with proper layout', () => {
141
141
  const parser = new StormEventParser(parserOptions);
142
- events.forEach((event) => parser.addEvent('kapeta', event));
142
+ events.forEach((event) => parser.processEvent('kapeta', event));
143
143
 
144
144
  const result = parser.toResult('kapeta');
145
145