@arkyn/server 3.0.1-beta.20 → 3.0.1-beta.200

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/README.md +423 -69
  2. package/dist/{api/arkynLogRequest.d.ts → http/api/_logRequest.d.ts} +22 -19
  3. package/dist/{api/arkynLogRequest.d.ts.map → http/api/_logRequest.d.ts.map} +1 -1
  4. package/dist/http/api/_makeRequest.d.ts +61 -0
  5. package/dist/http/api/_makeRequest.d.ts.map +1 -0
  6. package/dist/http/api/deleteRequest.d.ts +17 -0
  7. package/dist/http/api/deleteRequest.d.ts.map +1 -0
  8. package/dist/http/api/getRequest.d.ts +16 -0
  9. package/dist/http/api/getRequest.d.ts.map +1 -0
  10. package/dist/http/api/patchRequest.d.ts +17 -0
  11. package/dist/http/api/patchRequest.d.ts.map +1 -0
  12. package/dist/http/api/postRequest.d.ts +17 -0
  13. package/dist/http/api/postRequest.d.ts.map +1 -0
  14. package/dist/http/api/putRequest.d.ts +17 -0
  15. package/dist/http/api/putRequest.d.ts.map +1 -0
  16. package/dist/http/badResponses/_badResponse.d.ts +25 -0
  17. package/dist/http/badResponses/_badResponse.d.ts.map +1 -0
  18. package/dist/http/badResponses/badGateway.d.ts +14 -24
  19. package/dist/http/badResponses/badGateway.d.ts.map +1 -1
  20. package/dist/http/badResponses/badRequest.d.ts +12 -24
  21. package/dist/http/badResponses/badRequest.d.ts.map +1 -1
  22. package/dist/http/badResponses/conflict.d.ts +12 -24
  23. package/dist/http/badResponses/conflict.d.ts.map +1 -1
  24. package/dist/http/badResponses/forbidden.d.ts +12 -24
  25. package/dist/http/badResponses/forbidden.d.ts.map +1 -1
  26. package/dist/http/badResponses/notFound.d.ts +12 -24
  27. package/dist/http/badResponses/notFound.d.ts.map +1 -1
  28. package/dist/http/badResponses/notImplemented.d.ts +12 -24
  29. package/dist/http/badResponses/notImplemented.d.ts.map +1 -1
  30. package/dist/http/badResponses/serverError.d.ts +12 -24
  31. package/dist/http/badResponses/serverError.d.ts.map +1 -1
  32. package/dist/http/badResponses/unauthorized.d.ts +12 -24
  33. package/dist/http/badResponses/unauthorized.d.ts.map +1 -1
  34. package/dist/http/badResponses/unprocessableEntity.d.ts +25 -34
  35. package/dist/http/badResponses/unprocessableEntity.d.ts.map +1 -1
  36. package/dist/http/successResponses/_successResponse.d.ts +36 -0
  37. package/dist/http/successResponses/_successResponse.d.ts.map +1 -0
  38. package/dist/http/successResponses/created.d.ts +12 -26
  39. package/dist/http/successResponses/created.d.ts.map +1 -1
  40. package/dist/http/successResponses/found.d.ts +12 -29
  41. package/dist/http/successResponses/found.d.ts.map +1 -1
  42. package/dist/http/successResponses/noContent.d.ts +12 -17
  43. package/dist/http/successResponses/noContent.d.ts.map +1 -1
  44. package/dist/http/successResponses/success.d.ts +12 -26
  45. package/dist/http/successResponses/success.d.ts.map +1 -1
  46. package/dist/http/successResponses/updated.d.ts +13 -26
  47. package/dist/http/successResponses/updated.d.ts.map +1 -1
  48. package/dist/index.d.ts +19 -10
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +1067 -28
  51. package/dist/modules/http/api/_logRequest.js +56 -0
  52. package/dist/modules/http/api/_makeRequest.js +70 -0
  53. package/dist/modules/http/api/deleteRequest.js +13 -0
  54. package/dist/modules/http/api/getRequest.js +12 -0
  55. package/dist/modules/http/api/patchRequest.js +13 -0
  56. package/dist/modules/http/api/postRequest.js +13 -0
  57. package/dist/modules/http/api/putRequest.js +13 -0
  58. package/dist/modules/http/badResponses/_badResponse.js +63 -0
  59. package/dist/modules/http/badResponses/badGateway.js +24 -0
  60. package/dist/modules/http/badResponses/badRequest.js +24 -0
  61. package/dist/modules/http/badResponses/conflict.js +24 -0
  62. package/dist/modules/http/badResponses/forbidden.js +24 -0
  63. package/dist/modules/http/badResponses/notFound.js +24 -0
  64. package/dist/modules/http/badResponses/notImplemented.js +24 -0
  65. package/dist/modules/http/badResponses/serverError.js +24 -0
  66. package/dist/modules/http/badResponses/unauthorized.js +24 -0
  67. package/dist/modules/http/badResponses/unprocessableEntity.js +28 -0
  68. package/dist/modules/http/successResponses/_successResponse.js +62 -0
  69. package/dist/modules/http/successResponses/created.js +24 -0
  70. package/dist/modules/http/successResponses/found.js +24 -0
  71. package/dist/modules/http/successResponses/noContent.js +17 -0
  72. package/dist/modules/http/successResponses/success.js +24 -0
  73. package/dist/modules/http/successResponses/updated.js +24 -0
  74. package/dist/modules/index.js +34 -0
  75. package/dist/modules/services/apiService.js +109 -0
  76. package/dist/modules/services/debugService.js +36 -0
  77. package/dist/modules/services/logMapperService.js +31 -0
  78. package/dist/modules/services/logService.js +21 -0
  79. package/dist/modules/utilities/decodeRequestBody.js +20 -0
  80. package/dist/modules/utilities/decodeRequestErrorMessage.js +6 -0
  81. package/dist/modules/utilities/errorHandler.js +39 -0
  82. package/dist/modules/utilities/flushDebugLogs.js +16 -0
  83. package/dist/modules/utilities/formAsyncParse.js +14 -0
  84. package/dist/modules/utilities/formParse.js +14 -0
  85. package/dist/modules/utilities/getScopedParams.js +9 -0
  86. package/dist/modules/utilities/schemaValidator.js +55 -0
  87. package/dist/modules/validations/validateCep.js +9 -0
  88. package/dist/modules/validations/validateCnpj.js +54 -0
  89. package/dist/modules/validations/validateCpf.js +27 -0
  90. package/dist/modules/validations/validateDate.js +26 -0
  91. package/dist/modules/validations/validateEmail.js +54 -0
  92. package/dist/modules/validations/validatePassword.js +12 -0
  93. package/dist/modules/validations/validatePhone.js +10 -0
  94. package/dist/modules/validations/validateRg.js +8 -0
  95. package/dist/services/apiService.d.ts +83 -0
  96. package/dist/services/apiService.d.ts.map +1 -0
  97. package/dist/services/debugService.d.ts +37 -0
  98. package/dist/services/debugService.d.ts.map +1 -0
  99. package/dist/services/logMapperService.d.ts +86 -0
  100. package/dist/services/logMapperService.d.ts.map +1 -0
  101. package/dist/services/logService.d.ts +33 -0
  102. package/dist/services/logService.d.ts.map +1 -0
  103. package/dist/utilities/decodeRequestBody.d.ts +18 -0
  104. package/dist/utilities/decodeRequestBody.d.ts.map +1 -0
  105. package/dist/utilities/decodeRequestErrorMessage.d.ts +19 -0
  106. package/dist/utilities/decodeRequestErrorMessage.d.ts.map +1 -0
  107. package/dist/utilities/errorHandler.d.ts +25 -0
  108. package/dist/utilities/errorHandler.d.ts.map +1 -0
  109. package/dist/utilities/flushDebugLogs.d.ts +24 -0
  110. package/dist/utilities/flushDebugLogs.d.ts.map +1 -0
  111. package/dist/utilities/formAsyncParse.d.ts +38 -0
  112. package/dist/utilities/formAsyncParse.d.ts.map +1 -0
  113. package/dist/utilities/formParse.d.ts +38 -0
  114. package/dist/utilities/formParse.d.ts.map +1 -0
  115. package/dist/utilities/getScopedParams.d.ts +19 -0
  116. package/dist/utilities/getScopedParams.d.ts.map +1 -0
  117. package/dist/utilities/schemaValidator.d.ts +75 -0
  118. package/dist/utilities/schemaValidator.d.ts.map +1 -0
  119. package/dist/validations/validateCep.d.ts +19 -0
  120. package/dist/validations/validateCep.d.ts.map +1 -0
  121. package/dist/validations/validateCnpj.d.ts +21 -0
  122. package/dist/validations/validateCnpj.d.ts.map +1 -0
  123. package/dist/validations/validateCpf.d.ts +16 -0
  124. package/dist/validations/validateCpf.d.ts.map +1 -0
  125. package/dist/validations/validateDate.d.ts +23 -0
  126. package/dist/validations/validateDate.d.ts.map +1 -0
  127. package/dist/validations/validateEmail.d.ts +21 -0
  128. package/dist/validations/validateEmail.d.ts.map +1 -0
  129. package/dist/validations/validatePassword.d.ts +20 -0
  130. package/dist/validations/validatePassword.d.ts.map +1 -0
  131. package/dist/validations/validatePhone.d.ts +16 -0
  132. package/dist/validations/validatePhone.d.ts.map +1 -0
  133. package/dist/validations/validateRg.d.ts +21 -0
  134. package/dist/validations/validateRg.d.ts.map +1 -0
  135. package/package.json +222 -15
  136. package/dist/api/arkynLogRequest.js +0 -82
  137. package/dist/api/deleteRequest.d.ts +0 -13
  138. package/dist/api/deleteRequest.d.ts.map +0 -1
  139. package/dist/api/deleteRequest.js +0 -14
  140. package/dist/api/getRequest.d.ts +0 -12
  141. package/dist/api/getRequest.d.ts.map +0 -1
  142. package/dist/api/getRequest.js +0 -13
  143. package/dist/api/makeRequest.d.ts +0 -38
  144. package/dist/api/makeRequest.d.ts.map +0 -1
  145. package/dist/api/makeRequest.js +0 -103
  146. package/dist/api/patchRequest.d.ts +0 -13
  147. package/dist/api/patchRequest.d.ts.map +0 -1
  148. package/dist/api/patchRequest.js +0 -14
  149. package/dist/api/postRequest.d.ts +0 -13
  150. package/dist/api/postRequest.d.ts.map +0 -1
  151. package/dist/api/postRequest.js +0 -14
  152. package/dist/api/putRequest.d.ts +0 -13
  153. package/dist/api/putRequest.d.ts.map +0 -1
  154. package/dist/api/putRequest.js +0 -14
  155. package/dist/config/apiInstance.d.ts +0 -80
  156. package/dist/config/apiInstance.d.ts.map +0 -1
  157. package/dist/config/apiInstance.js +0 -111
  158. package/dist/config/arkynLogInstance.d.ts +0 -44
  159. package/dist/config/arkynLogInstance.d.ts.map +0 -1
  160. package/dist/config/arkynLogInstance.js +0 -49
  161. package/dist/http/badResponses/badGateway.js +0 -52
  162. package/dist/http/badResponses/badRequest.js +0 -52
  163. package/dist/http/badResponses/conflict.js +0 -52
  164. package/dist/http/badResponses/forbidden.js +0 -52
  165. package/dist/http/badResponses/notFound.js +0 -52
  166. package/dist/http/badResponses/notImplemented.js +0 -52
  167. package/dist/http/badResponses/serverError.js +0 -52
  168. package/dist/http/badResponses/unauthorized.js +0 -52
  169. package/dist/http/badResponses/unprocessableEntity.js +0 -60
  170. package/dist/http/successResponses/created.js +0 -54
  171. package/dist/http/successResponses/found.js +0 -57
  172. package/dist/http/successResponses/noContent.js +0 -35
  173. package/dist/http/successResponses/success.js +0 -54
  174. package/dist/http/successResponses/updated.js +0 -54
  175. package/dist/mapper/arkynLogRequestMapper.d.ts +0 -30
  176. package/dist/mapper/arkynLogRequestMapper.d.ts.map +0 -1
  177. package/dist/mapper/arkynLogRequestMapper.js +0 -44
  178. package/dist/services/decodeErrorMessageFromRequest.d.ts +0 -17
  179. package/dist/services/decodeErrorMessageFromRequest.d.ts.map +0 -1
  180. package/dist/services/decodeErrorMessageFromRequest.js +0 -30
  181. package/dist/services/decodeRequestBody.d.ts +0 -17
  182. package/dist/services/decodeRequestBody.d.ts.map +0 -1
  183. package/dist/services/decodeRequestBody.js +0 -38
  184. package/dist/services/errorHandler.d.ts +0 -44
  185. package/dist/services/errorHandler.d.ts.map +0 -1
  186. package/dist/services/errorHandler.js +0 -93
  187. package/dist/services/formParse.d.ts +0 -59
  188. package/dist/services/formParse.d.ts.map +0 -1
  189. package/dist/services/formParse.js +0 -59
  190. package/dist/services/getCaller.d.ts +0 -17
  191. package/dist/services/getCaller.d.ts.map +0 -1
  192. package/dist/services/getCaller.js +0 -65
  193. package/dist/services/getScopedParams.d.ts +0 -28
  194. package/dist/services/getScopedParams.d.ts.map +0 -1
  195. package/dist/services/getScopedParams.js +0 -34
  196. package/dist/services/httpDebug.d.ts +0 -35
  197. package/dist/services/httpDebug.d.ts.map +0 -1
  198. package/dist/services/httpDebug.js +0 -52
  199. package/dist/services/measureRouteExecution.d.ts +0 -3
  200. package/dist/services/measureRouteExecution.d.ts.map +0 -1
  201. package/dist/services/measureRouteExecution.js +0 -24
  202. package/dist/services/schemaValidator.d.ts +0 -13
  203. package/dist/services/schemaValidator.d.ts.map +0 -1
  204. package/dist/services/schemaValidator.js +0 -51
  205. package/dist/types/ApiResponseDTO.d.ts +0 -17
  206. package/dist/types/ApiResponseDTO.d.ts.map +0 -1
  207. package/dist/types/ApiResponseDTO.js +0 -1
  208. package/src/api/arkynLogRequest.ts +0 -118
  209. package/src/api/deleteRequest.ts +0 -22
  210. package/src/api/getRequest.ts +0 -20
  211. package/src/api/makeRequest.ts +0 -118
  212. package/src/api/patchRequest.ts +0 -22
  213. package/src/api/postRequest.ts +0 -22
  214. package/src/api/putRequest.ts +0 -22
  215. package/src/config/apiInstance.ts +0 -148
  216. package/src/config/arkynLogInstance.ts +0 -70
  217. package/src/http/badResponses/badGateway.ts +0 -63
  218. package/src/http/badResponses/badRequest.ts +0 -63
  219. package/src/http/badResponses/conflict.ts +0 -63
  220. package/src/http/badResponses/forbidden.ts +0 -63
  221. package/src/http/badResponses/notFound.ts +0 -63
  222. package/src/http/badResponses/notImplemented.ts +0 -63
  223. package/src/http/badResponses/serverError.ts +0 -63
  224. package/src/http/badResponses/unauthorized.ts +0 -63
  225. package/src/http/badResponses/unprocessableEntity.ts +0 -79
  226. package/src/http/successResponses/created.ts +0 -64
  227. package/src/http/successResponses/found.ts +0 -67
  228. package/src/http/successResponses/noContent.ts +0 -42
  229. package/src/http/successResponses/success.ts +0 -64
  230. package/src/http/successResponses/updated.ts +0 -64
  231. package/src/index.ts +0 -31
  232. package/src/mapper/arkynLogRequestMapper.ts +0 -73
  233. package/src/services/decodeErrorMessageFromRequest.ts +0 -36
  234. package/src/services/decodeRequestBody.ts +0 -43
  235. package/src/services/errorHandler.ts +0 -99
  236. package/src/services/formParse.ts +0 -86
  237. package/src/services/getCaller.ts +0 -82
  238. package/src/services/getScopedParams.ts +0 -43
  239. package/src/services/httpDebug.ts +0 -61
  240. package/src/services/measureRouteExecution.ts +0 -31
  241. package/src/services/schemaValidator.ts +0 -66
  242. package/src/types/ApiResponseDTO.ts +0 -19
  243. package/tsconfig.json +0 -21
  244. package/vitest.config.ts +0 -5
package/README.md CHANGED
@@ -1,116 +1,470 @@
1
- The `@arkyn/server` package provides utilities and services to streamline backend application development. It includes API configurations, HTTP error handlers, and various services for file manipulation.
1
+ # @arkyn/server
2
2
 
3
- ---
3
+ Comprehensive server-side utilities for building robust backend applications, featuring HTTP response helpers, error handlers, request utilities, and API configurations.
4
4
 
5
- ## Installation
5
+ [![npm version](https://img.shields.io/npm/v/@arkyn/server.svg)](https://www.npmjs.com/package/@arkyn/server)
6
+ [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
7
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
6
8
 
7
- Install the package using npm:
9
+ ## 🎯 What it solves
10
+
11
+ Backend code — Remix/React Router loaders and actions, or any fetch-based server — tends to reinvent the same plumbing on every project: consistent success/error response shapes, centralized error handling, request body/form parsing, schema validation, and validation of Brazilian documents (CPF/CNPJ/CEP/RG) plus generic fields (email/password/phone/date). `@arkyn/server` packages all of that into small, well-typed primitives so route handlers stay focused on business logic instead of response boilerplate.
12
+
13
+ ## ✨ Features
14
+
15
+ - 🌐 **HTTP success responses** - `Success`, `Created`, `Updated`, `Found`, `NoContent` with `.toResponse()` / `.toJson()`
16
+ - 🚨 **HTTP error responses** - `BadRequest`, `Unauthorized`, `Forbidden`, `NotFound`, `Conflict`, `UnprocessableEntity`, `ServerError`, `BadGateway`, `NotImplemented`
17
+ - 🧵 **Request utilities** - body decoding, scoped query params, form parsing (sync/async), error-message extraction
18
+ - 🧪 **Schema validation via Zod** - `SchemaValidator` and the underlying `formParse` / `formAsyncParse` helpers
19
+ - 🇧🇷 **Brazilian document validators** - `validateCpf`, `validateCnpj`, `validateCep`, `validateRg`
20
+ - 🔤 **Generic validators** - `validateEmail`, `validatePassword`, `validatePhone`, `validateDate`
21
+ - 🛠️ **Debug & logging services** - `DebugService`, `LogService`, `flushDebugLogs`, plus `ApiService` for outbound HTTP calls
22
+
23
+ ## 📋 Prerequisites
24
+
25
+ - **Node.js** `>=24.16.0` or **Bun** `>=1.3.14`
26
+ - Peer dependencies (install alongside `@arkyn/server`):
27
+ - `zod >=4.4.3` — required by `SchemaValidator`, `formParse`, and `formAsyncParse`.
28
+ - `libphonenumber-js >=1.13.7` — required by `validatePhone`.
29
+
30
+ ## 📦 Installation
8
31
 
9
32
  ```bash
10
- npm install @arkyn/server
33
+ npm install @arkyn/server zod libphonenumber-js
11
34
  ```
12
35
 
13
- ---
36
+ ## 🚀 Quick Start
14
37
 
15
- ## Features
38
+ ```typescript
39
+ import { Success, BadRequest, errorHandler, decodeRequestBody } from "@arkyn/server";
16
40
 
17
- ### Settings
41
+ export async function action({ request }: ActionFunctionArgs) {
42
+ try {
43
+ const body = await decodeRequestBody(request);
18
44
 
19
- - **`ApiInstance`**
20
- Pre-configured instance for API calls.
45
+ if (!body.email) throw new BadRequest("Email is required");
21
46
 
22
- - **`ArkynLogInstance`**
23
- Pre-configured instance for integration with Inbox Flow.
47
+ const user = await createUser(body);
48
+ return new Success("User created", { user }).toJson();
49
+ } catch (error) {
50
+ return errorHandler(error);
51
+ }
52
+ }
53
+ ```
24
54
 
25
- ---
55
+ ## 📖 API Reference
26
56
 
27
- ### HTTP Responses - Errors
57
+ ### HTTP Responses
28
58
 
29
- - **`BadGateway(message: string): Error`**
30
- Represents an HTTP 502 error.
59
+ Every response class extends a base with `.toResponse()` (returns a `Response` with a `Content-Type: application/json` header) and `.toJson()` (built on `Response.json()`). Both produce an equivalent JSON body — pick whichever reads better at the call site. `NoContent` only exposes `.toResponse()`, since it always returns a `null` body.
31
60
 
32
- - **`BadRequest(message: string): Error`**
33
- Represents an HTTP 400 error.
61
+ #### BadGateway
34
62
 
35
- - **`Conflict(message: string): Error`**
36
- Represents an HTTP 409 error.
63
+ HTTP 502 the upstream server returned an invalid or unexpected response.
37
64
 
38
- - **`Forbidden(message: string): Error`**
39
- Represents an HTTP 403 error.
65
+ ```typescript
66
+ throw new BadGateway("Payment gateway unavailable");
67
+ ```
40
68
 
41
- - **`NotFound(message: string): Error`**
42
- Represents an HTTP 404 error.
69
+ #### BadRequest
43
70
 
44
- - **`NotImplemented(message: string): Error`**
45
- Represents an HTTP 501 error.
71
+ HTTP 400 the request is malformed or contains invalid data.
46
72
 
47
- - **`ServerError(message: string): Error`**
48
- Represents an HTTP 500 error.
73
+ ```typescript
74
+ throw new BadRequest("Invalid request body");
75
+ ```
49
76
 
50
- - **`Unauthorized(message: string): Error`**
51
- Represents an HTTP 401 error.
77
+ #### Conflict
52
78
 
53
- - **`UnprocessableEntity(message: string): Error`**
54
- Represents an HTTP 422 error.
79
+ HTTP 409 — the request conflicts with the current state of the server (e.g. duplicate record).
55
80
 
56
- ---
81
+ ```typescript
82
+ throw new Conflict("Email already in use");
83
+ ```
84
+
85
+ #### Forbidden
86
+
87
+ HTTP 403 — authenticated but not authorized to access this resource.
88
+
89
+ ```typescript
90
+ throw new Forbidden("You don't have permission to delete this resource");
91
+ ```
92
+
93
+ #### NotFound
57
94
 
58
- ### HTTP Responses - Success
95
+ HTTP 404 the requested resource does not exist.
59
96
 
60
- - **`Created(data: any): Response`**
61
- Represents an HTTP 201 response.
97
+ ```typescript
98
+ throw new NotFound("Product not found");
99
+ ```
62
100
 
63
- - **`Found(data: any): Response`**
64
- Represents an HTTP 302 response.
101
+ #### NotImplemented
65
102
 
66
- - **`NoContent(): Response`**
67
- Represents an HTTP 204 response.
103
+ HTTP 501 — the server does not support the functionality required to fulfill the request.
68
104
 
69
- - **`Success(data: any): Response`**
70
- Represents an HTTP 200 response.
105
+ ```typescript
106
+ throw new NotImplemented("Webhook delivery is not yet implemented");
107
+ ```
108
+
109
+ #### ServerError
110
+
111
+ HTTP 500 — an unexpected condition prevented the server from fulfilling the request.
112
+
113
+ ```typescript
114
+ throw new ServerError("Failed to connect to the database");
115
+ ```
116
+
117
+ #### Unauthorized
118
+
119
+ HTTP 401 — the request lacks valid authentication credentials.
120
+
121
+ ```typescript
122
+ throw new Unauthorized("Invalid or expired token");
123
+ ```
124
+
125
+ #### UnprocessableEntity
126
+
127
+ HTTP 422 — the request is well-formed but contains semantic validation errors. Typically used for form field validation failures.
128
+
129
+ ```typescript
130
+ throw new UnprocessableEntity({
131
+ message: "Validation failed",
132
+ fieldErrors: { email: "Invalid email format", age: "Must be 18 or older" },
133
+ fields: { email: "not-an-email", age: "15" },
134
+ });
135
+ ```
136
+
137
+ #### Created
138
+
139
+ HTTP 201 — the request succeeded and a new resource was created.
140
+
141
+ ```typescript
142
+ return new Created("User created successfully", { id: user.id }).toJson();
143
+ ```
71
144
 
72
- - **`Updated(data: any): Response`**
73
- Represents an HTTP 200 response for updates.
145
+ #### Found
74
146
 
75
- ---
147
+ HTTP 302 — the resource was located and the response includes it in the body.
148
+
149
+ ```typescript
150
+ return new Found("Products retrieved", { products }).toJson();
151
+ ```
152
+
153
+ #### NoContent
154
+
155
+ HTTP 204 — the request succeeded but there is no content to return. Typically used for delete or update operations where a body is not needed.
156
+
157
+ ```typescript
158
+ return new NoContent("Record deleted").toResponse();
159
+ ```
160
+
161
+ #### Success
162
+
163
+ HTTP 200 — the request succeeded and the response body contains the result.
164
+
165
+ ```typescript
166
+ return new Success("Order fetched", { order }).toJson();
167
+ ```
168
+
169
+ #### Updated
170
+
171
+ HTTP 200 — the request succeeded and the resource was updated. Semantically equivalent to `Success` but signals an update operation to consumers.
172
+
173
+ ```typescript
174
+ return new Updated("Profile updated", { user }).toJson();
175
+ ```
76
176
 
77
177
  ### Services
78
178
 
79
- - **`decodeErrorMessageFromRequest(request: Request): string`**
80
- Decodes error messages from a request.
179
+ #### ApiService
180
+
181
+ HTTP client for external API calls. Wraps `fetch` with a base URL, default headers, an optional auth token, and per-request overrides for `get`, `post`, `put`, `patch`, and `delete`.
182
+
183
+ ```typescript
184
+ const api = new ApiService({
185
+ baseUrl: "https://api.example.com",
186
+ baseToken: session.token,
187
+ enableDebug: true,
188
+ });
189
+
190
+ const { data } = await api.get("/users/me");
191
+ const { data: created } = await api.post("/orders", { body: { productId: 1 } });
192
+ ```
193
+
194
+ #### DebugService
195
+
196
+ Static service that manages stack-trace configuration for debug output, allowing specific adapter/wrapper files to be skipped so logs show the actual business-logic caller. Used internally by the HTTP response classes; `setIgnoreFile` / `clearIgnoreFiles` let you tune it, and `getCaller()` returns `{ functionName, callerInfo }`.
197
+
198
+ ```typescript
199
+ // Skip httpAdapter.ts so debug output shows the calling route instead
200
+ DebugService.setIgnoreFile("httpAdapter.ts");
201
+ ```
202
+
203
+ #### LogService
204
+
205
+ Static service for log endpoint configuration. Stores a singleton configuration containing the traffic source identifier, user token, and log ingestion URL; `setConfig` only applies on the first call, `getConfig` reads it back, and `resetConfig` clears it.
206
+
207
+ ```typescript
208
+ LogService.setConfig({
209
+ trafficSourceId: "my-app",
210
+ userToken: session.token,
211
+ });
212
+
213
+ LogService.getConfig(); // { trafficSourceId, userToken, apiUrl }
214
+ ```
215
+
216
+ ### Utilities
217
+
218
+ #### decodeRequestBody
219
+
220
+ Decodes a request body into a plain object, trying JSON first then URL-encoded form data. Throws `BadRequest` if neither format can be parsed.
221
+
222
+ ```typescript
223
+ export async function action({ request }: ActionFunctionArgs) {
224
+ const body = await decodeRequestBody(request);
225
+ // body is now a plain JS object
226
+ }
227
+ ```
228
+
229
+ #### decodeRequestErrorMessage
230
+
231
+ Extracts a human-readable error message from an API response body or a `Response` object. Checks `data.message`, `data.operator_erro_message`, `data.error`, `data.error.message`, and `response.statusText` in that order, falling back to `"Missing error message"`.
81
232
 
82
- - **`decodeRequestBody(request: Request): any`**
83
- Decodes the body of a request.
233
+ ```typescript
234
+ const res = await fetch("/api/orders");
235
+ const data = await res.json().catch(() => null);
236
+ const message = decodeRequestErrorMessage(data, res);
237
+ ```
84
238
 
85
- - **`errorHandler(error: Error): Response`**
86
- Handles errors and returns an appropriate response.
239
+ #### errorHandler
87
240
 
88
- - **`formParse(request: Request): FormData`**
89
- Parses form data.
241
+ Converts any thrown value into a `Response`. Recognizes all `@arkyn/server` success and error response classes, native `Response` objects, and falls back to a 500 `ServerError` for anything else. Intended to be used as the catch handler of a route action or loader.
242
+
243
+ ```typescript
244
+ export async function action({ request }: ActionFunctionArgs) {
245
+ try {
246
+ const user = await findUser(id);
247
+ if (!user) throw new NotFound("User not found");
248
+ return new Success("User retrieved", { user }).toJson();
249
+ } catch (error) {
250
+ return errorHandler(error);
251
+ }
252
+ }
253
+ ```
254
+
255
+ #### flushDebugLogs
256
+
257
+ Writes colored `[name] message` lines to the console, but only when `NODE_ENV === "development"` or `DEBUG_MODE === "true"`. No-op in production.
258
+
259
+ ```typescript
260
+ flushDebugLogs({
261
+ name: "API",
262
+ scheme: "cyan",
263
+ debugs: ["POST /api/users", "Status: 201"],
264
+ });
265
+ ```
90
266
 
91
- - **`getCaller(): string`**
92
- Returns the name of the function that invoked the method.
267
+ #### formAsyncParse
93
268
 
94
- - **`getScopedParams(request: Request): URLSearchParams`**
95
- Retrieves scoped parameters from a request.
269
+ Async variant of `formParse` — uses `safeParseAsync` to support Zod schemas with async refinements. Returns `{ success: true, data }` on success or `{ success: false, fieldErrors, fields }` on failure.
270
+
271
+ ```typescript
272
+ const schema = z.object({ email: z.string().email() });
273
+ const result = await formAsyncParse([{ email: "bad" }, schema]);
274
+
275
+ if (!result.success) {
276
+ console.log(result.fieldErrors); // { email: "Invalid email" }
277
+ }
278
+ ```
279
+
280
+ #### formParse
281
+
282
+ Validates form data against a Zod schema synchronously. Returns `{ success: true, data }` on success or `{ success: false, fieldErrors, fields }` on failure.
283
+
284
+ ```typescript
285
+ const schema = z.object({ name: z.string().min(1, "Required"), age: z.number().min(18) });
286
+ const result = formParse([{ name: "", age: 15 }, schema]);
287
+
288
+ if (!result.success) {
289
+ console.log(result.fieldErrors); // { name: "Required", age: "..." }
290
+ }
291
+ ```
96
292
 
97
- - **`httpDebug(request: Request): void`**
98
- Displays debug information for an HTTP request.
293
+ #### getScopedParams
99
294
 
100
- - **`SchemaValidator(schema: any, data: any): boolean`**
101
- Validates data against a schema.
295
+ Extracts URL search parameters from a request, optionally filtered by a namespace prefix (e.g. `scope:key` → `key`). Without a scope, returns all search params as-is.
296
+
297
+ ```typescript
298
+ // URL: /products?table:page=2&table:sort=asc&other=1
299
+ const params = getScopedParams(request, "table");
300
+ params.get("page"); // "2"
301
+ params.get("sort"); // "asc"
302
+ ```
303
+
304
+ #### SchemaValidator
305
+
306
+ Wraps a Zod schema with convenience validation methods suited for server-side use: `isValid` (boolean check, never throws), `safeValidate` (raw Zod result, never throws), `validate` (throws `ServerError`, for trusted/internal data), and `formValidate` / `formAsyncValidate` (throw `UnprocessableEntity` with structured field errors, for user-submitted forms).
307
+
308
+ ```typescript
309
+ const validator = new SchemaValidator(z.object({ email: z.string().email() }));
310
+
311
+ // Inside a Remix action:
312
+ const body = validator.formValidate(await decodeRequestBody(request));
313
+ ```
314
+
315
+ ### Validators
316
+
317
+ #### validateCep
318
+
319
+ Validates a Brazilian CEP (postal code). A valid CEP must contain exactly 8 numeric digits, optionally formatted as `"12345-678"`.
320
+
321
+ ```typescript
322
+ validateCep("12345-678"); // true
323
+ validateCep("12345678"); // true
324
+ validateCep("ABCDE-123"); // false
325
+ ```
326
+
327
+ #### validateCnpj
328
+
329
+ Validates a Brazilian CNPJ (Cadastro Nacional da Pessoa Jurídica) number: sanitizes non-digit characters, checks length (14 digits), rejects repeating-digit sequences, and verifies both check digits.
330
+
331
+ ```typescript
332
+ validateCnpj("12.345.678/0001-95"); // false
333
+ validateCnpj("11.444.777/0001-61"); // true
334
+ ```
102
335
 
103
- - **`sendFileToS3(file: File, config: AwsConfig): Promise<{ url: string }>`**
104
- Uploads a file to AWS S3.
336
+ #### validateCpf
105
337
 
106
- ---
338
+ Validates a Brazilian CPF number. Strips formatting, checks length, rejects repeated-digit sequences, and verifies both check digits with the CPF algorithm.
107
339
 
108
- ## Contribution
340
+ ```typescript
341
+ validateCpf("123.456.789-09"); // false
342
+ validateCpf("111.444.777-35"); // true
343
+ ```
344
+
345
+ #### validateDate
346
+
347
+ Validates a date string against a format and optional year bounds. `inputFormat` accepts `"brazilianDate"` (`DD/MM/YYYY`, default), `"isoDate"` (`MM-DD-YYYY`), or `"timestamp"` (`YYYY-MM-DD`); `minYear` defaults to `1900` and `maxYear` to `3000`.
348
+
349
+ ```typescript
350
+ validateDate("31/12/2023"); // true
351
+ validateDate("2023-12-31", { inputFormat: "timestamp", minYear: 2000, maxYear: 2100 }); // true
352
+ validateDate("29/02/2023"); // false (not a leap year)
353
+ ```
354
+
355
+ #### validateEmail
356
+
357
+ Validates an email address comprehensively: basic format, advanced RFC 5322 syntax rules, and DNS resolution (MX/A/AAAA records) of the domain. Async because of the DNS lookup.
358
+
359
+ ```typescript
360
+ await validateEmail("user@gmail.com"); // true
361
+ await validateEmail("user@gmil.com"); // false (invalid domain)
362
+ await validateEmail("invalid-email"); // false (invalid format)
363
+ ```
364
+
365
+ #### validatePassword
366
+
367
+ Validates a password: at least 8 characters, at least 1 uppercase letter, at least 1 letter, at least 1 number, and at least 1 special character.
368
+
369
+ ```typescript
370
+ validatePassword("Senha@123"); // true
371
+ validatePassword("senha123"); // false (no uppercase, no special char)
372
+ ```
373
+
374
+ #### validatePhone
375
+
376
+ Validates an international phone number using `libphonenumber-js`, then confirms the parsed country code is present in the supported countries list.
377
+
378
+ ```typescript
379
+ validatePhone("+5532912345678"); // true (Brazil)
380
+ validatePhone("+55329123456178"); // false (invalid)
381
+ ```
382
+
383
+ #### validateRg
384
+
385
+ Validates a Brazilian RG (Registro Geral) with a generic structural check: removes non-alphanumeric characters, requires a length of 7–9 characters, and optionally allows a trailing letter verifier.
386
+
387
+ ```typescript
388
+ validateRg("12.345.678-9"); // true
389
+ validateRg("MG-12.345.678"); // false (not supported)
390
+ validateRg("12345678X"); // true
391
+ ```
392
+
393
+ ## 🔧 Advanced Usage
394
+
395
+ ### Parse → validate → respond pipeline
396
+
397
+ ```typescript
398
+ import {
399
+ decodeRequestBody,
400
+ SchemaValidator,
401
+ Success,
402
+ errorHandler,
403
+ } from "@arkyn/server";
404
+ import { z } from "zod";
405
+
406
+ const createUserSchema = z.object({
407
+ email: z.string().email(),
408
+ name: z.string().min(2),
409
+ });
410
+
411
+ const userValidator = new SchemaValidator(createUserSchema);
412
+
413
+ export async function action({ request }: ActionFunctionArgs) {
414
+ try {
415
+ const body = await decodeRequestBody(request);
416
+
417
+ // Throws UnprocessableEntity with fieldErrors/fields on failure
418
+ const data = userValidator.formValidate(body);
419
+
420
+ const user = await createUser(data);
421
+ return new Success("User created", { user }).toJson();
422
+ } catch (error) {
423
+ return errorHandler(error);
424
+ }
425
+ }
426
+ ```
427
+
428
+ ### Brazilian document validation before persisting
429
+
430
+ ```typescript
431
+ import {
432
+ decodeRequestBody,
433
+ validateCpf,
434
+ validateEmail,
435
+ UnprocessableEntity,
436
+ Created,
437
+ errorHandler,
438
+ } from "@arkyn/server";
439
+
440
+ export async function action({ request }: ActionFunctionArgs) {
441
+ try {
442
+ const body = await decodeRequestBody(request);
443
+ const fieldErrors: Record<string, string> = {};
444
+
445
+ if (!validateCpf(body.cpf)) fieldErrors.cpf = "Invalid CPF";
446
+ if (!(await validateEmail(body.email))) fieldErrors.email = "Invalid email";
447
+
448
+ if (Object.keys(fieldErrors).length > 0) {
449
+ throw new UnprocessableEntity({
450
+ message: "Validation failed",
451
+ fieldErrors,
452
+ fields: body,
453
+ });
454
+ }
455
+
456
+ const customer = await createCustomer(body);
457
+ return new Created("Customer created", { customer }).toJson();
458
+ } catch (error) {
459
+ return errorHandler(error);
460
+ }
461
+ }
462
+ ```
109
463
 
110
- Contributions are welcome! Feel free to open issues or submit pull requests to improve the project.
464
+ ## 📚 Documentation
111
465
 
112
- ---
466
+ Full documentation: [https://docs.arkyn.dev/docs/server/introduction](https://docs.arkyn.dev/docs/server/introduction)
113
467
 
114
- ## License
468
+ ## 📄 License
115
469
 
116
- This project is licensed under the Apache 2.0 License. See the `LICENSE` file for more details.
470
+ This project is licensed under the Apache 2.0 License - see the [LICENSE](./LICENSE.txt) file for details.
@@ -13,25 +13,28 @@ type ConfigProps = {
13
13
  /**
14
14
  * Sends a request to the inbox flow API with the provided configuration.
15
15
  *
16
- * @param config - The configuration object for the request.
17
- * @param config.rawUrl - The raw URL of the request.
18
- * @param config.status - The HTTP status code associated with the request.
19
- * @param config.method - The HTTP method used for the request. Can be "POST", "GET", "PUT", "DELETE", or "PATCH".
20
- * @param config.token - The authentication token for the request.
21
- * @param config.elapsedTime - The elapsed time for the request in milliseconds.
22
- * @param config.requestHeaders - The headers sent with the request.
23
- * @param config.requestBody - The body of the request, if applicable.
24
- * @param config.queryParams - The query parameters for the request.
25
- * @param config.responseHeaders - The headers received in the response.
26
- * @param config.responseBody - The body of the response received.
27
- *
28
- * @remarks
29
- * - This function retrieves the inbox flow configuration using `InboxFlowInstance.getInboxConfig()`.
16
+ * - This function retrieves the inbox flow configuration using `LogService.getConfig()`.
30
17
  * - If the configuration is not available, the function will return early without performing any action.
31
18
  * - In a development environment (`NODE_ENV === "development"`), the function will also return early.
32
19
  * - The request is sent as a POST request to the inbox API URL with the provided configuration details.
33
20
  * - If an error occurs during the request, it will be logged using the `httpDebug` service.
34
21
  *
22
+ * @param {ConfigProps} config - The configuration object for the request.
23
+ * @param {string} config.rawUrl - The raw URL of the request.
24
+ * @param {number} config.status - The HTTP status code associated with the request.
25
+ * @param {"GET" | "POST" | "PUT" | "DELETE" | "PATCH"} config.method - The HTTP method used for the request. Can be "POST", "GET", "PUT", "DELETE", or "PATCH".
26
+ * @param {string | null} config.token - The authentication token for the request.
27
+ * @param {number} config.elapsedTime - The elapsed time for the request in milliseconds.
28
+ * @param {Record<string, string>} config.requestHeaders - The headers sent with the request.
29
+ * @param {Record<string, string>} config.requestBody - The body of the request, if applicable.
30
+ * @param {Record<string, string>} config.queryParams - The query parameters for the request.
31
+ * @param {Record<string, string>} config.responseHeaders - The headers received in the response.
32
+ * @param {Record<string, string>} config.responseBody - The body of the response received.
33
+ *
34
+ * @remarks
35
+ *
36
+ * @returns {Promise<void>} A promise that resolves when the request is complete.
37
+ *
35
38
  * @example
36
39
  * ```typescript
37
40
  * const config = {
@@ -39,7 +42,7 @@ type ConfigProps = {
39
42
  * status: 200,
40
43
  * method: "GET",
41
44
  * token: "auth-token-123",
42
- * elapsedTime: "150ms",
45
+ * elapsedTime: 150,
43
46
  * requestHeaders: { "Accept": "application/json", "Authorization": "Bearer token123" },
44
47
  * requestBody: {},
45
48
  * queryParams: { "page": "1", "limit": "10" },
@@ -47,9 +50,9 @@ type ConfigProps = {
47
50
  * responseBody: { "data": "example response" }
48
51
  * };
49
52
  *
50
- * await arkynLogRequest(config);
53
+ * await logRequest(config);
51
54
  * ```
52
55
  */
53
- declare function arkynLogRequest(config: ConfigProps): Promise<void>;
54
- export { arkynLogRequest };
55
- //# sourceMappingURL=arkynLogRequest.d.ts.map
56
+ declare function logRequest(config: ConfigProps): Promise<void>;
57
+ export { logRequest };
58
+ //# sourceMappingURL=_logRequest.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"arkynLogRequest.d.ts","sourceRoot":"","sources":["../../src/api/arkynLogRequest.ts"],"names":[],"mappings":"AAGA,KAAK,WAAW,GAAG;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,iBAAe,eAAe,CAAC,MAAM,EAAE,WAAW,iBA0DjD;AAED,OAAO,EAAE,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"_logRequest.d.ts","sourceRoot":"","sources":["../../../src/http/api/_logRequest.ts"],"names":[],"mappings":"AAIA,KAAK,WAAW,GAAG;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,iBAAe,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA6E5D;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
@@ -0,0 +1,61 @@
1
+ type InputProps = {
2
+ url: string;
3
+ method: "POST" | "PUT" | "DELETE" | "PATCH" | "GET";
4
+ urlParams?: Record<string, string>;
5
+ headers?: HeadersInit;
6
+ body?: any;
7
+ };
8
+ type ApiSuccessResponse<T = any> = {
9
+ success: true;
10
+ status: number;
11
+ message: string;
12
+ response: T;
13
+ cause: null;
14
+ };
15
+ type ApiFailedResponse = {
16
+ success: false;
17
+ status: number;
18
+ message: string;
19
+ response: any;
20
+ cause: string | Error | null;
21
+ };
22
+ type ApiResponseDTO<T = any> = ApiSuccessResponse<T> | ApiFailedResponse;
23
+ /**
24
+ * Makes an HTTP request using the Fetch API and returns a standardized response.
25
+ *
26
+ * @template {any} T - The expected type of the response data.
27
+ *
28
+ * @param {"POST" | "PUT" | "DELETE" | "PATCH" | "GET"} method - The HTTP method to use for the request. Supported methods are:
29
+ * - "POST": Create a new resource.
30
+ * - "PUT": Update an existing resource.
31
+ * - "DELETE": Remove a resource.
32
+ * - "PATCH": Partially update a resource.
33
+ * - "GET": Retrieve a resource.
34
+ * @param {string} url - The URL to which the request is sent.
35
+ * @param {HeadersInit} headers - Optional headers to include in the request. Defaults to an empty object.
36
+ * @param {any} body - Optional body to include in the request. Should be serializable to JSON.
37
+ *
38
+ * @returns {ApiResponseDTO<T>} A promise that resolves to an `ApiResponseDTO<T>` object containing:
39
+ * - `success`: A boolean indicating whether the request was successful.
40
+ * - `status`: The HTTP status code of the response.
41
+ * - `message`: A message describing the result of the request.
42
+ * - `response`: The parsed JSON response data, or `null` if parsing fails.
43
+ * - `cause`: Additional error information, if applicable.
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * import { makeRequest } from "./makeRequest";
48
+ *
49
+ * async function fetchData() {
50
+ * const response = await makeRequest("GET", "https://api.example.com/data");
51
+ * if (response.success) {
52
+ * console.log("Data:", response.response);
53
+ * } else {
54
+ * console.error("Error:", response.message);
55
+ * }
56
+ * }
57
+ * ```
58
+ */
59
+ declare function makeRequest<T = any>(input: InputProps): Promise<ApiResponseDTO<T>>;
60
+ export { type ApiResponseDTO, makeRequest };
61
+ //# sourceMappingURL=_makeRequest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_makeRequest.d.ts","sourceRoot":"","sources":["../../../src/http/api/_makeRequest.ts"],"names":[],"mappings":"AAIA,KAAK,UAAU,GAAG;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,GAAG,KAAK,CAAC;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,OAAO,CAAC,EAAE,WAAW,CAAC;IAEtB,IAAI,CAAC,EAAE,GAAG,CAAC;CACX,CAAC;AAGF,KAAK,kBAAkB,CAAC,CAAC,GAAG,GAAG,IAAI;IAClC,OAAO,EAAE,IAAI,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,CAAC,CAAC;IACZ,KAAK,EAAE,IAAI,CAAC;CACZ,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACxB,OAAO,EAAE,KAAK,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAEhB,QAAQ,EAAE,GAAG,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAAC;CAC7B,CAAC;AAGF,KAAK,cAAc,CAAC,CAAC,GAAG,GAAG,IAAI,kBAAkB,CAAC,CAAC,CAAC,GAAG,iBAAiB,CAAC;AAEzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAGH,iBAAe,WAAW,CAAC,CAAC,GAAG,GAAG,EACjC,KAAK,EAAE,UAAU,GACf,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAqF5B;AAED,OAAO,EAAE,KAAK,cAAc,EAAE,WAAW,EAAE,CAAC"}