@arkyn/server 2.0.1-beta.9 → 2.0.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.
Files changed (244) hide show
  1. package/LICENSE.txt +24 -0
  2. package/README.md +116 -0
  3. package/dist/api/__test__/deleteRequest.spec.d.ts +2 -0
  4. package/dist/api/__test__/deleteRequest.spec.d.ts.map +1 -0
  5. package/dist/api/__test__/deleteRequest.spec.js +84 -0
  6. package/dist/api/__test__/getRequest.spec.d.ts +2 -0
  7. package/dist/api/__test__/getRequest.spec.d.ts.map +1 -0
  8. package/dist/api/__test__/getRequest.spec.js +62 -0
  9. package/dist/api/__test__/inboxFlowRequest.spec.d.ts +2 -0
  10. package/dist/api/__test__/inboxFlowRequest.spec.d.ts.map +1 -0
  11. package/dist/api/__test__/inboxFlowRequest.spec.js +96 -0
  12. package/dist/api/__test__/makeRequest.spec.d.ts +2 -0
  13. package/dist/api/__test__/makeRequest.spec.d.ts.map +1 -0
  14. package/dist/api/__test__/makeRequest.spec.js +80 -0
  15. package/dist/api/__test__/patchRequest.spec.d.ts +2 -0
  16. package/dist/api/__test__/patchRequest.spec.d.ts.map +1 -0
  17. package/dist/api/__test__/patchRequest.spec.js +84 -0
  18. package/dist/api/__test__/postRequest.spec.d.ts +2 -0
  19. package/dist/api/__test__/postRequest.spec.d.ts.map +1 -0
  20. package/dist/api/__test__/postRequest.spec.js +84 -0
  21. package/dist/api/__test__/putRequest.spec.d.ts +2 -0
  22. package/dist/api/__test__/putRequest.spec.d.ts.map +1 -0
  23. package/dist/api/__test__/putRequest.spec.js +84 -0
  24. package/dist/api/deleteRequest.d.ts +13 -0
  25. package/dist/api/deleteRequest.d.ts.map +1 -0
  26. package/dist/api/deleteRequest.js +14 -0
  27. package/dist/api/getRequest.d.ts +12 -0
  28. package/dist/api/getRequest.d.ts.map +1 -0
  29. package/dist/api/getRequest.js +13 -0
  30. package/dist/api/inboxFlowRequest.d.ts +40 -0
  31. package/dist/api/inboxFlowRequest.d.ts.map +1 -0
  32. package/dist/api/inboxFlowRequest.js +63 -0
  33. package/dist/api/makeRequest.d.ts +38 -0
  34. package/dist/api/makeRequest.d.ts.map +1 -0
  35. package/dist/api/makeRequest.js +103 -0
  36. package/dist/api/patchRequest.d.ts +13 -0
  37. package/dist/api/patchRequest.d.ts.map +1 -0
  38. package/dist/api/patchRequest.js +14 -0
  39. package/dist/api/postRequest.d.ts +13 -0
  40. package/dist/api/postRequest.d.ts.map +1 -0
  41. package/dist/api/postRequest.js +14 -0
  42. package/dist/api/putRequest.d.ts +13 -0
  43. package/dist/api/putRequest.d.ts.map +1 -0
  44. package/dist/api/putRequest.js +14 -0
  45. package/dist/config/__test__/apiInstance.spec.d.ts +2 -0
  46. package/dist/config/__test__/apiInstance.spec.d.ts.map +1 -0
  47. package/dist/config/__test__/apiInstance.spec.js +86 -0
  48. package/dist/config/__test__/inboxFlowInstance.spec.d.ts +2 -0
  49. package/dist/config/__test__/inboxFlowInstance.spec.d.ts.map +1 -0
  50. package/dist/config/__test__/inboxFlowInstance.spec.js +48 -0
  51. package/dist/config/apiInstance.d.ts +80 -0
  52. package/dist/config/apiInstance.d.ts.map +1 -0
  53. package/dist/config/apiInstance.js +111 -0
  54. package/dist/config/inboxFlowInstance.d.ts +44 -0
  55. package/dist/config/inboxFlowInstance.d.ts.map +1 -0
  56. package/dist/config/inboxFlowInstance.js +46 -0
  57. package/dist/http/badResponses/__test__/badGateway.spec.d.ts +2 -0
  58. package/dist/http/badResponses/__test__/badGateway.spec.d.ts.map +1 -0
  59. package/dist/http/badResponses/__test__/badGateway.spec.js +42 -0
  60. package/dist/http/badResponses/__test__/badRequest.spec.d.ts +2 -0
  61. package/dist/http/badResponses/__test__/badRequest.spec.d.ts.map +1 -0
  62. package/dist/http/badResponses/__test__/badRequest.spec.js +40 -0
  63. package/dist/http/badResponses/__test__/conflict.spec.d.ts +2 -0
  64. package/dist/http/badResponses/__test__/conflict.spec.d.ts.map +1 -0
  65. package/dist/http/badResponses/__test__/conflict.spec.js +40 -0
  66. package/dist/http/badResponses/__test__/forbidden.spec.d.ts +2 -0
  67. package/dist/http/badResponses/__test__/forbidden.spec.d.ts.map +1 -0
  68. package/dist/http/badResponses/__test__/forbidden.spec.js +40 -0
  69. package/dist/http/badResponses/__test__/notFound.spec.d.ts +2 -0
  70. package/dist/http/badResponses/__test__/notFound.spec.d.ts.map +1 -0
  71. package/dist/http/badResponses/__test__/notFound.spec.js +40 -0
  72. package/dist/http/badResponses/__test__/notImplemented.spec.d.ts +2 -0
  73. package/dist/http/badResponses/__test__/notImplemented.spec.d.ts.map +1 -0
  74. package/dist/http/badResponses/__test__/notImplemented.spec.js +40 -0
  75. package/dist/http/badResponses/__test__/serverError.spec.d.ts +2 -0
  76. package/dist/http/badResponses/__test__/serverError.spec.d.ts.map +1 -0
  77. package/dist/http/badResponses/__test__/serverError.spec.js +40 -0
  78. package/dist/http/badResponses/__test__/unauthorized.spec.d.ts +2 -0
  79. package/dist/http/badResponses/__test__/unauthorized.spec.d.ts.map +1 -0
  80. package/dist/http/badResponses/__test__/unauthorized.spec.js +40 -0
  81. package/dist/http/badResponses/__test__/unprocessableEntity.spec.d.ts +2 -0
  82. package/dist/http/badResponses/__test__/unprocessableEntity.spec.d.ts.map +1 -0
  83. package/dist/http/badResponses/__test__/unprocessableEntity.spec.js +66 -0
  84. package/dist/http/badResponses/badGateway.d.ts +23 -0
  85. package/dist/http/badResponses/badGateway.d.ts.map +1 -1
  86. package/dist/http/badResponses/badGateway.js +24 -1
  87. package/dist/http/badResponses/badRequest.d.ts +23 -0
  88. package/dist/http/badResponses/badRequest.d.ts.map +1 -1
  89. package/dist/http/badResponses/badRequest.js +24 -1
  90. package/dist/http/badResponses/conflict.d.ts +23 -0
  91. package/dist/http/badResponses/conflict.d.ts.map +1 -1
  92. package/dist/http/badResponses/conflict.js +24 -1
  93. package/dist/http/badResponses/forbidden.d.ts +23 -0
  94. package/dist/http/badResponses/forbidden.d.ts.map +1 -1
  95. package/dist/http/badResponses/forbidden.js +25 -2
  96. package/dist/http/badResponses/notFound.d.ts +23 -0
  97. package/dist/http/badResponses/notFound.d.ts.map +1 -1
  98. package/dist/http/badResponses/notFound.js +24 -1
  99. package/dist/http/badResponses/notImplemented.d.ts +23 -0
  100. package/dist/http/badResponses/notImplemented.d.ts.map +1 -1
  101. package/dist/http/badResponses/notImplemented.js +24 -1
  102. package/dist/http/badResponses/serverError.d.ts +23 -0
  103. package/dist/http/badResponses/serverError.d.ts.map +1 -1
  104. package/dist/http/badResponses/serverError.js +24 -1
  105. package/dist/http/badResponses/unauthorized.d.ts +23 -0
  106. package/dist/http/badResponses/unauthorized.d.ts.map +1 -1
  107. package/dist/http/badResponses/unauthorized.js +24 -1
  108. package/dist/http/badResponses/unprocessableEntity.d.ts +28 -1
  109. package/dist/http/badResponses/unprocessableEntity.d.ts.map +1 -1
  110. package/dist/http/badResponses/unprocessableEntity.js +30 -3
  111. package/dist/http/successResponses/__test__/created.spec.d.ts +2 -0
  112. package/dist/http/successResponses/__test__/created.spec.d.ts.map +1 -0
  113. package/dist/http/successResponses/__test__/created.spec.js +57 -0
  114. package/dist/http/successResponses/__test__/found.spec.d.ts +2 -0
  115. package/dist/http/successResponses/__test__/found.spec.d.ts.map +1 -0
  116. package/dist/http/successResponses/__test__/found.spec.js +57 -0
  117. package/dist/http/successResponses/__test__/noContent.spec.d.ts +2 -0
  118. package/dist/http/successResponses/__test__/noContent.spec.d.ts.map +1 -0
  119. package/dist/http/successResponses/__test__/noContent.spec.js +40 -0
  120. package/dist/http/successResponses/__test__/success.spec.d.ts +2 -0
  121. package/dist/http/successResponses/__test__/success.spec.d.ts.map +1 -0
  122. package/dist/http/successResponses/__test__/success.spec.js +60 -0
  123. package/dist/http/successResponses/__test__/updated.spec.d.ts +2 -0
  124. package/dist/http/successResponses/__test__/updated.spec.d.ts.map +1 -0
  125. package/dist/http/successResponses/__test__/updated.spec.js +60 -0
  126. package/dist/http/successResponses/created.d.ts +25 -0
  127. package/dist/http/successResponses/created.d.ts.map +1 -1
  128. package/dist/http/successResponses/created.js +25 -0
  129. package/dist/http/successResponses/found.d.ts +28 -0
  130. package/dist/http/successResponses/found.d.ts.map +1 -1
  131. package/dist/http/successResponses/found.js +28 -0
  132. package/dist/http/successResponses/noContent.d.ts +16 -1
  133. package/dist/http/successResponses/noContent.d.ts.map +1 -1
  134. package/dist/http/successResponses/noContent.js +16 -8
  135. package/dist/http/successResponses/success.d.ts +25 -0
  136. package/dist/http/successResponses/success.d.ts.map +1 -1
  137. package/dist/http/successResponses/success.js +25 -0
  138. package/dist/http/successResponses/updated.d.ts +25 -0
  139. package/dist/http/successResponses/updated.d.ts.map +1 -1
  140. package/dist/http/successResponses/updated.js +25 -0
  141. package/dist/index.d.ts +6 -0
  142. package/dist/index.d.ts.map +1 -1
  143. package/dist/index.js +10 -0
  144. package/dist/services/__test__/decodeRequestBody.spec.d.ts +2 -0
  145. package/dist/services/__test__/decodeRequestBody.spec.d.ts.map +1 -0
  146. package/dist/services/__test__/decodeRequestBody.spec.js +39 -0
  147. package/dist/services/__test__/errorHandler.spec.d.ts +2 -0
  148. package/dist/services/__test__/errorHandler.spec.d.ts.map +1 -0
  149. package/dist/services/__test__/errorHandler.spec.js +115 -0
  150. package/dist/services/__test__/formParse.spec.d.ts +2 -0
  151. package/dist/services/__test__/formParse.spec.d.ts.map +1 -0
  152. package/dist/services/__test__/formParse.spec.js +78 -0
  153. package/dist/services/__test__/getCaller.spec.d.ts +2 -0
  154. package/dist/services/__test__/getCaller.spec.d.ts.map +1 -0
  155. package/dist/services/__test__/getCaller.spec.js +60 -0
  156. package/dist/services/__test__/getScopedParams.spec.d.ts +2 -0
  157. package/dist/services/__test__/getScopedParams.spec.d.ts.map +1 -0
  158. package/dist/services/__test__/getScopedParams.spec.js +51 -0
  159. package/dist/services/__test__/schemaValidator.spec.d.ts +2 -0
  160. package/dist/services/__test__/schemaValidator.spec.d.ts.map +1 -0
  161. package/dist/services/__test__/schemaValidator.spec.js +89 -0
  162. package/dist/services/decodeErrorMessageFromRequest.d.ts +17 -0
  163. package/dist/services/decodeErrorMessageFromRequest.d.ts.map +1 -0
  164. package/dist/services/decodeErrorMessageFromRequest.js +30 -0
  165. package/dist/services/decodeRequestBody.d.ts.map +1 -1
  166. package/dist/services/decodeRequestBody.js +12 -16
  167. package/dist/services/errorHandler.d.ts +42 -1
  168. package/dist/services/errorHandler.d.ts.map +1 -1
  169. package/dist/services/errorHandler.js +42 -0
  170. package/dist/services/formParse.d.ts.map +1 -1
  171. package/dist/services/formParse.js +4 -2
  172. package/dist/services/getCaller.d.ts +17 -0
  173. package/dist/services/getCaller.d.ts.map +1 -0
  174. package/dist/services/getCaller.js +45 -0
  175. package/dist/services/httpDebug.d.ts +35 -0
  176. package/dist/services/httpDebug.d.ts.map +1 -0
  177. package/dist/services/httpDebug.js +56 -0
  178. package/dist/services/schemaValidator.d.ts +13 -0
  179. package/dist/services/schemaValidator.d.ts.map +1 -0
  180. package/dist/services/schemaValidator.js +51 -0
  181. package/package.json +11 -5
  182. package/src/api/__test__/deleteRequest.spec.ts +107 -0
  183. package/src/api/__test__/getRequest.spec.ts +76 -0
  184. package/src/api/__test__/inboxFlowRequest.spec.ts +125 -0
  185. package/src/api/__test__/makeRequest.spec.ts +121 -0
  186. package/src/api/__test__/patchRequest.spec.ts +125 -0
  187. package/src/api/__test__/postRequest.spec.ts +125 -0
  188. package/src/api/__test__/putRequest.spec.ts +125 -0
  189. package/src/api/deleteRequest.ts +22 -0
  190. package/src/api/getRequest.ts +20 -0
  191. package/src/api/inboxFlowRequest.ts +76 -0
  192. package/src/api/makeRequest.ts +117 -0
  193. package/src/api/patchRequest.ts +22 -0
  194. package/src/api/postRequest.ts +22 -0
  195. package/src/api/putRequest.ts +22 -0
  196. package/src/config/__test__/apiInstance.spec.ts +129 -0
  197. package/src/config/__test__/inboxFlowInstance.spec.ts +61 -0
  198. package/src/config/apiInstance.ts +148 -0
  199. package/src/config/inboxFlowInstance.ts +65 -0
  200. package/src/http/badResponses/__test__/badGateway.spec.ts +50 -0
  201. package/src/http/badResponses/__test__/badRequest.spec.ts +50 -0
  202. package/src/http/badResponses/__test__/conflict.spec.ts +50 -0
  203. package/src/http/badResponses/__test__/forbidden.spec.ts +50 -0
  204. package/src/http/badResponses/__test__/notFound.spec.ts +50 -0
  205. package/src/http/badResponses/__test__/notImplemented.spec.ts +50 -0
  206. package/src/http/badResponses/__test__/serverError.spec.ts +50 -0
  207. package/src/http/badResponses/__test__/unauthorized.spec.ts +50 -0
  208. package/src/http/badResponses/__test__/unprocessableEntity.spec.ts +76 -0
  209. package/src/http/badResponses/badGateway.ts +29 -2
  210. package/src/http/badResponses/badRequest.ts +29 -2
  211. package/src/http/badResponses/conflict.ts +29 -2
  212. package/src/http/badResponses/forbidden.ts +30 -3
  213. package/src/http/badResponses/notFound.ts +29 -2
  214. package/src/http/badResponses/notImplemented.ts +29 -2
  215. package/src/http/badResponses/serverError.ts +29 -2
  216. package/src/http/badResponses/unauthorized.ts +29 -2
  217. package/src/http/badResponses/unprocessableEntity.ts +33 -2
  218. package/src/http/successResponses/__test__/created.spec.ts +65 -0
  219. package/src/http/successResponses/__test__/found.spec.ts +65 -0
  220. package/src/http/successResponses/__test__/noContent.spec.ts +49 -0
  221. package/src/http/successResponses/__test__/success.spec.ts +68 -0
  222. package/src/http/successResponses/__test__/updated.spec.ts +68 -0
  223. package/src/http/successResponses/created.ts +31 -2
  224. package/src/http/successResponses/found.ts +32 -0
  225. package/src/http/successResponses/noContent.ts +20 -11
  226. package/src/http/successResponses/success.ts +31 -2
  227. package/src/http/successResponses/updated.ts +31 -2
  228. package/src/index.ts +9 -1
  229. package/src/services/__test__/decodeRequestBody.spec.ts +51 -0
  230. package/src/services/__test__/errorHandler.spec.ts +133 -0
  231. package/src/services/__test__/formParse.spec.ts +96 -0
  232. package/src/services/__test__/getCaller.spec.ts +78 -0
  233. package/src/services/__test__/getScopedParams.spec.ts +68 -0
  234. package/src/services/__test__/schemaValidator.spec.ts +106 -0
  235. package/src/services/decodeErrorMessageFromRequest.ts +36 -0
  236. package/src/services/decodeRequestBody.ts +11 -15
  237. package/src/services/errorHandler.ts +45 -1
  238. package/src/services/formParse.ts +4 -5
  239. package/src/services/getCaller.ts +39 -18
  240. package/src/services/httpDebug.ts +46 -5
  241. package/vitest.config.ts +5 -0
  242. package/dist/http/httpDebug.d.ts +0 -3
  243. package/dist/http/httpDebug.d.ts.map +0 -1
  244. package/dist/http/httpDebug.js +0 -15
@@ -0,0 +1,39 @@
1
+ import { decodeRequestBody } from "../decodeRequestBody";
2
+ import { BadRequest } from "../../http/badResponses/badRequest";
3
+ import { describe, expect, it } from "vitest";
4
+ describe("decodeRequestBody", () => {
5
+ it("should decode the request body as JSON", async () => {
6
+ const mockRequest = {
7
+ arrayBuffer: async () => new TextEncoder().encode(JSON.stringify({ key: "value" })).buffer,
8
+ };
9
+ const result = await decodeRequestBody(mockRequest);
10
+ expect(result).toEqual({ key: "value" });
11
+ });
12
+ it("should decode the request body as URL-encoded form data", async () => {
13
+ const mockRequest = {
14
+ arrayBuffer: async () => new TextEncoder().encode("key=value&anotherKey=anotherValue").buffer,
15
+ };
16
+ const result = await decodeRequestBody(mockRequest);
17
+ expect(result).toEqual({ key: "value", anotherKey: "anotherValue" });
18
+ });
19
+ it("should throw BadRequest if the text is neither valid JSON nor URL-encoded", async () => {
20
+ const mockRequest = {
21
+ arrayBuffer: async () => new TextEncoder().encode("{invalidJson").buffer,
22
+ };
23
+ await expect(decodeRequestBody(mockRequest)).rejects.toThrow();
24
+ });
25
+ it("should throw BadRequest if the text is not a valid format for URLSearchParams", async () => {
26
+ const mockRequest = {
27
+ arrayBuffer: async () => new TextEncoder().encode("invalidFormat").buffer,
28
+ };
29
+ await expect(decodeRequestBody(mockRequest)).rejects.toThrow();
30
+ });
31
+ it("should throw BadRequest if an error occurs while reading the body", async () => {
32
+ const mockRequest = {
33
+ arrayBuffer: async () => {
34
+ throw new Error("Error reading the body");
35
+ },
36
+ };
37
+ await expect(decodeRequestBody(mockRequest)).rejects.toThrow();
38
+ });
39
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=errorHandler.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errorHandler.spec.d.ts","sourceRoot":"","sources":["../../../src/services/__test__/errorHandler.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,115 @@
1
+ import { errorHandler } from "../errorHandler";
2
+ import { Found } from "../../http/successResponses/found";
3
+ import { Created } from "../../http/successResponses/created";
4
+ import { Updated } from "../../http/successResponses/updated";
5
+ import { Success } from "../../http/successResponses/success";
6
+ import { NoContent } from "../../http/successResponses/noContent";
7
+ import { BadGateway } from "../../http/badResponses/badGateway";
8
+ import { BadRequest } from "../../http/badResponses/badRequest";
9
+ import { Conflict } from "../../http/badResponses/conflict";
10
+ import { Forbidden } from "../../http/badResponses/forbidden";
11
+ import { NotFound } from "../../http/badResponses/notFound";
12
+ import { NotImplemented } from "../../http/badResponses/notImplemented";
13
+ import { ServerError } from "../../http/badResponses/serverError";
14
+ import { Unauthorized } from "../../http/badResponses/unauthorized";
15
+ import { UnprocessableEntity } from "../../http/badResponses/unprocessableEntity";
16
+ import { describe, expect, it } from "vitest";
17
+ describe("errorHandler", () => {
18
+ describe("Success Responses", () => {
19
+ it("should handle Found response", () => {
20
+ const found = new Found("Resource found");
21
+ const response = errorHandler(found);
22
+ expect(response.status).toBe(found.toResponse().status);
23
+ expect(response.statusText).toBe(found.toResponse().statusText);
24
+ });
25
+ it("should handle Created response", () => {
26
+ const created = new Created("Resource created");
27
+ const response = errorHandler(created);
28
+ expect(response.status).toBe(created.toResponse().status);
29
+ expect(response.statusText).toBe(created.toResponse().statusText);
30
+ });
31
+ it("should handle Updated response", () => {
32
+ const updated = new Updated("Resource updated");
33
+ const response = errorHandler(updated);
34
+ expect(response.status).toBe(updated.toResponse().status);
35
+ expect(response.statusText).toBe(updated.toResponse().statusText);
36
+ });
37
+ it("should handle Success response", () => {
38
+ const success = new Success("Operation successful");
39
+ const response = errorHandler(success);
40
+ expect(response.status).toBe(success.toResponse().status);
41
+ expect(response.statusText).toBe(success.toResponse().statusText);
42
+ });
43
+ it("should handle NoContent response", () => {
44
+ const noContent = new NoContent();
45
+ const response = errorHandler(noContent);
46
+ expect(response.status).toBe(noContent.toResponse().status);
47
+ expect(response.statusText).toBe(noContent.toResponse().statusText);
48
+ });
49
+ });
50
+ describe("Error Responses", () => {
51
+ it("should handle BadGateway error", () => {
52
+ const badGateway = new BadGateway("Bad gateway error");
53
+ const response = errorHandler(badGateway);
54
+ expect(response.status).toBe(badGateway.toResponse().status);
55
+ expect(response.statusText).toBe(badGateway.toResponse().statusText);
56
+ });
57
+ it("should handle BadRequest error", () => {
58
+ const badRequest = new BadRequest("Bad request error");
59
+ const response = errorHandler(badRequest);
60
+ expect(response.status).toBe(badRequest.toResponse().status);
61
+ expect(response.statusText).toBe(badRequest.toResponse().statusText);
62
+ });
63
+ it("should handle Conflict error", () => {
64
+ const conflict = new Conflict("Conflict error");
65
+ const response = errorHandler(conflict);
66
+ expect(response.status).toBe(conflict.toResponse().status);
67
+ expect(response.statusText).toBe(conflict.toResponse().statusText);
68
+ });
69
+ it("should handle Forbidden error", () => {
70
+ const forbidden = new Forbidden("Forbidden error");
71
+ const response = errorHandler(forbidden);
72
+ expect(response.status).toBe(forbidden.toResponse().status);
73
+ expect(response.statusText).toBe(forbidden.toResponse().statusText);
74
+ });
75
+ it("should handle NotFound error", () => {
76
+ const notFound = new NotFound("Not found error");
77
+ const response = errorHandler(notFound);
78
+ expect(response.status).toBe(notFound.toResponse().status);
79
+ expect(response.statusText).toBe(notFound.toResponse().statusText);
80
+ });
81
+ it("should handle NotImplemented error", () => {
82
+ const notImplemented = new NotImplemented("Not implemented error");
83
+ const response = errorHandler(notImplemented);
84
+ expect(response.status).toBe(notImplemented.toResponse().status);
85
+ expect(response.statusText).toBe(notImplemented.toResponse().statusText);
86
+ });
87
+ it("should handle ServerError error", () => {
88
+ const serverError = new ServerError("Server error");
89
+ const response = errorHandler(serverError);
90
+ expect(response.status).toBe(serverError.toResponse().status);
91
+ expect(response.statusText).toBe(serverError.toResponse().statusText);
92
+ });
93
+ it("should handle Unauthorized error", () => {
94
+ const unauthorized = new Unauthorized("Unauthorized error");
95
+ const response = errorHandler(unauthorized);
96
+ expect(response.status).toBe(unauthorized.toResponse().status);
97
+ expect(response.statusText).toBe(unauthorized.toResponse().statusText);
98
+ });
99
+ it("should handle UnprocessableEntity error", () => {
100
+ const unprocessableEntity = new UnprocessableEntity({});
101
+ const response = errorHandler(unprocessableEntity);
102
+ expect(response.status).toBe(unprocessableEntity.toResponse().status);
103
+ expect(response.statusText).toBe(unprocessableEntity.toResponse().statusText);
104
+ });
105
+ });
106
+ describe("Unknown Error", () => {
107
+ it("should return undefined for unknown error types", () => {
108
+ const unknownError = new Error("Unknown error");
109
+ const serverError = new ServerError("Server error");
110
+ const response = errorHandler(unknownError);
111
+ expect(response.status).toBe(serverError.toResponse().status);
112
+ expect(response.statusText).toBe(serverError.toResponse().statusText);
113
+ });
114
+ });
115
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=formParse.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formParse.spec.d.ts","sourceRoot":"","sources":["../../../src/services/__test__/formParse.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,78 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { z } from "zod";
3
+ import { formParse } from "../formParse";
4
+ describe("formParse", () => {
5
+ it("should return success and parsed data when validation passes", () => {
6
+ const schema = z.object({
7
+ name: z.string().min(1, "Name is required"),
8
+ age: z.number().min(18, "Must be at least 18"),
9
+ });
10
+ const formData = { name: "John", age: 25 };
11
+ const result = formParse([formData, schema]);
12
+ expect(result.success).toBe(true);
13
+ expect(result).toHaveProperty("data");
14
+ if (result.success)
15
+ expect(result.data).toEqual(formData);
16
+ });
17
+ it("should return field errors when validation fails", () => {
18
+ const schema = z.object({
19
+ name: z.string().min(1, "Name is required"),
20
+ age: z.number().min(18, "Must be at least 18"),
21
+ });
22
+ const formData = { name: "", age: 17 };
23
+ const result = formParse([formData, schema]);
24
+ expect(result.success).toBe(false);
25
+ expect(result).toHaveProperty("fieldErrors");
26
+ if (!result.success) {
27
+ expect(result.fieldErrors).toEqual({
28
+ name: "Name is required",
29
+ age: "Must be at least 18",
30
+ });
31
+ expect(result.fields).toEqual(formData);
32
+ }
33
+ });
34
+ it("should handle missing fields gracefully", () => {
35
+ const schema = z.object({
36
+ name: z
37
+ .string({ required_error: "Name is required" })
38
+ .min(1, "Name is required"),
39
+ age: z.number().min(18, "Must be at least 18"),
40
+ });
41
+ const formData = { age: 20 }; // Missing "name"
42
+ const result = formParse([formData, schema]);
43
+ expect(result.success).toBe(false);
44
+ if (!result.success) {
45
+ expect(result.fieldErrors).toEqual({ name: "Name is required" });
46
+ expect(result.fields).toEqual(formData);
47
+ }
48
+ });
49
+ it("should return success for an empty schema", () => {
50
+ const schema = z.object({});
51
+ const formData = {};
52
+ const result = formParse([formData, schema]);
53
+ expect(result.success).toBe(true);
54
+ expect(result).toHaveProperty("data");
55
+ if (result.success)
56
+ expect(result.data).toEqual(formData);
57
+ });
58
+ it("should handle nested schemas correctly", () => {
59
+ const schema = z.object({
60
+ user: z.object({
61
+ name: z.string().min(1, "Name is required"),
62
+ age: z.number().min(18, "Must be at least 18"),
63
+ }),
64
+ });
65
+ const formData = {
66
+ user: { name: "", age: 16 },
67
+ };
68
+ const result = formParse([formData, schema]);
69
+ expect(result.success).toBe(false);
70
+ if (!result.success) {
71
+ expect(result.fieldErrors).toEqual({
72
+ "user.name": "Name is required",
73
+ "user.age": "Must be at least 18",
74
+ });
75
+ expect(result.fields).toEqual(formData);
76
+ }
77
+ });
78
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=getCaller.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getCaller.spec.d.ts","sourceRoot":"","sources":["../../../src/services/__test__/getCaller.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,60 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { getCaller } from "../getCaller";
3
+ describe("getCaller", () => {
4
+ it("should return the correct caller function name and file path", () => {
5
+ function testFunction() {
6
+ return getCaller();
7
+ }
8
+ const result = testFunction();
9
+ expect(result.functionName).toBe("testFunction");
10
+ expect(result.callerInfo).toContain("getCaller.spec.ts");
11
+ });
12
+ it("should handle calls from anonymous functions", () => {
13
+ const result = (() => getCaller())();
14
+ expect(result.functionName).toBe("Unknown function");
15
+ expect(result.callerInfo).toContain("getCaller.spec.ts");
16
+ });
17
+ it("should return the correct name for nested functions", () => {
18
+ function outerFunction() {
19
+ function innerFunction() {
20
+ return getCaller();
21
+ }
22
+ return innerFunction();
23
+ }
24
+ const result = outerFunction();
25
+ expect(result.functionName).toBe("innerFunction");
26
+ expect(result.callerInfo).toContain("getCaller.spec.ts");
27
+ });
28
+ it("should return method name when called from object method", () => {
29
+ const obj = {
30
+ method() {
31
+ return getCaller();
32
+ },
33
+ };
34
+ const result = obj.method();
35
+ expect(result.functionName).toMatch(/method|Object.method/);
36
+ expect(result.callerInfo).toContain("getCaller.spec.ts");
37
+ });
38
+ it("should return method name when called from class method", () => {
39
+ class TestClass {
40
+ call() {
41
+ return getCaller();
42
+ }
43
+ }
44
+ const instance = new TestClass();
45
+ const result = instance.call();
46
+ expect(result.functionName).toMatch(/call|TestClass.call/);
47
+ expect(result.callerInfo).toContain("getCaller.spec.ts");
48
+ });
49
+ it("should return the correct caller for indirect calls", () => {
50
+ function intermediary(fn) {
51
+ return fn();
52
+ }
53
+ function actualCaller() {
54
+ return getCaller();
55
+ }
56
+ const result = intermediary(actualCaller);
57
+ expect(result.functionName).toBe("actualCaller");
58
+ expect(result.callerInfo).toContain("getCaller.spec.ts");
59
+ });
60
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=getScopedParams.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getScopedParams.spec.d.ts","sourceRoot":"","sources":["../../../src/services/__test__/getScopedParams.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,51 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { getScopedParams } from "../getScopedParams";
3
+ describe("getScopedParams", () => {
4
+ it("should return all query parameters when no scope is provided", () => {
5
+ const request = {
6
+ url: "https://example.com?key1=value1&key2=value2",
7
+ };
8
+ const params = getScopedParams(request);
9
+ expect(params.get("key1")).toBe("value1");
10
+ expect(params.get("key2")).toBe("value2");
11
+ expect(params.toString()).toBe("key1=value1&key2=value2");
12
+ });
13
+ it("should return only scoped query parameters when a scope is provided", () => {
14
+ const request = {
15
+ url: "https://example.com?scope:key1=value1&scope:key2=value2&key3=value3",
16
+ };
17
+ const params = getScopedParams(request, "scope");
18
+ expect(params.get("key1")).toBe("value1");
19
+ expect(params.get("key2")).toBe("value2");
20
+ expect(params.get("key3")).toBeNull();
21
+ expect(params.toString()).toBe("key1=value1&key2=value2");
22
+ });
23
+ it("should return an empty URLSearchParams object if no parameters match the scope", () => {
24
+ const request = {
25
+ url: "https://example.com?key1=value1&key2=value2",
26
+ };
27
+ const params = getScopedParams(request, "scope");
28
+ expect(params.toString()).toBe("");
29
+ });
30
+ it("should handle URLs with no query parameters", () => {
31
+ const request = { url: "https://example.com" };
32
+ const params = getScopedParams(request);
33
+ expect(params.toString()).toBe("");
34
+ });
35
+ it("should handle URLs with query parameters but no matching scope", () => {
36
+ const request = {
37
+ url: "https://example.com?other:key1=value1&other:key2=value2",
38
+ };
39
+ const params = getScopedParams(request, "scope");
40
+ expect(params.toString()).toBe("");
41
+ });
42
+ it("should handle special characters in query parameter keys and values", () => {
43
+ const request = {
44
+ url: "https://example.com?scope:key+1=value+1&scope:key+2=value+2",
45
+ };
46
+ const params = getScopedParams(request, "scope");
47
+ expect(params.get("key 1")).toBe("value 1");
48
+ expect(params.get("key 2")).toBe("value 2");
49
+ expect(params.toString()).toBe("key+1=value+1&key+2=value+2");
50
+ });
51
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=schemaValidator.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemaValidator.spec.d.ts","sourceRoot":"","sources":["../../../src/services/__test__/schemaValidator.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,89 @@
1
+ import { z } from "zod";
2
+ import { SchemaValidator } from "../schemaValidator";
3
+ import { httpDebug } from "../httpDebug";
4
+ import { ServerError } from "../../http/badResponses/serverError";
5
+ import { UnprocessableEntity } from "../../http/badResponses/unprocessableEntity";
6
+ import { describe, expect, it, vi } from "vitest";
7
+ vi.mock("../getCaller", () => ({
8
+ getCaller: vi.fn(() => ({
9
+ callerInfo: "mockedCallerInfo",
10
+ functionName: "mockedFunctionName",
11
+ })),
12
+ }));
13
+ vi.mock("../httpDebug", () => ({
14
+ httpDebug: vi.fn(),
15
+ }));
16
+ describe("SchemaValidator", () => {
17
+ const schema = z.object({
18
+ name: z.string().min(1, "Name is required"),
19
+ age: z.number().min(18, "Must be at least 18"),
20
+ });
21
+ const validator = new SchemaValidator(schema);
22
+ describe("constructor", () => {
23
+ it("should initialize with caller info and function name", () => {
24
+ expect(validator.callerInfo).toBe("mockedCallerInfo");
25
+ expect(validator.functionName).toBe("mockedFunctionName");
26
+ });
27
+ });
28
+ describe("isValid", () => {
29
+ it("should return true for valid data", () => {
30
+ const data = { name: "John", age: 25 };
31
+ expect(validator.isValid(data)).toBe(true);
32
+ });
33
+ it("should return false for invalid data", () => {
34
+ const data = { name: "", age: 17 };
35
+ expect(validator.isValid(data)).toBe(false);
36
+ });
37
+ });
38
+ describe("safeValidate", () => {
39
+ it("should return success for valid data", () => {
40
+ const data = { name: "John", age: 25 };
41
+ const result = validator.safeValidate(data);
42
+ expect(result.success).toBe(true);
43
+ expect(result.data).toEqual(data);
44
+ });
45
+ it("should return failure for invalid data", () => {
46
+ const data = { name: "", age: 17 };
47
+ const result = validator.safeValidate(data);
48
+ expect(result.success).toBe(false);
49
+ if (!result.success)
50
+ expect(result.error.issues).toHaveLength(2);
51
+ });
52
+ });
53
+ describe("validate", () => {
54
+ it("should return parsed data for valid input", () => {
55
+ const data = { name: "John", age: 25 };
56
+ expect(validator.validate(data)).toEqual(data);
57
+ });
58
+ it("should throw ServerError for invalid input", () => {
59
+ const data = { name: "", age: 17 };
60
+ expect(() => validator.validate(data)).toThrow(ServerError);
61
+ });
62
+ });
63
+ describe("formValidate", () => {
64
+ it("should return parsed data for valid input", () => {
65
+ const data = { name: "John", age: 25 };
66
+ expect(validator.formValidate(data)).toEqual(data);
67
+ });
68
+ it("should throw UnprocessableEntity for invalid input", () => {
69
+ const data = { name: "", age: 17 };
70
+ expect(() => validator.formValidate(data)).toThrow(UnprocessableEntity);
71
+ });
72
+ it("should call httpDebug with formParsed data on validation failure", () => {
73
+ const data = { name: "", age: 17 };
74
+ try {
75
+ validator.formValidate(data);
76
+ }
77
+ catch (error) {
78
+ // Ignore the error
79
+ }
80
+ expect(httpDebug).toHaveBeenCalledWith("UnprocessableEntity", expect.objectContaining({
81
+ success: false,
82
+ fieldErrors: {
83
+ name: "Name is required",
84
+ age: "Must be at least 18",
85
+ },
86
+ }));
87
+ });
88
+ });
89
+ });
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Decodes an error message from a given request data object or response object.
3
+ *
4
+ * This function attempts to extract a meaningful error message from the provided
5
+ * `data` or `response` objects by checking various properties in a specific order.
6
+ * If no valid error message is found, it returns a default message: "Missing error message".
7
+ *
8
+ * @param data - The data object that may contain error information. It can have properties
9
+ * such as `message`, `error`, or `error.message` that are checked for a string value.
10
+ * @param response - The response object that may contain a `statusText` property
11
+ * representing the HTTP status text.
12
+ * @returns A string representing the decoded error message, or a default message
13
+ * if no error message is found.
14
+ */
15
+ declare function decodeErrorMessageFromRequest(data: any, response: Response): string;
16
+ export { decodeErrorMessageFromRequest };
17
+ //# sourceMappingURL=decodeErrorMessageFromRequest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decodeErrorMessageFromRequest.d.ts","sourceRoot":"","sources":["../../src/services/decodeErrorMessageFromRequest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,iBAAS,6BAA6B,CAAC,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAkB5E;AAED,OAAO,EAAE,6BAA6B,EAAE,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Decodes an error message from a given request data object or response object.
3
+ *
4
+ * This function attempts to extract a meaningful error message from the provided
5
+ * `data` or `response` objects by checking various properties in a specific order.
6
+ * If no valid error message is found, it returns a default message: "Missing error message".
7
+ *
8
+ * @param data - The data object that may contain error information. It can have properties
9
+ * such as `message`, `error`, or `error.message` that are checked for a string value.
10
+ * @param response - The response object that may contain a `statusText` property
11
+ * representing the HTTP status text.
12
+ * @returns A string representing the decoded error message, or a default message
13
+ * if no error message is found.
14
+ */
15
+ function decodeErrorMessageFromRequest(data, response) {
16
+ if (data?.message && typeof data?.message === "string") {
17
+ return data?.message;
18
+ }
19
+ if (data?.error && typeof data?.error === "string") {
20
+ return data?.error;
21
+ }
22
+ if (data?.error?.message && typeof data?.error?.message === "string") {
23
+ return data?.error?.message;
24
+ }
25
+ if (response?.statusText && typeof response?.statusText === "string") {
26
+ return response?.statusText;
27
+ }
28
+ return "Missing error message";
29
+ }
30
+ export { decodeErrorMessageFromRequest };
@@ -1 +1 @@
1
- {"version":3,"file":"decodeRequestBody.d.ts","sourceRoot":"","sources":["../../src/services/decodeRequestBody.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAE9D;;;;;;;;;;;;GAYG;AAEH,QAAA,MAAM,iBAAiB,EAAE,yBA2BxB,CAAC;AAEF,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
1
+ {"version":3,"file":"decodeRequestBody.d.ts","sourceRoot":"","sources":["../../src/services/decodeRequestBody.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAG9D;;;;;;;;;;;;GAYG;AAEH,QAAA,MAAM,iBAAiB,EAAE,yBAsBxB,CAAC;AAEF,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { BadRequest } from "../http/badResponses/badRequest";
1
2
  /**
2
3
  * Decodes the body of an incoming request into a JavaScript object.
3
4
  *
@@ -13,29 +14,24 @@
13
14
  */
14
15
  const decodeRequestBody = async (req) => {
15
16
  let data;
17
+ const arrayBuffer = await req.arrayBuffer();
18
+ const text = new TextDecoder().decode(arrayBuffer);
16
19
  try {
17
- const arrayBuffer = await req.arrayBuffer();
18
- const text = new TextDecoder().decode(arrayBuffer);
20
+ data = JSON.parse(text);
21
+ }
22
+ catch (jsonError) {
19
23
  try {
20
- data = JSON.parse(text);
21
- }
22
- catch (jsonError) {
23
- try {
24
+ if (text.includes("=")) {
24
25
  const formData = new URLSearchParams(text);
25
26
  data = Object.fromEntries(formData.entries());
26
27
  }
27
- catch (formDataError) {
28
- console.error("Failed to extract data from request:", {
29
- jsonError,
30
- formDataError,
31
- });
32
- data = {};
28
+ else {
29
+ throw new BadRequest("Invalid URLSearchParams format");
33
30
  }
34
31
  }
35
- }
36
- catch (error) {
37
- console.error("Failed to read request body:", error);
38
- data = {};
32
+ catch (formDataError) {
33
+ throw new BadRequest("Failed to extract data from request");
34
+ }
39
35
  }
40
36
  return data;
41
37
  };
@@ -1,3 +1,44 @@
1
- declare function errorHandler(error: any): Response | undefined;
1
+ /**
2
+ * Handles errors and converts them into appropriate HTTP responses.
3
+ *
4
+ * This function takes an error object and determines its type to return
5
+ * the corresponding HTTP response. It supports both success and error
6
+ * response types, converting them into a standardized format using the
7
+ * `toResponse` method when applicable.
8
+ *
9
+ * @param error - The error object to handle. It can be an instance of various
10
+ * HTTP response classes or a generic error.
11
+ *
12
+ * @returns The corresponding HTTP response object if the error matches a known
13
+ * type, or `undefined` if no match is found.
14
+ *
15
+ * ### Supported Success Responses:
16
+ * - `Found`
17
+ * - `Created`
18
+ * - `Updated`
19
+ * - `Success`
20
+ * - `NoContent`
21
+ *
22
+ * ### Supported Error Responses:
23
+ * - `BadGateway`
24
+ * - `BadRequest`
25
+ * - `Conflict`
26
+ * - `Forbidden`
27
+ * - `NotFound`
28
+ * - `NotImplemented`
29
+ * - `ServerError`
30
+ * - `Unauthorized`
31
+ * - `UnprocessableEntity`
32
+ *
33
+ * ### Example Usage:
34
+ * ```typescript
35
+ * try {
36
+ * // Some operation that might throw an error
37
+ * } catch (error) {
38
+ * return errorHandler(error);
39
+ * }
40
+ * ```
41
+ */
42
+ declare function errorHandler(error: any): Response;
2
43
  export { errorHandler };
3
44
  //# sourceMappingURL=errorHandler.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errorHandler.d.ts","sourceRoot":"","sources":["../../src/services/errorHandler.ts"],"names":[],"mappings":"AAgBA,iBAAS,YAAY,CAAC,KAAK,EAAE,GAAG,wBAoC/B;AAED,OAAO,EAAE,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"errorHandler.d.ts","sourceRoot":"","sources":["../../src/services/errorHandler.ts"],"names":[],"mappings":"AAgBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,iBAAS,YAAY,CAAC,KAAK,EAAE,GAAG,GAAG,QAAQ,CAsC1C;AAED,OAAO,EAAE,YAAY,EAAE,CAAC"}