@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.
@@ -222,7 +222,6 @@ export const createAccount = async (account: Account, security: Security) => {
222
222
  username: account.cloudProvider.username || "",
223
223
  password: account.cloudProvider.password || "",
224
224
  region: account.cloudProvider?.region || "",
225
- project_id: account.cloudProvider?.project_id || "",
226
225
  }
227
226
  : {
228
227
  method: providerName,
@@ -334,7 +333,6 @@ export const createAccount = async (account: Account, security: Security) => {
334
333
  password: account.cloudProvider.password || "",
335
334
  region: account.cloudProvider?.region || "",
336
335
  domain: account.cloudProvider?.domain || "",
337
- project_id: account.cloudProvider?.project_id || "",
338
336
  }
339
337
  : {
340
338
  method: providerName,
@@ -613,7 +611,6 @@ export const deleteAccount = async (account: Account, security: Security) => {
613
611
  credentials: {
614
612
  username: account.cloudProvider.username,
615
613
  password: account.cloudProvider.password,
616
- project_id: account.cloudProvider.project_id || "",
617
614
  },
618
615
  },
619
616
  };
@@ -628,7 +625,6 @@ export const deleteAccount = async (account: Account, security: Security) => {
628
625
  username: account.cloudProvider.username,
629
626
  password: account.cloudProvider.password,
630
627
  domain: account.cloudProvider.domain,
631
- project_id: account.cloudProvider.project_id || "",
632
628
  },
633
629
  },
634
630
  };
@@ -994,7 +990,6 @@ export const updateAccount = async (account: Account, security: Security) => {
994
990
  username: account.cloudProvider.username || "",
995
991
  password: account.cloudProvider.password || "",
996
992
  region: account.cloudProvider?.region || "",
997
- project_id: account.cloudProvider?.project_id || "",
998
993
  }
999
994
  : {
1000
995
  method: providerName,
@@ -1104,7 +1099,6 @@ export const updateAccount = async (account: Account, security: Security) => {
1104
1099
  password: account.cloudProvider.password || "",
1105
1100
  region: account.cloudProvider?.region || "",
1106
1101
  domain: account.cloudProvider?.domain || "",
1107
- project_id: account.cloudProvider?.project_id || "",
1108
1102
  }
1109
1103
  : {
1110
1104
  method: providerName,
@@ -7,7 +7,6 @@ import {
7
7
  makeGlobalWebSocketRequest,
8
8
  } from "../websocket-manager";
9
9
  import { Link, Notification, Service } from "@kumori/aurora-interfaces";
10
- import { Revision } from "@kumori/aurora-interfaces/interfaces/revision-interface";
11
10
  let pendingLinks = new Map<string, Link[]>();
12
11
  /**
13
12
  * Function to deploy a service
@@ -16,13 +15,13 @@ let pendingLinks = new Map<string, Link[]>();
16
15
  export const deployService = async (data: Service, token: string) => {
17
16
  try {
18
17
  const url = new URL(
19
- `${environment.apiServer.baseUrl}/api/${environment.apiServer.apiVersion}/tenant/${data.tenant}/service/${data.name}`
18
+ `${environment.apiServer.baseUrl}/api/${environment.apiServer.apiVersion}/tenant/${data.tenant}/service/${data.name}`,
20
19
  );
21
20
  url.searchParams.append("dryrun", "false");
22
21
  url.searchParams.append("accept", "true");
23
22
  url.searchParams.append("wait", "30000");
24
23
  url.searchParams.append("validate", "true");
25
- if(data.dsl){
24
+ if (data.dsl) {
26
25
  url.searchParams.append("dsl", "true");
27
26
  }
28
27
  if (data.serviceData) {
@@ -33,7 +32,7 @@ export const deployService = async (data: Service, token: string) => {
33
32
  JSON.stringify({
34
33
  targetAccount: data.account,
35
34
  targetEnvironment: data.environment,
36
- })
35
+ }),
37
36
  );
38
37
  formData.append("labels", JSON.stringify({ project: data.project }));
39
38
  formData.append("comment", " ");
@@ -48,7 +47,7 @@ export const deployService = async (data: Service, token: string) => {
48
47
  const jsonResponse = await response.json();
49
48
 
50
49
  const isTimeout = jsonResponse?.events?.some(
51
- (event: any) => event.content === "_timeout_"
50
+ (event: any) => event.content === "_timeout_",
52
51
  );
53
52
 
54
53
  if (isTimeout) {
@@ -81,7 +80,7 @@ export const deployService = async (data: Service, token: string) => {
81
80
  const jsonResponse = await response.json();
82
81
 
83
82
  const isTimeout = jsonResponse?.events?.some(
84
- (event: any) => event.content === "_timeout_"
83
+ (event: any) => event.content === "_timeout_",
85
84
  );
86
85
 
87
86
  if (isTimeout) {
@@ -111,7 +110,7 @@ export const redeployService = async (data: Service) => {
111
110
  try {
112
111
  const formData = await deployServiceHelper(data);
113
112
  const url = new URL(
114
- `${environment.apiServer.baseUrl}/api/${environment.apiServer.apiVersion}/tenant/${data.tenant}/service/${data.name}/revision/${data.currentRevision}`
113
+ `${environment.apiServer.baseUrl}/api/${environment.apiServer.apiVersion}/tenant/${data.tenant}/service/${data.name}/revision/${data.currentRevision}`,
115
114
  );
116
115
  url.searchParams.append("dryrun", "false");
117
116
  url.searchParams.append("accept", "true");
@@ -130,7 +129,7 @@ export const redeployService = async (data: Service) => {
130
129
  const jsonResponse = await response.json();
131
130
 
132
131
  const isTimeout = jsonResponse?.events?.some(
133
- (event: any) => event.content === "_timeout_"
132
+ (event: any) => event.content === "_timeout_",
134
133
  );
135
134
 
136
135
  if (isTimeout) {
@@ -163,7 +162,7 @@ export const deleteService = async (data: Service, security: string) => {
163
162
  deleteBody,
164
163
  30000,
165
164
  "DELETE",
166
- data.name
165
+ data.name,
167
166
  );
168
167
  return response;
169
168
  } catch (err) {
@@ -188,7 +187,7 @@ export const restartService = async (data: Service, security: string) => {
188
187
  restartBody,
189
188
  30000,
190
189
  "RESTART",
191
- data.name
190
+ data.name,
192
191
  );
193
192
 
194
193
  const updatedService: Service = {
@@ -209,31 +208,63 @@ export const restartService = async (data: Service, security: string) => {
209
208
  }
210
209
  };
211
210
  const generateLinkBody = (data: Service, link: Link) => {
211
+ console.log("[Backend Handler] generateLinkBody - Link:", link);
212
+ console.log("[Backend Handler] generateLinkBody - Service:", data);
213
+
212
214
  const originInClient = data.clientChannels.find(
213
215
  (channel) =>
214
- channel.name === link.originChannel || channel.from === link.originChannel
216
+ channel.name === link.originChannel ||
217
+ channel.from === link.originChannel,
215
218
  );
216
219
  const originInServer = data.serverChannels.find(
217
220
  (channel) =>
218
- channel.name === link.originChannel || channel.from === link.originChannel
221
+ channel.name === link.originChannel ||
222
+ channel.from === link.originChannel,
219
223
  );
220
224
  const originInDuplex = data.duplexChannels.find(
221
225
  (channel) =>
222
- channel.name === link.originChannel || channel.from === link.originChannel
226
+ channel.name === link.originChannel ||
227
+ channel.from === link.originChannel,
223
228
  );
224
229
  const targetInClient = data.clientChannels.find(
225
230
  (channel) =>
226
- channel.name === link.targetChannel || channel.from === link.targetChannel
231
+ channel.name === link.targetChannel ||
232
+ channel.from === link.targetChannel,
227
233
  );
228
234
  const targetInServer = data.serverChannels.find(
229
235
  (channel) =>
230
- channel.name === link.targetChannel || channel.from === link.targetChannel
236
+ channel.name === link.targetChannel ||
237
+ channel.from === link.targetChannel,
231
238
  );
232
239
  const targetInDuplex = data.duplexChannels.find(
233
240
  (channel) =>
234
- channel.name === link.targetChannel || channel.from === link.targetChannel
241
+ channel.name === link.targetChannel ||
242
+ channel.from === link.targetChannel,
243
+ );
244
+ console.log(
245
+ "[Backend Handler] generateLinkBody - Origin in client:",
246
+ originInClient,
247
+ );
248
+ console.log(
249
+ "[Backend Handler] generateLinkBody - Origin in server:",
250
+ originInServer,
251
+ );
252
+ console.log(
253
+ "[Backend Handler] generateLinkBody - Origin in duplex:",
254
+ originInDuplex,
255
+ );
256
+ console.log(
257
+ "[Backend Handler] generateLinkBody - Target in client:",
258
+ targetInClient,
259
+ );
260
+ console.log(
261
+ "[Backend Handler] generateLinkBody - Target in server:",
262
+ targetInServer,
263
+ );
264
+ console.log(
265
+ "[Backend Handler] generateLinkBody - Target in duplex:",
266
+ targetInDuplex,
235
267
  );
236
-
237
268
  let linkBody;
238
269
  if (originInClient) {
239
270
  linkBody = {
@@ -291,7 +322,7 @@ const generateLinkBody = (data: Service, link: Link) => {
291
322
  };
292
323
  } else {
293
324
  console.warn(
294
- `No se encontraron canales para el enlace: origin=${link.origin}, target=${link.target}`
325
+ `No se encontraron canales para el enlace: origin=${link.origin}, target=${link.target}`,
295
326
  );
296
327
  linkBody = {
297
328
  client_tenant: data.tenant,
@@ -302,6 +333,8 @@ const generateLinkBody = (data: Service, link: Link) => {
302
333
  server_channel: link.targetChannel,
303
334
  };
304
335
  }
336
+
337
+ console.log("[Backend Handler] generateLinkBody - Link body:", linkBody);
305
338
  return linkBody;
306
339
  };
307
340
  export const linkPendingServices = async (service: Service, token: string) => {
@@ -319,7 +352,7 @@ export const linkPendingServices = async (service: Service, token: string) => {
319
352
  linkBody,
320
353
  30000,
321
354
  "LINK",
322
- service.name
355
+ service.name,
323
356
  );
324
357
 
325
358
  const notification: Notification = {
@@ -353,7 +386,7 @@ export const linkPendingServices = async (service: Service, token: string) => {
353
386
  };
354
387
  eventHelper.notification.publish.creation(notification);
355
388
  }
356
- })
389
+ }),
357
390
  );
358
391
  }
359
392
  };
@@ -375,7 +408,7 @@ export const requestRevisionData = async (service: Service, token: string) => {
375
408
  "GET_REVISION",
376
409
  service.name,
377
410
  "service",
378
- service
411
+ service,
379
412
  );
380
413
  return response;
381
414
  } catch (err) {
@@ -402,203 +435,163 @@ export const updateService = async (
402
435
  // pendingLinks.set(data.name, newLinksToCreate);
403
436
  // await linkPendingServices(serviceWithNewLinks, token);
404
437
  // }
405
- const url = new URL(
406
- `${environment.apiServer.baseUrl}/api/${environment.apiServer.apiVersion}/tenant/${data.tenant}/service/${data.name}/revision/${data.currentRevision}`,
407
- );
408
- if (data.dsl) {
409
- url.searchParams.append("dsl", "true");
410
- }
411
- if (data.serviceData) {
412
- const formData = new FormData();
413
- formData.append("type", "update-bundle");
414
- formData.append("bundle", data.serviceData);
415
- formData.append(
416
- "meta",
417
- JSON.stringify({
418
- targetAccount: data.account,
419
- targetEnvironment: data.environment,
420
- }),
421
- );
422
- formData.append("labels", JSON.stringify({ project: data.project }));
423
- formData.append("comment", " ");
424
- const response = await fetch(url.toString(), {
425
- method: "POST",
426
- body: formData,
438
+
439
+ const parameterObject: Record<string, any> = {};
440
+ if (data.parameters && data.parameters.length > 0) {
441
+ data.parameters.forEach((param) => {
442
+ const key = param.configKey || param.name;
443
+ const paramType = param.type?.toLowerCase();
444
+ if (paramType === "number" || paramType === "integer") {
445
+ parameterObject[key] = Number(param.value) || 0;
446
+ } else if (paramType === "boolean") {
447
+ parameterObject[key] = param.value === "true";
448
+ } else {
449
+ parameterObject[key] = param.value;
450
+ }
427
451
  });
428
- if (!response.ok) {
429
- throw new Error(`HTTP error! status: ${response.status}`);
430
- }
452
+ }
431
453
 
432
- const jsonResponse = await response.json();
433
- const isTimeout = jsonResponse?.events?.some(
434
- (event: any) => event.content === "_timeout_",
435
- );
454
+ const resourceObject: Record<string, any> = {};
455
+ if (data.resources && data.resources.length > 0) {
456
+ data.resources.forEach((resource) => {
457
+ if (resource.type === "volume") {
458
+ resourceObject[resource.name] = {
459
+ volume: {
460
+ kind: "storage",
461
+ size: parseInt(resource.value) || 1,
462
+ unit: "G",
463
+ type: resource.kind,
464
+ },
465
+ };
466
+ } else if (resource.type === "secret") {
467
+ resourceObject[resource.name] = {
468
+ secret: `${data.tenant}/${resource.value}`,
469
+ };
470
+ } else if (resource.type === "domain") {
471
+ resourceObject[resource.name] = {
472
+ domain: `${data.tenant}/${resource.value}`,
473
+ };
474
+ } else if (resource.type === "ca") {
475
+ resourceObject[resource.name] = {
476
+ ca: `${data.tenant}/${resource.value}`,
477
+ };
478
+ } else if (resource.type === "certificate") {
479
+ resourceObject[resource.name] = {
480
+ certificate: `${data.tenant}/${resource.value}`,
481
+ };
482
+ } else if (resource.type === "port") {
483
+ resourceObject[resource.name] = {
484
+ port: `${data.tenant}/${resource.value}`,
485
+ };
486
+ }
487
+ });
488
+ }
436
489
 
437
- if (isTimeout) {
438
- console.error("Timeout en la petición:", {
439
- isOk: false,
440
- code: "TIMEOUT",
441
- error: "_timeout_",
442
- });
490
+ let previousRevision = 1;
491
+ if (data.currentRevision) {
492
+ previousRevision = parseInt(data.currentRevision.toString(), 10);
493
+ if (isNaN(previousRevision)) {
494
+ console.warn("currentRevision is not a valid number, using 1");
495
+ previousRevision = 1;
443
496
  }
444
497
  } else {
445
- const parameterObject: Record<string, any> = {};
446
- if (data.parameters && data.parameters.length > 0) {
447
- data.parameters.forEach((param) => {
448
- const key = param.configKey || param.name;
449
- const paramType = param.type?.toLowerCase();
450
- if (paramType === "number" || paramType === "integer") {
451
- parameterObject[key] = Number(param.value) || 0;
452
- } else if (paramType === "boolean") {
453
- parameterObject[key] = param.value === "true";
454
- } else {
455
- parameterObject[key] = param.value;
456
- }
457
- });
458
- }
459
-
460
- const resourceObject: Record<string, any> = {};
461
- if (data.resources && data.resources.length > 0) {
462
- data.resources.forEach((resource) => {
463
- if (resource.type === "volume") {
464
- resourceObject[resource.name] = {
465
- volume: {
466
- kind: "storage",
467
- size: parseInt(resource.value) || 1,
468
- unit: "G",
469
- type: resource.kind,
470
- },
471
- };
472
- } else if (resource.type === "secret") {
473
- resourceObject[resource.name] = {
474
- secret: `${data.tenant}/${resource.value}`,
475
- };
476
- } else if (resource.type === "domain") {
477
- resourceObject[resource.name] = {
478
- domain: `${data.tenant}/${resource.value}`,
479
- };
480
- } else if (resource.type === "ca") {
481
- resourceObject[resource.name] = {
482
- ca: `${data.tenant}/${resource.value}`,
483
- };
484
- } else if (resource.type === "certificate") {
485
- resourceObject[resource.name] = {
486
- certificate: `${data.tenant}/${resource.value}`,
487
- };
488
- } else if (resource.type === "port") {
489
- resourceObject[resource.name] = {
490
- port: `${data.tenant}/${resource.value}`,
491
- };
492
- }
493
- });
494
- }
498
+ previousRevision = getLatestRevision(data.revisions) || 1;
499
+ }
495
500
 
496
- let previousRevision = 1;
497
- if (data.currentRevision) {
498
- previousRevision = parseInt(data.currentRevision.toString(), 10);
499
- if (isNaN(previousRevision)) {
500
- console.warn("currentRevision is not a valid number, using 1");
501
- previousRevision = 1;
502
- }
503
- } else {
504
- previousRevision = getLatestRevision(data.revisions) || 1;
505
- }
501
+ const scaleConfig: any = {};
502
+ if (data.role && data.role.length > 0) {
503
+ scaleConfig.detail = {};
504
+ data.role.forEach((role) => {
505
+ scaleConfig.detail[role.name] = {
506
+ hsize: role.hsize || scale || data.minReplicas || 1,
507
+ };
508
+ });
509
+ } else {
510
+ scaleConfig.hsize = scale || data.minReplicas || 1;
511
+ }
512
+ const meta = {
513
+ scaling: {
514
+ simple:
515
+ data.role?.reduce(
516
+ (acc, role) => {
517
+ if (role.scalling && role.name) {
518
+ acc[role.name] = {
519
+ scale_up: {
520
+ cpu: Math.min(parseInt(role.scalling.cpu.up) || 0, 100),
521
+ memory: Math.min(
522
+ parseInt(role.scalling.memory.up) || 0,
523
+ 100,
524
+ ),
525
+ },
526
+ scale_down: {
527
+ cpu: Math.min(parseInt(role.scalling.cpu.down) || 0, 100),
528
+ memory: Math.min(
529
+ parseInt(role.scalling.memory.down) || 0,
530
+ 100,
531
+ ),
532
+ },
533
+ hysteresis: parseInt(role.scalling.histeresys) || 0,
534
+ min_replicas: role.scalling.instances.min || 0,
535
+ max_replicas: role.scalling.instances.max || 0,
536
+ };
537
+ }
538
+ return acc;
539
+ },
540
+ {} as Record<string, any>,
541
+ ) || {},
542
+ },
543
+ };
506
544
 
507
- const scaleConfig: any = {};
508
- if (data.role && data.role.length > 0) {
509
- scaleConfig.detail = {};
510
- data.role.forEach((role) => {
511
- scaleConfig.detail[role.name] = {
512
- hsize: role.hsize || scale || data.minReplicas || 1,
513
- };
514
- });
515
- } else {
516
- scaleConfig.hsize = scale || data.minReplicas || 1;
517
- }
518
- const meta = {
519
- scaling: {
520
- simple:
521
- data.role?.reduce(
522
- (acc, role) => {
523
- if (role.scalling && role.name) {
524
- acc[role.name] = {
525
- scale_up: {
526
- cpu: Math.min(parseInt(role.scalling.cpu.up) || 0, 100),
527
- memory: Math.min(
528
- parseInt(role.scalling.memory.up) || 0,
529
- 100,
530
- ),
531
- },
532
- scale_down: {
533
- cpu: Math.min(parseInt(role.scalling.cpu.down) || 0, 100),
534
- memory: Math.min(
535
- parseInt(role.scalling.memory.down) || 0,
536
- 100,
537
- ),
538
- },
539
- hysteresis: parseInt(role.scalling.histeresys) || 0,
540
- min_replicas: role.scalling.instances.min || 0,
541
- max_replicas: role.scalling.instances.max || 0,
542
- };
543
- }
544
- return acc;
545
- },
546
- {} as Record<string, any>,
547
- ) || {},
545
+ const updateBody = {
546
+ spec: {
547
+ type: "update-config",
548
+ comment: "Service configuration update",
549
+ config: {
550
+ parameter: parameterObject,
551
+ resource: resourceObject,
552
+ resilience: 0,
553
+ scale: scaleConfig,
548
554
  },
549
- };
555
+ meta: meta,
556
+ },
557
+ tenant: data.tenant,
558
+ service: data.name,
559
+ previous: previousRevision,
560
+ };
550
561
 
551
- const updateBody = {
552
- spec: {
553
- type: "update-config",
554
- comment: "Service configuration update",
555
- config: {
556
- parameter: parameterObject,
557
- resource: resourceObject,
558
- resilience: 0,
559
- scale: scaleConfig,
560
- },
561
- meta: meta,
562
- },
563
- tenant: data.tenant,
564
- service: data.name,
565
- previous: previousRevision,
566
- };
562
+ const response = await makeGlobalWebSocketRequest(
563
+ "revision:update_revision",
564
+ updateBody,
565
+ 30000,
566
+ "UPDATE_CONFIG",
567
+ data.name,
568
+ );
567
569
 
568
- const response = await makeGlobalWebSocketRequest(
569
- "revision:update_revision",
570
- updateBody,
571
- 30000,
572
- "UPDATE_CONFIG",
573
- data.name,
574
- );
575
- const updatedService: Service = {
576
- ...data,
577
- status: {
578
- code: "PENDING",
579
- message: "",
580
- timestamp: "",
581
- args: [],
582
- },
583
- };
584
- eventHelper.service.publish.updated(updatedService);
585
-
586
- const updateNotification: Notification = {
587
- type: "success",
588
- subtype: "service-updated",
589
- date: Date.now().toString(),
590
- status: "unread",
591
- callToAction: false,
592
- data: {
593
- service: data.name,
594
- tenant: data.tenant,
595
- },
596
- };
597
-
598
- eventHelper.notification.publish.creation(updateNotification);
599
- return response;
600
- }
570
+ const updatedService: Service = {
571
+ ...data,
572
+ status: {
573
+ code: "PENDING",
574
+ message: "",
575
+ timestamp: "",
576
+ args: [],
577
+ },
578
+ };
579
+ eventHelper.service.publish.updated(updatedService);
580
+
581
+ const updateNotification: Notification = {
582
+ type: "success",
583
+ subtype: "service-updated",
584
+ date: Date.now().toString(),
585
+ status: "unread",
586
+ callToAction: false,
587
+ data: {
588
+ service: data.name,
589
+ tenant: data.tenant,
590
+ },
591
+ };
601
592
 
593
+ eventHelper.notification.publish.creation(updateNotification);
594
+ return response;
602
595
  } catch (err) {
603
596
  console.error("Error updating service configuration via WebSocket:", err);
604
597
  const notification: Notification = {
@@ -623,7 +616,7 @@ export const updateService = async (
623
616
  };
624
617
  export const unlinkServices = async (service: Service, token: string) => {
625
618
  const deleteLinks: Link[] = service.links.filter(
626
- (link) => link.delete === true
619
+ (link) => link.delete === true,
627
620
  );
628
621
  if (deleteLinks.length > 0) {
629
622
  await Promise.all(
@@ -638,7 +631,7 @@ export const unlinkServices = async (service: Service, token: string) => {
638
631
  unlinkBody,
639
632
  30000,
640
633
  "UNLINK",
641
- service.name
634
+ service.name,
642
635
  );
643
636
 
644
637
  const unlinkNotification: Notification = {
@@ -674,7 +667,7 @@ export const unlinkServices = async (service: Service, token: string) => {
674
667
  };
675
668
  eventHelper.notification.publish.creation(notification);
676
669
  }
677
- })
670
+ }),
678
671
  );
679
672
  }
680
673
  };
@@ -699,7 +692,7 @@ export const updateServiceLinks = async (link: Link, token: string) => {
699
692
  linkBody,
700
693
  30000,
701
694
  "UNLINK",
702
- link.origin
695
+ link.origin,
703
696
  );
704
697
 
705
698
  // const unlinkNotification: Notification = {
@@ -745,7 +738,7 @@ export const updateServiceLinks = async (link: Link, token: string) => {
745
738
  linkBody,
746
739
  30000,
747
740
  "LINK",
748
- link.origin
741
+ link.origin,
749
742
  );
750
743
 
751
744
  const notification: Notification = {
@@ -801,7 +794,7 @@ export const changeRevision = async (data: Service, token: string) => {
801
794
  revisionBody,
802
795
  30000,
803
796
  "UPDATE_REVISION",
804
- data.name
797
+ data.name,
805
798
  );
806
799
  const notification: Notification = {
807
800
  type: "success",
@@ -833,10 +826,10 @@ export const changeRevision = async (data: Service, token: string) => {
833
826
  eventHelper.notification.publish.creation(notification);
834
827
  }
835
828
  };
836
- function getLatestRevision(revisions: Revision[]): number | null {
829
+ function getLatestRevision(revisions: string[]): number | null {
837
830
  if (!revisions || revisions.length === 0) {
838
831
  return null;
839
832
  }
840
-
841
- return Math.max(...revisions.map((revision) => Number(revision.id)));
842
- }
833
+
834
+ return Math.max(...revisions.map(Number));
835
+ }