@kumori/aurora-backend-handler 1.0.118 → 1.0.122

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.
@@ -171,6 +171,24 @@ export const deleteService = async (data: Service, security: string) => {
171
171
  return response;
172
172
  } catch (err) {
173
173
  console.error("Error in service deletion WebSocket request:", err);
174
+ const errorInfo = (err as any)?.error;
175
+ const notification: Notification = {
176
+ type: "error",
177
+ subtype: errors.service.deletionError.subtype,
178
+ date: Date.now().toString(),
179
+ info_content: {
180
+ code: errorInfo?.code ?? ((err as any)?.isTimeout ? "_timeout_" : "_unknown_error_"),
181
+ message: errorInfo?.content ?? (err as any)?.message ?? "Unknown error",
182
+ },
183
+ status: "unread",
184
+ callToAction: false,
185
+ data: {
186
+ service: data.name,
187
+ tenant: data.tenant,
188
+ },
189
+ userError: true,
190
+ };
191
+ eventHelper.notification.publish.creation(notification);
174
192
  eventHelper.service.publish.deletionError(data);
175
193
  throw err;
176
194
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kumori/aurora-backend-handler",
3
- "version": "1.0.118",
3
+ "version": "1.0.122",
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.34",
14
+ "@kumori/aurora-interfaces": "1.0.36",
15
15
  "@kumori/kumori-dsl-generator": "1.0.11",
16
16
  "@kumori/kumori-module-generator": "^1.1.6",
17
17
  "ts-node": "^10.9.2",
@@ -0,0 +1,105 @@
1
+ import { errors, Service } from "@kumori/aurora-interfaces";
2
+ import { deleteService } from "../api/service-api-service";
3
+ import { makeGlobalWebSocketRequest } from "../websocket-manager";
4
+
5
+ const mockPublishNotification = jest.fn();
6
+ const mockPublishDeletionError = jest.fn();
7
+
8
+ jest.mock("../backend-handler", () => ({
9
+ eventHelper: {
10
+ notification: { publish: { creation: (...args: unknown[]) => mockPublishNotification(...args) } },
11
+ service: { publish: { deletionError: (...args: unknown[]) => mockPublishDeletionError(...args) } },
12
+ },
13
+ }));
14
+
15
+ jest.mock("../websocket-manager", () => ({
16
+ initializeGlobalWebSocketClient: jest.fn().mockResolvedValue(undefined),
17
+ getWebSocketStatus: jest.fn(),
18
+ makeGlobalWebSocketRequest: jest.fn(),
19
+ }));
20
+
21
+ jest.mock("../environment", () => ({ environment: {} }));
22
+
23
+ jest.mock("../api/deploy-service-helper", () => ({
24
+ deployServiceHelper: jest.fn(),
25
+ }));
26
+
27
+ const service = { name: "my-service", tenant: "my-tenant" } as Service;
28
+
29
+ describe("deleteService", () => {
30
+ beforeEach(() => {
31
+ jest.clearAllMocks();
32
+ jest.spyOn(console, "error").mockImplementation(() => undefined);
33
+ });
34
+
35
+ afterEach(() => {
36
+ jest.restoreAllMocks();
37
+ });
38
+
39
+ it("devuelve la respuesta y no publica errores cuando la petición funciona", async () => {
40
+ (makeGlobalWebSocketRequest as jest.Mock).mockResolvedValue({ ok: true });
41
+
42
+ await expect(deleteService(service, "")).resolves.toEqual({ ok: true });
43
+
44
+ expect(mockPublishNotification).not.toHaveBeenCalled();
45
+ expect(mockPublishDeletionError).not.toHaveBeenCalled();
46
+ });
47
+
48
+ it("publica una notificación de error con el código y el mensaje del backend ante un 409", async () => {
49
+ const backendError = {
50
+ type: "error",
51
+ error: {
52
+ status: 409,
53
+ code: "_invalid_account_credentials_",
54
+ content:
55
+ "The configured credentials for the '/tenant/hegtestdiogo/account/accountcreatedbydiogo' account are invalid: Authentication failed",
56
+ },
57
+ };
58
+ (makeGlobalWebSocketRequest as jest.Mock).mockRejectedValue(backendError);
59
+
60
+ await expect(deleteService(service, "")).rejects.toBe(backendError);
61
+
62
+ expect(mockPublishNotification).toHaveBeenCalledTimes(1);
63
+ expect(mockPublishNotification).toHaveBeenCalledWith(
64
+ expect.objectContaining({
65
+ type: "error",
66
+ subtype: errors.service.deletionError.subtype,
67
+ status: "unread",
68
+ userError: true,
69
+ info_content: {
70
+ code: "_invalid_account_credentials_",
71
+ message: backendError.error.content,
72
+ },
73
+ data: { service: "my-service", tenant: "my-tenant" },
74
+ })
75
+ );
76
+ expect(mockPublishDeletionError).toHaveBeenCalledWith(service);
77
+ });
78
+
79
+ it("publica una notificación de error con código _timeout_ cuando la petición expira", async () => {
80
+ const timeoutError = Object.assign(new Error("Request timeout for service:delete_service"), { isTimeout: true });
81
+ (makeGlobalWebSocketRequest as jest.Mock).mockRejectedValue(timeoutError);
82
+
83
+ await expect(deleteService(service, "")).rejects.toBe(timeoutError);
84
+
85
+ expect(mockPublishNotification).toHaveBeenCalledWith(
86
+ expect.objectContaining({
87
+ subtype: errors.service.deletionError.subtype,
88
+ info_content: { code: "_timeout_", message: "Request timeout for service:delete_service" },
89
+ })
90
+ );
91
+ expect(mockPublishDeletionError).toHaveBeenCalledWith(service);
92
+ });
93
+
94
+ it("publica una notificación de error genérica cuando el error no tiene formato del backend", async () => {
95
+ (makeGlobalWebSocketRequest as jest.Mock).mockRejectedValue(new Error("WebSocket connection closed"));
96
+
97
+ await expect(deleteService(service, "")).rejects.toThrow("WebSocket connection closed");
98
+
99
+ expect(mockPublishNotification).toHaveBeenCalledWith(
100
+ expect.objectContaining({
101
+ info_content: { code: "_unknown_error_", message: "WebSocket connection closed" },
102
+ })
103
+ );
104
+ });
105
+ });
@@ -737,7 +737,7 @@ const handleEvent = async (message: WSMessage) => {
737
737
  if (message.payload.deleted === true) {
738
738
  await handleDeleteEvent(message);
739
739
  } else {
740
- const kind = message.payload.record.id.kind;
740
+ const kind = message.payload.record.id.kind || 'unknown';
741
741
  const eventData = message.payload.record;
742
742
  const entityId = eventData.id.name;
743
743
  const hasRequestingServices =
@@ -966,7 +966,7 @@ const handleEvent = async (message: WSMessage) => {
966
966
  subtype: errors.tenant.roleChanged.subtype,
967
967
  date: Date.now().toString(),
968
968
  status: "unread",
969
- callToAction: false,
969
+ notificationType: 'regular',
970
970
  data: {
971
971
  tenant: newTenant.name,
972
972
  oldRole: existingTenant.role,
@@ -985,7 +985,7 @@ const handleEvent = async (message: WSMessage) => {
985
985
  subtype: currentUser ? "tenant-invitation-accepted" : "tenant-invitation-declined",
986
986
  date: Date.now().toString(),
987
987
  status: "unread",
988
- callToAction: false,
988
+ notificationType: 'regular',
989
989
  data: {
990
990
  tenant: newTenant.name,
991
991
  user: previousUser.id,
@@ -1786,7 +1786,7 @@ const handleDeleteEvent = async (message: WSMessage) => {
1786
1786
  type: "success",
1787
1787
  subtype: errors.environment.deleted.subtype,
1788
1788
  date: Date.now().toString(),
1789
- callToAction: false,
1789
+ notificationType: 'regular',
1790
1790
  status: "unread",
1791
1791
  data: {
1792
1792
  environment: deletedEnv.name,
@@ -1806,7 +1806,7 @@ const handleDeleteEvent = async (message: WSMessage) => {
1806
1806
  type: "success",
1807
1807
  subtype: errors.account.deleted.subtype,
1808
1808
  date: Date.now().toString(),
1809
- callToAction: false,
1809
+ notificationType: 'regular',
1810
1810
  status: "unread",
1811
1811
  data: {
1812
1812
  account: deletedAccount.name,
@@ -1945,7 +1945,7 @@ const handleDeleteEvent = async (message: WSMessage) => {
1945
1945
  subtype: errors.registry.deleted.subtype,
1946
1946
  date: Date.now().toString(),
1947
1947
  status: "unread",
1948
- callToAction: false,
1948
+ notificationType: 'regular',
1949
1949
  data: {
1950
1950
  registry: deletedRegistry,
1951
1951
  tenant: registryTenant,
@@ -2001,7 +2001,7 @@ const handleDeleteEvent = async (message: WSMessage) => {
2001
2001
  subtype: errors.service.unlinked.subtype,
2002
2002
  date: Date.now().toString(),
2003
2003
  status: "unread",
2004
- callToAction: false,
2004
+ notificationType: 'regular',
2005
2005
  data: {
2006
2006
  originService: deletedLinkInfo.origin,
2007
2007
  targetService: deletedLinkInfo.target,