acrylblends 0.4.1 → 0.5.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 (416) hide show
  1. package/LICENSE +73 -0
  2. package/docs/framework/README.md +51 -51
  3. package/docs/framework/UPSTREAM.md +1 -1
  4. package/docs/framework/agents/index.md +24 -0
  5. package/docs/framework/api/acryl.md +259 -0
  6. package/docs/framework/api/context.md +527 -0
  7. package/docs/framework/api/exception.md +80 -0
  8. package/docs/framework/api/index.md +12 -0
  9. package/docs/framework/api/presets.md +65 -0
  10. package/docs/framework/api/request.md +396 -0
  11. package/docs/framework/api/routing.md +303 -0
  12. package/docs/framework/{api-summary.md → api/summary.md} +19 -17
  13. package/docs/framework/concepts/benchmarks.md +26 -0
  14. package/docs/framework/concepts/developer-experience.md +5 -0
  15. package/docs/framework/concepts/middleware.md +21 -0
  16. package/docs/framework/concepts/motivation.md +14 -0
  17. package/docs/framework/concepts/routers.md +63 -0
  18. package/docs/framework/concepts/stacks.md +235 -0
  19. package/docs/framework/concepts/web-standard.md +37 -0
  20. package/docs/framework/{getting-started.md → cordis/acryl-in-a-cordis-app.md} +16 -16
  21. package/docs/framework/{concepts.md → cordis/concepts.md} +2 -2
  22. package/docs/framework/cordis/middleware.md +8 -0
  23. package/docs/framework/{migration-from-0-3.md → cordis/migration-from-0-3.md} +16 -13
  24. package/docs/framework/cordis/migration-from-0-4.md +14 -0
  25. package/docs/framework/{migration-from-dsh-webserver.md → cordis/migration-from-dsh-webserver.md} +7 -7
  26. package/docs/framework/{routing.md → cordis/mounting.md} +5 -108
  27. package/docs/framework/{node-server.md → cordis/node-server.md} +4 -4
  28. package/docs/framework/{surfaces.md → cordis/surfaces.md} +2 -2
  29. package/docs/framework/cordis/transport-and-cancellation.md +57 -0
  30. package/docs/framework/{validation.md → cordis/validation.md} +9 -9
  31. package/docs/framework/getting-started/basic.md +196 -0
  32. package/docs/framework/getting-started/bun.md +221 -0
  33. package/docs/framework/getting-started/nodejs.md +344 -0
  34. package/docs/framework/getting-started/other-runtimes.md +23 -0
  35. package/docs/framework/guides/best-practices.md +231 -0
  36. package/docs/framework/guides/create-acrylblends.md +79 -0
  37. package/docs/framework/guides/examples.md +3 -0
  38. package/docs/framework/guides/faq.md +19 -0
  39. package/docs/framework/guides/helpers.md +33 -0
  40. package/docs/framework/guides/jsx-dom.md +299 -0
  41. package/docs/framework/guides/jsx.md +440 -0
  42. package/docs/framework/guides/middleware.md +253 -0
  43. package/docs/framework/guides/rpc.md +886 -0
  44. package/docs/framework/guides/testing.md +133 -0
  45. package/docs/framework/guides/validation.md +383 -0
  46. package/docs/framework/helpers/accepts.md +60 -0
  47. package/docs/framework/helpers/adapter.md +87 -0
  48. package/docs/framework/helpers/conninfo.md +112 -0
  49. package/docs/framework/helpers/cookie.md +232 -0
  50. package/docs/framework/helpers/css.md +285 -0
  51. package/docs/framework/helpers/dev.md +67 -0
  52. package/docs/framework/helpers/factory.md +180 -0
  53. package/docs/framework/helpers/html.md +123 -0
  54. package/docs/framework/helpers/jwt.md +184 -0
  55. package/docs/framework/helpers/proxy.md +118 -0
  56. package/docs/framework/helpers/route.md +143 -0
  57. package/docs/framework/helpers/ssg.md +393 -0
  58. package/docs/framework/helpers/streaming.md +119 -0
  59. package/docs/framework/helpers/testing.md +101 -0
  60. package/docs/framework/helpers/websocket.md +215 -0
  61. package/docs/framework/middleware/builtin/basic-auth.md +165 -0
  62. package/docs/framework/middleware/builtin/bearer-auth.md +138 -0
  63. package/docs/framework/middleware/builtin/body-limit.md +71 -0
  64. package/docs/framework/middleware/builtin/cache.md +122 -0
  65. package/docs/framework/middleware/builtin/combine.md +94 -0
  66. package/docs/framework/middleware/builtin/compress.md +59 -0
  67. package/docs/framework/middleware/builtin/context-storage.md +78 -0
  68. package/docs/framework/middleware/builtin/cors.md +135 -0
  69. package/docs/framework/middleware/builtin/csrf.md +105 -0
  70. package/docs/framework/middleware/builtin/etag.md +54 -0
  71. package/docs/framework/middleware/builtin/ip-restriction.md +69 -0
  72. package/docs/framework/middleware/builtin/jsx-renderer.md +286 -0
  73. package/docs/framework/middleware/builtin/jwk.md +192 -0
  74. package/docs/framework/middleware/builtin/jwt.md +145 -0
  75. package/docs/framework/middleware/builtin/language.md +232 -0
  76. package/docs/framework/middleware/builtin/logger.md +74 -0
  77. package/docs/framework/middleware/builtin/loopback-only.md +31 -0
  78. package/docs/framework/middleware/builtin/method-not-allowed.md +48 -0
  79. package/docs/framework/middleware/builtin/method-override.md +80 -0
  80. package/docs/framework/middleware/builtin/mount.md +106 -0
  81. package/docs/framework/middleware/builtin/pretty-json.md +53 -0
  82. package/docs/framework/middleware/builtin/request-id.md +94 -0
  83. package/docs/framework/middleware/builtin/secure-headers.md +247 -0
  84. package/docs/framework/middleware/builtin/timeout.md +98 -0
  85. package/docs/framework/middleware/builtin/timing.md +101 -0
  86. package/docs/framework/middleware/builtin/trailing-slash.md +74 -0
  87. package/docs/framework/middleware/third-party.md +4 -0
  88. package/docs/framework/upstream.json +3 -3
  89. package/lib/accepts-XBuZPVRI.js +52 -0
  90. package/lib/accepts.d.ts +33 -0
  91. package/lib/accepts.js +2 -0
  92. package/lib/acryl-base.d.ts +2 -0
  93. package/lib/acryl-base.js +332 -0
  94. package/lib/adapter.d.ts +12 -0
  95. package/lib/adapter.js +37 -0
  96. package/lib/app-BM0rTCp7.js +26 -0
  97. package/lib/app-CmAYW1Al.d.ts +21 -0
  98. package/lib/basic-auth.d.ts +72 -0
  99. package/lib/basic-auth.js +95 -0
  100. package/lib/bearer-auth.d.ts +89 -0
  101. package/lib/bearer-auth.js +94 -0
  102. package/lib/body-limit.d.ts +42 -0
  103. package/lib/body-limit.js +66 -0
  104. package/lib/client-BHTr318g.js +266 -0
  105. package/lib/client.d.ts +3 -0
  106. package/lib/client.js +2 -0
  107. package/lib/combine.d.ts +85 -0
  108. package/lib/combine.js +137 -0
  109. package/lib/compose-BuW2B6PZ.js +50 -0
  110. package/lib/compress.d.ts +38 -0
  111. package/lib/compress.js +79 -0
  112. package/lib/connection-C7xgP1hP.js +24 -0
  113. package/lib/conninfo.d.ts +25 -0
  114. package/lib/conninfo.js +2 -0
  115. package/lib/constants-Dy7ZvN1H.js +4 -0
  116. package/lib/context-Bm7rI-oK.d.ts +1234 -0
  117. package/lib/context-DDO0cfuP.js +365 -0
  118. package/lib/context-storage.d.ts +38 -0
  119. package/lib/context-storage.js +52 -0
  120. package/lib/cookie-ClMaKDQf.d.ts +40 -0
  121. package/lib/cookie.d.ts +24 -0
  122. package/lib/cookie.js +82 -0
  123. package/lib/cors.d.ts +52 -0
  124. package/lib/cors.js +106 -0
  125. package/lib/csrf.d.ts +75 -0
  126. package/lib/csrf.js +101 -0
  127. package/lib/etag.d.ts +40 -0
  128. package/lib/etag.js +135 -0
  129. package/lib/factory.d.ts +35 -0
  130. package/lib/factory.js +30 -0
  131. package/lib/headers-tu2YYN8T.d.ts +11 -0
  132. package/lib/html.d.ts +6 -0
  133. package/lib/html.js +31 -0
  134. package/lib/http-exception.d.ts +57 -0
  135. package/lib/http-exception.js +54 -0
  136. package/lib/http-status-DaAwGAFL.d.ts +35 -0
  137. package/lib/index-B-3F4wt2.d.ts +12 -0
  138. package/lib/index-UTBmM3GX.d.ts +68 -0
  139. package/lib/index-oOClm_Xk.d.ts +45 -0
  140. package/lib/index.d.ts +5 -0
  141. package/lib/index.js +28 -0
  142. package/lib/ip-restriction.d.ts +68 -0
  143. package/lib/ip-restriction.js +166 -0
  144. package/lib/jwk.d.ts +52 -0
  145. package/lib/jwk.js +117 -0
  146. package/lib/jwt-BGJBw5AF.js +403 -0
  147. package/lib/jwt-Dg493Tai.d.ts +51 -0
  148. package/lib/jwt.d.ts +72 -0
  149. package/lib/jwt.js +115 -0
  150. package/lib/language.d.ts +88 -0
  151. package/lib/language.js +198 -0
  152. package/lib/logger.d.ts +22 -0
  153. package/lib/logger.js +54 -0
  154. package/lib/loopback-only.d.ts +45 -0
  155. package/lib/loopback-only.js +90 -0
  156. package/lib/method-not-allowed.d.ts +47 -0
  157. package/lib/method-not-allowed.js +82 -0
  158. package/lib/method-override.d.ts +46 -0
  159. package/lib/method-override.js +103 -0
  160. package/lib/mime-BQOYHl-l.d.ts +72 -0
  161. package/lib/node-server/conninfo.d.ts +11 -0
  162. package/lib/node-server/conninfo.js +19 -0
  163. package/lib/node-server/serve-static.d.ts +19 -0
  164. package/lib/node-server/serve-static.js +2 -0
  165. package/lib/node-server.d.ts +103 -0
  166. package/lib/node-server.js +1325 -0
  167. package/lib/powered-by.d.ts +28 -0
  168. package/lib/powered-by.js +24 -0
  169. package/lib/pretty-json.d.ts +40 -0
  170. package/lib/pretty-json.js +39 -0
  171. package/lib/reg-exp-router-DC1R3qoY.js +363 -0
  172. package/lib/request-id.d.ts +45 -0
  173. package/lib/request-id.js +34 -0
  174. package/lib/request.d.ts +2 -0
  175. package/lib/request.js +323 -0
  176. package/lib/route.d.ts +78 -0
  177. package/lib/route.js +126 -0
  178. package/lib/router/linear-router.d.ts +11 -0
  179. package/lib/router/linear-router.js +96 -0
  180. package/lib/router/pattern-router.d.ts +11 -0
  181. package/lib/router/pattern-router.js +41 -0
  182. package/lib/router/reg-exp-router.d.ts +35 -0
  183. package/lib/router/reg-exp-router.js +2 -0
  184. package/lib/router/smart-router.d.ts +15 -0
  185. package/lib/router/smart-router.js +2 -0
  186. package/lib/router/trie-router.d.ts +11 -0
  187. package/lib/router/trie-router.js +2 -0
  188. package/lib/router-CvUxUTOq.d.ts +99 -0
  189. package/lib/router.d.ts +2 -0
  190. package/lib/router.js +35 -0
  191. package/lib/schema-validator.d.ts +28 -0
  192. package/lib/schema-validator.js +22 -0
  193. package/lib/secure-headers.d.ts +125 -0
  194. package/lib/secure-headers.js +163 -0
  195. package/lib/serve-static-Dw_m6KxR.js +213 -0
  196. package/lib/serve-static.d.ts +31 -0
  197. package/lib/serve-static.js +77 -0
  198. package/lib/smart-router-C5CZ5XSM.js +49 -0
  199. package/lib/stream-CPdqZ0Fp.d.ts +34 -0
  200. package/lib/streaming-DHST3Scg.js +96 -0
  201. package/lib/streaming.d.ts +23 -0
  202. package/lib/streaming.js +2 -0
  203. package/lib/testing.d.ts +10 -0
  204. package/lib/testing.js +17 -0
  205. package/lib/timeout.d.ts +30 -0
  206. package/lib/timeout.js +42 -0
  207. package/lib/timing.d.ts +130 -0
  208. package/lib/timing.js +183 -0
  209. package/lib/trailing-slash.d.ts +91 -0
  210. package/lib/trailing-slash.js +85 -0
  211. package/lib/trie-router-CfFbapzL.js +146 -0
  212. package/lib/types-CDO6I3B0.d.ts +40 -0
  213. package/lib/types-CHesD1KG.d.ts +195 -0
  214. package/lib/types-CwrQjlaM.d.ts +105 -0
  215. package/lib/types-DR95J00T.d.ts +29 -0
  216. package/lib/types.d.ts +2 -0
  217. package/lib/types.js +4 -0
  218. package/lib/utils/accept.d.ts +9 -0
  219. package/lib/utils/accept.js +193 -0
  220. package/lib/utils/basic-auth.d.ts +8 -0
  221. package/lib/utils/basic-auth.js +20 -0
  222. package/lib/utils/body.d.ts +2 -0
  223. package/lib/utils/body.js +94 -0
  224. package/lib/utils/buffer.d.ts +19 -0
  225. package/lib/utils/buffer.js +51 -0
  226. package/lib/utils/color.d.ts +24 -0
  227. package/lib/utils/color.js +37 -0
  228. package/lib/utils/compress.d.ts +11 -0
  229. package/lib/utils/compress.js +11 -0
  230. package/lib/utils/concurrent.d.ts +17 -0
  231. package/lib/utils/concurrent.js +30 -0
  232. package/lib/utils/constants.d.ts +7 -0
  233. package/lib/utils/constants.js +7 -0
  234. package/lib/utils/cookie.d.ts +2 -0
  235. package/lib/utils/cookie.js +125 -0
  236. package/lib/utils/crypto.d.ts +14 -0
  237. package/lib/utils/crypto.js +34 -0
  238. package/lib/utils/encode.d.ts +11 -0
  239. package/lib/utils/encode.js +33 -0
  240. package/lib/utils/filepath.d.ts +14 -0
  241. package/lib/utils/filepath.js +25 -0
  242. package/lib/utils/handler.d.ts +9 -0
  243. package/lib/utils/handler.js +12 -0
  244. package/lib/utils/headers.d.ts +2 -0
  245. package/lib/utils/headers.js +1 -0
  246. package/lib/utils/html.d.ts +46 -0
  247. package/lib/utils/html.js +103 -0
  248. package/lib/utils/http-status.d.ts +2 -0
  249. package/lib/utils/http-status.js +1 -0
  250. package/lib/utils/ipaddr.d.ts +56 -0
  251. package/lib/utils/ipaddr.js +238 -0
  252. package/lib/utils/jwt.d.ts +24 -0
  253. package/lib/utils/jwt.js +2 -0
  254. package/lib/utils/mime.d.ts +2 -0
  255. package/lib/utils/mime.js +77 -0
  256. package/lib/utils/stream.d.ts +2 -0
  257. package/lib/utils/stream.js +88 -0
  258. package/lib/utils/types.d.ts +2 -0
  259. package/lib/utils/types.js +1 -0
  260. package/lib/utils/url.d.ts +46 -0
  261. package/lib/utils/url.js +197 -0
  262. package/lib/utils-dw8lxqjL.js +4 -0
  263. package/lib/validator-D84mq-dO.js +65 -0
  264. package/lib/validator.d.ts +42 -0
  265. package/lib/validator.js +2 -0
  266. package/lib/ws.d.ts +2 -0
  267. package/lib/ws.js +53 -0
  268. package/package.json +312 -14
  269. package/plugins/acryl-inspect/src/service.ts +2 -2
  270. package/plugins/acryl-inspect/tests/service.spec.ts +3 -3
  271. package/plugins/acryl-inspect/upstream.json +2 -2
  272. package/plugins/acryl-node-server/tests/adapter/app.ts +2 -2
  273. package/plugins/acryl-node-server/tests/adapter/assets/static/acryl.html +1 -1
  274. package/plugins/acryl-node-server/tests/adapter/assets/static/index.html +1 -1
  275. package/plugins/acryl-node-server/tests/adapter/conninfo.test.ts +2 -2
  276. package/plugins/acryl-node-server/tests/adapter/content-length.test.ts +4 -4
  277. package/plugins/acryl-node-server/tests/adapter/early-hints.test.ts +5 -5
  278. package/plugins/acryl-node-server/tests/adapter/request-client-disconnect.test.ts +2 -2
  279. package/plugins/acryl-node-server/tests/adapter/serve-static.test.ts +20 -20
  280. package/plugins/acryl-node-server/tests/adapter/server-socket.test.ts +2 -2
  281. package/plugins/acryl-node-server/tests/adapter/server.test.ts +50 -50
  282. package/plugins/acryl-node-server/tests/adapter/utils/response.test.ts +4 -4
  283. package/plugins/acryl-node-server/tests/adapter/websocket.test.ts +9 -9
  284. package/plugins/acryl-node-server/tests/server.spec.ts +6 -6
  285. package/plugins/acryl-node-server/upstream.json +2 -2
  286. package/plugins/acryl-router/src/client.ts +1 -1
  287. package/plugins/acryl-router/src/connection.ts +2 -2
  288. package/plugins/acryl-router/src/core/app-base.ts +29 -29
  289. package/plugins/acryl-router/src/core/app.test.ts +175 -175
  290. package/plugins/acryl-router/src/core/app.ts +8 -8
  291. package/plugins/acryl-router/src/core/client/client.test.ts +76 -76
  292. package/plugins/acryl-router/src/core/client/client.ts +2 -2
  293. package/plugins/acryl-router/src/core/client/fetch-result-please.ts +1 -1
  294. package/plugins/acryl-router/src/core/client/index.ts +1 -1
  295. package/plugins/acryl-router/src/core/client/types.test.ts +6 -6
  296. package/plugins/acryl-router/src/core/client/types.ts +16 -16
  297. package/plugins/acryl-router/src/core/client/utils.test.ts +2 -2
  298. package/plugins/acryl-router/src/core/context.test.ts +4 -4
  299. package/plugins/acryl-router/src/core/context.ts +6 -6
  300. package/plugins/acryl-router/src/core/helper/accepts/accepts.test.ts +3 -3
  301. package/plugins/acryl-router/src/core/helper/accepts/index.ts +1 -1
  302. package/plugins/acryl-router/src/core/helper/adapter/index.test.ts +6 -6
  303. package/plugins/acryl-router/src/core/helper/adapter/index.ts +1 -1
  304. package/plugins/acryl-router/src/core/helper/conninfo/index.ts +1 -1
  305. package/plugins/acryl-router/src/core/helper/cookie/index.test.ts +8 -8
  306. package/plugins/acryl-router/src/core/helper/cookie/index.ts +1 -1
  307. package/plugins/acryl-router/src/core/helper/factory/index.test.ts +9 -9
  308. package/plugins/acryl-router/src/core/helper/factory/index.ts +10 -10
  309. package/plugins/acryl-router/src/core/helper/html/index.test.ts +4 -4
  310. package/plugins/acryl-router/src/core/helper/html/index.ts +1 -1
  311. package/plugins/acryl-router/src/core/helper/route/index.test.ts +7 -7
  312. package/plugins/acryl-router/src/core/helper/route/index.ts +8 -8
  313. package/plugins/acryl-router/src/core/helper/streaming/index.ts +1 -1
  314. package/plugins/acryl-router/src/core/helper/testing/index.test.ts +6 -6
  315. package/plugins/acryl-router/src/core/helper/testing/index.ts +4 -4
  316. package/plugins/acryl-router/src/core/helper/websocket/index.ts +2 -1
  317. package/plugins/acryl-router/src/core/http-exception.ts +1 -1
  318. package/plugins/acryl-router/src/core/index.ts +9 -9
  319. package/plugins/acryl-router/src/core/middleware/basic-auth/index.test.ts +6 -6
  320. package/plugins/acryl-router/src/core/middleware/basic-auth/index.ts +3 -3
  321. package/plugins/acryl-router/src/core/middleware/bearer-auth/index.test.ts +5 -5
  322. package/plugins/acryl-router/src/core/middleware/bearer-auth/index.ts +3 -3
  323. package/plugins/acryl-router/src/core/middleware/body-limit/index.test.ts +6 -6
  324. package/plugins/acryl-router/src/core/middleware/body-limit/index.ts +3 -3
  325. package/plugins/acryl-router/src/core/middleware/combine/index.test.ts +9 -9
  326. package/plugins/acryl-router/src/core/middleware/combine/index.ts +7 -7
  327. package/plugins/acryl-router/src/core/middleware/compress/index.test.ts +9 -9
  328. package/plugins/acryl-router/src/core/middleware/compress/index.ts +3 -3
  329. package/plugins/acryl-router/src/core/middleware/context-storage/index.test.ts +5 -5
  330. package/plugins/acryl-router/src/core/middleware/context-storage/index.ts +4 -4
  331. package/plugins/acryl-router/src/core/middleware/cors/index.test.ts +7 -7
  332. package/plugins/acryl-router/src/core/middleware/cors/index.ts +3 -3
  333. package/plugins/acryl-router/src/core/middleware/csrf/index.test.ts +10 -10
  334. package/plugins/acryl-router/src/core/middleware/csrf/index.ts +3 -3
  335. package/plugins/acryl-router/src/core/middleware/etag/index.test.ts +42 -42
  336. package/plugins/acryl-router/src/core/middleware/etag/index.ts +4 -4
  337. package/plugins/acryl-router/src/core/middleware/ip-restriction/index.test.ts +4 -4
  338. package/plugins/acryl-router/src/core/middleware/ip-restriction/index.ts +6 -6
  339. package/plugins/acryl-router/src/core/middleware/jwk/index.test.ts +16 -16
  340. package/plugins/acryl-router/src/core/middleware/jwk/jwk.ts +7 -6
  341. package/plugins/acryl-router/src/core/middleware/jwt/index.test.ts +16 -16
  342. package/plugins/acryl-router/src/core/middleware/jwt/jwt.ts +4 -3
  343. package/plugins/acryl-router/src/core/middleware/language/index.test.ts +3 -3
  344. package/plugins/acryl-router/src/core/middleware/language/language.ts +3 -3
  345. package/plugins/acryl-router/src/core/middleware/logger/index.test.ts +5 -5
  346. package/plugins/acryl-router/src/core/middleware/logger/index.ts +4 -4
  347. package/plugins/acryl-router/src/core/middleware/method-not-allowed/index.test.ts +24 -24
  348. package/plugins/acryl-router/src/core/middleware/method-not-allowed/index.ts +8 -8
  349. package/plugins/acryl-router/src/core/middleware/method-override/index.test.ts +5 -5
  350. package/plugins/acryl-router/src/core/middleware/method-override/index.ts +6 -6
  351. package/plugins/acryl-router/src/core/middleware/powered-by/index.test.ts +4 -4
  352. package/plugins/acryl-router/src/core/middleware/powered-by/index.ts +6 -6
  353. package/plugins/acryl-router/src/core/middleware/pretty-json/index.test.ts +30 -30
  354. package/plugins/acryl-router/src/core/middleware/pretty-json/index.ts +4 -4
  355. package/plugins/acryl-router/src/core/middleware/request-id/index.test.ts +15 -15
  356. package/plugins/acryl-router/src/core/middleware/request-id/request-id.ts +3 -3
  357. package/plugins/acryl-router/src/core/middleware/secure-headers/index.test.ts +35 -35
  358. package/plugins/acryl-router/src/core/middleware/secure-headers/secure-headers.ts +3 -3
  359. package/plugins/acryl-router/src/core/middleware/serve-static/index.test.ts +23 -23
  360. package/plugins/acryl-router/src/core/middleware/serve-static/index.ts +1 -1
  361. package/plugins/acryl-router/src/core/middleware/timeout/index.test.ts +2 -2
  362. package/plugins/acryl-router/src/core/middleware/timeout/index.ts +3 -3
  363. package/plugins/acryl-router/src/core/middleware/timing/index.test.ts +14 -14
  364. package/plugins/acryl-router/src/core/middleware/timing/timing.ts +3 -3
  365. package/plugins/acryl-router/src/core/middleware/trailing-slash/index.test.ts +7 -7
  366. package/plugins/acryl-router/src/core/middleware/trailing-slash/index.ts +7 -7
  367. package/plugins/acryl-router/src/core/request.test.ts +42 -42
  368. package/plugins/acryl-router/src/core/request.ts +6 -6
  369. package/plugins/acryl-router/src/core/router/linear-router/index.ts +1 -1
  370. package/plugins/acryl-router/src/core/router/pattern-router/index.ts +1 -1
  371. package/plugins/acryl-router/src/core/router/reg-exp-router/index.ts +1 -1
  372. package/plugins/acryl-router/src/core/router/smart-router/index.ts +1 -1
  373. package/plugins/acryl-router/src/core/router/trie-router/index.ts +1 -1
  374. package/plugins/acryl-router/src/core/types.test.ts +115 -115
  375. package/plugins/acryl-router/src/core/types.ts +72 -72
  376. package/plugins/acryl-router/src/core/utils/body.ts +8 -8
  377. package/plugins/acryl-router/src/core/utils/html.ts +1 -1
  378. package/plugins/acryl-router/src/core/utils/jwt/jws.ts +3 -3
  379. package/plugins/acryl-router/src/core/utils/jwt/jwt.test.ts +2 -2
  380. package/plugins/acryl-router/src/core/utils/jwt/jwt.ts +3 -3
  381. package/plugins/acryl-router/src/core/utils/jwt/types.ts +1 -1
  382. package/plugins/acryl-router/src/core/utils/types.ts +42 -0
  383. package/plugins/acryl-router/src/core/utils/url.test.ts +2 -2
  384. package/plugins/acryl-router/src/core/validator/index.ts +1 -1
  385. package/plugins/acryl-router/src/core/validator/validator.test.ts +28 -28
  386. package/plugins/acryl-router/src/deprecated.ts +15 -0
  387. package/plugins/acryl-router/src/index.ts +3 -2
  388. package/plugins/acryl-router/src/service.ts +10 -10
  389. package/plugins/acryl-router/tests/docs-examples.spec.ts +11 -11
  390. package/plugins/acryl-router/tests/live-install.spec.ts +2 -2
  391. package/plugins/acryl-router/tests/loader.spec.ts +3 -3
  392. package/plugins/acryl-router/tests/loopback-only.spec.ts +4 -4
  393. package/plugins/acryl-router/tests/no-dom/consumer.ts +11 -0
  394. package/plugins/acryl-router/tests/no-dom/tsconfig.json +13 -0
  395. package/plugins/acryl-router/tests/service.spec.ts +23 -23
  396. package/plugins/acryl-router/upstream.json +3 -3
  397. package/plugins/acryl-router-http/tests/adapter.spec.ts +3 -3
  398. package/plugins/acryl-router-http/tests/surfaces.spec.ts +2 -2
  399. package/plugins/acryl-router-http/upstream.json +2 -2
  400. package/plugins/acryl-state/src/service.ts +2 -2
  401. package/plugins/acryl-state/upstream.json +2 -2
  402. package/plugins/builder/script.ts +2 -2
  403. package/plugins/extensions/resolve.ts +70 -10
  404. package/plugins/openai/prompt.ts +5 -5
  405. package/shared/AGENTS.core.md +16 -9
  406. package/templates/agent/src/routes.ts +2 -2
  407. package/templates/agent/test/model.test.ts +2 -2
  408. package/templates/agent/tsconfig.json +40 -0
  409. package/templates/blank/src/routes.ts +2 -2
  410. package/templates/todo/src/todo.ts +2 -2
  411. package/templates/todo/upstream.json +2 -2
  412. package/docs/framework/context.md +0 -129
  413. package/docs/framework/helpers.md +0 -118
  414. package/docs/framework/middleware.md +0 -154
  415. package/docs/framework/request.md +0 -106
  416. /package/docs/framework/{plugin-lifecycle.md → cordis/plugin-lifecycle.md} +0 -0
package/lib/jwt.js ADDED
@@ -0,0 +1,115 @@
1
+ import { HTTPException } from "./http-exception.js";
2
+ import { getCookie, getSignedCookie } from "./cookie.js";
3
+ import { n as AlgorithmTypes, t as Jwt } from "./jwt-BGJBw5AF.js";
4
+ //#region ../../plugins/acryl-router/src/core/middleware/jwt/jwt.ts
5
+ /**
6
+ * JWT Auth Middleware for Acryl.
7
+ *
8
+ *
9
+ * @param {object} options - The options for the JWT middleware.
10
+ * @param {SignatureKey} options.secret - A value of your secret key.
11
+ * @param {string} [options.cookie] - If this value is set, then the value is retrieved from the cookie header using that value as a key, which is then validated as a token.
12
+ * @param {SignatureAlgorithm} options.alg - An algorithm type that is used for verifying (required). Available types are `HS256` | `HS384` | `HS512` | `RS256` | `RS384` | `RS512` | `PS256` | `PS384` | `PS512` | `ES256` | `ES384` | `ES512` | `EdDSA`.
13
+ * @param {string} [options.headerName='Authorization'] - The name of the header to look for the JWT token. Default is 'Authorization'.
14
+ * @param {string} [options.realm] - The protection space described by the `realm` parameter of the returned `WWW-Authenticate` challenge header. Defaults to the request URL.
15
+ * @param {VerifyOptions} [options.verification] - Additional options for JWT payload verification.
16
+ * @returns {MiddlewareHandler} The middleware handler function.
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * const app = new Acryl()
21
+ *
22
+ * app.use(
23
+ * '/auth/*',
24
+ * jwt({
25
+ * secret: process.env.JWT_SECRET, // never a literal in source
26
+ * alg: 'HS256',
27
+ * headerName: 'x-custom-auth-header', // Optional, default is 'Authorization'
28
+ * })
29
+ * )
30
+ *
31
+ * app.get('/auth/page', (c) => {
32
+ * return c.text('You are authorized')
33
+ * })
34
+ * ```
35
+ */
36
+ const jwt = (options) => {
37
+ const verifyOpts = options.verification || {};
38
+ if (!options || !options.secret) throw new Error("JWT auth middleware requires options for \"secret\"");
39
+ if (!options.alg) throw new Error("JWT auth middleware requires options for \"alg\"");
40
+ if (!crypto.subtle || !crypto.subtle.importKey) throw new Error("`crypto.subtle.importKey` is undefined. JWT auth middleware requires it.");
41
+ return async function jwt(ctx, next) {
42
+ const headerName = options.headerName || "Authorization";
43
+ const credentials = ctx.req.raw.headers.get(headerName);
44
+ let token;
45
+ if (credentials) {
46
+ const parts = credentials.split(/\s+/);
47
+ if (parts.length !== 2 || parts[0].toLowerCase() !== "bearer") {
48
+ const errDescription = "invalid credentials structure";
49
+ throw new HTTPException(401, {
50
+ message: errDescription,
51
+ res: unauthorizedResponse({
52
+ ctx,
53
+ error: "invalid_request",
54
+ errDescription,
55
+ realm: options.realm
56
+ })
57
+ });
58
+ } else token = parts[1];
59
+ } else if (options.cookie) if (typeof options.cookie == "string") token = getCookie(ctx, options.cookie);
60
+ else if (options.cookie.secret) if (options.cookie.prefixOptions) token = await getSignedCookie(ctx, options.cookie.secret, options.cookie.key, options.cookie.prefixOptions);
61
+ else token = await getSignedCookie(ctx, options.cookie.secret, options.cookie.key);
62
+ else if (options.cookie.prefixOptions) token = getCookie(ctx, options.cookie.key, options.cookie.prefixOptions);
63
+ else token = getCookie(ctx, options.cookie.key);
64
+ if (!token) {
65
+ const errDescription = "no authorization included in request";
66
+ throw new HTTPException(401, {
67
+ message: errDescription,
68
+ res: unauthorizedResponse({
69
+ ctx,
70
+ error: "invalid_request",
71
+ errDescription,
72
+ realm: options.realm
73
+ })
74
+ });
75
+ }
76
+ let payload;
77
+ let cause;
78
+ try {
79
+ payload = await Jwt.verify(token, options.secret, {
80
+ alg: options.alg,
81
+ ...verifyOpts
82
+ });
83
+ } catch (e) {
84
+ cause = e;
85
+ }
86
+ if (!payload) throw new HTTPException(401, {
87
+ message: "Unauthorized",
88
+ res: unauthorizedResponse({
89
+ ctx,
90
+ error: "invalid_token",
91
+ statusText: "Unauthorized",
92
+ errDescription: "token verification failure",
93
+ realm: options.realm
94
+ }),
95
+ cause
96
+ });
97
+ ctx.set("jwtPayload", payload);
98
+ await next();
99
+ };
100
+ };
101
+ function unauthorizedResponse(opts) {
102
+ const realm = (opts.realm ?? opts.ctx.req.url).replace(/"/g, "\\\"");
103
+ const errDescription = opts.errDescription.replace(/"/g, "\\\"");
104
+ return new Response("Unauthorized", {
105
+ status: 401,
106
+ statusText: opts.statusText,
107
+ headers: { "WWW-Authenticate": `Bearer realm="${realm}",error="${opts.error}",error_description="${errDescription}"` }
108
+ });
109
+ }
110
+ const verifyWithJwks = Jwt.verifyWithJwks;
111
+ const verify = Jwt.verify;
112
+ const decode = Jwt.decode;
113
+ const sign = Jwt.sign;
114
+ //#endregion
115
+ export { AlgorithmTypes, decode, jwt, sign, verify, verifyWithJwks };
@@ -0,0 +1,88 @@
1
+ import { I as MiddlewareHandler, t as Context } from "./context-Bm7rI-oK.js";
2
+
3
+ //#region ../../plugins/acryl-router/src/core/middleware/language/language.d.ts
4
+ type DetectorType = 'path' | 'querystring' | 'cookie' | 'header';
5
+ type CacheType = 'cookie';
6
+ interface DetectorOptions {
7
+ /** Order of language detection strategies */
8
+ order: DetectorType[];
9
+ /** Query parameter name for language */
10
+ lookupQueryString: string;
11
+ /** Cookie name for language */
12
+ lookupCookie: string;
13
+ /** Index in URL path where language code appears */
14
+ lookupFromPathIndex: number;
15
+ /** Header key for language detection */
16
+ lookupFromHeaderKey: string;
17
+ /** Caching strategies */
18
+ caches: CacheType[] | false;
19
+ /** Cookie configuration options */
20
+ cookieOptions?: {
21
+ domain?: string;
22
+ path?: string;
23
+ sameSite?: 'Strict' | 'Lax' | 'None';
24
+ secure?: boolean;
25
+ maxAge?: number;
26
+ httpOnly?: boolean;
27
+ };
28
+ /** Whether to ignore case in language codes */
29
+ ignoreCase: boolean;
30
+ /** Default language if none detected */
31
+ fallbackLanguage: string;
32
+ /** List of supported language codes */
33
+ supportedLanguages: string[];
34
+ /** Optional function to transform detected language codes */
35
+ convertDetectedLanguage?: (lang: string) => string;
36
+ /** Enable debug logging */
37
+ debug?: boolean;
38
+ }
39
+ interface LanguageVariables {
40
+ language: string;
41
+ }
42
+ /**
43
+ * Detects language from query parameter
44
+ */
45
+ declare const detectFromQuery: (c: Context, options: DetectorOptions) => string | undefined;
46
+ /**
47
+ * Detects language from cookie
48
+ */
49
+ declare const detectFromCookie: (c: Context, options: DetectorOptions) => string | undefined;
50
+ /**
51
+ * Detects language from Accept-Language header
52
+ */
53
+ declare function detectFromHeader(c: Context, options: DetectorOptions): string | undefined;
54
+ /**
55
+ * Detects language from URL path
56
+ */
57
+ declare function detectFromPath(c: Context, options: DetectorOptions): string | undefined;
58
+ /**
59
+ * Language detector middleware factory
60
+ * @param userOptions Configuration options for the language detector
61
+ * @returns Acryl middleware function
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * type Variables = LanguageVariables
66
+ * const app = new Acryl<{ Variables: Variables }>()
67
+ *
68
+ * app.use(
69
+ * languageDetector({
70
+ * supportedLanguages: ['en', 'ja'], // Must include fallback
71
+ * fallbackLanguage: 'en', // Required
72
+ * })
73
+ * )
74
+ *
75
+ * app.get('/', (c) => {
76
+ * const lang = c.get('language')
77
+ * return c.text(`Current language: ${lang}`)
78
+ * })
79
+ * ```
80
+ */
81
+ declare const languageDetector: (userOptions: Partial<DetectorOptions>) => MiddlewareHandler;
82
+ //#endregion
83
+ //#region ../../plugins/acryl-router/src/core/middleware/language/index.d.ts
84
+ declare module '../../context.ts' {
85
+ interface ContextVariableMap extends LanguageVariables {}
86
+ }
87
+ //#endregion
88
+ export { type CacheType, type DetectorOptions, type DetectorType, type LanguageVariables, detectFromCookie, detectFromHeader, detectFromPath, detectFromQuery, languageDetector };
@@ -0,0 +1,198 @@
1
+ import { parseAccept } from "./utils/accept.js";
2
+ import { getCookie, setCookie } from "./cookie.js";
3
+ //#region ../../plugins/acryl-router/src/core/middleware/language/language.ts
4
+ const DEFAULT_OPTIONS = {
5
+ order: [
6
+ "querystring",
7
+ "cookie",
8
+ "header"
9
+ ],
10
+ lookupQueryString: "lang",
11
+ lookupCookie: "language",
12
+ lookupFromHeaderKey: "accept-language",
13
+ lookupFromPathIndex: 0,
14
+ caches: ["cookie"],
15
+ ignoreCase: true,
16
+ fallbackLanguage: "en",
17
+ supportedLanguages: ["en"],
18
+ cookieOptions: {
19
+ sameSite: "Strict",
20
+ secure: true,
21
+ maxAge: 365 * 24 * 60 * 60,
22
+ httpOnly: true
23
+ },
24
+ debug: false
25
+ };
26
+ /**
27
+ * Parse Accept-Language header values with quality scores
28
+ * @param header Accept-Language header string
29
+ * @returns Array of parsed languages with quality scores
30
+ */
31
+ function parseAcceptLanguage(header) {
32
+ return parseAccept(header).map(({ type, q }) => ({
33
+ lang: type,
34
+ q
35
+ }));
36
+ }
37
+ /**
38
+ * Validate and normalize language codes
39
+ * @param lang Language code to normalize
40
+ * @param options Detector options
41
+ * @returns Normalized language code or undefined
42
+ */
43
+ const normalizeLanguage = (lang, options) => {
44
+ if (!lang) return;
45
+ try {
46
+ let normalizedLang = lang.trim();
47
+ if (options.convertDetectedLanguage) normalizedLang = options.convertDetectedLanguage(normalizedLang);
48
+ const compLang = options.ignoreCase ? normalizedLang.toLowerCase() : normalizedLang;
49
+ const compSupported = options.supportedLanguages.map((l) => options.ignoreCase ? l.toLowerCase() : l);
50
+ const exactIndex = compSupported.indexOf(compLang);
51
+ if (exactIndex !== -1) return options.supportedLanguages[exactIndex];
52
+ let longestMatchIndex = -1;
53
+ let longestMatchLength = -1;
54
+ for (let i = 0; i < compSupported.length; i++) {
55
+ const candidate = compSupported[i];
56
+ if (candidate.length < compLang.length && candidate.length > longestMatchLength && compLang.startsWith(candidate) && compLang[candidate.length] === "-") {
57
+ longestMatchIndex = i;
58
+ longestMatchLength = candidate.length;
59
+ }
60
+ }
61
+ if (longestMatchIndex !== -1) return options.supportedLanguages[longestMatchIndex];
62
+ return;
63
+ } catch {
64
+ return;
65
+ }
66
+ };
67
+ /**
68
+ * Detects language from query parameter
69
+ */
70
+ const detectFromQuery = (c, options) => {
71
+ const query = c.req.query(options.lookupQueryString);
72
+ return normalizeLanguage(query, options);
73
+ };
74
+ /**
75
+ * Detects language from cookie
76
+ */
77
+ const detectFromCookie = (c, options) => {
78
+ const cookie = getCookie(c, options.lookupCookie);
79
+ return normalizeLanguage(cookie, options);
80
+ };
81
+ /**
82
+ * Detects language from Accept-Language header
83
+ */
84
+ function detectFromHeader(c, options) {
85
+ try {
86
+ const acceptLanguage = c.req.header(options.lookupFromHeaderKey);
87
+ if (!acceptLanguage) return;
88
+ const languages = parseAcceptLanguage(acceptLanguage);
89
+ for (const { lang, q } of languages) {
90
+ if (q === 0) continue;
91
+ const normalizedLang = normalizeLanguage(lang, options);
92
+ if (normalizedLang) return normalizedLang;
93
+ }
94
+ return;
95
+ } catch {
96
+ return;
97
+ }
98
+ }
99
+ /**
100
+ * Detects language from URL path
101
+ */
102
+ function detectFromPath(c, options) {
103
+ const langSegment = new URL(c.req.url).pathname.split("/").filter(Boolean)[options.lookupFromPathIndex];
104
+ return normalizeLanguage(langSegment, options);
105
+ }
106
+ /**
107
+ * Collection of all language detection strategies
108
+ */
109
+ const detectors = {
110
+ querystring: detectFromQuery,
111
+ cookie: detectFromCookie,
112
+ header: detectFromHeader,
113
+ path: detectFromPath
114
+ };
115
+ /**
116
+ * Validate detector options
117
+ * @param options Detector options to validate
118
+ * @throws Error if options are invalid
119
+ */
120
+ function validateOptions(options) {
121
+ if (!options.supportedLanguages.includes(options.fallbackLanguage)) throw new Error("Fallback language must be included in supported languages");
122
+ if (options.lookupFromPathIndex < 0) throw new Error("Path index must be non-negative");
123
+ if (!options.order.every((detector) => Object.keys(detectors).includes(detector))) throw new Error("Invalid detector type in order array");
124
+ }
125
+ /**
126
+ * Cache detected language
127
+ */
128
+ function cacheLanguage(c, language, options) {
129
+ if (!Array.isArray(options.caches) || !options.caches.includes("cookie")) return;
130
+ try {
131
+ setCookie(c, options.lookupCookie, language, options.cookieOptions);
132
+ } catch (error) {
133
+ if (options.debug) console.error("Failed to cache language:", error);
134
+ }
135
+ }
136
+ /**
137
+ * Detect language from request
138
+ */
139
+ const detectLanguage = (c, options) => {
140
+ let detectedLang;
141
+ for (const detectorName of options.order) {
142
+ const detector = detectors[detectorName];
143
+ try {
144
+ detectedLang = detector(c, options);
145
+ if (detectedLang) {
146
+ if (options.debug) console.log(`Language detected from ${detectorName}: ${detectedLang}`);
147
+ break;
148
+ }
149
+ } catch (error) {
150
+ if (options.debug) console.error(`Error in ${detectorName} detector:`, error);
151
+ continue;
152
+ }
153
+ }
154
+ const finalLang = detectedLang || options.fallbackLanguage;
155
+ if (detectedLang && options.caches) cacheLanguage(c, finalLang, options);
156
+ return finalLang;
157
+ };
158
+ /**
159
+ * Language detector middleware factory
160
+ * @param userOptions Configuration options for the language detector
161
+ * @returns Acryl middleware function
162
+ *
163
+ * @example
164
+ * ```ts
165
+ * type Variables = LanguageVariables
166
+ * const app = new Acryl<{ Variables: Variables }>()
167
+ *
168
+ * app.use(
169
+ * languageDetector({
170
+ * supportedLanguages: ['en', 'ja'], // Must include fallback
171
+ * fallbackLanguage: 'en', // Required
172
+ * })
173
+ * )
174
+ *
175
+ * app.get('/', (c) => {
176
+ * const lang = c.get('language')
177
+ * return c.text(`Current language: ${lang}`)
178
+ * })
179
+ * ```
180
+ */
181
+ const languageDetector = (userOptions) => {
182
+ const options = {
183
+ ...DEFAULT_OPTIONS,
184
+ ...userOptions,
185
+ cookieOptions: {
186
+ ...DEFAULT_OPTIONS.cookieOptions,
187
+ ...userOptions.cookieOptions
188
+ }
189
+ };
190
+ validateOptions(options);
191
+ return async function languageDetector(ctx, next) {
192
+ const lang = detectLanguage(ctx, options);
193
+ ctx.set("language", lang);
194
+ await next();
195
+ };
196
+ };
197
+ //#endregion
198
+ export { detectFromCookie, detectFromHeader, detectFromPath, detectFromQuery, languageDetector };
@@ -0,0 +1,22 @@
1
+ import { I as MiddlewareHandler } from "./context-Bm7rI-oK.js";
2
+
3
+ //#region ../../plugins/acryl-router/src/core/middleware/logger/index.d.ts
4
+ type PrintFunc = (str: string, ...rest: string[]) => void;
5
+ /**
6
+ * Logger Middleware for Acryl.
7
+ *
8
+ *
9
+ * @param {PrintFunc} [fn=console.log] - Optional function for customized logging behavior.
10
+ * @returns {MiddlewareHandler} The middleware handler function.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * const app = new Acryl()
15
+ *
16
+ * app.use(logger())
17
+ * app.get('/', (c) => c.text('Hello Acryl!'))
18
+ * ```
19
+ */
20
+ declare const logger: (fn?: PrintFunc) => MiddlewareHandler;
21
+ //#endregion
22
+ export { logger };
package/lib/logger.js ADDED
@@ -0,0 +1,54 @@
1
+ import { getColorEnabledAsync } from "./utils/color.js";
2
+ //#region ../../plugins/acryl-router/src/core/middleware/logger/index.ts
3
+ const LogPrefix = {
4
+ Outgoing: "-->",
5
+ Incoming: "<--",
6
+ Error: "xxx"
7
+ };
8
+ const humanize = (times) => {
9
+ const [delimiter, separator] = [",", "."];
10
+ return times.map((v) => v.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1" + delimiter)).join(separator);
11
+ };
12
+ const time = (start) => {
13
+ const delta = Date.now() - start;
14
+ return humanize([delta < 1e3 ? delta + "ms" : Math.round(delta / 1e3) + "s"]);
15
+ };
16
+ const colorStatus = async (status) => {
17
+ if (await getColorEnabledAsync()) switch (status / 100 | 0) {
18
+ case 5: return `\x1b[31m${status}\x1b[0m`;
19
+ case 4: return `\x1b[33m${status}\x1b[0m`;
20
+ case 3: return `\x1b[36m${status}\x1b[0m`;
21
+ case 2: return `\x1b[32m${status}\x1b[0m`;
22
+ }
23
+ return `${status}`;
24
+ };
25
+ async function log(fn, prefix, method, path, status = 0, elapsed) {
26
+ fn(prefix === LogPrefix.Incoming ? `${prefix} ${method} ${path}` : `${prefix} ${method} ${path} ${await colorStatus(status)} ${elapsed}`);
27
+ }
28
+ /**
29
+ * Logger Middleware for Acryl.
30
+ *
31
+ *
32
+ * @param {PrintFunc} [fn=console.log] - Optional function for customized logging behavior.
33
+ * @returns {MiddlewareHandler} The middleware handler function.
34
+ *
35
+ * @example
36
+ * ```ts
37
+ * const app = new Acryl()
38
+ *
39
+ * app.use(logger())
40
+ * app.get('/', (c) => c.text('Hello Acryl!'))
41
+ * ```
42
+ */
43
+ const logger = (fn = console.log) => {
44
+ return async function logger(c, next) {
45
+ const { method, url } = c.req;
46
+ const path = url.slice(url.indexOf("/", 8));
47
+ await log(fn, LogPrefix.Incoming, method, path);
48
+ const start = Date.now();
49
+ await next();
50
+ await log(fn, LogPrefix.Outgoing, method, path, c.res.status, time(start));
51
+ };
52
+ };
53
+ //#endregion
54
+ export { logger };
@@ -0,0 +1,45 @@
1
+ import { I as MiddlewareHandler, t as Context } from "./context-Bm7rI-oK.js";
2
+
3
+ //#region ../../plugins/acryl-router/src/middleware/loopback-only.d.ts
4
+ interface LoopbackOptions {
5
+ /** Hostnames a `Host` header may name. Default: the loopback names `127.0.0.1`, `localhost` and `[::1]`. */
6
+ readonly hostnames?: readonly string[];
7
+ /**
8
+ * What a request that changes things (not GET, HEAD or OPTIONS) must show: `same-origin` (default) refuses an `Origin` header that is not this same
9
+ * authority (including `null`), which stops another web page from driving a local app. A browser always sends `Origin` on a cross-origin change, so a
10
+ * request with no `Origin` (curl, a script) is allowed: the `Host` it names is already checked to be a loopback address with this server's port, which
11
+ * is what stops DNS rebinding. `none` checks only the peer and the `Host`.
12
+ */
13
+ readonly mutations?: 'same-origin' | 'none';
14
+ /**
15
+ * A call made inside the process (the terminal UI, a test) has no socket, so no peer to check. `deny` (default) refuses it, the safe choice for a route
16
+ * that guards something; `allow` lets it through for routes whose in-process caller is the host's own code. A request that came over a socket is always
17
+ * checked in full: only a call with no connection facts at all counts as in process.
18
+ */
19
+ readonly inProcess?: 'deny' | 'allow';
20
+ /**
21
+ * Who may call. `local` (default): any program on this machine, a browser page only as `mutations` allows. `own-page`: only this app's own page,
22
+ * for private routes a script on the machine must not drive or read either. A request then shows an `Origin` that is exactly this authority (with
23
+ * `Sec-Fetch-Site` absent or `same-origin`), or, for a read (GET, HEAD, OPTIONS), which browsers often send without `Origin`, `Sec-Fetch-Site:
24
+ * same-origin` and a `Referer` from this authority. `mutations` is not consulted: every request is held to that rule.
25
+ */
26
+ readonly callers?: 'local' | 'own-page';
27
+ }
28
+ /**
29
+ * The authority a loopback request addressed: the `Host` header as a URL, or `undefined` when the request does not come from a loopback peer to the
30
+ * real local port, names another host, or is marked cross-site by the browser. The peer and the port come from the transport (`connectionOf(c)`), never
31
+ * from a header; an in-process call has neither and is refused.
32
+ */
33
+ declare const LOOPBACK_HOSTNAMES: readonly string[];
34
+ declare function loopbackAuthority(c: Context, hostnames?: readonly string[]): URL | undefined;
35
+ /** Whether a changing request is acceptable by its `Origin`: absent (not a browser cross-origin change) or naming this same authority. `null` and any other origin are not. */
36
+ declare function sameOrigin(c: Context, authority: URL): boolean;
37
+ /** Whether the request comes from a page served by this authority itself: the `own-page` rule of {@link LoopbackOptions.callers}. */
38
+ declare function fromOwnPage(c: Context, authority: URL): boolean;
39
+ /**
40
+ * Only requests from this machine to this app: loopback peer, the real port, an allowed `Host`, and for mutations a matching `Origin` (with
41
+ * `callers: 'own-page'`, every request from this app's own page). Everything else gets a 403.
42
+ */
43
+ declare function loopbackOnly(options?: LoopbackOptions): MiddlewareHandler;
44
+ //#endregion
45
+ export { LOOPBACK_HOSTNAMES, LoopbackOptions, fromOwnPage, loopbackAuthority, loopbackOnly, sameOrigin };
@@ -0,0 +1,90 @@
1
+ import { t as connectionOf } from "./connection-C7xgP1hP.js";
2
+ import { BlockList, isIP } from "node:net";
3
+ //#region ../../plugins/acryl-router/src/middleware/loopback-only.ts
4
+ const loopback = new BlockList();
5
+ loopback.addSubnet("127.0.0.0", 8, "ipv4");
6
+ loopback.addSubnet("::1", 128, "ipv6");
7
+ const SAFE_METHODS = /* @__PURE__ */ new Set([
8
+ "GET",
9
+ "HEAD",
10
+ "OPTIONS"
11
+ ]);
12
+ /**
13
+ * The authority a loopback request addressed: the `Host` header as a URL, or `undefined` when the request does not come from a loopback peer to the
14
+ * real local port, names another host, or is marked cross-site by the browser. The peer and the port come from the transport (`connectionOf(c)`), never
15
+ * from a header; an in-process call has neither and is refused.
16
+ */
17
+ const LOOPBACK_HOSTNAMES = [
18
+ "127.0.0.1",
19
+ "localhost",
20
+ "[::1]"
21
+ ];
22
+ function loopbackAuthority(c, hostnames = LOOPBACK_HOSTNAMES) {
23
+ const { remoteAddress, localPort } = connectionOf(c);
24
+ const host = c.req.header("host");
25
+ if (remoteAddress === void 0 || localPort === void 0 || host === void 0) return void 0;
26
+ const address = (remoteAddress.replace(/^\[|\]$/gu, "").split("%", 1)[0] ?? "").replace(/^::ffff:/iu, "");
27
+ const family = isIP(address);
28
+ if (family === 0 || !loopback.check(address, family === 4 ? "ipv4" : "ipv6")) return void 0;
29
+ let authority;
30
+ try {
31
+ authority = new URL(`http://${host}`);
32
+ } catch {
33
+ return;
34
+ }
35
+ if (authority.protocol !== "http:" || Number(authority.port || "80") !== localPort || !hostnames.includes(authority.hostname) || c.req.header("sec-fetch-site") === "cross-site") return void 0;
36
+ return authority;
37
+ }
38
+ /** Whether a changing request is acceptable by its `Origin`: absent (not a browser cross-origin change) or naming this same authority. `null` and any other origin are not. */
39
+ function sameOrigin(c, authority) {
40
+ const origin = c.req.header("origin");
41
+ if (origin === void 0) return true;
42
+ try {
43
+ const parsed = new URL(origin);
44
+ return parsed.protocol === "http:" && parsed.host === authority.host && parsed.pathname === "/";
45
+ } catch {
46
+ return false;
47
+ }
48
+ }
49
+ function originOf(value) {
50
+ if (value === void 0) return void 0;
51
+ try {
52
+ return new URL(value).origin;
53
+ } catch {
54
+ return;
55
+ }
56
+ }
57
+ /** Whether the request comes from a page served by this authority itself: the `own-page` rule of {@link LoopbackOptions.callers}. */
58
+ function fromOwnPage(c, authority) {
59
+ const origin = c.req.header("origin");
60
+ const fetchSite = c.req.header("sec-fetch-site");
61
+ if (origin !== void 0 && originOf(origin) === origin && origin === authority.origin) return fetchSite === void 0 || fetchSite === "same-origin";
62
+ return SAFE_METHODS.has(c.req.method) && fetchSite === "same-origin" && originOf(c.req.header("referer")) === authority.origin;
63
+ }
64
+ /**
65
+ * Only requests from this machine to this app: loopback peer, the real port, an allowed `Host`, and for mutations a matching `Origin` (with
66
+ * `callers: 'own-page'`, every request from this app's own page). Everything else gets a 403.
67
+ */
68
+ function loopbackOnly(options = {}) {
69
+ const mutations = options.mutations ?? "same-origin";
70
+ const inProcess = options.inProcess ?? "deny";
71
+ const ownPage = options.callers === "own-page";
72
+ return async (c, next) => {
73
+ const connection = connectionOf(c);
74
+ if (inProcess === "allow" && connection.remoteAddress === void 0 && connection.localPort === void 0) {
75
+ await next();
76
+ return;
77
+ }
78
+ const authority = loopbackAuthority(c, options.hostnames);
79
+ if (authority === void 0) return c.json({ error: "request authority rejected" }, 403);
80
+ if (ownPage) {
81
+ if (!fromOwnPage(c, authority)) return c.json({ error: "only this app's own page may call this" }, 403);
82
+ await next();
83
+ return;
84
+ }
85
+ if (mutations === "same-origin" && !SAFE_METHODS.has(c.req.method) && !sameOrigin(c, authority)) return c.json({ error: "a change must come from this app's own origin" }, 403);
86
+ await next();
87
+ };
88
+ }
89
+ //#endregion
90
+ export { LOOPBACK_HOSTNAMES, fromOwnPage, loopbackAuthority, loopbackOnly, sameOrigin };
@@ -0,0 +1,47 @@
1
+ import { I as MiddlewareHandler, _ as Env, t as Context } from "./context-Bm7rI-oK.js";
2
+ import { t as Acryl } from "./app-CmAYW1Al.js";
3
+
4
+ //#region ../../plugins/acryl-router/src/core/middleware/method-not-allowed/index.d.ts
5
+ type MethodNotAllowedHandler<E extends Env> = (c: Context<E>, allowedMethods: string[]) => Response | Promise<Response>;
6
+ type MethodNotAllowedOptions<E extends Env> = {
7
+ app: Acryl<E, any, any>;
8
+ onMethodNotAllowed?: MethodNotAllowedHandler<E>;
9
+ };
10
+ /**
11
+ * Method Not Allowed Middleware for Acryl.
12
+ *
13
+ * Returns a `405 Method Not Allowed` response with an `Allow` header when the request path
14
+ * matches a registered route but the request method is not supported.
15
+ *
16
+ * @param {MethodNotAllowedOptions} options - The options for the middleware.
17
+ * @param {Acryl} options.app - The Acryl instance used by the application.
18
+ * @param {MethodNotAllowedHandler} [options.onMethodNotAllowed] - Generates the response, including its `Allow` header.
19
+ * @returns {MiddlewareHandler} The middleware handler function.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * const app = new Acryl()
24
+ *
25
+ * app.use(methodNotAllowed({ app }))
26
+ *
27
+ * app.get('/hello', (c) => c.text('Hello!'))
28
+ * app.post('/hello', (c) => c.text('Posted!'))
29
+ *
30
+ * // PUT /hello -> 405 Method Not Allowed
31
+ * // Allow: GET, HEAD, POST
32
+ * ```
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * app.use(
37
+ * methodNotAllowed({
38
+ * app,
39
+ * onMethodNotAllowed: (c, methods) =>
40
+ * c.json({ error: 'Method Not Allowed' }, 405, { Allow: methods.join(', ') }),
41
+ * })
42
+ * )
43
+ * ```
44
+ */
45
+ declare const methodNotAllowed: <E extends Env = Env>(options: MethodNotAllowedOptions<E>) => MiddlewareHandler<E>;
46
+ //#endregion
47
+ export { methodNotAllowed };