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

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 +425 -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,472 @@
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
31
+
32
+ > **ESM only.** This package ships as native ES modules with no CommonJS build — use `import`, not `require()`.
8
33
 
9
34
  ```bash
10
- npm install @arkyn/server
35
+ npm install @arkyn/server zod libphonenumber-js
36
+ ```
37
+
38
+ ## 🚀 Quick Start
39
+
40
+ ```typescript
41
+ import { Success, BadRequest, errorHandler, decodeRequestBody } from "@arkyn/server";
42
+
43
+ export async function action({ request }: ActionFunctionArgs) {
44
+ try {
45
+ const body = await decodeRequestBody(request);
46
+
47
+ if (!body.email) throw new BadRequest("Email is required");
48
+
49
+ const user = await createUser(body);
50
+ return new Success("User created", { user }).toJson();
51
+ } catch (error) {
52
+ return errorHandler(error);
53
+ }
54
+ }
55
+ ```
56
+
57
+ ## 📖 API Reference
58
+
59
+ ### HTTP Responses
60
+
61
+ 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.
62
+
63
+ #### BadGateway
64
+
65
+ HTTP 502 — the upstream server returned an invalid or unexpected response.
66
+
67
+ ```typescript
68
+ throw new BadGateway("Payment gateway unavailable");
69
+ ```
70
+
71
+ #### BadRequest
72
+
73
+ HTTP 400 — the request is malformed or contains invalid data.
74
+
75
+ ```typescript
76
+ throw new BadRequest("Invalid request body");
77
+ ```
78
+
79
+ #### Conflict
80
+
81
+ HTTP 409 — the request conflicts with the current state of the server (e.g. duplicate record).
82
+
83
+ ```typescript
84
+ throw new Conflict("Email already in use");
85
+ ```
86
+
87
+ #### Forbidden
88
+
89
+ HTTP 403 — authenticated but not authorized to access this resource.
90
+
91
+ ```typescript
92
+ throw new Forbidden("You don't have permission to delete this resource");
93
+ ```
94
+
95
+ #### NotFound
96
+
97
+ HTTP 404 — the requested resource does not exist.
98
+
99
+ ```typescript
100
+ throw new NotFound("Product not found");
11
101
  ```
12
102
 
13
- ---
103
+ #### NotImplemented
14
104
 
15
- ## Features
105
+ HTTP 501 — the server does not support the functionality required to fulfill the request.
16
106
 
17
- ### Settings
107
+ ```typescript
108
+ throw new NotImplemented("Webhook delivery is not yet implemented");
109
+ ```
18
110
 
19
- - **`ApiInstance`**
20
- Pre-configured instance for API calls.
111
+ #### ServerError
21
112
 
22
- - **`ArkynLogInstance`**
23
- Pre-configured instance for integration with Inbox Flow.
113
+ HTTP 500 — an unexpected condition prevented the server from fulfilling the request.
24
114
 
25
- ---
115
+ ```typescript
116
+ throw new ServerError("Failed to connect to the database");
117
+ ```
26
118
 
27
- ### HTTP Responses - Errors
119
+ #### Unauthorized
28
120
 
29
- - **`BadGateway(message: string): Error`**
30
- Represents an HTTP 502 error.
121
+ HTTP 401 the request lacks valid authentication credentials.
31
122
 
32
- - **`BadRequest(message: string): Error`**
33
- Represents an HTTP 400 error.
123
+ ```typescript
124
+ throw new Unauthorized("Invalid or expired token");
125
+ ```
34
126
 
35
- - **`Conflict(message: string): Error`**
36
- Represents an HTTP 409 error.
127
+ #### UnprocessableEntity
37
128
 
38
- - **`Forbidden(message: string): Error`**
39
- Represents an HTTP 403 error.
129
+ HTTP 422 — the request is well-formed but contains semantic validation errors. Typically used for form field validation failures.
40
130
 
41
- - **`NotFound(message: string): Error`**
42
- Represents an HTTP 404 error.
131
+ ```typescript
132
+ throw new UnprocessableEntity({
133
+ message: "Validation failed",
134
+ fieldErrors: { email: "Invalid email format", age: "Must be 18 or older" },
135
+ fields: { email: "not-an-email", age: "15" },
136
+ });
137
+ ```
43
138
 
44
- - **`NotImplemented(message: string): Error`**
45
- Represents an HTTP 501 error.
139
+ #### Created
46
140
 
47
- - **`ServerError(message: string): Error`**
48
- Represents an HTTP 500 error.
141
+ HTTP 201 the request succeeded and a new resource was created.
49
142
 
50
- - **`Unauthorized(message: string): Error`**
51
- Represents an HTTP 401 error.
143
+ ```typescript
144
+ return new Created("User created successfully", { id: user.id }).toJson();
145
+ ```
52
146
 
53
- - **`UnprocessableEntity(message: string): Error`**
54
- Represents an HTTP 422 error.
147
+ #### Found
55
148
 
56
- ---
149
+ HTTP 302 — the resource was located and the response includes it in the body.
57
150
 
58
- ### HTTP Responses - Success
151
+ ```typescript
152
+ return new Found("Products retrieved", { products }).toJson();
153
+ ```
59
154
 
60
- - **`Created(data: any): Response`**
61
- Represents an HTTP 201 response.
155
+ #### NoContent
62
156
 
63
- - **`Found(data: any): Response`**
64
- Represents an HTTP 302 response.
157
+ 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.
65
158
 
66
- - **`NoContent(): Response`**
67
- Represents an HTTP 204 response.
159
+ ```typescript
160
+ return new NoContent("Record deleted").toResponse();
161
+ ```
162
+
163
+ #### Success
164
+
165
+ HTTP 200 — the request succeeded and the response body contains the result.
166
+
167
+ ```typescript
168
+ return new Success("Order fetched", { order }).toJson();
169
+ ```
68
170
 
69
- - **`Success(data: any): Response`**
70
- Represents an HTTP 200 response.
171
+ #### Updated
71
172
 
72
- - **`Updated(data: any): Response`**
73
- Represents an HTTP 200 response for updates.
173
+ HTTP 200 the request succeeded and the resource was updated. Semantically equivalent to `Success` but signals an update operation to consumers.
74
174
 
75
- ---
175
+ ```typescript
176
+ return new Updated("Profile updated", { user }).toJson();
177
+ ```
76
178
 
77
179
  ### Services
78
180
 
79
- - **`decodeErrorMessageFromRequest(request: Request): string`**
80
- Decodes error messages from a request.
181
+ #### ApiService
81
182
 
82
- - **`decodeRequestBody(request: Request): any`**
83
- Decodes the body of a request.
183
+ 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`.
84
184
 
85
- - **`errorHandler(error: Error): Response`**
86
- Handles errors and returns an appropriate response.
185
+ ```typescript
186
+ const api = new ApiService({
187
+ baseUrl: "https://api.example.com",
188
+ baseToken: session.token,
189
+ enableDebug: true,
190
+ });
87
191
 
88
- - **`formParse(request: Request): FormData`**
89
- Parses form data.
192
+ const { data } = await api.get("/users/me");
193
+ const { data: created } = await api.post("/orders", { body: { productId: 1 } });
194
+ ```
90
195
 
91
- - **`getCaller(): string`**
92
- Returns the name of the function that invoked the method.
196
+ #### DebugService
93
197
 
94
- - **`getScopedParams(request: Request): URLSearchParams`**
95
- Retrieves scoped parameters from a request.
198
+ 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 }`.
96
199
 
97
- - **`httpDebug(request: Request): void`**
98
- Displays debug information for an HTTP request.
200
+ ```typescript
201
+ // Skip httpAdapter.ts so debug output shows the calling route instead
202
+ DebugService.setIgnoreFile("httpAdapter.ts");
203
+ ```
99
204
 
100
- - **`SchemaValidator(schema: any, data: any): boolean`**
101
- Validates data against a schema.
205
+ #### LogService
102
206
 
103
- - **`sendFileToS3(file: File, config: AwsConfig): Promise<{ url: string }>`**
104
- Uploads a file to AWS S3.
207
+ 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.
208
+
209
+ ```typescript
210
+ LogService.setConfig({
211
+ trafficSourceId: "my-app",
212
+ userToken: session.token,
213
+ });
214
+
215
+ LogService.getConfig(); // { trafficSourceId, userToken, apiUrl }
216
+ ```
217
+
218
+ ### Utilities
219
+
220
+ #### decodeRequestBody
221
+
222
+ Decodes a request body into a plain object, trying JSON first then URL-encoded form data. Throws `BadRequest` if neither format can be parsed.
223
+
224
+ ```typescript
225
+ export async function action({ request }: ActionFunctionArgs) {
226
+ const body = await decodeRequestBody(request);
227
+ // body is now a plain JS object
228
+ }
229
+ ```
230
+
231
+ #### decodeRequestErrorMessage
232
+
233
+ 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"`.
234
+
235
+ ```typescript
236
+ const res = await fetch("/api/orders");
237
+ const data = await res.json().catch(() => null);
238
+ const message = decodeRequestErrorMessage(data, res);
239
+ ```
240
+
241
+ #### errorHandler
242
+
243
+ 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.
244
+
245
+ ```typescript
246
+ export async function action({ request }: ActionFunctionArgs) {
247
+ try {
248
+ const user = await findUser(id);
249
+ if (!user) throw new NotFound("User not found");
250
+ return new Success("User retrieved", { user }).toJson();
251
+ } catch (error) {
252
+ return errorHandler(error);
253
+ }
254
+ }
255
+ ```
105
256
 
106
- ---
257
+ #### flushDebugLogs
107
258
 
108
- ## Contribution
259
+ Writes colored `[name] message` lines to the console, but only when `NODE_ENV === "development"` or `DEBUG_MODE === "true"`. No-op in production.
260
+
261
+ ```typescript
262
+ flushDebugLogs({
263
+ name: "API",
264
+ scheme: "cyan",
265
+ debugs: ["POST /api/users", "Status: 201"],
266
+ });
267
+ ```
268
+
269
+ #### formAsyncParse
270
+
271
+ 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.
272
+
273
+ ```typescript
274
+ const schema = z.object({ email: z.string().email() });
275
+ const result = await formAsyncParse([{ email: "bad" }, schema]);
276
+
277
+ if (!result.success) {
278
+ console.log(result.fieldErrors); // { email: "Invalid email" }
279
+ }
280
+ ```
281
+
282
+ #### formParse
283
+
284
+ Validates form data against a Zod schema synchronously. Returns `{ success: true, data }` on success or `{ success: false, fieldErrors, fields }` on failure.
285
+
286
+ ```typescript
287
+ const schema = z.object({ name: z.string().min(1, "Required"), age: z.number().min(18) });
288
+ const result = formParse([{ name: "", age: 15 }, schema]);
289
+
290
+ if (!result.success) {
291
+ console.log(result.fieldErrors); // { name: "Required", age: "..." }
292
+ }
293
+ ```
294
+
295
+ #### getScopedParams
296
+
297
+ 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.
298
+
299
+ ```typescript
300
+ // URL: /products?table:page=2&table:sort=asc&other=1
301
+ const params = getScopedParams(request, "table");
302
+ params.get("page"); // "2"
303
+ params.get("sort"); // "asc"
304
+ ```
305
+
306
+ #### SchemaValidator
307
+
308
+ 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).
309
+
310
+ ```typescript
311
+ const validator = new SchemaValidator(z.object({ email: z.string().email() }));
312
+
313
+ // Inside a Remix action:
314
+ const body = validator.formValidate(await decodeRequestBody(request));
315
+ ```
316
+
317
+ ### Validators
318
+
319
+ #### validateCep
320
+
321
+ Validates a Brazilian CEP (postal code). A valid CEP must contain exactly 8 numeric digits, optionally formatted as `"12345-678"`.
322
+
323
+ ```typescript
324
+ validateCep("12345-678"); // true
325
+ validateCep("12345678"); // true
326
+ validateCep("ABCDE-123"); // false
327
+ ```
328
+
329
+ #### validateCnpj
330
+
331
+ 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.
332
+
333
+ ```typescript
334
+ validateCnpj("12.345.678/0001-95"); // false
335
+ validateCnpj("11.444.777/0001-61"); // true
336
+ ```
337
+
338
+ #### validateCpf
339
+
340
+ Validates a Brazilian CPF number. Strips formatting, checks length, rejects repeated-digit sequences, and verifies both check digits with the CPF algorithm.
341
+
342
+ ```typescript
343
+ validateCpf("123.456.789-09"); // false
344
+ validateCpf("111.444.777-35"); // true
345
+ ```
346
+
347
+ #### validateDate
348
+
349
+ 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`.
350
+
351
+ ```typescript
352
+ validateDate("31/12/2023"); // true
353
+ validateDate("2023-12-31", { inputFormat: "timestamp", minYear: 2000, maxYear: 2100 }); // true
354
+ validateDate("29/02/2023"); // false (not a leap year)
355
+ ```
356
+
357
+ #### validateEmail
358
+
359
+ 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.
360
+
361
+ ```typescript
362
+ await validateEmail("user@gmail.com"); // true
363
+ await validateEmail("user@gmil.com"); // false (invalid domain)
364
+ await validateEmail("invalid-email"); // false (invalid format)
365
+ ```
366
+
367
+ #### validatePassword
368
+
369
+ 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.
370
+
371
+ ```typescript
372
+ validatePassword("Senha@123"); // true
373
+ validatePassword("senha123"); // false (no uppercase, no special char)
374
+ ```
375
+
376
+ #### validatePhone
377
+
378
+ Validates an international phone number using `libphonenumber-js`, then confirms the parsed country code is present in the supported countries list.
379
+
380
+ ```typescript
381
+ validatePhone("+5532912345678"); // true (Brazil)
382
+ validatePhone("+55329123456178"); // false (invalid)
383
+ ```
384
+
385
+ #### validateRg
386
+
387
+ 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.
388
+
389
+ ```typescript
390
+ validateRg("12.345.678-9"); // true
391
+ validateRg("MG-12.345.678"); // false (not supported)
392
+ validateRg("12345678X"); // true
393
+ ```
394
+
395
+ ## 🔧 Advanced Usage
396
+
397
+ ### Parse → validate → respond pipeline
398
+
399
+ ```typescript
400
+ import {
401
+ decodeRequestBody,
402
+ SchemaValidator,
403
+ Success,
404
+ errorHandler,
405
+ } from "@arkyn/server";
406
+ import { z } from "zod";
407
+
408
+ const createUserSchema = z.object({
409
+ email: z.string().email(),
410
+ name: z.string().min(2),
411
+ });
412
+
413
+ const userValidator = new SchemaValidator(createUserSchema);
414
+
415
+ export async function action({ request }: ActionFunctionArgs) {
416
+ try {
417
+ const body = await decodeRequestBody(request);
418
+
419
+ // Throws UnprocessableEntity with fieldErrors/fields on failure
420
+ const data = userValidator.formValidate(body);
421
+
422
+ const user = await createUser(data);
423
+ return new Success("User created", { user }).toJson();
424
+ } catch (error) {
425
+ return errorHandler(error);
426
+ }
427
+ }
428
+ ```
429
+
430
+ ### Brazilian document validation before persisting
431
+
432
+ ```typescript
433
+ import {
434
+ decodeRequestBody,
435
+ validateCpf,
436
+ validateEmail,
437
+ UnprocessableEntity,
438
+ Created,
439
+ errorHandler,
440
+ } from "@arkyn/server";
441
+
442
+ export async function action({ request }: ActionFunctionArgs) {
443
+ try {
444
+ const body = await decodeRequestBody(request);
445
+ const fieldErrors: Record<string, string> = {};
446
+
447
+ if (!validateCpf(body.cpf)) fieldErrors.cpf = "Invalid CPF";
448
+ if (!(await validateEmail(body.email))) fieldErrors.email = "Invalid email";
449
+
450
+ if (Object.keys(fieldErrors).length > 0) {
451
+ throw new UnprocessableEntity({
452
+ message: "Validation failed",
453
+ fieldErrors,
454
+ fields: body,
455
+ });
456
+ }
457
+
458
+ const customer = await createCustomer(body);
459
+ return new Created("Customer created", { customer }).toJson();
460
+ } catch (error) {
461
+ return errorHandler(error);
462
+ }
463
+ }
464
+ ```
109
465
 
110
- Contributions are welcome! Feel free to open issues or submit pull requests to improve the project.
466
+ ## 📚 Documentation
111
467
 
112
- ---
468
+ Full documentation: [https://docs.arkyn.dev/docs/server/introduction](https://docs.arkyn.dev/docs/server/introduction)
113
469
 
114
- ## License
470
+ ## 📄 License
115
471
 
116
- This project is licensed under the Apache 2.0 License. See the `LICENSE` file for more details.
472
+ 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"}