@kapeta/local-cluster-service 0.53.4 → 0.54.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/.eslintrc.cjs +1 -0
- package/CHANGELOG.md +17 -0
- package/dist/cjs/src/storm/codegen.js +68 -22
- package/dist/cjs/src/storm/event-parser.js +26 -11
- package/dist/cjs/src/storm/events.d.ts +1 -0
- package/dist/cjs/src/storm/stormClient.d.ts +2 -1
- package/dist/cjs/src/storm/stormClient.js +6 -0
- package/dist/cjs/src/storm/stream.d.ts +8 -0
- package/dist/cjs/test/storm/event-parser.test.js +18 -0
- package/dist/cjs/test/storm/simple-blog-events.json +470 -0
- package/dist/esm/src/storm/codegen.js +68 -22
- package/dist/esm/src/storm/event-parser.js +26 -11
- package/dist/esm/src/storm/events.d.ts +1 -0
- package/dist/esm/src/storm/stormClient.d.ts +2 -1
- package/dist/esm/src/storm/stormClient.js +6 -0
- package/dist/esm/src/storm/stream.d.ts +8 -0
- package/dist/esm/test/storm/event-parser.test.js +18 -0
- package/dist/esm/test/storm/simple-blog-events.json +470 -0
- package/package.json +2 -2
- package/src/storm/codegen.ts +101 -39
- package/src/storm/event-parser.ts +30 -13
- package/src/storm/events.ts +1 -0
- package/src/storm/stormClient.ts +9 -1
- package/src/storm/stream.ts +9 -0
- package/test/storm/event-parser.test.ts +19 -0
- package/test/storm/simple-blog-events.json +470 -0
- package/tsconfig.json +2 -1
@@ -0,0 +1,470 @@
|
|
1
|
+
[
|
2
|
+
{
|
3
|
+
"type": "MODEL_RESPONSE",
|
4
|
+
"reason": "",
|
5
|
+
"payload": {
|
6
|
+
"text": "Certainly! Here's how you can design a simple blog system. It will consist of a backend block for managing posts and users, a frontend block for displaying the blog, and a gateway block for making the blog publicly accessible."
|
7
|
+
},
|
8
|
+
"created": 1718365003668
|
9
|
+
},
|
10
|
+
{
|
11
|
+
"type": "CREATE_PLAN_PROPERTIES",
|
12
|
+
"reason": "Define the properties for the plan itself",
|
13
|
+
"payload": {
|
14
|
+
"description": "A simple blog system with a backend for managing posts and users, a frontend for displaying the blog, and a gateway for making the blog publicly accessible.",
|
15
|
+
"name": "Simple Blog"
|
16
|
+
},
|
17
|
+
"created": 1718365004184
|
18
|
+
},
|
19
|
+
{
|
20
|
+
"type": "CREATE_BLOCK",
|
21
|
+
"reason": "The system needs a backend to handle posts and users",
|
22
|
+
"payload": {
|
23
|
+
"description": "Handles posts and users",
|
24
|
+
"name": "blog-service",
|
25
|
+
"resources": [
|
26
|
+
{
|
27
|
+
"description": "Stores blog posts",
|
28
|
+
"name": "posts",
|
29
|
+
"type": "DATABASE"
|
30
|
+
},
|
31
|
+
{
|
32
|
+
"description": "Stores user information",
|
33
|
+
"name": "users",
|
34
|
+
"type": "DATABASE"
|
35
|
+
},
|
36
|
+
{
|
37
|
+
"description": "Handles blog posts",
|
38
|
+
"name": "posts",
|
39
|
+
"type": "API"
|
40
|
+
},
|
41
|
+
{
|
42
|
+
"description": "Handles user information",
|
43
|
+
"name": "users",
|
44
|
+
"type": "API"
|
45
|
+
},
|
46
|
+
{
|
47
|
+
"description": "Handles JWT token generation and validation",
|
48
|
+
"name": "jwt-provider",
|
49
|
+
"type": "JWTPROVIDER"
|
50
|
+
},
|
51
|
+
{
|
52
|
+
"description": "Sends emails for user registration and password reset",
|
53
|
+
"name": "smtp-client",
|
54
|
+
"type": "SMTPCLIENT"
|
55
|
+
}
|
56
|
+
],
|
57
|
+
"type": "BACKEND",
|
58
|
+
"blockRef": "kapeta://kapeta/blog-service:local",
|
59
|
+
"instanceId": "d8d25816-bb83-5797-9881-a6282fe7a20b"
|
60
|
+
},
|
61
|
+
"created": 1718365005843
|
62
|
+
},
|
63
|
+
{
|
64
|
+
"type": "CREATE_BLOCK",
|
65
|
+
"reason": "The system needs a frontend to display the blog",
|
66
|
+
"payload": {
|
67
|
+
"description": "Displays the blog",
|
68
|
+
"name": "blog-ui",
|
69
|
+
"resources": [
|
70
|
+
{
|
71
|
+
"description": "Fetches blog posts from the backend",
|
72
|
+
"name": "posts",
|
73
|
+
"type": "CLIENT"
|
74
|
+
},
|
75
|
+
{
|
76
|
+
"description": "Handles user authentication and registration",
|
77
|
+
"name": "users",
|
78
|
+
"type": "CLIENT"
|
79
|
+
},
|
80
|
+
{
|
81
|
+
"description": "Displays the main page of the blog",
|
82
|
+
"name": "main",
|
83
|
+
"type": "WEBPAGE"
|
84
|
+
}
|
85
|
+
],
|
86
|
+
"type": "FRONTEND",
|
87
|
+
"blockRef": "kapeta://kapeta/blog-ui:local",
|
88
|
+
"instanceId": "79761687-1528-5f8f-8036-b8d49e23b49d"
|
89
|
+
},
|
90
|
+
"created": 1718365006823
|
91
|
+
},
|
92
|
+
{
|
93
|
+
"type": "CREATE_BLOCK",
|
94
|
+
"reason": "The system needs a gateway to make the blog publicly accessible",
|
95
|
+
"payload": {
|
96
|
+
"description": "Makes the blog publicly accessible",
|
97
|
+
"name": "gateway",
|
98
|
+
"resources": [
|
99
|
+
{
|
100
|
+
"description": "Makes the posts API public under '/posts' path",
|
101
|
+
"name": "posts",
|
102
|
+
"path": "/posts",
|
103
|
+
"type": "CLIENT"
|
104
|
+
},
|
105
|
+
{
|
106
|
+
"description": "Makes the main page public under '/' path",
|
107
|
+
"name": "main",
|
108
|
+
"path": "/",
|
109
|
+
"type": "WEBFRAGMENT"
|
110
|
+
}
|
111
|
+
],
|
112
|
+
"type": "GATEWAY",
|
113
|
+
"blockRef": "kapeta://kapeta/gateway:local",
|
114
|
+
"instanceId": "f7327a25-7fc2-57b6-99e6-1b7e07378790"
|
115
|
+
},
|
116
|
+
"created": 1718365007689
|
117
|
+
},
|
118
|
+
{
|
119
|
+
"type": "CREATE_CONNECTION",
|
120
|
+
"reason": "The frontend needs to fetch blog posts from the backend",
|
121
|
+
"payload": {
|
122
|
+
"fromComponent": "blog-service",
|
123
|
+
"fromResource": "posts",
|
124
|
+
"fromResourceType": "API",
|
125
|
+
"toComponent": "blog-ui",
|
126
|
+
"toResource": "posts",
|
127
|
+
"toResourceType": "CLIENT",
|
128
|
+
"fromBlockId": "d8d25816-bb83-5797-9881-a6282fe7a20b",
|
129
|
+
"toBlockId": "79761687-1528-5f8f-8036-b8d49e23b49d"
|
130
|
+
},
|
131
|
+
"created": 1718365008108
|
132
|
+
},
|
133
|
+
{
|
134
|
+
"type": "CREATE_CONNECTION",
|
135
|
+
"reason": "The frontend needs to handle user authentication and registration",
|
136
|
+
"payload": {
|
137
|
+
"fromComponent": "blog-service",
|
138
|
+
"fromResource": "users",
|
139
|
+
"fromResourceType": "API",
|
140
|
+
"toComponent": "blog-ui",
|
141
|
+
"toResource": "users",
|
142
|
+
"toResourceType": "CLIENT",
|
143
|
+
"fromBlockId": "d8d25816-bb83-5797-9881-a6282fe7a20b",
|
144
|
+
"toBlockId": "79761687-1528-5f8f-8036-b8d49e23b49d"
|
145
|
+
},
|
146
|
+
"created": 1718365008526
|
147
|
+
},
|
148
|
+
{
|
149
|
+
"type": "CREATE_CONNECTION",
|
150
|
+
"reason": "The gateway needs to make the posts API publicly accessible",
|
151
|
+
"payload": {
|
152
|
+
"fromComponent": "blog-service",
|
153
|
+
"fromResource": "posts",
|
154
|
+
"fromResourceType": "API",
|
155
|
+
"toComponent": "gateway",
|
156
|
+
"toResource": "posts",
|
157
|
+
"toResourceType": "CLIENT",
|
158
|
+
"fromBlockId": "d8d25816-bb83-5797-9881-a6282fe7a20b",
|
159
|
+
"toBlockId": "f7327a25-7fc2-57b6-99e6-1b7e07378790"
|
160
|
+
},
|
161
|
+
"created": 1718365008990
|
162
|
+
},
|
163
|
+
{
|
164
|
+
"type": "CREATE_CONNECTION",
|
165
|
+
"reason": "The gateway needs to make the main page publicly accessible",
|
166
|
+
"payload": {
|
167
|
+
"fromComponent": "blog-ui",
|
168
|
+
"fromResource": "main",
|
169
|
+
"fromResourceType": "WEBPAGE",
|
170
|
+
"toComponent": "gateway",
|
171
|
+
"toResource": "main",
|
172
|
+
"toResourceType": "WEBFRAGMENT",
|
173
|
+
"fromBlockId": "79761687-1528-5f8f-8036-b8d49e23b49d",
|
174
|
+
"toBlockId": "f7327a25-7fc2-57b6-99e6-1b7e07378790"
|
175
|
+
},
|
176
|
+
"created": 1718365009823
|
177
|
+
},
|
178
|
+
{
|
179
|
+
"type": "CREATE_CONNECTION",
|
180
|
+
"reason": "The blog service needs to be able to authenticate requests",
|
181
|
+
"payload": {
|
182
|
+
"fromComponent": "blog-service",
|
183
|
+
"fromResource": "jwt-provider",
|
184
|
+
"fromResourceType": "JWTPROVIDER",
|
185
|
+
"toComponent": "blog-service",
|
186
|
+
"toResource": "jwt-consumer",
|
187
|
+
"toResourceType": "JWTCONSUMER",
|
188
|
+
"fromBlockId": "d8d25816-bb83-5797-9881-a6282fe7a20b",
|
189
|
+
"toBlockId": "d8d25816-bb83-5797-9881-a6282fe7a20b"
|
190
|
+
},
|
191
|
+
"created": 1718365009974
|
192
|
+
},
|
193
|
+
{
|
194
|
+
"type": "PLAN_RETRY",
|
195
|
+
"reason": "Found issues in the response but will try again",
|
196
|
+
"payload": {
|
197
|
+
"agent": "plan",
|
198
|
+
"errors": [
|
199
|
+
"Resource jwt-consumer is not defined for component blog-service in connection: 'blog-service.jwt-provider.JWTPROVIDER' to 'blog-service.jwt-consumer.JWTCONSUMER'"
|
200
|
+
]
|
201
|
+
},
|
202
|
+
"created": 1718365010012
|
203
|
+
},
|
204
|
+
{
|
205
|
+
"type": "MODEL_RESPONSE",
|
206
|
+
"reason": "",
|
207
|
+
"payload": {
|
208
|
+
"text": "Certainly! Here's how you can design a simple blog system. It will consist of a backend block for managing posts and users, a frontend block for displaying the blog, and a gateway block for making the blog publicly accessible."
|
209
|
+
},
|
210
|
+
"created": 1718365011059
|
211
|
+
},
|
212
|
+
{
|
213
|
+
"type": "CREATE_PLAN_PROPERTIES",
|
214
|
+
"reason": "Define the properties for the plan itself",
|
215
|
+
"payload": {
|
216
|
+
"description": "A simple blog system with a backend for managing posts and users, a frontend for displaying the blog, and a gateway for making the blog publicly accessible.",
|
217
|
+
"name": "Simple Blog"
|
218
|
+
},
|
219
|
+
"created": 1718365011625
|
220
|
+
},
|
221
|
+
{
|
222
|
+
"type": "CREATE_BLOCK",
|
223
|
+
"reason": "The system needs a backend to handle posts and users",
|
224
|
+
"payload": {
|
225
|
+
"description": "Handles posts and users",
|
226
|
+
"name": "blog-service",
|
227
|
+
"resources": [
|
228
|
+
{
|
229
|
+
"description": "Stores blog posts",
|
230
|
+
"name": "posts",
|
231
|
+
"type": "DATABASE"
|
232
|
+
},
|
233
|
+
{
|
234
|
+
"description": "Stores user information",
|
235
|
+
"name": "users",
|
236
|
+
"type": "DATABASE"
|
237
|
+
},
|
238
|
+
{
|
239
|
+
"description": "Handles blog posts",
|
240
|
+
"name": "posts",
|
241
|
+
"type": "API"
|
242
|
+
},
|
243
|
+
{
|
244
|
+
"description": "Handles user information",
|
245
|
+
"name": "users",
|
246
|
+
"type": "API"
|
247
|
+
},
|
248
|
+
{
|
249
|
+
"description": "Handles JWT token generation and validation",
|
250
|
+
"name": "jwt-provider",
|
251
|
+
"type": "JWTPROVIDER"
|
252
|
+
},
|
253
|
+
{
|
254
|
+
"description": "Handles JWT token validation",
|
255
|
+
"name": "jwt-consumer",
|
256
|
+
"type": "JWTCONSUMER"
|
257
|
+
},
|
258
|
+
{
|
259
|
+
"description": "Sends emails for user registration and password reset",
|
260
|
+
"name": "smtp-client",
|
261
|
+
"type": "SMTPCLIENT"
|
262
|
+
}
|
263
|
+
],
|
264
|
+
"type": "BACKEND",
|
265
|
+
"blockRef": "kapeta://kapeta/blog-service:local",
|
266
|
+
"instanceId": "d8d25816-bb83-5797-9881-a6282fe7a20b"
|
267
|
+
},
|
268
|
+
"created": 1718365013238
|
269
|
+
},
|
270
|
+
{
|
271
|
+
"type": "CREATE_BLOCK",
|
272
|
+
"reason": "The system needs a frontend to display the blog",
|
273
|
+
"payload": {
|
274
|
+
"description": "Displays the blog",
|
275
|
+
"name": "blog-ui",
|
276
|
+
"resources": [
|
277
|
+
{
|
278
|
+
"description": "Fetches blog posts from the backend",
|
279
|
+
"name": "posts",
|
280
|
+
"type": "CLIENT"
|
281
|
+
},
|
282
|
+
{
|
283
|
+
"description": "Handles user authentication and registration",
|
284
|
+
"name": "users",
|
285
|
+
"type": "CLIENT"
|
286
|
+
},
|
287
|
+
{
|
288
|
+
"description": "Displays the main page of the blog",
|
289
|
+
"name": "main",
|
290
|
+
"type": "WEBPAGE"
|
291
|
+
}
|
292
|
+
],
|
293
|
+
"type": "FRONTEND",
|
294
|
+
"blockRef": "kapeta://kapeta/blog-ui:local",
|
295
|
+
"instanceId": "79761687-1528-5f8f-8036-b8d49e23b49d"
|
296
|
+
},
|
297
|
+
"created": 1718365014077
|
298
|
+
},
|
299
|
+
{
|
300
|
+
"type": "CREATE_BLOCK",
|
301
|
+
"reason": "The system needs a gateway to make the blog publicly accessible",
|
302
|
+
"payload": {
|
303
|
+
"description": "Makes the blog publicly accessible",
|
304
|
+
"name": "gateway",
|
305
|
+
"resources": [
|
306
|
+
{
|
307
|
+
"description": "Makes the posts API public under '/posts' path",
|
308
|
+
"name": "posts",
|
309
|
+
"path": "/posts",
|
310
|
+
"type": "CLIENT"
|
311
|
+
},
|
312
|
+
{
|
313
|
+
"description": "Makes the main page public under '/' path",
|
314
|
+
"name": "main",
|
315
|
+
"path": "/",
|
316
|
+
"type": "WEBFRAGMENT"
|
317
|
+
}
|
318
|
+
],
|
319
|
+
"type": "GATEWAY",
|
320
|
+
"blockRef": "kapeta://kapeta/gateway:local",
|
321
|
+
"instanceId": "f7327a25-7fc2-57b6-99e6-1b7e07378790"
|
322
|
+
},
|
323
|
+
"created": 1718365015029
|
324
|
+
},
|
325
|
+
{
|
326
|
+
"type": "CREATE_CONNECTION",
|
327
|
+
"reason": "The frontend needs to fetch blog posts from the backend",
|
328
|
+
"payload": {
|
329
|
+
"fromComponent": "blog-service",
|
330
|
+
"fromResource": "posts",
|
331
|
+
"fromResourceType": "API",
|
332
|
+
"toComponent": "blog-ui",
|
333
|
+
"toResource": "posts",
|
334
|
+
"toResourceType": "CLIENT",
|
335
|
+
"fromBlockId": "d8d25816-bb83-5797-9881-a6282fe7a20b",
|
336
|
+
"toBlockId": "79761687-1528-5f8f-8036-b8d49e23b49d"
|
337
|
+
},
|
338
|
+
"created": 1718365015463
|
339
|
+
},
|
340
|
+
{
|
341
|
+
"type": "CREATE_CONNECTION",
|
342
|
+
"reason": "The frontend needs to handle user authentication and registration",
|
343
|
+
"payload": {
|
344
|
+
"fromComponent": "blog-service",
|
345
|
+
"fromResource": "users",
|
346
|
+
"fromResourceType": "API",
|
347
|
+
"toComponent": "blog-ui",
|
348
|
+
"toResource": "users",
|
349
|
+
"toResourceType": "CLIENT",
|
350
|
+
"fromBlockId": "d8d25816-bb83-5797-9881-a6282fe7a20b",
|
351
|
+
"toBlockId": "79761687-1528-5f8f-8036-b8d49e23b49d"
|
352
|
+
},
|
353
|
+
"created": 1718365016463
|
354
|
+
},
|
355
|
+
{
|
356
|
+
"type": "CREATE_CONNECTION",
|
357
|
+
"reason": "The gateway needs to make the posts API publicly accessible",
|
358
|
+
"payload": {
|
359
|
+
"fromComponent": "blog-service",
|
360
|
+
"fromResource": "posts",
|
361
|
+
"fromResourceType": "API",
|
362
|
+
"toComponent": "gateway",
|
363
|
+
"toResource": "posts",
|
364
|
+
"toResourceType": "CLIENT",
|
365
|
+
"fromBlockId": "d8d25816-bb83-5797-9881-a6282fe7a20b",
|
366
|
+
"toBlockId": "f7327a25-7fc2-57b6-99e6-1b7e07378790"
|
367
|
+
},
|
368
|
+
"created": 1718365016884
|
369
|
+
},
|
370
|
+
{
|
371
|
+
"type": "CREATE_CONNECTION",
|
372
|
+
"reason": "The gateway needs to make the main page publicly accessible",
|
373
|
+
"payload": {
|
374
|
+
"fromComponent": "blog-ui",
|
375
|
+
"fromResource": "main",
|
376
|
+
"fromResourceType": "WEBPAGE",
|
377
|
+
"toComponent": "gateway",
|
378
|
+
"toResource": "main",
|
379
|
+
"toResourceType": "WEBFRAGMENT",
|
380
|
+
"fromBlockId": "79761687-1528-5f8f-8036-b8d49e23b49d",
|
381
|
+
"toBlockId": "f7327a25-7fc2-57b6-99e6-1b7e07378790"
|
382
|
+
},
|
383
|
+
"created": 1718365017299
|
384
|
+
},
|
385
|
+
{
|
386
|
+
"type": "CREATE_CONNECTION",
|
387
|
+
"reason": "The blog service needs to be able to authenticate requests",
|
388
|
+
"payload": {
|
389
|
+
"fromComponent": "blog-service",
|
390
|
+
"fromResource": "jwt-provider",
|
391
|
+
"fromResourceType": "JWTPROVIDER",
|
392
|
+
"toComponent": "blog-service",
|
393
|
+
"toResource": "jwt-consumer",
|
394
|
+
"toResourceType": "JWTCONSUMER",
|
395
|
+
"fromBlockId": "d8d25816-bb83-5797-9881-a6282fe7a20b",
|
396
|
+
"toBlockId": "d8d25816-bb83-5797-9881-a6282fe7a20b"
|
397
|
+
},
|
398
|
+
"created": 1718365017692
|
399
|
+
},
|
400
|
+
{
|
401
|
+
"type": "CREATE_TYPE",
|
402
|
+
"reason": "",
|
403
|
+
"payload": {
|
404
|
+
"blockName": "blog-service",
|
405
|
+
"content": "type Post {\n\tid: string\n\ttitle: string\n\tcontent: string\n\tauthorId: string\n\tcreatedAt: date\n\tupdatedAt: date\n}",
|
406
|
+
"blockRef": "kapeta://kapeta/blog-service:local",
|
407
|
+
"instanceId": "d8d25816-bb83-5797-9881-a6282fe7a20b"
|
408
|
+
},
|
409
|
+
"created": 1718365018773
|
410
|
+
},
|
411
|
+
{
|
412
|
+
"type": "CREATE_TYPE",
|
413
|
+
"reason": "",
|
414
|
+
"payload": {
|
415
|
+
"blockName": "blog-service",
|
416
|
+
"content": "type User {\n\tid: string\n\tusername: string\n\temail: string\n\tpassword: string\n\tcreatedAt: date\n\tupdatedAt: date\n}",
|
417
|
+
"blockRef": "kapeta://kapeta/blog-service:local",
|
418
|
+
"instanceId": "d8d25816-bb83-5797-9881-a6282fe7a20b"
|
419
|
+
},
|
420
|
+
"created": 1718365019329
|
421
|
+
},
|
422
|
+
{
|
423
|
+
"type": "CREATE_API",
|
424
|
+
"reason": "",
|
425
|
+
"payload": {
|
426
|
+
"blockName": "blog-service",
|
427
|
+
"content": "controller Post(\"/posts\") {\n\n\t@GET(\"/\")\n\tgetPosts():Post[]\n\t\n\t@GET(\"/{id}\")\n\tgetPost(@Path(\"id\") id:string):Post\n\t\n\t@POST(\"/\")\n\tcreatePost(@Body post:Post):Post\n\t\n\t@PUT(\"/{id}\")\n\tupdatePost(@Path(\"id\") id:string, @Body post:Post):Post\n\t\n\t@DELETE(\"/{id}\")\n\tdeletePost(@Path(\"id\") id:string):void\n}",
|
428
|
+
"blockRef": "kapeta://kapeta/blog-service:local",
|
429
|
+
"instanceId": "d8d25816-bb83-5797-9881-a6282fe7a20b",
|
430
|
+
"resourceName": "posts"
|
431
|
+
},
|
432
|
+
"created": 1718365020235
|
433
|
+
},
|
434
|
+
{
|
435
|
+
"type": "CREATE_API",
|
436
|
+
"reason": "",
|
437
|
+
"payload": {
|
438
|
+
"blockName": "blog-service",
|
439
|
+
"content": "controller User(\"/users\") {\n\n\t@GET(\"/\")\n\tgetUsers():User[]\n\t\n\t@GET(\"/{id}\")\n\tgetUser(@Path(\"id\") id:string):User\n\t\n\t@POST(\"/\")\n\tcreateUser(@Body user:User):User\n\t\n\t@PUT(\"/{id}\")\n\tupdateUser(@Path(\"id\") id:string, @Body user:User):User\n\t\n\t@DELETE(\"/{id}\")\n\tdeleteUser(@Path(\"id\") id:string):void\n}",
|
440
|
+
"blockRef": "kapeta://kapeta/blog-service:local",
|
441
|
+
"instanceId": "d8d25816-bb83-5797-9881-a6282fe7a20b",
|
442
|
+
"resourceName": "posts"
|
443
|
+
},
|
444
|
+
"created": 1718365020558
|
445
|
+
},
|
446
|
+
{
|
447
|
+
"type": "CREATE_MODEL",
|
448
|
+
"reason": "",
|
449
|
+
"payload": {
|
450
|
+
"blockName": "blog-service",
|
451
|
+
"content": "type Post {\n\t@Id\n\tid: string\n\ttitle: string\n\tcontent: string\n\tauthorId: string\n\tcreatedAt: date\n\tupdatedAt: date\n}",
|
452
|
+
"blockRef": "kapeta://kapeta/blog-service:local",
|
453
|
+
"instanceId": "d8d25816-bb83-5797-9881-a6282fe7a20b",
|
454
|
+
"resourceName": "posts"
|
455
|
+
},
|
456
|
+
"created": 1718365022396
|
457
|
+
},
|
458
|
+
{
|
459
|
+
"type": "CREATE_MODEL",
|
460
|
+
"reason": "",
|
461
|
+
"payload": {
|
462
|
+
"blockName": "blog-service",
|
463
|
+
"content": "type User {\n\t@Id\n\tid: string\n\tusername: string\n\temail: string\n\tpassword: string\n\tcreatedAt: date\n\tupdatedAt: date\n}",
|
464
|
+
"blockRef": "kapeta://kapeta/blog-service:local",
|
465
|
+
"instanceId": "d8d25816-bb83-5797-9881-a6282fe7a20b",
|
466
|
+
"resourceName": "posts"
|
467
|
+
},
|
468
|
+
"created": 1718365022826
|
469
|
+
}
|
470
|
+
]
|
@@ -44,7 +44,6 @@ const path_2 = __importStar(require("path"));
|
|
44
44
|
const node_os_1 = __importDefault(require("node:os"));
|
45
45
|
const fs_1 = require("fs");
|
46
46
|
const yaml_1 = __importDefault(require("yaml"));
|
47
|
-
const fs = __importStar(require("node:fs"));
|
48
47
|
const SIMULATED_DELAY = 1000;
|
49
48
|
const ENABLE_SIMULATED_DELAY = false;
|
50
49
|
class SimulatedFileDelay {
|
@@ -239,8 +238,11 @@ class StormCodegen {
|
|
239
238
|
return;
|
240
239
|
}
|
241
240
|
const blockUri = (0, nodejs_utils_1.parseKapetaUri)(block.uri);
|
242
|
-
const relevantFiles = allFiles.filter((file) => file.type !== codegen_1.AIFileTypes.IGNORE &&
|
241
|
+
const relevantFiles = allFiles.filter((file) => file.type !== codegen_1.AIFileTypes.IGNORE &&
|
242
|
+
file.type !== codegen_1.AIFileTypes.WEB_SCREEN &&
|
243
|
+
file.type !== codegen_1.AIFileTypes.WEB_ROUTER);
|
243
244
|
const uiTemplates = allFiles.filter((file) => file.type === codegen_1.AIFileTypes.WEB_SCREEN);
|
245
|
+
const webRouters = allFiles.filter((file) => file.type === codegen_1.AIFileTypes.WEB_ROUTER);
|
244
246
|
const screenFiles = [];
|
245
247
|
let filteredEvents = [];
|
246
248
|
for (const event of this.events) {
|
@@ -249,14 +251,55 @@ class StormCodegen {
|
|
249
251
|
filteredEvents = [];
|
250
252
|
}
|
251
253
|
}
|
252
|
-
|
253
|
-
|
254
|
+
const screenEvents = [];
|
255
|
+
// generate screens
|
256
|
+
const screenStream = await stormClient_1.stormClient.listScreens({
|
257
|
+
events: filteredEvents,
|
258
|
+
templates: uiTemplates,
|
259
|
+
context: relevantFiles,
|
260
|
+
blockName: block.aiName,
|
261
|
+
prompt: this.userPrompt,
|
262
|
+
});
|
263
|
+
screenStream.on('data', (evt) => {
|
264
|
+
if (evt.type === 'SCREEN') {
|
265
|
+
screenEvents.push(evt);
|
266
|
+
}
|
267
|
+
this.handleUiOutput(blockUri, block.aiName, evt);
|
268
|
+
});
|
269
|
+
this.out.on('aborted', () => {
|
270
|
+
screenStream.abort();
|
271
|
+
});
|
272
|
+
await screenStream.waitForDone();
|
273
|
+
// screenfiles
|
274
|
+
const screenTemplates = screenEvents
|
275
|
+
.map((screenEvent) => ({
|
276
|
+
...uiTemplates.find((template) => template.filename.endsWith(screenEvent.payload.template)),
|
277
|
+
filename: screenEvent.payload.filename,
|
278
|
+
}))
|
279
|
+
.filter((tpl) => !!tpl.content);
|
280
|
+
await Promise.all(screenTemplates.concat(webRouters).map(async (template) => {
|
281
|
+
const payload = {
|
254
282
|
events: filteredEvents,
|
255
|
-
templates: uiTemplates,
|
256
|
-
context: relevantFiles,
|
257
283
|
blockName: block.aiName,
|
284
|
+
filename: template.filename,
|
285
|
+
template: template,
|
286
|
+
context: relevantFiles.concat([
|
287
|
+
{
|
288
|
+
type: codegen_1.AIFileTypes.INSTRUCTIONS,
|
289
|
+
mode: codegen_1.MODE_CREATE_ONLY,
|
290
|
+
permissions: '0644',
|
291
|
+
filename: '<screens>.md',
|
292
|
+
content: `
|
293
|
+
# Generated screens
|
294
|
+
|
295
|
+
${JSON.stringify({ screenEvents })}
|
296
|
+
|
297
|
+
`,
|
298
|
+
},
|
299
|
+
]),
|
258
300
|
prompt: this.userPrompt,
|
259
|
-
}
|
301
|
+
};
|
302
|
+
const uiStream = await stormClient_1.stormClient.createUIImplementation(payload);
|
260
303
|
uiStream.on('data', (evt) => {
|
261
304
|
const uiFile = this.handleUiOutput(blockUri, block.aiName, evt);
|
262
305
|
if (uiFile != undefined) {
|
@@ -267,21 +310,34 @@ class StormCodegen {
|
|
267
310
|
uiStream.abort();
|
268
311
|
});
|
269
312
|
await uiStream.waitForDone();
|
270
|
-
}
|
313
|
+
}));
|
271
314
|
if (this.isAborted()) {
|
272
315
|
return;
|
273
316
|
}
|
317
|
+
const basePath = this.getBasePath(block.content.metadata.name);
|
318
|
+
const screenFilesConverted = screenFiles.map((screenFile) => {
|
319
|
+
return {
|
320
|
+
filename: screenFile.payload.filename,
|
321
|
+
content: screenFile.payload.content,
|
322
|
+
mode: codegen_1.MODE_CREATE_ONLY,
|
323
|
+
permissions: '0644',
|
324
|
+
type: codegen_1.AIFileTypes.WEB_SCREEN,
|
325
|
+
};
|
326
|
+
});
|
274
327
|
// Gather the context files for implementation. These will be all be passed to the AI
|
275
|
-
const contextFiles = relevantFiles.filter((file) => ![codegen_1.AIFileTypes.SERVICE, codegen_1.AIFileTypes.WEB_SCREEN].includes(file.type));
|
328
|
+
const contextFiles = relevantFiles.filter((file) => ![codegen_1.AIFileTypes.SERVICE, codegen_1.AIFileTypes.WEB_SCREEN, codegen_1.AIFileTypes.WEB_ROUTER].includes(file.type));
|
276
329
|
// Send the service and UI templates to the AI. These will be sent one-by-one in addition to the context files
|
277
330
|
const serviceFiles = allFiles.filter((file) => file.type === codegen_1.AIFileTypes.SERVICE);
|
278
331
|
if (serviceFiles.length > 0) {
|
279
332
|
await this.processTemplates(blockUri, block.aiName, stormClient_1.stormClient.createServiceImplementation.bind(stormClient_1.stormClient), serviceFiles, contextFiles);
|
280
333
|
}
|
281
|
-
const basePath = this.getBasePath(block.content.metadata.name);
|
282
334
|
if (this.isAborted()) {
|
283
335
|
return;
|
284
336
|
}
|
337
|
+
for (const screenFile of screenFilesConverted) {
|
338
|
+
const filePath = (0, path_2.join)(basePath, screenFile.filename);
|
339
|
+
await (0, promises_1.writeFile)(filePath, screenFile.content);
|
340
|
+
}
|
285
341
|
for (const serviceFile of serviceFiles) {
|
286
342
|
const filePath = (0, path_2.join)(basePath, serviceFile.filename);
|
287
343
|
await (0, promises_1.writeFile)(filePath, serviceFile.content);
|
@@ -296,16 +352,6 @@ class StormCodegen {
|
|
296
352
|
const filePath = (0, path_2.join)(basePath, screenFile.payload.filename);
|
297
353
|
await (0, promises_1.writeFile)(filePath, screenFile.payload.content);
|
298
354
|
}
|
299
|
-
const screenFilesConverted = screenFiles.map((screenFile) => {
|
300
|
-
return {
|
301
|
-
filename: screenFile.payload.filename,
|
302
|
-
content: screenFile.payload.content,
|
303
|
-
mode: codegen_1.MODE_CREATE_ONLY,
|
304
|
-
permissions: '0644',
|
305
|
-
type: codegen_1.AIFileTypes.WEB_SCREEN,
|
306
|
-
};
|
307
|
-
});
|
308
|
-
allFiles.push(...screenFilesConverted);
|
309
355
|
const blockRef = block.uri;
|
310
356
|
this.emitBlockStatus(blockUri, block.aiName, events_1.StormEventBlockStatusType.QA);
|
311
357
|
const filesToBeFixed = serviceFiles.concat(contextFiles).concat(screenFilesConverted);
|
@@ -466,7 +512,7 @@ class StormCodegen {
|
|
466
512
|
const files = new Set(filesForContext);
|
467
513
|
files.add(filename);
|
468
514
|
const requestedFiles = Array.from(files).flatMap((file) => {
|
469
|
-
if (
|
515
|
+
if ((0, fs_1.existsSync)(file)) {
|
470
516
|
return file;
|
471
517
|
}
|
472
518
|
// file does not exist - look for similar
|
@@ -551,7 +597,7 @@ class StormCodegen {
|
|
551
597
|
// They will need to be implemented by the AI
|
552
598
|
return;
|
553
599
|
}
|
554
|
-
if (
|
600
|
+
if ([codegen_1.AIFileTypes.WEB_ROUTER, codegen_1.AIFileTypes.WEB_SCREEN].includes(file.type)) {
|
555
601
|
// Don't send the web screen files to the stream yet
|
556
602
|
// They will need to be implemented by the AI
|
557
603
|
return;
|