@kumori/aurora-backend-handler 1.0.49 → 1.0.50

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.
@@ -1,5 +1,5 @@
1
+
1
2
  import { Channel, Service, Tenant, Usage } from "@kumori/aurora-interfaces";
2
- import { Revision } from "@kumori/aurora-interfaces/interfaces/revision-interface";
3
3
  import { getTimestamp } from "../utils/utils";
4
4
 
5
5
  interface Role {
@@ -24,6 +24,21 @@ interface Role {
24
24
  hsize?: number;
25
25
  }
26
26
 
27
+ interface Revision {
28
+ service: string;
29
+ revision: string;
30
+ usage: Usage;
31
+ status: {
32
+ code: string;
33
+ message: string;
34
+ timestamp: string;
35
+ args: string[];
36
+ };
37
+ errorCode?: string;
38
+ errorMsg?: string;
39
+ createdAt?: string;
40
+ }
41
+
27
42
  interface HandleServiceEventParams {
28
43
  entityId: string;
29
44
  eventData: any;
@@ -43,7 +58,6 @@ interface HandleServiceEventResult {
43
58
  pendingProject: { tenant: string; project: string } | null;
44
59
  updatedPendingRevisionErrors: Array<{ service: string; revision: Revision }>;
45
60
  }
46
-
47
61
  interface HandleServiceOperationSuccessParams {
48
62
  action: string;
49
63
  entityName: string;
@@ -83,6 +97,9 @@ interface HandleServiceOperationErrorResult {
83
97
  shouldResetRoles: boolean;
84
98
  }
85
99
 
100
+ /**
101
+ * Parse key path to extract entity names
102
+ */
86
103
  const parseKeyPath = (key: string): { [entity: string]: string } => {
87
104
  if (!key) {
88
105
  return {};
@@ -92,12 +109,17 @@ const parseKeyPath = (key: string): { [entity: string]: string } => {
92
109
  const result: { [entity: string]: string } = {};
93
110
  for (let i = 0; i < parts.length; i += 2) {
94
111
  if (parts[i] && parts[i + 1]) {
95
- result[parts[i]] = parts[i + 1];
112
+ const entityType = parts[i];
113
+ const entityName = parts[i + 1];
114
+ result[entityType] = entityName;
96
115
  }
97
116
  }
98
117
  return result;
99
118
  };
100
119
 
120
+ /**
121
+ * Get default usage object
122
+ */
101
123
  const getDefaultUsage = (): Usage => ({
102
124
  current: {
103
125
  cpu: 0,
@@ -118,6 +140,25 @@ const getDefaultUsage = (): Usage => ({
118
140
  cost: 0,
119
141
  });
120
142
 
143
+ /**
144
+ * Collect revisions for a service from revisionsMap
145
+ */
146
+ const collectServiceRevisions = (
147
+ entityId: string,
148
+ revisionsMap: Map<string, Revision>,
149
+ ): string[] => {
150
+ const serviceRevisions: string[] = [];
151
+ revisionsMap.forEach((revision, key) => {
152
+ if (revision.service === entityId) {
153
+ serviceRevisions.push(revision.revision);
154
+ }
155
+ });
156
+ return serviceRevisions;
157
+ };
158
+
159
+ /**
160
+ * Determine final status and error based on timestamps
161
+ */
121
162
  const determineFinalStatusAndError = (
122
163
  existingService: Service | undefined,
123
164
  eventData: any,
@@ -138,13 +179,13 @@ const determineFinalStatusAndError = (
138
179
 
139
180
  if (isNewer) {
140
181
  finalStatus = incomingStatus;
182
+
141
183
  if (eventData.status.error) {
142
184
  finalError = eventData.status.error;
143
185
  } else {
144
186
  finalError = undefined;
145
187
  }
146
188
  }
147
-
148
189
  const pendingErrorIndex = pendingRevisionErrors.findIndex(
149
190
  (pending) => pending.service === entityId,
150
191
  );
@@ -166,7 +207,10 @@ const determineFinalStatusAndError = (
166
207
 
167
208
  return { finalStatus, finalError, pendingErrorIndex };
168
209
  };
169
-
210
+ /**
211
+ * Handles the "service" event from WebSocket messages
212
+ * Processes service data updates and manages project labels
213
+ */
170
214
  export const handleServiceEvent = ({
171
215
  entityId,
172
216
  eventData,
@@ -186,14 +230,7 @@ export const handleServiceEvent = ({
186
230
  const projectLabel = eventData.meta?.labels?.project;
187
231
  const serviceRoles = roleMap.get(serviceFullKey) || [];
188
232
  const serviceUsage = currentRevision?.usage || getDefaultUsage();
189
-
190
- const serviceRevisions: Revision[] = [];
191
- revisionsMap.forEach((revision, key) => {
192
- if (key.startsWith(`${serviceFullKey}-`)) {
193
- serviceRevisions.push(revision);
194
- }
195
- });
196
-
233
+ const serviceRevisions = collectServiceRevisions(entityId, revisionsMap);
197
234
  const environmentPath = eventData.spec.environment;
198
235
  const pathParts = parseKeyPath(environmentPath);
199
236
  const existingService = servicesMap.get(serviceFullKey);
@@ -204,37 +241,30 @@ export const handleServiceEvent = ({
204
241
  pendingRevisionErrors,
205
242
  entityId,
206
243
  );
207
-
208
244
  const updatedPendingRevisionErrors = [...pendingRevisionErrors];
209
245
  if (pendingErrorIndex !== -1) {
210
246
  updatedPendingRevisionErrors.splice(pendingErrorIndex, 1);
211
247
  }
212
-
213
- const currentRevisionId =
214
- eventData.status.revision ||
215
- (serviceRevisions.length > 0
216
- ? Math.max(...serviceRevisions.map((r) => Number(r.id))).toString()
217
- : "");
218
-
219
248
  const baseServiceData = {
220
249
  tenant: serviceTenantId,
221
250
  account: eventData.spec.metadata.targetAccount || pathParts.account,
222
251
  environment:
223
252
  eventData.spec.metadata.targetEnvironment || pathParts.environment,
224
253
  name: entityId,
225
- revisions: [...serviceRevisions].sort(
226
- (a, b) => Number(b.id) - Number(a.id),
227
- ),
254
+ revisions: [...serviceRevisions].sort((a, b) => Number(b) - Number(a)),
228
255
  status: finalStatus || eventData.status.state,
229
256
  error: finalError,
230
257
  role: serviceRoles.length > 0 ? serviceRoles : existingService?.role || [],
231
258
  usage: serviceUsage,
232
259
  lastDeployed: eventData.spec.ctstamp,
233
260
  project: projectLabel || existingService?.project || "",
234
- currentRevision: currentRevisionId,
261
+ currentRevision:
262
+ eventData.status.revision ||
263
+ (serviceRevisions.length > 0
264
+ ? Math.max(...serviceRevisions.map(Number)).toString()
265
+ : ""),
235
266
  startedAt: currentRevision?.createdAt || existingService?.startedAt || "",
236
267
  };
237
-
238
268
  let newService: Service;
239
269
 
240
270
  if (existingService) {
@@ -263,7 +293,6 @@ export const handleServiceEvent = ({
263
293
  ...baseServiceData,
264
294
  };
265
295
  }
266
-
267
296
  const oldStatusCode = existingService?.status?.code;
268
297
  const newStatusCode = newService.status.code;
269
298
 
@@ -272,7 +301,6 @@ export const handleServiceEvent = ({
272
301
  oldStatusCode !== "SERVICE_READY" &&
273
302
  newStatusCode === "SERVICE_READY" &&
274
303
  eventData.status.deployed === true;
275
-
276
304
  let pendingProject: { tenant: string; project: string } | null = null;
277
305
 
278
306
  if (projectLabel) {
@@ -301,6 +329,9 @@ export const handleServiceEvent = ({
301
329
  };
302
330
  };
303
331
 
332
+ /**
333
+ * Handles successful service operations
334
+ */
304
335
  export const handleServiceOperationSuccess = ({
305
336
  action,
306
337
  entityName,
@@ -341,8 +372,12 @@ export const handleServiceOperationSuccess = ({
341
372
  }
342
373
 
343
374
  if (!revisionData?.solution) {
375
+ const resetService = {
376
+ ...service,
377
+ role: [],
378
+ };
344
379
  return {
345
- updatedService: { ...service, role: [] },
380
+ updatedService: resetService,
346
381
  shouldDelete: false,
347
382
  eventType: null,
348
383
  processRevisionData: false,
@@ -350,7 +385,6 @@ export const handleServiceOperationSuccess = ({
350
385
  serviceId,
351
386
  };
352
387
  }
353
-
354
388
  return {
355
389
  updatedService: service,
356
390
  shouldDelete: false,
@@ -365,16 +399,17 @@ export const handleServiceOperationSuccess = ({
365
399
  const existingService = servicesMap.get(serviceId);
366
400
 
367
401
  if (existingService) {
368
- return {
369
- updatedService: {
370
- ...existingService,
371
- status: {
372
- code: "REMOVING_SERVICE",
373
- message: `Service ${entityName} is being removed`,
374
- args: [],
375
- timestamp: new Date().toISOString(),
376
- },
402
+ const updatedService = {
403
+ ...existingService,
404
+ status: {
405
+ code: "REMOVING_SERVICE",
406
+ message: `Service ${entityName} is being removed`,
407
+ args: [],
408
+ timestamp: new Date().toISOString(),
377
409
  },
410
+ };
411
+ return {
412
+ updatedService,
378
413
  shouldDelete: false,
379
414
  eventType: "deleting",
380
415
  processRevisionData: false,
@@ -392,25 +427,28 @@ export const handleServiceOperationSuccess = ({
392
427
  serviceId,
393
428
  };
394
429
  }
395
-
396
430
  if (originalData) {
397
- return {
398
- updatedService: {
399
- ...originalData,
400
- status: {
401
- code: "SERVICE_READY",
402
- message: `Service (${entityName}) is ready.`,
403
- args: [],
404
- timestamp: new Date().toISOString(),
405
- },
431
+ const updatedService = {
432
+ ...originalData,
433
+ status: {
434
+ code: "SERVICE_READY",
435
+ message: `Service (${entityName}) is ready.`,
436
+ args: [],
437
+ timestamp: new Date().toISOString(),
406
438
  },
439
+ };
440
+
441
+ let eventType: "deployed" | "updated" | null = null;
442
+ if (action === "CREATE") {
443
+ eventType = "deployed";
444
+ } else if (action === "UPDATE") {
445
+ eventType = "updated";
446
+ }
447
+
448
+ return {
449
+ updatedService,
407
450
  shouldDelete: false,
408
- eventType:
409
- action === "CREATE"
410
- ? "deployed"
411
- : action === "UPDATE"
412
- ? "updated"
413
- : null,
451
+ eventType,
414
452
  processRevisionData: false,
415
453
  revisionData: null,
416
454
  serviceId,
@@ -427,6 +465,9 @@ export const handleServiceOperationSuccess = ({
427
465
  };
428
466
  };
429
467
 
468
+ /**
469
+ * Handles failed service operations
470
+ */
430
471
  export const handleServiceOperationError = ({
431
472
  action,
432
473
  entityName,
@@ -440,27 +481,46 @@ export const handleServiceOperationError = ({
440
481
  : entityName;
441
482
 
442
483
  if (action === "CREATE") {
443
- return { eventType: "deploymentError", serviceId, shouldResetRoles: false };
484
+ return {
485
+ eventType: "deploymentError",
486
+ serviceId,
487
+ shouldResetRoles: false,
488
+ };
444
489
  }
445
490
 
446
491
  if (action === "UPDATE") {
447
- return { eventType: "updateError", serviceId, shouldResetRoles: false };
492
+ return {
493
+ eventType: "updateError",
494
+ serviceId,
495
+ shouldResetRoles: false,
496
+ };
448
497
  }
449
498
 
450
499
  if (action === "DELETE") {
451
- return { eventType: "deletionError", serviceId, shouldResetRoles: false };
500
+ return {
501
+ eventType: "deletionError",
502
+ serviceId,
503
+ shouldResetRoles: false,
504
+ };
452
505
  }
453
506
 
454
507
  if (action === "GET_REVISION") {
455
508
  const service = servicesMap.get(serviceId);
456
509
  if (service) {
457
- return { eventType: "revisionError", serviceId, shouldResetRoles: true };
510
+ return {
511
+ eventType: "revisionError",
512
+ serviceId,
513
+ shouldResetRoles: true,
514
+ };
458
515
  }
459
516
  }
460
517
 
461
- return { eventType: null, serviceId, shouldResetRoles: false };
518
+ return {
519
+ eventType: null,
520
+ serviceId,
521
+ shouldResetRoles: false,
522
+ };
462
523
  };
463
-
464
524
  export const mapChannelsFromApiData = (
465
525
  apiData: any,
466
526
  entityId: string,
@@ -476,28 +536,45 @@ export const mapChannelsFromApiData = (
476
536
 
477
537
  const publicChannelNames = new Set<string>();
478
538
 
479
- const collectPublic = (section: any) => {
480
- if (!section) return;
481
- Object.keys(section).forEach((channelName) => {
539
+ if (apiData.server) {
540
+ Object.keys(apiData.server).forEach((channelName) => {
482
541
  if (channelName.endsWith(inboundSuffix)) {
483
542
  const baseName = channelName.slice(0, -inboundSuffix.length);
484
- if (section[baseName]) {
543
+ if (apiData.server[baseName]) {
485
544
  publicChannelNames.add(baseName);
486
545
  }
487
546
  }
488
547
  });
489
- };
548
+ }
490
549
 
491
- collectPublic(apiData.server);
492
- collectPublic(apiData.client);
493
- collectPublic(apiData.duplex);
550
+ if (apiData.client) {
551
+ Object.keys(apiData.client).forEach((channelName) => {
552
+ if (channelName.endsWith(inboundSuffix)) {
553
+ const baseName = channelName.slice(0, -inboundSuffix.length);
554
+ if (apiData.client[baseName]) {
555
+ publicChannelNames.add(baseName);
556
+ }
557
+ }
558
+ });
559
+ }
494
560
 
495
- const mapChannels = (section: any, target: Channel[]) => {
496
- if (!section) return;
497
- Object.entries(section).forEach(
561
+ if (apiData.duplex) {
562
+ Object.keys(apiData.duplex).forEach((channelName) => {
563
+ if (channelName.endsWith(inboundSuffix)) {
564
+ const baseName = channelName.slice(0, -inboundSuffix.length);
565
+ if (apiData.duplex[baseName]) {
566
+ publicChannelNames.add(baseName);
567
+ }
568
+ }
569
+ });
570
+ }
571
+ if (apiData.server) {
572
+ Object.entries(apiData.server).forEach(
498
573
  ([channelName, channelData]: [string, any]) => {
499
- if (channelName.endsWith(inboundSuffix)) return;
500
- target.push({
574
+ if (channelName.endsWith(inboundSuffix)) {
575
+ return;
576
+ }
577
+ serverChannels.push({
501
578
  name: channelName,
502
579
  from: entityId,
503
580
  to: "",
@@ -508,11 +585,43 @@ export const mapChannelsFromApiData = (
508
585
  });
509
586
  },
510
587
  );
511
- };
512
-
513
- mapChannels(apiData.server, serverChannels);
514
- mapChannels(apiData.client, clientChannels);
515
- mapChannels(apiData.duplex, duplexChannels);
588
+ }
589
+ if (apiData.client) {
590
+ Object.entries(apiData.client).forEach(
591
+ ([channelName, channelData]: [string, any]) => {
592
+ if (channelName.endsWith(inboundSuffix)) {
593
+ return;
594
+ }
595
+ clientChannels.push({
596
+ name: channelName,
597
+ from: entityId,
598
+ to: "",
599
+ protocol: channelData.protocol as "http" | "tcp" | "https",
600
+ port: channelData.port,
601
+ portNum: channelData.port,
602
+ isPublic: publicChannelNames.has(channelName),
603
+ });
604
+ },
605
+ );
606
+ }
607
+ if (apiData.duplex) {
608
+ Object.entries(apiData.duplex).forEach(
609
+ ([channelName, channelData]: [string, any]) => {
610
+ if (channelName.endsWith(inboundSuffix)) {
611
+ return;
612
+ }
613
+ duplexChannels.push({
614
+ name: channelName,
615
+ from: entityId,
616
+ to: "",
617
+ protocol: channelData.protocol as "http" | "tcp" | "https",
618
+ port: channelData.port,
619
+ portNum: channelData.port,
620
+ isPublic: publicChannelNames.has(channelName),
621
+ });
622
+ },
623
+ );
624
+ }
516
625
 
517
626
  return { serverChannels, clientChannels, duplexChannels };
518
- };
627
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kumori/aurora-backend-handler",
3
- "version": "1.0.49",
3
+ "version": "1.0.50",
4
4
  "description": "backend handler",
5
5
  "main": "backend-handler.ts",
6
6
  "scripts": {
@@ -11,7 +11,7 @@
11
11
  "glob": "^11.0.0"
12
12
  },
13
13
  "dependencies": {
14
- "@kumori/aurora-interfaces": "^1.0.7",
14
+ "@kumori/aurora-interfaces": "^1.0.4",
15
15
  "@kumori/kumori-dsl-generator": "^1.0.3",
16
16
  "@kumori/kumori-module-generator": "^1.1.6",
17
17
  "ts-node": "^10.9.2",
@@ -74,7 +74,6 @@ import {
74
74
  } from "./helpers/token-helper";
75
75
  import { handleLinkEvent } from "./helpers/link-helper";
76
76
  import { eventHelper } from "./backend-handler";
77
- import { Revision } from "@kumori/aurora-interfaces/interfaces/revision-interface";
78
77
 
79
78
  let WebSocketClass: any;
80
79
 
@@ -89,9 +88,19 @@ interface WSMessage {
89
88
  content?: string;
90
89
  };
91
90
  }
92
- interface RevisionWs {
91
+ interface Revision {
93
92
  service: string;
94
- revision: Revision;
93
+ revision: string;
94
+ usage: Usage;
95
+ status: {
96
+ code: string;
97
+ message: string;
98
+ timestamp: string;
99
+ args: string[];
100
+ };
101
+ errorCode?: string;
102
+ errorMsg?: string;
103
+ createdAt?: string;
95
104
  }
96
105
  interface PendingOperation {
97
106
  resolve: Function;
@@ -1218,8 +1227,6 @@ const handleOperationSuccess = (operation: PendingOperation, response: any) => {
1218
1227
  const updatedService = processRevisionData(
1219
1228
  svcSuccessResult.updatedService!,
1220
1229
  svcSuccessResult.revisionData,
1221
- revisionsMap,
1222
- svcSuccessResult.serviceId,
1223
1230
  );
1224
1231
 
1225
1232
  if (svcSuccessResult.revisionData.revision_error) {