@arkyn/server 2.0.1-beta.8 → 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 +13 -6
  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 -21
  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
@@ -12,6 +12,47 @@ import { Found } from "../http/successResponses/found";
12
12
  import { NoContent } from "../http/successResponses/noContent";
13
13
  import { Success } from "../http/successResponses/success";
14
14
  import { Updated } from "../http/successResponses/updated";
15
+ /**
16
+ * Handles errors and converts them into appropriate HTTP responses.
17
+ *
18
+ * This function takes an error object and determines its type to return
19
+ * the corresponding HTTP response. It supports both success and error
20
+ * response types, converting them into a standardized format using the
21
+ * `toResponse` method when applicable.
22
+ *
23
+ * @param error - The error object to handle. It can be an instance of various
24
+ * HTTP response classes or a generic error.
25
+ *
26
+ * @returns The corresponding HTTP response object if the error matches a known
27
+ * type, or `undefined` if no match is found.
28
+ *
29
+ * ### Supported Success Responses:
30
+ * - `Found`
31
+ * - `Created`
32
+ * - `Updated`
33
+ * - `Success`
34
+ * - `NoContent`
35
+ *
36
+ * ### Supported Error Responses:
37
+ * - `BadGateway`
38
+ * - `BadRequest`
39
+ * - `Conflict`
40
+ * - `Forbidden`
41
+ * - `NotFound`
42
+ * - `NotImplemented`
43
+ * - `ServerError`
44
+ * - `Unauthorized`
45
+ * - `UnprocessableEntity`
46
+ *
47
+ * ### Example Usage:
48
+ * ```typescript
49
+ * try {
50
+ * // Some operation that might throw an error
51
+ * } catch (error) {
52
+ * return errorHandler(error);
53
+ * }
54
+ * ```
55
+ */
15
56
  function errorHandler(error) {
16
57
  switch (true) {
17
58
  case error instanceof Response:
@@ -47,5 +88,6 @@ function errorHandler(error) {
47
88
  case error instanceof UnprocessableEntity:
48
89
  return error.toResponse();
49
90
  }
91
+ return new ServerError("Server error").toResponse();
50
92
  }
51
93
  export { errorHandler };
@@ -1 +1 @@
1
- {"version":3,"file":"formParse.d.ts","sourceRoot":"","sources":["../../src/services/formParse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAExE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,iBAAS,SAAS,CAAC,CAAC,SAAS,cAAc,EAAE,CAC3C,QAAQ,EACR,MAAM,EACP,EAAE,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAoB5B;AAED,OAAO,EAAE,SAAS,EAAE,CAAC"}
1
+ {"version":3,"file":"formParse.d.ts","sourceRoot":"","sources":["../../src/services/formParse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAExE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,iBAAS,SAAS,CAAC,CAAC,SAAS,cAAc,EAAE,CAC3C,QAAQ,EACR,MAAM,EACP,EAAE,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAmB5B;AAED,OAAO,EAAE,SAAS,EAAE,CAAC"}
@@ -39,8 +39,10 @@
39
39
  function formParse([formData, schema,]) {
40
40
  const zodResponse = schema.safeParse(formData);
41
41
  if (zodResponse.success === false) {
42
- const errorsArray = Object.entries(zodResponse.error.formErrors.fieldErrors);
43
- const errorsObject = Object.fromEntries(errorsArray.map((item) => [item[0], item[1]?.[0] || "Error"]));
42
+ const errorsObject = Object.fromEntries(zodResponse.error.errors.map((item) => [
43
+ item.path.join("."),
44
+ item.message,
45
+ ]));
44
46
  return {
45
47
  success: zodResponse.success,
46
48
  fieldErrors: errorsObject,
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Retrieves information about the caller of the current function.
3
+ *
4
+ * This function analyzes the stack trace to determine the file path and function name
5
+ * of the caller. It excludes stack trace entries related to the `@arkyn/server` package
6
+ * and attempts to resolve the file path relative to the project root directory.
7
+ *
8
+ * @returns An object containing:
9
+ * - `functionName`: The name of the function that called the current function, or "Unknown function" if it cannot be determined.
10
+ * - `callerInfo`: The file path of the caller relative to the project root, or "Unknown caller" if it cannot be determined.
11
+ */
12
+ declare function getCaller(): {
13
+ functionName: string;
14
+ callerInfo: string;
15
+ };
16
+ export { getCaller };
17
+ //# sourceMappingURL=getCaller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getCaller.d.ts","sourceRoot":"","sources":["../../src/services/getCaller.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AAEH,iBAAS,SAAS;;;EAyCjB;AAED,OAAO,EAAE,SAAS,EAAE,CAAC"}
@@ -0,0 +1,45 @@
1
+ import path from "path";
2
+ /**
3
+ * Retrieves information about the caller of the current function.
4
+ *
5
+ * This function analyzes the stack trace to determine the file path and function name
6
+ * of the caller. It excludes stack trace entries related to the `@arkyn/server` package
7
+ * and attempts to resolve the file path relative to the project root directory.
8
+ *
9
+ * @returns An object containing:
10
+ * - `functionName`: The name of the function that called the current function, or "Unknown function" if it cannot be determined.
11
+ * - `callerInfo`: The file path of the caller relative to the project root, or "Unknown caller" if it cannot be determined.
12
+ */
13
+ function getCaller() {
14
+ const projectRoot = process.cwd();
15
+ const error = new Error();
16
+ const stackLines = error.stack?.split("\n").map((line) => line.trim()) || [];
17
+ let callerInfo = "Unknown caller";
18
+ let functionName = "Unknown function";
19
+ const relevantLines = stackLines.filter((line) => !line.includes("@arkyn/server"));
20
+ let foundGetCaller = false;
21
+ for (const line of relevantLines) {
22
+ if (!foundGetCaller) {
23
+ if (line.includes("getCaller")) {
24
+ foundGetCaller = true;
25
+ }
26
+ continue;
27
+ }
28
+ const match = line.match(/at (.+?) \((.+?)\)/) || line.match(/at (.+)/);
29
+ if (match) {
30
+ const rawFuncName = match[1]?.split(" ")[0] || "";
31
+ functionName =
32
+ rawFuncName && !rawFuncName.includes("/")
33
+ ? rawFuncName
34
+ : "Unknown function";
35
+ let fullPath = match[2] || match[1];
36
+ if (fullPath.startsWith(projectRoot)) {
37
+ fullPath = path.relative(projectRoot, fullPath);
38
+ }
39
+ callerInfo = fullPath;
40
+ break;
41
+ }
42
+ }
43
+ return { functionName, callerInfo };
44
+ }
45
+ export { getCaller };
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Logs debug information to the console when in development mode or when the
3
+ * `SHOW_ERRORS_IN_CONSOLE` environment variable is set to "true".
4
+ *
5
+ * This function provides detailed information about the caller function,
6
+ * its location, and the provided body and cause, if any.
7
+ *
8
+ * @param name - A string representing the name or context of the debug log.
9
+ * @param body - The main content or data to be logged.
10
+ * @param cause - (Optional) Additional information or error cause to be logged.
11
+ *
12
+ * @remarks
13
+ * The debug logs are only displayed when the application is running in
14
+ * development mode (`NODE_ENV === "development"`) or when the
15
+ * `SHOW_ERRORS_IN_CONSOLE` environment variable is explicitly set to "true".
16
+ *
17
+ * The logs include:
18
+ * - The name of the debug context.
19
+ * - The caller function name and its location.
20
+ * - The provided body content.
21
+ * - The optional cause, if provided.
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * httpDebug("FetchUserData", { userId: 123 });
26
+ * ```
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * httpDebug("FetchUserDataError", { userId: 123 }, new Error("User not found"));
31
+ * ```
32
+ */
33
+ declare function httpDebug(name: string, body: any, cause?: any): void;
34
+ export { httpDebug };
35
+ //# sourceMappingURL=httpDebug.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"httpDebug.d.ts","sourceRoot":"","sources":["../../src/services/httpDebug.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,iBAAS,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,EAAE,GAAG,QAyBtD;AAED,OAAO,EAAE,SAAS,EAAE,CAAC"}
@@ -0,0 +1,56 @@
1
+ import { InboxFlowInstance } from "../config/inboxFlowInstance";
2
+ import { getCaller } from "../services/getCaller";
3
+ /**
4
+ * Logs debug information to the console when in development mode or when the
5
+ * `SHOW_ERRORS_IN_CONSOLE` environment variable is set to "true".
6
+ *
7
+ * This function provides detailed information about the caller function,
8
+ * its location, and the provided body and cause, if any.
9
+ *
10
+ * @param name - A string representing the name or context of the debug log.
11
+ * @param body - The main content or data to be logged.
12
+ * @param cause - (Optional) Additional information or error cause to be logged.
13
+ *
14
+ * @remarks
15
+ * The debug logs are only displayed when the application is running in
16
+ * development mode (`NODE_ENV === "development"`) or when the
17
+ * `SHOW_ERRORS_IN_CONSOLE` environment variable is explicitly set to "true".
18
+ *
19
+ * The logs include:
20
+ * - The name of the debug context.
21
+ * - The caller function name and its location.
22
+ * - The provided body content.
23
+ * - The optional cause, if provided.
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * httpDebug("FetchUserData", { userId: 123 });
28
+ * ```
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * httpDebug("FetchUserDataError", { userId: 123 }, new Error("User not found"));
33
+ * ```
34
+ */
35
+ function httpDebug(name, body, cause) {
36
+ const isDebugMode = process.env.NODE_ENV === "development" ||
37
+ process.env?.SHOW_ERRORS_IN_CONSOLE === "true";
38
+ if (isDebugMode) {
39
+ const reset = "\x1b[0m";
40
+ const cyan = "\x1b[36m";
41
+ const debugName = `${cyan}[ARKYN-DEBUG]${reset}`;
42
+ const { callerInfo, functionName } = getCaller();
43
+ let consoleData = `${debugName} ${name} initialized\n`;
44
+ consoleData += `${debugName} Caller Function: ${functionName}\n`;
45
+ consoleData += `${debugName} Caller Location: ${callerInfo}\n`;
46
+ consoleData += `${debugName} Body: ${JSON.stringify(body, null, 2)}\n`;
47
+ if (cause) {
48
+ consoleData += `${debugName} Cause: ${JSON.stringify(cause, null, 2)}\n`;
49
+ }
50
+ console.log(consoleData);
51
+ const arkynKeys = InboxFlowInstance.getInboxConfig();
52
+ if (arkynKeys)
53
+ console.log(arkynKeys);
54
+ }
55
+ }
56
+ export { httpDebug };
@@ -0,0 +1,13 @@
1
+ import { Schema, z } from "zod";
2
+ declare class SchemaValidator<T extends Schema> {
3
+ readonly schema: T;
4
+ functionName: string;
5
+ callerInfo: string;
6
+ constructor(schema: T);
7
+ isValid(data: any): boolean;
8
+ safeValidate(data: any): z.SafeParseReturnType<z.infer<T>, z.infer<T>>;
9
+ validate(data: any): z.infer<T>;
10
+ formValidate(data: any, message?: string): z.infer<T>;
11
+ }
12
+ export { SchemaValidator };
13
+ //# sourceMappingURL=schemaValidator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemaValidator.d.ts","sourceRoot":"","sources":["../../src/services/schemaValidator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAiBhC,cAAM,eAAe,CAAC,CAAC,SAAS,MAAM;IAIxB,QAAQ,CAAC,MAAM,EAAE,CAAC;IAH9B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;gBAEE,MAAM,EAAE,CAAC;IAM9B,OAAO,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO;IAI3B,YAAY,CAAC,IAAI,EAAE,GAAG,GAAG,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAItE,QAAQ,CAAC,IAAI,EAAE,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IAQ/B,YAAY,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;CAoBtD;AAED,OAAO,EAAE,eAAe,EAAE,CAAC"}
@@ -0,0 +1,51 @@
1
+ import { Schema, z } from "zod";
2
+ import { ServerError } from "../http/badResponses/serverError";
3
+ import { UnprocessableEntity } from "../http/badResponses/unprocessableEntity";
4
+ import { formParse } from "./formParse";
5
+ import { getCaller } from "./getCaller";
6
+ import { httpDebug } from "./httpDebug";
7
+ function formatErrorMessage(error) {
8
+ const title = "Error validating:";
9
+ const lines = error.issues.map(({ path, message }) => `-> ${path.join(".")}: ${message}`);
10
+ return [title, ...lines].join("\n");
11
+ }
12
+ class SchemaValidator {
13
+ schema;
14
+ functionName;
15
+ callerInfo;
16
+ constructor(schema) {
17
+ this.schema = schema;
18
+ const { callerInfo, functionName } = getCaller();
19
+ this.callerInfo = callerInfo;
20
+ this.functionName = functionName;
21
+ }
22
+ isValid(data) {
23
+ return this.schema.safeParse(data).success;
24
+ }
25
+ safeValidate(data) {
26
+ return this.schema.safeParse(data);
27
+ }
28
+ validate(data) {
29
+ try {
30
+ return this.schema.parse(data);
31
+ }
32
+ catch (error) {
33
+ throw new ServerError(formatErrorMessage(error));
34
+ }
35
+ }
36
+ formValidate(data, message) {
37
+ const formParsed = formParse([data, this.schema]);
38
+ if (!formParsed.success) {
39
+ httpDebug("UnprocessableEntity", formParsed);
40
+ const firstErrorKey = Object.keys(formParsed.fieldErrors)[0];
41
+ throw new UnprocessableEntity({
42
+ fields: formParsed.fields,
43
+ fieldErrors: formParsed.fieldErrors,
44
+ data: { scrollTo: firstErrorKey },
45
+ message,
46
+ }, false);
47
+ }
48
+ return formParsed.data;
49
+ }
50
+ }
51
+ export { SchemaValidator };
package/package.json CHANGED
@@ -1,24 +1,31 @@
1
1
  {
2
2
  "name": "@arkyn/server",
3
- "version": "2.0.1-beta.8",
3
+ "version": "2.0.1",
4
4
  "main": "./dist/bundle.js",
5
5
  "module": "./src/index.ts",
6
6
  "type": "module",
7
7
  "types": "./dist/index.d.ts",
8
+ "license": "Apache-2.0",
9
+ "author": "Arkyn | Lucas Gonçalves",
10
+ "description": "Server-side utilities for projects.",
8
11
  "scripts": {
9
12
  "clean": "rm -rf dist",
10
13
  "build": "bun run clean && bunx tsc --project tsconfig.json",
14
+ "test": "vitest --config vitest.config.ts",
11
15
  "typecheck": "bunx tsc --project tsconfig.json --noEmit"
12
16
  },
13
17
  "dependencies": {
14
- "@arkyn/server": "*",
15
18
  "@arkyn/shared": "*",
16
- "@aws-sdk/client-s3": "^3.775.0",
17
- "@remix-run/node": "^2.16.2",
18
- "sharp": "^0.33.5"
19
+ "@aws-sdk/client-s3": "^3.782.0",
20
+ "sharp": "^0.33.5",
21
+ "zod": "^3.24.2"
22
+ },
23
+ "peerDependencies": {
24
+ "@remix-run/node": "^2.16.4"
19
25
  },
20
26
  "devDependencies": {
21
27
  "bun-types": "latest",
22
- "typescript": "^5.8.2"
28
+ "vitest": "^3.1.1",
29
+ "typescript": "^5.8.3"
23
30
  }
24
31
  }
@@ -0,0 +1,107 @@
1
+ import { describe, it, expect, vi } from "vitest";
2
+ import { deleteRequest } from "../deleteRequest";
3
+
4
+ global.fetch = vi.fn() as any;
5
+
6
+ describe("deleteRequest", () => {
7
+ it("should return success response for a successfully delete request", async () => {
8
+ const mockResponse = { message: "Resource deleted successfully" };
9
+ (fetch as any).mockResolvedValueOnce({
10
+ ok: true,
11
+ status: 200,
12
+ json: async () => mockResponse,
13
+ });
14
+
15
+ const response = await deleteRequest("https://api.example.com/resource");
16
+
17
+ expect(response).toEqual({
18
+ success: true,
19
+ status: 200,
20
+ message: "Resource deleted successfully",
21
+ response: mockResponse,
22
+ cause: null,
23
+ });
24
+ });
25
+
26
+ it("should return failed response for a failed delete request", async () => {
27
+ const mockErrorResponse = { error: "Resource not found" };
28
+
29
+ (fetch as any).mockResolvedValueOnce({
30
+ ok: false,
31
+ status: 404,
32
+ json: async () => mockErrorResponse,
33
+ });
34
+
35
+ const response = await deleteRequest("https://api.example.com/resource");
36
+
37
+ expect(response.success).toBe(false);
38
+ expect(response.status).toBe(404);
39
+ expect(response.response).toEqual(mockErrorResponse);
40
+ expect(response.message).toBeDefined();
41
+ });
42
+
43
+ it("should handle network errors gracefully", async () => {
44
+ (fetch as any).mockRejectedValueOnce(new Error("Network Error"));
45
+
46
+ const response = await deleteRequest("https://api.example.com/resource");
47
+
48
+ expect(response).toEqual({
49
+ success: false,
50
+ status: 0,
51
+ message: "Network error or request failed",
52
+ response: null,
53
+ cause: "Network Error",
54
+ });
55
+ });
56
+
57
+ it("should handle invalid JSON response gracefully", async () => {
58
+ (fetch as any).mockResolvedValueOnce({
59
+ ok: true,
60
+ status: 200,
61
+ json: async () => {
62
+ throw new Error("Invalid JSON");
63
+ },
64
+ });
65
+
66
+ const response = await deleteRequest("https://api.example.com/resource");
67
+
68
+ expect(response).toEqual({
69
+ success: true,
70
+ status: 200,
71
+ message: "Resource deleted successfully",
72
+ response: null,
73
+ cause: null,
74
+ });
75
+ });
76
+
77
+ it("should send a body with the delete request if provided", async () => {
78
+ const mockResponse = { message: "Resource deleted successfully" };
79
+ const mockBody = { reason: "No longer needed" };
80
+
81
+ (fetch as any).mockResolvedValueOnce({
82
+ ok: true,
83
+ status: 200,
84
+ json: async () => mockResponse,
85
+ });
86
+
87
+ const response = await deleteRequest(
88
+ "https://api.example.com/resource",
89
+ { "Content-Type": "application/json" },
90
+ mockBody
91
+ );
92
+
93
+ expect(fetch).toHaveBeenCalledWith("https://api.example.com/resource", {
94
+ method: "DELETE",
95
+ headers: { "Content-Type": "application/json" },
96
+ body: JSON.stringify(mockBody),
97
+ });
98
+
99
+ expect(response).toEqual({
100
+ success: true,
101
+ status: 200,
102
+ message: "Resource deleted successfully",
103
+ response: mockResponse,
104
+ cause: null,
105
+ });
106
+ });
107
+ });
@@ -0,0 +1,76 @@
1
+ import { describe, it, expect, vi } from "vitest";
2
+ import { getRequest } from "../getRequest";
3
+
4
+ global.fetch = vi.fn() as any;
5
+
6
+ describe("getRequest", () => {
7
+ it("should return success response for a successful request", async () => {
8
+ const mockResponse = { message: "Request successful", data: { id: 1 } };
9
+ (fetch as any).mockResolvedValueOnce({
10
+ ok: true,
11
+ status: 200,
12
+ json: async () => mockResponse,
13
+ });
14
+
15
+ const response = await getRequest("https://api.example.com/resource");
16
+
17
+ expect(response).toEqual({
18
+ success: true,
19
+ status: 200,
20
+ message: "Request successful",
21
+ response: mockResponse,
22
+ cause: null,
23
+ });
24
+ });
25
+
26
+ it("should return failed response for a failed request", async () => {
27
+ const mockErrorResponse = { error: "Not Found" };
28
+
29
+ (fetch as any).mockResolvedValueOnce({
30
+ ok: false,
31
+ status: 404,
32
+ json: async () => mockErrorResponse,
33
+ });
34
+
35
+ const response = await getRequest("https://api.example.com/resource");
36
+
37
+ expect(response.success).toBe(false);
38
+ expect(response.status).toBe(404);
39
+ expect(response.response).toEqual(mockErrorResponse);
40
+ expect(response.message).toBeDefined();
41
+ });
42
+
43
+ it("should handle network errors gracefully", async () => {
44
+ (fetch as any).mockRejectedValueOnce(new Error("Network Error"));
45
+
46
+ const response = await getRequest("https://api.example.com/resource");
47
+
48
+ expect(response).toEqual({
49
+ success: false,
50
+ status: 0,
51
+ message: "Network error or request failed",
52
+ response: null,
53
+ cause: "Network Error",
54
+ });
55
+ });
56
+
57
+ it("should handle invalid JSON response gracefully", async () => {
58
+ (fetch as any).mockResolvedValueOnce({
59
+ ok: true,
60
+ status: 200,
61
+ json: async () => {
62
+ throw new Error("Invalid JSON");
63
+ },
64
+ });
65
+
66
+ const response = await getRequest("https://api.example.com/resource");
67
+
68
+ expect(response).toEqual({
69
+ success: true,
70
+ status: 200,
71
+ message: "Request successful",
72
+ response: null,
73
+ cause: null,
74
+ });
75
+ });
76
+ });
@@ -0,0 +1,125 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { inboxFlowRequest } from "../inboxFlowRequest";
3
+ import { InboxFlowInstance } from "../../config/inboxFlowInstance";
4
+ import { httpDebug } from "../../services/httpDebug";
5
+
6
+ vi.mock("../../config/inboxFlowInstance");
7
+ vi.mock("../../services/httpDebug");
8
+
9
+ global.fetch = vi.fn() as any;
10
+
11
+ describe("inboxFlowRequest", () => {
12
+ beforeEach(() => {
13
+ vi.clearAllMocks();
14
+ });
15
+
16
+ it("should send a POST request with correct body and headers", async () => {
17
+ const mockConfig = {
18
+ status: 200,
19
+ method: "POST" as any,
20
+ request: "Request data",
21
+ response: "Response data",
22
+ token: "test-token",
23
+ };
24
+
25
+ const mockInboxConfig = {
26
+ inboxChannelId: "channel-id",
27
+ inboxUserToken: "user-token",
28
+ inboxApiUrl: "https://api.example.com/inbox",
29
+ };
30
+
31
+ (InboxFlowInstance.getInboxConfig as any).mockReturnValue(mockInboxConfig);
32
+
33
+ (fetch as any).mockResolvedValueOnce({
34
+ ok: true,
35
+ status: 200,
36
+ });
37
+
38
+ await inboxFlowRequest(mockConfig);
39
+
40
+ expect(fetch).toHaveBeenCalledWith(mockInboxConfig.inboxApiUrl, {
41
+ method: "POST",
42
+ body: JSON.stringify({
43
+ status: mockConfig.status,
44
+ channelId: mockInboxConfig.inboxChannelId,
45
+ method: mockConfig.method,
46
+ token: mockConfig.token,
47
+ request: mockConfig.request,
48
+ response: mockConfig.response,
49
+ }),
50
+ headers: {
51
+ "Content-Type": "application/json",
52
+ Authorization: `Bearer ${mockInboxConfig.inboxUserToken}`,
53
+ },
54
+ });
55
+ });
56
+
57
+ it("should not send a request if inbox configuration is not set", async () => {
58
+ (InboxFlowInstance.getInboxConfig as any).mockReturnValue(undefined);
59
+
60
+ await inboxFlowRequest({
61
+ status: 200,
62
+ method: "POST",
63
+ request: "Request data",
64
+ response: "Response data",
65
+ token: "test-token",
66
+ });
67
+
68
+ expect(fetch).not.toHaveBeenCalled();
69
+ });
70
+
71
+ it("should handle fetch errors gracefully", async () => {
72
+ const mockConfig = {
73
+ status: 500,
74
+ method: "ERROR" as any,
75
+ request: "Request data",
76
+ response: "Error response",
77
+ token: "test-token",
78
+ };
79
+
80
+ const mockInboxConfig = {
81
+ inboxChannelId: "channel-id",
82
+ inboxUserToken: "user-token",
83
+ inboxApiUrl: "https://api.example.com/inbox",
84
+ };
85
+
86
+ (InboxFlowInstance.getInboxConfig as any).mockReturnValue(mockInboxConfig);
87
+
88
+ (fetch as any).mockRejectedValueOnce(new Error("Network Error"));
89
+
90
+ await inboxFlowRequest(mockConfig);
91
+
92
+ expect(httpDebug).toHaveBeenCalledWith(
93
+ "inboxFlowRequest",
94
+ "Error sending inbox flow request",
95
+ expect.any(Error)
96
+ );
97
+ });
98
+
99
+ it("should not send a request in development environment", async () => {
100
+ const originalEnv = process.env.NODE_ENV;
101
+ process.env.NODE_ENV = "development";
102
+
103
+ const mockConfig = {
104
+ status: 200,
105
+ method: "POST" as any,
106
+ request: "Request data",
107
+ response: "Response data",
108
+ token: "test-token",
109
+ };
110
+
111
+ const mockInboxConfig = {
112
+ inboxChannelId: "channel-id",
113
+ inboxUserToken: "user-token",
114
+ inboxApiUrl: "https://api.example.com/inbox",
115
+ };
116
+
117
+ (InboxFlowInstance.getInboxConfig as any).mockReturnValue(mockInboxConfig);
118
+
119
+ await inboxFlowRequest(mockConfig);
120
+
121
+ expect(fetch).not.toHaveBeenCalled();
122
+
123
+ process.env.NODE_ENV = originalEnv;
124
+ });
125
+ });