acrylblends 0.2.0 → 0.4.0

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 (335) hide show
  1. package/dist/index.d.ts +22 -16
  2. package/dist/index.js +65 -20
  3. package/dist/index.js.map +1 -1
  4. package/package.json +1 -1
  5. package/plugins/acryl-inspect/LICENSE +21 -0
  6. package/plugins/acryl-inspect/plugin.json +12 -0
  7. package/plugins/acryl-inspect/src/index.ts +3 -0
  8. package/plugins/acryl-inspect/src/report.ts +126 -0
  9. package/plugins/acryl-inspect/src/service.ts +68 -0
  10. package/plugins/acryl-inspect/tests/report.spec.ts +63 -0
  11. package/plugins/acryl-inspect/tests/service.spec.ts +121 -0
  12. package/plugins/acryl-inspect/upstream.json +18 -0
  13. package/plugins/acryl-node-server/LICENSE +47 -0
  14. package/plugins/acryl-node-server/plugin.json +13 -0
  15. package/plugins/acryl-node-server/src/adapter/conninfo.ts +23 -0
  16. package/plugins/acryl-node-server/src/adapter/early-hints.ts +55 -0
  17. package/plugins/acryl-node-server/src/adapter/error.ts +11 -0
  18. package/plugins/acryl-node-server/src/adapter/headers.ts +249 -0
  19. package/plugins/acryl-node-server/src/adapter/index.ts +6 -0
  20. package/plugins/acryl-node-server/src/adapter/listener.ts +540 -0
  21. package/plugins/acryl-node-server/src/adapter/request.ts +797 -0
  22. package/plugins/acryl-node-server/src/adapter/response.ts +186 -0
  23. package/plugins/acryl-node-server/src/adapter/serve-static.ts +238 -0
  24. package/plugins/acryl-node-server/src/adapter/server.ts +36 -0
  25. package/plugins/acryl-node-server/src/adapter/types.ts +82 -0
  26. package/plugins/acryl-node-server/src/adapter/url.ts +42 -0
  27. package/plugins/acryl-node-server/src/adapter/utils/response/constants.ts +1 -0
  28. package/plugins/acryl-node-server/src/adapter/utils/response.ts +4 -0
  29. package/plugins/acryl-node-server/src/adapter/utils/stream.ts +88 -0
  30. package/plugins/acryl-node-server/src/adapter/utils.ts +96 -0
  31. package/plugins/acryl-node-server/src/adapter/websocket-types.ts +45 -0
  32. package/plugins/acryl-node-server/src/adapter/websocket.ts +375 -0
  33. package/plugins/acryl-node-server/src/index.ts +107 -0
  34. package/plugins/acryl-node-server/tests/adapter/app.ts +76 -0
  35. package/plugins/acryl-node-server/tests/adapter/assets/.static/plain.txt +1 -0
  36. package/plugins/acryl-node-server/tests/adapter/assets/favicon.ico +0 -0
  37. package/plugins/acryl-node-server/tests/adapter/assets/secret.txt +1 -0
  38. package/plugins/acryl-node-server/tests/adapter/assets/static/acryl.html +1 -0
  39. package/plugins/acryl-node-server/tests/adapter/assets/static/admin/secret.txt +1 -0
  40. package/plugins/acryl-node-server/tests/adapter/assets/static/data.json +5 -0
  41. package/plugins/acryl-node-server/tests/adapter/assets/static/extensionless +1 -0
  42. package/plugins/acryl-node-server/tests/adapter/assets/static/foo..bar.txt +0 -0
  43. package/plugins/acryl-node-server/tests/adapter/assets/static/index.html +1 -0
  44. package/plugins/acryl-node-server/tests/adapter/assets/static/plain.txt +1 -0
  45. package/plugins/acryl-node-server/tests/adapter/assets/static-with-context-path/plain.txt +1 -0
  46. package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.bin +1 -0
  47. package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.bin.br +1 -0
  48. package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.txt +1 -0
  49. package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.txt.br +1 -0
  50. package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.txt.zst +1 -0
  51. package/plugins/acryl-node-server/tests/adapter/conninfo.test.ts +34 -0
  52. package/plugins/acryl-node-server/tests/adapter/content-length.test.ts +248 -0
  53. package/plugins/acryl-node-server/tests/adapter/early-hints.test.ts +457 -0
  54. package/plugins/acryl-node-server/tests/adapter/fixtures/keys/agent1-cert.pem +23 -0
  55. package/plugins/acryl-node-server/tests/adapter/fixtures/keys/agent1-key.pem +27 -0
  56. package/plugins/acryl-node-server/tests/adapter/headers.test.ts +252 -0
  57. package/plugins/acryl-node-server/tests/adapter/helpers/request.ts +190 -0
  58. package/plugins/acryl-node-server/tests/adapter/listener.test.ts +727 -0
  59. package/plugins/acryl-node-server/tests/adapter/request-client-disconnect.test.ts +189 -0
  60. package/plugins/acryl-node-server/tests/adapter/request.test.ts +1230 -0
  61. package/plugins/acryl-node-server/tests/adapter/response.test.ts +285 -0
  62. package/plugins/acryl-node-server/tests/adapter/serve-static.test.ts +849 -0
  63. package/plugins/acryl-node-server/tests/adapter/server-socket.test.ts +790 -0
  64. package/plugins/acryl-node-server/tests/adapter/server.test.ts +1302 -0
  65. package/plugins/acryl-node-server/tests/adapter/setup.ts +16 -0
  66. package/plugins/acryl-node-server/tests/adapter/url.test.ts +76 -0
  67. package/plugins/acryl-node-server/tests/adapter/utils/response.test.ts +23 -0
  68. package/plugins/acryl-node-server/tests/adapter/utils/stream.test.ts +75 -0
  69. package/plugins/acryl-node-server/tests/adapter/utils.test.ts +235 -0
  70. package/plugins/acryl-node-server/tests/adapter/websocket.test.ts +260 -0
  71. package/plugins/acryl-node-server/tests/server.spec.ts +141 -0
  72. package/plugins/acryl-node-server/upstream.json +18 -0
  73. package/plugins/acryl-router/LICENSE +47 -0
  74. package/plugins/acryl-router/plugin.json +13 -0
  75. package/plugins/acryl-router/src/client.ts +2 -0
  76. package/plugins/acryl-router/src/connection.ts +42 -0
  77. package/plugins/acryl-router/src/core/app-base.ts +544 -0
  78. package/plugins/acryl-router/src/core/app.test.ts +3833 -0
  79. package/plugins/acryl-router/src/core/app.ts +34 -0
  80. package/plugins/acryl-router/src/core/client/client.test.ts +2313 -0
  81. package/plugins/acryl-router/src/core/client/client.ts +249 -0
  82. package/plugins/acryl-router/src/core/client/fetch-result-please.ts +95 -0
  83. package/plugins/acryl-router/src/core/client/index.ts +17 -0
  84. package/plugins/acryl-router/src/core/client/types.test.ts +149 -0
  85. package/plugins/acryl-router/src/core/client/types.ts +393 -0
  86. package/plugins/acryl-router/src/core/client/utils.test.ts +405 -0
  87. package/plugins/acryl-router/src/core/client/utils.ts +117 -0
  88. package/plugins/acryl-router/src/core/compose.test.ts +751 -0
  89. package/plugins/acryl-router/src/core/compose.ts +73 -0
  90. package/plugins/acryl-router/src/core/context.test.ts +629 -0
  91. package/plugins/acryl-router/src/core/context.ts +781 -0
  92. package/plugins/acryl-router/src/core/helper/accepts/accepts.test.ts +344 -0
  93. package/plugins/acryl-router/src/core/helper/accepts/accepts.ts +96 -0
  94. package/plugins/acryl-router/src/core/helper/accepts/index.ts +6 -0
  95. package/plugins/acryl-router/src/core/helper/adapter/index.test.ts +55 -0
  96. package/plugins/acryl-router/src/core/helper/adapter/index.ts +90 -0
  97. package/plugins/acryl-router/src/core/helper/conninfo/index.ts +6 -0
  98. package/plugins/acryl-router/src/core/helper/conninfo/types.ts +45 -0
  99. package/plugins/acryl-router/src/core/helper/cookie/index.test.ts +510 -0
  100. package/plugins/acryl-router/src/core/helper/cookie/index.ts +146 -0
  101. package/plugins/acryl-router/src/core/helper/factory/index.test.ts +434 -0
  102. package/plugins/acryl-router/src/core/helper/factory/index.ts +375 -0
  103. package/plugins/acryl-router/src/core/helper/html/index.test.ts +78 -0
  104. package/plugins/acryl-router/src/core/helper/html/index.ts +57 -0
  105. package/plugins/acryl-router/src/core/helper/route/index.test.ts +259 -0
  106. package/plugins/acryl-router/src/core/helper/route/index.ts +144 -0
  107. package/plugins/acryl-router/src/core/helper/streaming/index.ts +9 -0
  108. package/plugins/acryl-router/src/core/helper/streaming/sse.ts +101 -0
  109. package/plugins/acryl-router/src/core/helper/streaming/stream.test.ts +128 -0
  110. package/plugins/acryl-router/src/core/helper/streaming/stream.ts +45 -0
  111. package/plugins/acryl-router/src/core/helper/streaming/text.test.ts +34 -0
  112. package/plugins/acryl-router/src/core/helper/streaming/text.ts +15 -0
  113. package/plugins/acryl-router/src/core/helper/streaming/utils.ts +11 -0
  114. package/plugins/acryl-router/src/core/helper/testing/index.test.ts +42 -0
  115. package/plugins/acryl-router/src/core/helper/testing/index.ts +28 -0
  116. package/plugins/acryl-router/src/core/helper/websocket/index.test.ts +124 -0
  117. package/plugins/acryl-router/src/core/helper/websocket/index.ts +140 -0
  118. package/plugins/acryl-router/src/core/http-exception.test.ts +45 -0
  119. package/plugins/acryl-router/src/core/http-exception.ts +77 -0
  120. package/plugins/acryl-router/src/core/index.ts +53 -0
  121. package/plugins/acryl-router/src/core/middleware/basic-auth/index.test.ts +434 -0
  122. package/plugins/acryl-router/src/core/middleware/basic-auth/index.ts +152 -0
  123. package/plugins/acryl-router/src/core/middleware/bearer-auth/index.test.ts +1018 -0
  124. package/plugins/acryl-router/src/core/middleware/bearer-auth/index.ts +220 -0
  125. package/plugins/acryl-router/src/core/middleware/body-limit/index.test.ts +273 -0
  126. package/plugins/acryl-router/src/core/middleware/body-limit/index.ts +110 -0
  127. package/plugins/acryl-router/src/core/middleware/combine/index.test.ts +355 -0
  128. package/plugins/acryl-router/src/core/middleware/combine/index.ts +171 -0
  129. package/plugins/acryl-router/src/core/middleware/compress/index.test.ts +535 -0
  130. package/plugins/acryl-router/src/core/middleware/compress/index.ts +142 -0
  131. package/plugins/acryl-router/src/core/middleware/context-storage/index.test.ts +43 -0
  132. package/plugins/acryl-router/src/core/middleware/context-storage/index.ts +58 -0
  133. package/plugins/acryl-router/src/core/middleware/cors/index.test.ts +532 -0
  134. package/plugins/acryl-router/src/core/middleware/cors/index.ts +163 -0
  135. package/plugins/acryl-router/src/core/middleware/csrf/index.test.ts +534 -0
  136. package/plugins/acryl-router/src/core/middleware/csrf/index.ts +150 -0
  137. package/plugins/acryl-router/src/core/middleware/etag/digest.test.ts +21 -0
  138. package/plugins/acryl-router/src/core/middleware/etag/digest.ts +95 -0
  139. package/plugins/acryl-router/src/core/middleware/etag/index.test.ts +503 -0
  140. package/plugins/acryl-router/src/core/middleware/etag/index.ts +135 -0
  141. package/plugins/acryl-router/src/core/middleware/ip-restriction/index.test.ts +217 -0
  142. package/plugins/acryl-router/src/core/middleware/ip-restriction/index.ts +278 -0
  143. package/plugins/acryl-router/src/core/middleware/jwk/index.test.ts +1135 -0
  144. package/plugins/acryl-router/src/core/middleware/jwk/index.ts +1 -0
  145. package/plugins/acryl-router/src/core/middleware/jwk/jwk.ts +195 -0
  146. package/plugins/acryl-router/src/core/middleware/jwk/keys.test.json +48 -0
  147. package/plugins/acryl-router/src/core/middleware/jwt/index.test.ts +802 -0
  148. package/plugins/acryl-router/src/core/middleware/jwt/index.ts +9 -0
  149. package/plugins/acryl-router/src/core/middleware/jwt/jwt.ts +189 -0
  150. package/plugins/acryl-router/src/core/middleware/language/index.test.ts +552 -0
  151. package/plugins/acryl-router/src/core/middleware/language/index.ts +12 -0
  152. package/plugins/acryl-router/src/core/middleware/language/language.ts +314 -0
  153. package/plugins/acryl-router/src/core/middleware/logger/index.test.ts +204 -0
  154. package/plugins/acryl-router/src/core/middleware/logger/index.ts +95 -0
  155. package/plugins/acryl-router/src/core/middleware/method-not-allowed/index.test.ts +292 -0
  156. package/plugins/acryl-router/src/core/middleware/method-not-allowed/index.ts +141 -0
  157. package/plugins/acryl-router/src/core/middleware/method-override/index.test.ts +221 -0
  158. package/plugins/acryl-router/src/core/middleware/method-override/index.ts +147 -0
  159. package/plugins/acryl-router/src/core/middleware/powered-by/index.test.ts +37 -0
  160. package/plugins/acryl-router/src/core/middleware/powered-by/index.ts +35 -0
  161. package/plugins/acryl-router/src/core/middleware/pretty-json/index.test.ts +218 -0
  162. package/plugins/acryl-router/src/core/middleware/pretty-json/index.ts +67 -0
  163. package/plugins/acryl-router/src/core/middleware/request-id/index.test.ts +168 -0
  164. package/plugins/acryl-router/src/core/middleware/request-id/index.ts +7 -0
  165. package/plugins/acryl-router/src/core/middleware/request-id/request-id.ts +59 -0
  166. package/plugins/acryl-router/src/core/middleware/secure-headers/index.test.ts +671 -0
  167. package/plugins/acryl-router/src/core/middleware/secure-headers/index.ts +8 -0
  168. package/plugins/acryl-router/src/core/middleware/secure-headers/permissions-policy.ts +101 -0
  169. package/plugins/acryl-router/src/core/middleware/secure-headers/secure-headers.ts +340 -0
  170. package/plugins/acryl-router/src/core/middleware/serve-static/index.test.ts +450 -0
  171. package/plugins/acryl-router/src/core/middleware/serve-static/index.ts +135 -0
  172. package/plugins/acryl-router/src/core/middleware/serve-static/path.test.ts +50 -0
  173. package/plugins/acryl-router/src/core/middleware/serve-static/path.ts +25 -0
  174. package/plugins/acryl-router/src/core/middleware/timeout/index.test.ts +70 -0
  175. package/plugins/acryl-router/src/core/middleware/timeout/index.ts +58 -0
  176. package/plugins/acryl-router/src/core/middleware/timing/index.test.ts +310 -0
  177. package/plugins/acryl-router/src/core/middleware/timing/index.ts +8 -0
  178. package/plugins/acryl-router/src/core/middleware/timing/timing.ts +256 -0
  179. package/plugins/acryl-router/src/core/middleware/trailing-slash/index.test.ts +381 -0
  180. package/plugins/acryl-router/src/core/middleware/trailing-slash/index.ts +156 -0
  181. package/plugins/acryl-router/src/core/request/constants.ts +1 -0
  182. package/plugins/acryl-router/src/core/request.test.ts +751 -0
  183. package/plugins/acryl-router/src/core/request.ts +502 -0
  184. package/plugins/acryl-router/src/core/router/common.case.test.ts +1132 -0
  185. package/plugins/acryl-router/src/core/router/linear-router/index.ts +6 -0
  186. package/plugins/acryl-router/src/core/router/linear-router/router.test.ts +80 -0
  187. package/plugins/acryl-router/src/core/router/linear-router/router.ts +152 -0
  188. package/plugins/acryl-router/src/core/router/pattern-router/index.ts +6 -0
  189. package/plugins/acryl-router/src/core/router/pattern-router/router.test.ts +46 -0
  190. package/plugins/acryl-router/src/core/router/pattern-router/router.ts +54 -0
  191. package/plugins/acryl-router/src/core/router/reg-exp-router/index.ts +7 -0
  192. package/plugins/acryl-router/src/core/router/reg-exp-router/matcher.ts +33 -0
  193. package/plugins/acryl-router/src/core/router/reg-exp-router/node.ts +170 -0
  194. package/plugins/acryl-router/src/core/router/reg-exp-router/prepared-router.test.ts +154 -0
  195. package/plugins/acryl-router/src/core/router/reg-exp-router/prepared-router.ts +165 -0
  196. package/plugins/acryl-router/src/core/router/reg-exp-router/router.test.ts +265 -0
  197. package/plugins/acryl-router/src/core/router/reg-exp-router/router.ts +174 -0
  198. package/plugins/acryl-router/src/core/router/reg-exp-router/trie.ts +84 -0
  199. package/plugins/acryl-router/src/core/router/smart-router/index.ts +6 -0
  200. package/plugins/acryl-router/src/core/router/smart-router/router.test.ts +13 -0
  201. package/plugins/acryl-router/src/core/router/smart-router/router.ts +70 -0
  202. package/plugins/acryl-router/src/core/router/trie-router/index.ts +6 -0
  203. package/plugins/acryl-router/src/core/router/trie-router/node.test.ts +896 -0
  204. package/plugins/acryl-router/src/core/router/trie-router/node.ts +221 -0
  205. package/plugins/acryl-router/src/core/router/trie-router/router.test.ts +8 -0
  206. package/plugins/acryl-router/src/core/router/trie-router/router.ts +18 -0
  207. package/plugins/acryl-router/src/core/router/utils.ts +1 -0
  208. package/plugins/acryl-router/src/core/router.ts +103 -0
  209. package/plugins/acryl-router/src/core/types.test.ts +4134 -0
  210. package/plugins/acryl-router/src/core/types.ts +2782 -0
  211. package/plugins/acryl-router/src/core/utils/accept.test.ts +299 -0
  212. package/plugins/acryl-router/src/core/utils/accept.ts +268 -0
  213. package/plugins/acryl-router/src/core/utils/basic-auth.test.ts +56 -0
  214. package/plugins/acryl-router/src/core/utils/basic-auth.ts +26 -0
  215. package/plugins/acryl-router/src/core/utils/body.test.ts +496 -0
  216. package/plugins/acryl-router/src/core/utils/body.ts +263 -0
  217. package/plugins/acryl-router/src/core/utils/buffer.test.ts +147 -0
  218. package/plugins/acryl-router/src/core/utils/buffer.ts +117 -0
  219. package/plugins/acryl-router/src/core/utils/color.test.ts +23 -0
  220. package/plugins/acryl-router/src/core/utils/color.ts +56 -0
  221. package/plugins/acryl-router/src/core/utils/compress.ts +10 -0
  222. package/plugins/acryl-router/src/core/utils/concurrent.test.ts +69 -0
  223. package/plugins/acryl-router/src/core/utils/concurrent.ts +55 -0
  224. package/plugins/acryl-router/src/core/utils/constants.ts +4 -0
  225. package/plugins/acryl-router/src/core/utils/cookie.test.ts +460 -0
  226. package/plugins/acryl-router/src/core/utils/cookie.ts +281 -0
  227. package/plugins/acryl-router/src/core/utils/crypto.test.ts +43 -0
  228. package/plugins/acryl-router/src/core/utils/crypto.ts +58 -0
  229. package/plugins/acryl-router/src/core/utils/encode.test.ts +61 -0
  230. package/plugins/acryl-router/src/core/utils/encode.ts +34 -0
  231. package/plugins/acryl-router/src/core/utils/filepath.test.ts +78 -0
  232. package/plugins/acryl-router/src/core/utils/filepath.ts +60 -0
  233. package/plugins/acryl-router/src/core/utils/handler.ts +15 -0
  234. package/plugins/acryl-router/src/core/utils/headers.ts +355 -0
  235. package/plugins/acryl-router/src/core/utils/html.test.ts +16 -0
  236. package/plugins/acryl-router/src/core/utils/html.ts +182 -0
  237. package/plugins/acryl-router/src/core/utils/http-status.ts +72 -0
  238. package/plugins/acryl-router/src/core/utils/ipaddr.test.ts +149 -0
  239. package/plugins/acryl-router/src/core/utils/ipaddr.ts +374 -0
  240. package/plugins/acryl-router/src/core/utils/jwt/index.ts +7 -0
  241. package/plugins/acryl-router/src/core/utils/jwt/jwa.test.ts +86 -0
  242. package/plugins/acryl-router/src/core/utils/jwt/jwa.ts +38 -0
  243. package/plugins/acryl-router/src/core/utils/jwt/jws.ts +235 -0
  244. package/plugins/acryl-router/src/core/utils/jwt/jwt.test.ts +1788 -0
  245. package/plugins/acryl-router/src/core/utils/jwt/jwt.ts +292 -0
  246. package/plugins/acryl-router/src/core/utils/jwt/types.ts +157 -0
  247. package/plugins/acryl-router/src/core/utils/jwt/utf8.ts +7 -0
  248. package/plugins/acryl-router/src/core/utils/mime.test.ts +64 -0
  249. package/plugins/acryl-router/src/core/utils/mime.ts +94 -0
  250. package/plugins/acryl-router/src/core/utils/stream.test.ts +212 -0
  251. package/plugins/acryl-router/src/core/utils/stream.ts +107 -0
  252. package/plugins/acryl-router/src/core/utils/types.test.ts +295 -0
  253. package/plugins/acryl-router/src/core/utils/types.ts +123 -0
  254. package/plugins/acryl-router/src/core/utils/url.test.ts +384 -0
  255. package/plugins/acryl-router/src/core/utils/url.ts +337 -0
  256. package/plugins/acryl-router/src/core/validator/index.ts +8 -0
  257. package/plugins/acryl-router/src/core/validator/utils.test.ts +82 -0
  258. package/plugins/acryl-router/src/core/validator/utils.ts +69 -0
  259. package/plugins/acryl-router/src/core/validator/validator.test.ts +1488 -0
  260. package/plugins/acryl-router/src/core/validator/validator.ts +185 -0
  261. package/plugins/acryl-router/src/helpers/index.ts +13 -0
  262. package/plugins/acryl-router/src/helpers/schema-validator.ts +35 -0
  263. package/plugins/acryl-router/src/index.ts +6 -0
  264. package/plugins/acryl-router/src/middleware/index.ts +25 -0
  265. package/plugins/acryl-router/src/middleware/loopback-only.ts +88 -0
  266. package/plugins/acryl-router/src/service.ts +356 -0
  267. package/plugins/acryl-router/tests/docs-examples.spec.ts +152 -0
  268. package/plugins/acryl-router/tests/live-install.spec.ts +64 -0
  269. package/plugins/acryl-router/tests/loader.spec.ts +72 -0
  270. package/plugins/acryl-router/tests/service.spec.ts +409 -0
  271. package/plugins/acryl-router/tests/shadow-state.spec.ts +79 -0
  272. package/plugins/acryl-router/upstream.json +20 -0
  273. package/plugins/acryl-router-http/LICENSE +21 -0
  274. package/plugins/acryl-router-http/plugin.json +12 -0
  275. package/plugins/acryl-router-http/src/bridge.ts +54 -0
  276. package/plugins/acryl-router-http/src/index.ts +63 -0
  277. package/plugins/acryl-router-http/src/serve.ts +24 -0
  278. package/plugins/acryl-router-http/tests/adapter.spec.ts +174 -0
  279. package/plugins/acryl-router-http/tests/stream.spec.ts +133 -0
  280. package/plugins/acryl-router-http/tests/surfaces.spec.ts +101 -0
  281. package/plugins/acryl-router-http/upstream.json +22 -0
  282. package/plugins/acryl-state/LICENSE +21 -0
  283. package/plugins/acryl-state/NOTICE +30 -0
  284. package/plugins/acryl-state/plugin.json +12 -0
  285. package/plugins/acryl-state/src/cell.ts +67 -0
  286. package/plugins/acryl-state/src/index.ts +3 -0
  287. package/plugins/acryl-state/src/react.ts +11 -0
  288. package/plugins/acryl-state/src/service.ts +119 -0
  289. package/plugins/acryl-state/tests/cell.spec.ts +71 -0
  290. package/plugins/acryl-state/tests/react.spec.ts +39 -0
  291. package/plugins/acryl-state/tests/service.spec.ts +132 -0
  292. package/plugins/acryl-state/upstream.json +22 -0
  293. package/plugins/builder/script.ts +6 -10
  294. package/plugins/extensions/index.ts +20 -3
  295. package/plugins/extensions/resolve.ts +28 -3
  296. package/plugins/openai/prompt.ts +12 -6
  297. package/plugins/tasks/index.ts +14 -0
  298. package/plugins/tsconfig.json +14 -5
  299. package/templates/agent/blend.yaml +5 -7
  300. package/templates/agent/src/app.ts +8 -8
  301. package/templates/agent/src/routes.ts +39 -38
  302. package/templates/agent/template.json +3 -3
  303. package/templates/agent/test/builder.test.ts +22 -14
  304. package/templates/agent/test/model.test.ts +3 -3
  305. package/templates/agent/tsconfig.json +8 -5
  306. package/templates/{app → blank}/blend.yaml +3 -3
  307. package/templates/{app → blank}/src/app.ts +5 -5
  308. package/templates/blank/src/routes.ts +16 -0
  309. package/templates/blank/template.json +1 -0
  310. package/templates/{app → blank}/test/app.test.ts +1 -1
  311. package/templates/{app → blank}/tsconfig.json +2 -4
  312. package/templates/todo/README.md +27 -0
  313. package/templates/todo/blend.yaml +25 -0
  314. package/templates/todo/gitignore +2 -0
  315. package/templates/todo/package.json +23 -0
  316. package/templates/todo/src/app.ts +71 -0
  317. package/templates/todo/src/main.ts +19 -0
  318. package/templates/todo/src/page.ts +28 -0
  319. package/templates/todo/src/todo.ts +123 -0
  320. package/templates/todo/template.json +1 -0
  321. package/templates/todo/test/todo.test.ts +145 -0
  322. package/templates/todo/tsconfig.json +17 -0
  323. package/templates/todo/upstream.json +12 -0
  324. package/plugins/events/index.ts +0 -42
  325. package/plugins/events/plugin.json +0 -9
  326. package/plugins/http/index.ts +0 -64
  327. package/plugins/http/plugin.json +0 -10
  328. package/plugins/server/index.ts +0 -138
  329. package/plugins/server/plugin.json +0 -10
  330. package/templates/app/src/routes.ts +0 -14
  331. package/templates/app/template.json +0 -1
  332. /package/templates/{app → blank}/README.md +0 -0
  333. /package/templates/{app → blank}/gitignore +0 -0
  334. /package/templates/{app → blank}/package.json +0 -0
  335. /package/templates/{app → blank}/src/main.ts +0 -0
@@ -0,0 +1,147 @@
1
+ /**
2
+ * @module
3
+ * Method Override Middleware for App.
4
+ */
5
+
6
+ import type { Context, ExecutionContext } from '../../context.ts'
7
+ import type { App } from '../../app.ts'
8
+ import type { MiddlewareHandler } from '../../types.ts'
9
+ import { parseBody } from '../../utils/body.ts'
10
+
11
+ type MethodOverrideOptions = {
12
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
+ app: App<any, any, any>
14
+ } & (
15
+ | {
16
+ // Default is 'form' and the value is `_method`
17
+ form?: string
18
+ header?: never
19
+ query?: never
20
+ }
21
+ | {
22
+ form?: never
23
+ header: string
24
+ query?: never
25
+ }
26
+ | {
27
+ form?: never
28
+ header?: never
29
+ query: string
30
+ }
31
+ )
32
+
33
+ const DEFAULT_METHOD_FORM_NAME = '_method'
34
+
35
+ /**
36
+ * Method Override Middleware for App.
37
+ *
38
+ *
39
+ * @param {MethodOverrideOptions} options - The options for the method override middleware.
40
+ * @param {App} options.app - The instance of App is used in your application.
41
+ * @param {string} [options.form=_method] - Form key with a value containing the method name.
42
+ * @param {string} [options.header] - Header name with a value containing the method name.
43
+ * @param {string} [options.query] - Query parameter key with a value containing the method name.
44
+ * @returns {MiddlewareHandler} The middleware handler function.
45
+ *
46
+ * @example
47
+ * ```ts
48
+ * const app = new App()
49
+ *
50
+ * // If no options are specified, the value of `_method` in the form,
51
+ * // e.g. DELETE, is used as the method.
52
+ * app.use('/posts', methodOverride({ app }))
53
+ *
54
+ * app.delete('/posts', (c) => {
55
+ * // ....
56
+ * })
57
+ * ```
58
+ */
59
+ export const methodOverride = (options: MethodOverrideOptions): MiddlewareHandler =>
60
+ async function methodOverride(c, next) {
61
+ if (c.req.method === 'GET') {
62
+ return await next()
63
+ }
64
+
65
+ const app = options.app
66
+ // Method override by form
67
+ if (!(options.header || options.query)) {
68
+ const contentType = c.req.header('content-type')
69
+ const methodFormName = options.form || DEFAULT_METHOD_FORM_NAME
70
+ const clonedRequest = c.req.raw.clone()
71
+ const newRequest = clonedRequest.clone()
72
+ // Content-Type is `multipart/form-data`
73
+ if (contentType?.startsWith('multipart/form-data')) {
74
+ const form = await clonedRequest.formData()
75
+ const method = form.get(methodFormName)
76
+ if (method) {
77
+ const newForm = await newRequest.formData()
78
+ newForm.delete(methodFormName)
79
+ const newHeaders = new Headers(clonedRequest.headers)
80
+ newHeaders.delete('content-type')
81
+ newHeaders.delete('content-length')
82
+ const request = new Request(c.req.url, {
83
+ body: newForm,
84
+ headers: newHeaders,
85
+ method: method as string,
86
+ })
87
+ return app.fetch(request, c.env, getExecutionCtx(c))
88
+ }
89
+ }
90
+ // Content-Type is `application/x-www-form-urlencoded`
91
+ if (contentType?.startsWith('application/x-www-form-urlencoded')) {
92
+ const params = await parseBody<Record<string, string>>(clonedRequest)
93
+ const method = params[methodFormName]
94
+ if (method) {
95
+ delete params[methodFormName]
96
+ const newParams = new URLSearchParams(params)
97
+ const request = new Request(newRequest, {
98
+ body: newParams,
99
+ method: method as string,
100
+ })
101
+ return app.fetch(request, c.env, getExecutionCtx(c))
102
+ }
103
+ }
104
+ }
105
+ // Method override by header
106
+ else if (options.header) {
107
+ const headerName = options.header
108
+ const method = c.req.header(headerName)
109
+ if (method) {
110
+ const newHeaders = new Headers(c.req.raw.headers)
111
+ newHeaders.delete(headerName)
112
+ const request = new Request(c.req.raw, {
113
+ headers: newHeaders,
114
+ method,
115
+ })
116
+ return app.fetch(request, c.env, getExecutionCtx(c))
117
+ }
118
+ }
119
+ // Method override by query
120
+ else if (options.query) {
121
+ const queryName = options.query
122
+ const method = c.req.query(queryName)
123
+ if (method) {
124
+ const url = new URL(c.req.url)
125
+ url.searchParams.delete(queryName)
126
+ const requestInit: RequestInit & { duplex?: 'half' } = {
127
+ body: c.req.raw.body,
128
+ headers: c.req.raw.headers,
129
+ method,
130
+ duplex: c.req.raw.body ? 'half' : undefined,
131
+ }
132
+ const request = new Request(url.toString(), requestInit)
133
+ return app.fetch(request, c.env, getExecutionCtx(c))
134
+ }
135
+ }
136
+ await next()
137
+ }
138
+
139
+ const getExecutionCtx = (c: Context) => {
140
+ let executionCtx: ExecutionContext | undefined
141
+ try {
142
+ executionCtx = c.executionCtx
143
+ } catch {
144
+ // Do nothing
145
+ }
146
+ return executionCtx
147
+ }
@@ -0,0 +1,37 @@
1
+ import { poweredBy } from './index.ts'
2
+ import { App } from '../../app.ts'
3
+
4
+ describe('Powered by Middleware', () => {
5
+ const app = new App()
6
+
7
+ app.use('/poweredBy/*', poweredBy())
8
+ app.get('/poweredBy', (c) => c.text('root'))
9
+
10
+ app.use('/poweredBy2/*', poweredBy())
11
+ app.use('/poweredBy2/*', poweredBy())
12
+ app.get('/poweredBy2', (c) => c.text('root'))
13
+
14
+ app.use('/poweredBy3/*', poweredBy({ serverName: 'Foo' }))
15
+ app.get('/poweredBy3', (c) => c.text('root'))
16
+
17
+ it('Should return with X-Powered-By header', async () => {
18
+ const res = await app.request('http://localhost/poweredBy')
19
+ expect(res).not.toBeNull()
20
+ expect(res.status).toBe(200)
21
+ expect(res.headers.get('X-Powered-By')).toBe('ACRYL')
22
+ })
23
+
24
+ it('Should not return duplicate values', async () => {
25
+ const res = await app.request('http://localhost/poweredBy2')
26
+ expect(res).not.toBeNull()
27
+ expect(res.status).toBe(200)
28
+ expect(res.headers.get('X-Powered-By')).toBe('ACRYL')
29
+ })
30
+
31
+ it('Should return custom serverName', async () => {
32
+ const res = await app.request('http://localhost/poweredBy3')
33
+ expect(res).not.toBeNull()
34
+ expect(res.status).toBe(200)
35
+ expect(res.headers.get('X-Powered-By')).toBe('Foo')
36
+ })
37
+ })
@@ -0,0 +1,35 @@
1
+ /**
2
+ * @module
3
+ * Powered By Middleware for App.
4
+ */
5
+ import type { MiddlewareHandler } from '../../types.ts'
6
+
7
+ type PoweredByOptions = {
8
+ /**
9
+ * The value for X-Powered-By header.
10
+ * @default App
11
+ */
12
+ serverName?: string
13
+ }
14
+
15
+ /**
16
+ * Powered By Middleware for App.
17
+ *
18
+ * @param options - The options for the Powered By Middleware.
19
+ * @returns {MiddlewareHandler} The middleware handler function.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * import { poweredBy } from 'acryl-router/middleware'
24
+ *
25
+ * const app = new App()
26
+ *
27
+ * app.use(poweredBy()) // With options: poweredBy({ serverName: "My Server" })
28
+ * ```
29
+ */
30
+ export const poweredBy = (options?: PoweredByOptions): MiddlewareHandler => {
31
+ return async function poweredBy(c, next) {
32
+ await next()
33
+ c.res.headers.set('X-Powered-By', options?.serverName ?? 'ACRYL')
34
+ }
35
+ }
@@ -0,0 +1,218 @@
1
+ import { prettyJSON } from './index.ts'
2
+ import { App } from '../../app.ts'
3
+
4
+ describe('JSON pretty by Middleware', () => {
5
+ it('Should return pretty JSON output', async () => {
6
+ const app = new App()
7
+ app.use('*', prettyJSON())
8
+ app.get('/', (c) => {
9
+ return c.json({ message: 'App!' })
10
+ })
11
+
12
+ const res = await app.request('http://localhost/?pretty')
13
+ expect(res).not.toBeNull()
14
+ expect(res.status).toBe(200)
15
+ expect(await res.text()).toBe(`{
16
+ "message": "App!"
17
+ }`)
18
+ })
19
+
20
+ it('Should return pretty JSON output with 4 spaces', async () => {
21
+ const app = new App()
22
+ app.use('*', prettyJSON({ space: 4 }))
23
+ app.get('/', (c) => {
24
+ return c.json({ message: 'App!' })
25
+ })
26
+
27
+ const res = await app.request('http://localhost/?pretty')
28
+ expect(res).not.toBeNull()
29
+ expect(res.status).toBe(200)
30
+ expect(await res.text()).toBe(`{
31
+ "message": "App!"
32
+ }`)
33
+ })
34
+
35
+ it('Should return pretty JSON output when middleware received custom query', async () => {
36
+ const targetQuery = 'format'
37
+
38
+ const app = new App()
39
+ app.use(
40
+ '*',
41
+ prettyJSON({
42
+ query: targetQuery,
43
+ })
44
+ )
45
+ app.get('/', (c) =>
46
+ c.json({
47
+ message: 'App!',
48
+ })
49
+ )
50
+
51
+ const prettyText = await (await app.request(`?${targetQuery}`)).text()
52
+ expect(prettyText).toBe(`{
53
+ "message": "App!"
54
+ }`)
55
+ const nonPrettyText = await (await app.request('?pretty')).text()
56
+ expect(nonPrettyText).toBe('{"message":"App!"}')
57
+ })
58
+
59
+ it('Should force pretty JSON output when force option is true', async () => {
60
+ const app = new App()
61
+ app.use('*', prettyJSON({ force: true }))
62
+ app.get('/', (c) => {
63
+ return c.json({ message: 'App!' })
64
+ })
65
+
66
+ const resWithoutQuery = await (await app.request('http://localhost/')).text()
67
+ expect(resWithoutQuery).toBe(`{
68
+ "message": "App!"
69
+ }`)
70
+
71
+ const resWithQuery = await (await app.request('http://localhost/?pretty')).text()
72
+ expect(resWithQuery).toBe(`{
73
+ "message": "App!"
74
+ }`)
75
+ })
76
+
77
+ it('Should return pretty JSON output for structured JSON content-types (+json)', async () => {
78
+ const app = new App()
79
+ app.use('*', prettyJSON({ force: true }))
80
+ app.get('/problem', (c) => {
81
+ return c.newResponse(JSON.stringify({ type: 'about:blank', title: 'Bad Request' }), 400, {
82
+ 'Content-Type': 'application/problem+json',
83
+ })
84
+ })
85
+ app.get('/jsonapi', (c) => {
86
+ return c.newResponse(JSON.stringify({ data: { id: '1', type: 'articles' } }), 200, {
87
+ 'Content-Type': 'application/vnd.api+json',
88
+ })
89
+ })
90
+
91
+ const problemRes = await app.request('http://localhost/problem')
92
+ expect(await problemRes.text()).toBe(`{
93
+ "type": "about:blank",
94
+ "title": "Bad Request"
95
+ }`)
96
+
97
+ const jsonApiRes = await app.request('http://localhost/jsonapi')
98
+ expect(await jsonApiRes.text()).toBe(`{
99
+ "data": {
100
+ "id": "1",
101
+ "type": "articles"
102
+ }
103
+ }`)
104
+ })
105
+
106
+ it('Should not touch responses with non-JSON content-types', async () => {
107
+ const app = new App()
108
+ app.use('*', prettyJSON({ force: true }))
109
+ app.get('/text', (c) => c.text('{"message":"App!"}'))
110
+ app.get('/json-seq', (c) => {
111
+ return c.body('{"message":"App!"}', 200, {
112
+ 'Content-Type': 'application/json-seq',
113
+ })
114
+ })
115
+
116
+ const textRes = await app.request('http://localhost/text')
117
+ expect(await textRes.text()).toBe('{"message":"App!"}')
118
+
119
+ const jsonSeqRes = await app.request('http://localhost/json-seq')
120
+ expect(await jsonSeqRes.text()).toBe('{"message":"App!"}')
121
+ })
122
+
123
+ it('Should not break 204 responses with a JSON content-type', async () => {
124
+ const app = new App()
125
+ app.use('*', prettyJSON({ force: true }))
126
+ app.delete('/x', (c) => {
127
+ c.header('Content-Type', 'application/json')
128
+ return c.body(null, 204)
129
+ })
130
+
131
+ const res = await app.request('http://localhost/x', { method: 'DELETE' })
132
+ expect(res.status).toBe(204)
133
+ expect(res.body).toBeNull()
134
+ })
135
+
136
+ it('Should not break 304 responses with a JSON content-type', async () => {
137
+ const app = new App()
138
+ app.use('*', prettyJSON({ force: true }))
139
+ app.get('/x', (c) => {
140
+ c.header('Content-Type', 'application/json')
141
+ return c.body(null, 304)
142
+ })
143
+
144
+ const res = await app.request('http://localhost/x')
145
+ expect(res.status).toBe(304)
146
+ expect(res.body).toBeNull()
147
+ })
148
+
149
+ it('Should not break empty responses with a JSON content-type', async () => {
150
+ const app = new App()
151
+ app.use('*', prettyJSON())
152
+ app.get('/x', () => new Response('', { headers: { 'Content-Type': 'application/json' } }))
153
+
154
+ const res = await app.request('http://localhost/x?pretty')
155
+ expect(res.status).toBe(200)
156
+ expect(await res.text()).toBe('')
157
+ })
158
+
159
+ it('Should pass through a response with an invalid JSON body unchanged', async () => {
160
+ const app = new App()
161
+ app.use('*', prettyJSON({ force: true }))
162
+ app.get(
163
+ '/x',
164
+ () =>
165
+ new Response('not json', {
166
+ status: 200,
167
+ headers: {
168
+ 'Content-Type': 'application/json',
169
+ 'X-Custom': 'custom',
170
+ ETag: '"abc"',
171
+ 'Content-Length': '8',
172
+ },
173
+ })
174
+ )
175
+
176
+ const res = await app.request('http://localhost/x')
177
+ expect(res.status).toBe(200)
178
+ expect(res.headers.get('X-Custom')).toBe('custom')
179
+ expect(res.headers.get('ETag')).toBe('"abc"')
180
+ expect(res.headers.get('Content-Length')).toBe('8')
181
+ expect(await res.text()).toBe('not json')
182
+ })
183
+
184
+ it('Should pass through a response whose body was already consumed by another middleware', async () => {
185
+ const app = new App()
186
+ app.use('*', prettyJSON({ force: true }))
187
+ app.use('*', async (c, next) => {
188
+ await next()
189
+ await c.res.text()
190
+ })
191
+ app.get('/x', (c) => c.json({ message: 'App!' }))
192
+
193
+ // The other middleware has read the body, so the bytes are no longer available;
194
+ // pretty JSON must not turn this into a 500 and must leave the response as is.
195
+ const res = await app.request('http://localhost/x')
196
+ expect(res.status).toBe(200)
197
+ expect(res.bodyUsed).toBe(true)
198
+ await expect(res.text()).rejects.toThrow()
199
+ })
200
+
201
+ it('Should remove a stale Content-Length when the body is prettified', async () => {
202
+ const app = new App()
203
+ app.use('*', prettyJSON({ force: true }))
204
+ app.get(
205
+ '/x',
206
+ () =>
207
+ new Response('{"message":"App!"}', {
208
+ headers: { 'Content-Type': 'application/json', 'Content-Length': '19' },
209
+ })
210
+ )
211
+
212
+ const res = await app.request('http://localhost/x')
213
+ expect(await res.text()).toBe(`{
214
+ "message": "App!"
215
+ }`)
216
+ expect(res.headers.get('Content-Length')).toBeNull()
217
+ })
218
+ })
@@ -0,0 +1,67 @@
1
+ /**
2
+ * @module
3
+ * Pretty JSON Middleware for App.
4
+ */
5
+
6
+ import type { MiddlewareHandler } from '../../types.ts'
7
+
8
+ interface PrettyOptions {
9
+ /**
10
+ * Number of spaces for indentation.
11
+ * @default 2
12
+ */
13
+ space?: number
14
+
15
+ /**
16
+ * Query conditions for when to Pretty.
17
+ * @default 'pretty'
18
+ */
19
+ query?: string
20
+
21
+ /**
22
+ * Force prettification of JSON responses regardless of query parameters.
23
+ * @default false
24
+ */
25
+ force?: boolean
26
+ }
27
+
28
+ const jsonContentTypeRegex = /^application\/(?:[a-z0-9._-]+\+)?json(?=$|[;\s])/i
29
+
30
+ /**
31
+ * Pretty JSON Middleware for App.
32
+ *
33
+ *
34
+ * @param options - The options for the pretty JSON middleware.
35
+ * @returns {MiddlewareHandler} The middleware handler function.
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * const app = new App()
40
+ *
41
+ * app.use(prettyJSON()) // With options: prettyJSON({ space: 4 })
42
+ * app.get('/', (c) => {
43
+ * return c.json({ message: 'App!' })
44
+ * })
45
+ * ```
46
+ */
47
+ export const prettyJSON = (options?: PrettyOptions): MiddlewareHandler => {
48
+ const targetQuery = options?.query ?? 'pretty'
49
+ return async function prettyJSON(c, next) {
50
+ const pretty = options?.force || c.req.query(targetQuery) || c.req.query(targetQuery) === ''
51
+ await next()
52
+ const contentType = c.res.headers.get('Content-Type')
53
+ if (pretty && contentType && jsonContentTypeRegex.test(contentType)) {
54
+ // Read from a clone so that the response is kept intact when the body is not parseable as JSON
55
+ let obj: unknown
56
+ try {
57
+ obj = await c.res.clone().json()
58
+ } catch {
59
+ // e.g. an empty 204 response or a body that is not valid JSON
60
+ return
61
+ }
62
+ c.res = new Response(JSON.stringify(obj, null, options?.space ?? 2), c.res)
63
+ // The length of the body has changed, so remove the stale Content-Length
64
+ c.res.headers.delete('Content-Length')
65
+ }
66
+ }
67
+ }
@@ -0,0 +1,168 @@
1
+ import { requestId } from './index.ts'
2
+ import type { Context } from '../../context.ts'
3
+ import { App } from '../../app.ts'
4
+
5
+ const regexUUIDv4 = /([0-9a-f]{8})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{12})/
6
+
7
+ describe('Request ID Middleware', () => {
8
+ const app = new App()
9
+ app.use('*', requestId())
10
+ app.get('/requestId', (c) => c.text(c.get('requestId') ?? 'No Request ID'))
11
+
12
+ it('Should return random request id', async () => {
13
+ const res = await app.request('http://localhost/requestId')
14
+ expect(res).not.toBeNull()
15
+ expect(res.status).toBe(200)
16
+ expect(res.headers.get('X-Request-Id')).toMatch(regexUUIDv4)
17
+ expect(await res.text()).match(regexUUIDv4)
18
+ })
19
+
20
+ it('Should return custom request id', async () => {
21
+ const res = await app.request('http://localhost/requestId', {
22
+ headers: {
23
+ 'X-Request-Id': 'acryl-is-hot',
24
+ },
25
+ })
26
+ expect(res).not.toBeNull()
27
+ expect(res.status).toBe(200)
28
+ expect(res.headers.get('X-Request-Id')).toBe('acryl-is-hot')
29
+ expect(await res.text()).toBe('acryl-is-hot')
30
+ })
31
+
32
+ it('Should return custom request id with all valid characters', async () => {
33
+ const validRequestId = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_='
34
+ const res = await app.request('http://localhost/requestId', {
35
+ headers: {
36
+ 'X-Request-Id': validRequestId,
37
+ },
38
+ })
39
+ expect(res).not.toBeNull()
40
+ expect(res.status).toBe(200)
41
+ expect(res.headers.get('X-Request-Id')).toBe(validRequestId)
42
+ expect(await res.text()).toBe(validRequestId)
43
+ })
44
+
45
+ it('Should return random request id without using request header', async () => {
46
+ const res = await app.request('http://localhost/requestId', {
47
+ headers: {
48
+ 'X-Request-Id': 'Hello!12345-@*^',
49
+ },
50
+ })
51
+ expect(res).not.toBeNull()
52
+ expect(res.status).toBe(200)
53
+ expect(res.headers.get('X-Request-Id')).toMatch(regexUUIDv4)
54
+ expect(await res.text()).toMatch(regexUUIDv4)
55
+ })
56
+ })
57
+
58
+ describe('Request ID Middleware with custom generator', () => {
59
+ function generateWord() {
60
+ return 'AppIsWebFramework'
61
+ }
62
+ function generateDoubleRequestId(c: Context) {
63
+ const appId = c.req.header('App-Request-Id')
64
+ const ohnoId = c.req.header('Ohno-Request-Id')
65
+ if (appId && ohnoId) {
66
+ return appId + ohnoId
67
+ }
68
+ return crypto.randomUUID()
69
+ }
70
+ const app = new App()
71
+ app.use('/word', requestId({ generator: generateWord }))
72
+ app.use('/doubleRequestId', requestId({ generator: generateDoubleRequestId }))
73
+ app.get('/word', (c) => c.text(c.get('requestId') ?? 'No Request ID'))
74
+ app.get('/doubleRequestId', (c) => c.text(c.get('requestId') ?? 'No Request ID'))
75
+ it('Should return custom request id', async () => {
76
+ const res = await app.request('http://localhost/word')
77
+ expect(res).not.toBeNull()
78
+ expect(res.status).toBe(200)
79
+ expect(res.headers.get('X-Request-Id')).toBe('AppIsWebFramework')
80
+ expect(await res.text()).toBe('AppIsWebFramework')
81
+ })
82
+
83
+ it('Should return complex request id', async () => {
84
+ const res = await app.request('http://localhost/doubleRequestId', {
85
+ headers: {
86
+ 'App-Request-Id': 'Hello',
87
+ 'Ohno-Request-Id': 'World',
88
+ },
89
+ })
90
+ expect(res).not.toBeNull()
91
+ expect(res.status).toBe(200)
92
+ expect(res.headers.get('X-Request-Id')).toBe('HelloWorld')
93
+ expect(await res.text()).toBe('HelloWorld')
94
+ })
95
+ })
96
+
97
+ describe('Request ID Middleware with limit length', () => {
98
+ const charactersOf255 = 'h'.repeat(255)
99
+ const charactersOf256 = 'h'.repeat(256)
100
+
101
+ const app = new App()
102
+ app.use('/requestId', requestId())
103
+ app.use('/limit256', requestId({ limitLength: 256 }))
104
+ app.get('/requestId', (c) => c.text(c.get('requestId') ?? 'No Request ID'))
105
+ app.get('/limit256', (c) => c.text(c.get('requestId') ?? 'No Request ID'))
106
+
107
+ it('Should return custom request id', async () => {
108
+ const res = await app.request('http://localhost/requestId', {
109
+ headers: {
110
+ 'X-Request-Id': charactersOf255,
111
+ },
112
+ })
113
+ expect(res).not.toBeNull()
114
+ expect(res.status).toBe(200)
115
+ expect(res.headers.get('X-Request-Id')).toBe(charactersOf255)
116
+ expect(await res.text()).toBe(charactersOf255)
117
+ })
118
+ it('Should return random request id without using request header', async () => {
119
+ const res = await app.request('http://localhost/requestId', {
120
+ headers: {
121
+ 'X-Request-Id': charactersOf256,
122
+ },
123
+ })
124
+ expect(res).not.toBeNull()
125
+ expect(res.status).toBe(200)
126
+ expect(res.headers.get('X-Request-Id')).toMatch(regexUUIDv4)
127
+ expect(await res.text()).toMatch(regexUUIDv4)
128
+ })
129
+ it('Should return custom request id with 256 characters', async () => {
130
+ const res = await app.request('http://localhost/limit256', {
131
+ headers: {
132
+ 'X-Request-Id': charactersOf256,
133
+ },
134
+ })
135
+ expect(res).not.toBeNull()
136
+ expect(res.status).toBe(200)
137
+ expect(res.headers.get('X-Request-Id')).toBe(charactersOf256)
138
+ expect(await res.text()).toBe(charactersOf256)
139
+ })
140
+ })
141
+
142
+ describe('Request ID Middleware with custom header', () => {
143
+ const app = new App()
144
+ app.use('/requestId', requestId({ headerName: 'App-Request-Id' }))
145
+ app.get('/emptyId', requestId({ headerName: '' }))
146
+ app.get('/requestId', (c) => c.text(c.get('requestId') ?? 'No Request ID'))
147
+ app.get('/emptyId', (c) => c.text(c.get('requestId') ?? 'No Request ID'))
148
+
149
+ it('Should return custom request id', async () => {
150
+ const res = await app.request('http://localhost/requestId', {
151
+ headers: {
152
+ 'App-Request-Id': 'acryl-is-hot',
153
+ },
154
+ })
155
+ expect(res).not.toBeNull()
156
+ expect(res.status).toBe(200)
157
+ expect(res.headers.get('App-Request-Id')).toBe('acryl-is-hot')
158
+ expect(await res.text()).toBe('acryl-is-hot')
159
+ })
160
+
161
+ it('Should not return request id', async () => {
162
+ const res = await app.request('http://localhost/emptyId')
163
+ expect(res).not.toBeNull()
164
+ expect(res.status).toBe(200)
165
+ expect(res.headers.get('X-Request-Id')).toBeNull()
166
+ expect(await res.text()).toMatch(regexUUIDv4)
167
+ })
168
+ })
@@ -0,0 +1,7 @@
1
+ import type { RequestIdVariables } from './request-id.ts'
2
+ export type { RequestIdVariables }
3
+ export { requestId } from './request-id.ts'
4
+
5
+ declare module '../../context.ts' {
6
+ interface ContextVariableMap extends RequestIdVariables {}
7
+ }