acrylblends 0.4.0 → 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 (426) hide show
  1. package/LICENSE +73 -0
  2. package/dist/index.js +56 -2
  3. package/dist/index.js.map +1 -1
  4. package/docs/framework/LICENSE +23 -0
  5. package/docs/framework/README.md +63 -0
  6. package/docs/framework/UPSTREAM.md +3 -0
  7. package/docs/framework/agents/index.md +24 -0
  8. package/docs/framework/api/acryl.md +259 -0
  9. package/docs/framework/api/context.md +527 -0
  10. package/docs/framework/api/exception.md +80 -0
  11. package/docs/framework/api/index.md +12 -0
  12. package/docs/framework/api/presets.md +65 -0
  13. package/docs/framework/api/request.md +396 -0
  14. package/docs/framework/api/routing.md +303 -0
  15. package/docs/framework/api/summary.md +140 -0
  16. package/docs/framework/concepts/benchmarks.md +26 -0
  17. package/docs/framework/concepts/developer-experience.md +5 -0
  18. package/docs/framework/concepts/middleware.md +21 -0
  19. package/docs/framework/concepts/motivation.md +14 -0
  20. package/docs/framework/concepts/routers.md +63 -0
  21. package/docs/framework/concepts/stacks.md +235 -0
  22. package/docs/framework/concepts/web-standard.md +37 -0
  23. package/docs/framework/cordis/acryl-in-a-cordis-app.md +146 -0
  24. package/docs/framework/cordis/concepts.md +105 -0
  25. package/docs/framework/cordis/middleware.md +8 -0
  26. package/docs/framework/cordis/migration-from-0-3.md +111 -0
  27. package/docs/framework/cordis/migration-from-0-4.md +14 -0
  28. package/docs/framework/cordis/migration-from-dsh-webserver.md +103 -0
  29. package/docs/framework/cordis/mounting.md +85 -0
  30. package/docs/framework/cordis/node-server.md +75 -0
  31. package/docs/framework/cordis/plugin-lifecycle.md +111 -0
  32. package/docs/framework/cordis/surfaces.md +71 -0
  33. package/docs/framework/cordis/transport-and-cancellation.md +57 -0
  34. package/docs/framework/cordis/validation.md +135 -0
  35. package/docs/framework/getting-started/basic.md +196 -0
  36. package/docs/framework/getting-started/bun.md +221 -0
  37. package/docs/framework/getting-started/nodejs.md +344 -0
  38. package/docs/framework/getting-started/other-runtimes.md +23 -0
  39. package/docs/framework/guides/best-practices.md +231 -0
  40. package/docs/framework/guides/create-acrylblends.md +79 -0
  41. package/docs/framework/guides/examples.md +3 -0
  42. package/docs/framework/guides/faq.md +19 -0
  43. package/docs/framework/guides/helpers.md +33 -0
  44. package/docs/framework/guides/jsx-dom.md +299 -0
  45. package/docs/framework/guides/jsx.md +440 -0
  46. package/docs/framework/guides/middleware.md +253 -0
  47. package/docs/framework/guides/rpc.md +886 -0
  48. package/docs/framework/guides/testing.md +133 -0
  49. package/docs/framework/guides/validation.md +383 -0
  50. package/docs/framework/helpers/accepts.md +60 -0
  51. package/docs/framework/helpers/adapter.md +87 -0
  52. package/docs/framework/helpers/conninfo.md +112 -0
  53. package/docs/framework/helpers/cookie.md +232 -0
  54. package/docs/framework/helpers/css.md +285 -0
  55. package/docs/framework/helpers/dev.md +67 -0
  56. package/docs/framework/helpers/factory.md +180 -0
  57. package/docs/framework/helpers/html.md +123 -0
  58. package/docs/framework/helpers/jwt.md +184 -0
  59. package/docs/framework/helpers/proxy.md +118 -0
  60. package/docs/framework/helpers/route.md +143 -0
  61. package/docs/framework/helpers/ssg.md +393 -0
  62. package/docs/framework/helpers/streaming.md +119 -0
  63. package/docs/framework/helpers/testing.md +101 -0
  64. package/docs/framework/helpers/websocket.md +215 -0
  65. package/docs/framework/middleware/builtin/basic-auth.md +165 -0
  66. package/docs/framework/middleware/builtin/bearer-auth.md +138 -0
  67. package/docs/framework/middleware/builtin/body-limit.md +71 -0
  68. package/docs/framework/middleware/builtin/cache.md +122 -0
  69. package/docs/framework/middleware/builtin/combine.md +94 -0
  70. package/docs/framework/middleware/builtin/compress.md +59 -0
  71. package/docs/framework/middleware/builtin/context-storage.md +78 -0
  72. package/docs/framework/middleware/builtin/cors.md +135 -0
  73. package/docs/framework/middleware/builtin/csrf.md +105 -0
  74. package/docs/framework/middleware/builtin/etag.md +54 -0
  75. package/docs/framework/middleware/builtin/ip-restriction.md +69 -0
  76. package/docs/framework/middleware/builtin/jsx-renderer.md +286 -0
  77. package/docs/framework/middleware/builtin/jwk.md +192 -0
  78. package/docs/framework/middleware/builtin/jwt.md +145 -0
  79. package/docs/framework/middleware/builtin/language.md +232 -0
  80. package/docs/framework/middleware/builtin/logger.md +74 -0
  81. package/docs/framework/middleware/builtin/loopback-only.md +31 -0
  82. package/docs/framework/middleware/builtin/method-not-allowed.md +48 -0
  83. package/docs/framework/middleware/builtin/method-override.md +80 -0
  84. package/docs/framework/middleware/builtin/mount.md +106 -0
  85. package/docs/framework/middleware/builtin/pretty-json.md +53 -0
  86. package/docs/framework/middleware/builtin/request-id.md +94 -0
  87. package/docs/framework/middleware/builtin/secure-headers.md +247 -0
  88. package/docs/framework/middleware/builtin/timeout.md +98 -0
  89. package/docs/framework/middleware/builtin/timing.md +101 -0
  90. package/docs/framework/middleware/builtin/trailing-slash.md +74 -0
  91. package/docs/framework/middleware/third-party.md +4 -0
  92. package/docs/framework/upstream.json +9 -0
  93. package/lib/accepts-XBuZPVRI.js +52 -0
  94. package/lib/accepts.d.ts +33 -0
  95. package/lib/accepts.js +2 -0
  96. package/lib/acryl-base.d.ts +2 -0
  97. package/lib/acryl-base.js +332 -0
  98. package/lib/adapter.d.ts +12 -0
  99. package/lib/adapter.js +37 -0
  100. package/lib/app-BM0rTCp7.js +26 -0
  101. package/lib/app-CmAYW1Al.d.ts +21 -0
  102. package/lib/basic-auth.d.ts +72 -0
  103. package/lib/basic-auth.js +95 -0
  104. package/lib/bearer-auth.d.ts +89 -0
  105. package/lib/bearer-auth.js +94 -0
  106. package/lib/body-limit.d.ts +42 -0
  107. package/lib/body-limit.js +66 -0
  108. package/lib/client-BHTr318g.js +266 -0
  109. package/lib/client.d.ts +3 -0
  110. package/lib/client.js +2 -0
  111. package/lib/combine.d.ts +85 -0
  112. package/lib/combine.js +137 -0
  113. package/lib/compose-BuW2B6PZ.js +50 -0
  114. package/lib/compress.d.ts +38 -0
  115. package/lib/compress.js +79 -0
  116. package/lib/connection-C7xgP1hP.js +24 -0
  117. package/lib/conninfo.d.ts +25 -0
  118. package/lib/conninfo.js +2 -0
  119. package/lib/constants-Dy7ZvN1H.js +4 -0
  120. package/lib/context-Bm7rI-oK.d.ts +1234 -0
  121. package/lib/context-DDO0cfuP.js +365 -0
  122. package/lib/context-storage.d.ts +38 -0
  123. package/lib/context-storage.js +52 -0
  124. package/lib/cookie-ClMaKDQf.d.ts +40 -0
  125. package/lib/cookie.d.ts +24 -0
  126. package/lib/cookie.js +82 -0
  127. package/lib/cors.d.ts +52 -0
  128. package/lib/cors.js +106 -0
  129. package/lib/csrf.d.ts +75 -0
  130. package/lib/csrf.js +101 -0
  131. package/lib/etag.d.ts +40 -0
  132. package/lib/etag.js +135 -0
  133. package/lib/factory.d.ts +35 -0
  134. package/lib/factory.js +30 -0
  135. package/lib/headers-tu2YYN8T.d.ts +11 -0
  136. package/lib/html.d.ts +6 -0
  137. package/lib/html.js +31 -0
  138. package/lib/http-exception.d.ts +57 -0
  139. package/lib/http-exception.js +54 -0
  140. package/lib/http-status-DaAwGAFL.d.ts +35 -0
  141. package/lib/index-B-3F4wt2.d.ts +12 -0
  142. package/lib/index-UTBmM3GX.d.ts +68 -0
  143. package/lib/index-oOClm_Xk.d.ts +45 -0
  144. package/lib/index.d.ts +5 -0
  145. package/lib/index.js +28 -0
  146. package/lib/ip-restriction.d.ts +68 -0
  147. package/lib/ip-restriction.js +166 -0
  148. package/lib/jwk.d.ts +52 -0
  149. package/lib/jwk.js +117 -0
  150. package/lib/jwt-BGJBw5AF.js +403 -0
  151. package/lib/jwt-Dg493Tai.d.ts +51 -0
  152. package/lib/jwt.d.ts +72 -0
  153. package/lib/jwt.js +115 -0
  154. package/lib/language.d.ts +88 -0
  155. package/lib/language.js +198 -0
  156. package/lib/logger.d.ts +22 -0
  157. package/lib/logger.js +54 -0
  158. package/lib/loopback-only.d.ts +45 -0
  159. package/lib/loopback-only.js +90 -0
  160. package/lib/method-not-allowed.d.ts +47 -0
  161. package/lib/method-not-allowed.js +82 -0
  162. package/lib/method-override.d.ts +46 -0
  163. package/lib/method-override.js +103 -0
  164. package/lib/mime-BQOYHl-l.d.ts +72 -0
  165. package/lib/node-server/conninfo.d.ts +11 -0
  166. package/lib/node-server/conninfo.js +19 -0
  167. package/lib/node-server/serve-static.d.ts +19 -0
  168. package/lib/node-server/serve-static.js +2 -0
  169. package/lib/node-server.d.ts +103 -0
  170. package/lib/node-server.js +1325 -0
  171. package/lib/powered-by.d.ts +28 -0
  172. package/lib/powered-by.js +24 -0
  173. package/lib/pretty-json.d.ts +40 -0
  174. package/lib/pretty-json.js +39 -0
  175. package/lib/reg-exp-router-DC1R3qoY.js +363 -0
  176. package/lib/request-id.d.ts +45 -0
  177. package/lib/request-id.js +34 -0
  178. package/lib/request.d.ts +2 -0
  179. package/lib/request.js +323 -0
  180. package/lib/route.d.ts +78 -0
  181. package/lib/route.js +126 -0
  182. package/lib/router/linear-router.d.ts +11 -0
  183. package/lib/router/linear-router.js +96 -0
  184. package/lib/router/pattern-router.d.ts +11 -0
  185. package/lib/router/pattern-router.js +41 -0
  186. package/lib/router/reg-exp-router.d.ts +35 -0
  187. package/lib/router/reg-exp-router.js +2 -0
  188. package/lib/router/smart-router.d.ts +15 -0
  189. package/lib/router/smart-router.js +2 -0
  190. package/lib/router/trie-router.d.ts +11 -0
  191. package/lib/router/trie-router.js +2 -0
  192. package/lib/router-CvUxUTOq.d.ts +99 -0
  193. package/lib/router.d.ts +2 -0
  194. package/lib/router.js +35 -0
  195. package/lib/schema-validator.d.ts +28 -0
  196. package/lib/schema-validator.js +22 -0
  197. package/lib/secure-headers.d.ts +125 -0
  198. package/lib/secure-headers.js +163 -0
  199. package/lib/serve-static-Dw_m6KxR.js +213 -0
  200. package/lib/serve-static.d.ts +31 -0
  201. package/lib/serve-static.js +77 -0
  202. package/lib/smart-router-C5CZ5XSM.js +49 -0
  203. package/lib/stream-CPdqZ0Fp.d.ts +34 -0
  204. package/lib/streaming-DHST3Scg.js +96 -0
  205. package/lib/streaming.d.ts +23 -0
  206. package/lib/streaming.js +2 -0
  207. package/lib/testing.d.ts +10 -0
  208. package/lib/testing.js +17 -0
  209. package/lib/timeout.d.ts +30 -0
  210. package/lib/timeout.js +42 -0
  211. package/lib/timing.d.ts +130 -0
  212. package/lib/timing.js +183 -0
  213. package/lib/trailing-slash.d.ts +91 -0
  214. package/lib/trailing-slash.js +85 -0
  215. package/lib/trie-router-CfFbapzL.js +146 -0
  216. package/lib/types-CDO6I3B0.d.ts +40 -0
  217. package/lib/types-CHesD1KG.d.ts +195 -0
  218. package/lib/types-CwrQjlaM.d.ts +105 -0
  219. package/lib/types-DR95J00T.d.ts +29 -0
  220. package/lib/types.d.ts +2 -0
  221. package/lib/types.js +4 -0
  222. package/lib/utils/accept.d.ts +9 -0
  223. package/lib/utils/accept.js +193 -0
  224. package/lib/utils/basic-auth.d.ts +8 -0
  225. package/lib/utils/basic-auth.js +20 -0
  226. package/lib/utils/body.d.ts +2 -0
  227. package/lib/utils/body.js +94 -0
  228. package/lib/utils/buffer.d.ts +19 -0
  229. package/lib/utils/buffer.js +51 -0
  230. package/lib/utils/color.d.ts +24 -0
  231. package/lib/utils/color.js +37 -0
  232. package/lib/utils/compress.d.ts +11 -0
  233. package/lib/utils/compress.js +11 -0
  234. package/lib/utils/concurrent.d.ts +17 -0
  235. package/lib/utils/concurrent.js +30 -0
  236. package/lib/utils/constants.d.ts +7 -0
  237. package/lib/utils/constants.js +7 -0
  238. package/lib/utils/cookie.d.ts +2 -0
  239. package/lib/utils/cookie.js +125 -0
  240. package/lib/utils/crypto.d.ts +14 -0
  241. package/lib/utils/crypto.js +34 -0
  242. package/lib/utils/encode.d.ts +11 -0
  243. package/lib/utils/encode.js +33 -0
  244. package/lib/utils/filepath.d.ts +14 -0
  245. package/lib/utils/filepath.js +25 -0
  246. package/lib/utils/handler.d.ts +9 -0
  247. package/lib/utils/handler.js +12 -0
  248. package/lib/utils/headers.d.ts +2 -0
  249. package/lib/utils/headers.js +1 -0
  250. package/lib/utils/html.d.ts +46 -0
  251. package/lib/utils/html.js +103 -0
  252. package/lib/utils/http-status.d.ts +2 -0
  253. package/lib/utils/http-status.js +1 -0
  254. package/lib/utils/ipaddr.d.ts +56 -0
  255. package/lib/utils/ipaddr.js +238 -0
  256. package/lib/utils/jwt.d.ts +24 -0
  257. package/lib/utils/jwt.js +2 -0
  258. package/lib/utils/mime.d.ts +2 -0
  259. package/lib/utils/mime.js +77 -0
  260. package/lib/utils/stream.d.ts +2 -0
  261. package/lib/utils/stream.js +88 -0
  262. package/lib/utils/types.d.ts +2 -0
  263. package/lib/utils/types.js +1 -0
  264. package/lib/utils/url.d.ts +46 -0
  265. package/lib/utils/url.js +197 -0
  266. package/lib/utils-dw8lxqjL.js +4 -0
  267. package/lib/validator-D84mq-dO.js +65 -0
  268. package/lib/validator.d.ts +42 -0
  269. package/lib/validator.js +2 -0
  270. package/lib/ws.d.ts +2 -0
  271. package/lib/ws.js +53 -0
  272. package/package.json +315 -15
  273. package/plugins/acryl-inspect/src/report.ts +15 -10
  274. package/plugins/acryl-inspect/src/service.ts +2 -2
  275. package/plugins/acryl-inspect/tests/report.spec.ts +9 -3
  276. package/plugins/acryl-inspect/tests/service.spec.ts +3 -3
  277. package/plugins/acryl-inspect/upstream.json +2 -2
  278. package/plugins/acryl-node-server/tests/adapter/app.ts +2 -2
  279. package/plugins/acryl-node-server/tests/adapter/assets/static/acryl.html +1 -1
  280. package/plugins/acryl-node-server/tests/adapter/assets/static/index.html +1 -1
  281. package/plugins/acryl-node-server/tests/adapter/conninfo.test.ts +2 -2
  282. package/plugins/acryl-node-server/tests/adapter/content-length.test.ts +4 -4
  283. package/plugins/acryl-node-server/tests/adapter/early-hints.test.ts +5 -5
  284. package/plugins/acryl-node-server/tests/adapter/request-client-disconnect.test.ts +2 -2
  285. package/plugins/acryl-node-server/tests/adapter/serve-static.test.ts +20 -20
  286. package/plugins/acryl-node-server/tests/adapter/server-socket.test.ts +2 -2
  287. package/plugins/acryl-node-server/tests/adapter/server.test.ts +50 -50
  288. package/plugins/acryl-node-server/tests/adapter/utils/response.test.ts +4 -4
  289. package/plugins/acryl-node-server/tests/adapter/websocket.test.ts +9 -9
  290. package/plugins/acryl-node-server/tests/server.spec.ts +6 -6
  291. package/plugins/acryl-node-server/upstream.json +2 -2
  292. package/plugins/acryl-router/src/client.ts +1 -1
  293. package/plugins/acryl-router/src/connection.ts +2 -2
  294. package/plugins/acryl-router/src/core/app-base.ts +29 -29
  295. package/plugins/acryl-router/src/core/app.test.ts +175 -175
  296. package/plugins/acryl-router/src/core/app.ts +8 -8
  297. package/plugins/acryl-router/src/core/client/client.test.ts +76 -76
  298. package/plugins/acryl-router/src/core/client/client.ts +2 -2
  299. package/plugins/acryl-router/src/core/client/fetch-result-please.ts +1 -1
  300. package/plugins/acryl-router/src/core/client/index.ts +1 -1
  301. package/plugins/acryl-router/src/core/client/types.test.ts +6 -6
  302. package/plugins/acryl-router/src/core/client/types.ts +16 -16
  303. package/plugins/acryl-router/src/core/client/utils.test.ts +2 -2
  304. package/plugins/acryl-router/src/core/context.test.ts +4 -4
  305. package/plugins/acryl-router/src/core/context.ts +6 -6
  306. package/plugins/acryl-router/src/core/helper/accepts/accepts.test.ts +3 -3
  307. package/plugins/acryl-router/src/core/helper/accepts/index.ts +1 -1
  308. package/plugins/acryl-router/src/core/helper/adapter/index.test.ts +6 -6
  309. package/plugins/acryl-router/src/core/helper/adapter/index.ts +1 -1
  310. package/plugins/acryl-router/src/core/helper/conninfo/index.ts +1 -1
  311. package/plugins/acryl-router/src/core/helper/cookie/index.test.ts +8 -8
  312. package/plugins/acryl-router/src/core/helper/cookie/index.ts +1 -1
  313. package/plugins/acryl-router/src/core/helper/factory/index.test.ts +9 -9
  314. package/plugins/acryl-router/src/core/helper/factory/index.ts +10 -10
  315. package/plugins/acryl-router/src/core/helper/html/index.test.ts +4 -4
  316. package/plugins/acryl-router/src/core/helper/html/index.ts +1 -1
  317. package/plugins/acryl-router/src/core/helper/route/index.test.ts +7 -7
  318. package/plugins/acryl-router/src/core/helper/route/index.ts +8 -8
  319. package/plugins/acryl-router/src/core/helper/streaming/index.ts +1 -1
  320. package/plugins/acryl-router/src/core/helper/testing/index.test.ts +6 -6
  321. package/plugins/acryl-router/src/core/helper/testing/index.ts +4 -4
  322. package/plugins/acryl-router/src/core/helper/websocket/index.ts +2 -1
  323. package/plugins/acryl-router/src/core/http-exception.ts +1 -1
  324. package/plugins/acryl-router/src/core/index.ts +9 -9
  325. package/plugins/acryl-router/src/core/middleware/basic-auth/index.test.ts +6 -6
  326. package/plugins/acryl-router/src/core/middleware/basic-auth/index.ts +3 -3
  327. package/plugins/acryl-router/src/core/middleware/bearer-auth/index.test.ts +5 -5
  328. package/plugins/acryl-router/src/core/middleware/bearer-auth/index.ts +3 -3
  329. package/plugins/acryl-router/src/core/middleware/body-limit/index.test.ts +6 -6
  330. package/plugins/acryl-router/src/core/middleware/body-limit/index.ts +3 -3
  331. package/plugins/acryl-router/src/core/middleware/combine/index.test.ts +9 -9
  332. package/plugins/acryl-router/src/core/middleware/combine/index.ts +7 -7
  333. package/plugins/acryl-router/src/core/middleware/compress/index.test.ts +9 -9
  334. package/plugins/acryl-router/src/core/middleware/compress/index.ts +3 -3
  335. package/plugins/acryl-router/src/core/middleware/context-storage/index.test.ts +5 -5
  336. package/plugins/acryl-router/src/core/middleware/context-storage/index.ts +4 -4
  337. package/plugins/acryl-router/src/core/middleware/cors/index.test.ts +7 -7
  338. package/plugins/acryl-router/src/core/middleware/cors/index.ts +3 -3
  339. package/plugins/acryl-router/src/core/middleware/csrf/index.test.ts +10 -10
  340. package/plugins/acryl-router/src/core/middleware/csrf/index.ts +3 -3
  341. package/plugins/acryl-router/src/core/middleware/etag/index.test.ts +42 -42
  342. package/plugins/acryl-router/src/core/middleware/etag/index.ts +4 -4
  343. package/plugins/acryl-router/src/core/middleware/ip-restriction/index.test.ts +4 -4
  344. package/plugins/acryl-router/src/core/middleware/ip-restriction/index.ts +6 -6
  345. package/plugins/acryl-router/src/core/middleware/jwk/index.test.ts +16 -16
  346. package/plugins/acryl-router/src/core/middleware/jwk/jwk.ts +7 -6
  347. package/plugins/acryl-router/src/core/middleware/jwt/index.test.ts +16 -16
  348. package/plugins/acryl-router/src/core/middleware/jwt/jwt.ts +4 -3
  349. package/plugins/acryl-router/src/core/middleware/language/index.test.ts +3 -3
  350. package/plugins/acryl-router/src/core/middleware/language/language.ts +3 -3
  351. package/plugins/acryl-router/src/core/middleware/logger/index.test.ts +5 -5
  352. package/plugins/acryl-router/src/core/middleware/logger/index.ts +4 -4
  353. package/plugins/acryl-router/src/core/middleware/method-not-allowed/index.test.ts +24 -24
  354. package/plugins/acryl-router/src/core/middleware/method-not-allowed/index.ts +8 -8
  355. package/plugins/acryl-router/src/core/middleware/method-override/index.test.ts +5 -5
  356. package/plugins/acryl-router/src/core/middleware/method-override/index.ts +6 -6
  357. package/plugins/acryl-router/src/core/middleware/powered-by/index.test.ts +4 -4
  358. package/plugins/acryl-router/src/core/middleware/powered-by/index.ts +6 -6
  359. package/plugins/acryl-router/src/core/middleware/pretty-json/index.test.ts +30 -30
  360. package/plugins/acryl-router/src/core/middleware/pretty-json/index.ts +4 -4
  361. package/plugins/acryl-router/src/core/middleware/request-id/index.test.ts +15 -15
  362. package/plugins/acryl-router/src/core/middleware/request-id/request-id.ts +3 -3
  363. package/plugins/acryl-router/src/core/middleware/secure-headers/index.test.ts +35 -35
  364. package/plugins/acryl-router/src/core/middleware/secure-headers/secure-headers.ts +3 -3
  365. package/plugins/acryl-router/src/core/middleware/serve-static/index.test.ts +23 -23
  366. package/plugins/acryl-router/src/core/middleware/serve-static/index.ts +1 -1
  367. package/plugins/acryl-router/src/core/middleware/timeout/index.test.ts +2 -2
  368. package/plugins/acryl-router/src/core/middleware/timeout/index.ts +3 -3
  369. package/plugins/acryl-router/src/core/middleware/timing/index.test.ts +14 -14
  370. package/plugins/acryl-router/src/core/middleware/timing/timing.ts +3 -3
  371. package/plugins/acryl-router/src/core/middleware/trailing-slash/index.test.ts +7 -7
  372. package/plugins/acryl-router/src/core/middleware/trailing-slash/index.ts +7 -7
  373. package/plugins/acryl-router/src/core/request.test.ts +42 -42
  374. package/plugins/acryl-router/src/core/request.ts +6 -6
  375. package/plugins/acryl-router/src/core/router/linear-router/index.ts +1 -1
  376. package/plugins/acryl-router/src/core/router/pattern-router/index.ts +1 -1
  377. package/plugins/acryl-router/src/core/router/reg-exp-router/index.ts +1 -1
  378. package/plugins/acryl-router/src/core/router/smart-router/index.ts +1 -1
  379. package/plugins/acryl-router/src/core/router/trie-router/index.ts +1 -1
  380. package/plugins/acryl-router/src/core/types.test.ts +115 -115
  381. package/plugins/acryl-router/src/core/types.ts +72 -72
  382. package/plugins/acryl-router/src/core/utils/body.ts +8 -8
  383. package/plugins/acryl-router/src/core/utils/html.ts +1 -1
  384. package/plugins/acryl-router/src/core/utils/jwt/jws.ts +3 -3
  385. package/plugins/acryl-router/src/core/utils/jwt/jwt.test.ts +2 -2
  386. package/plugins/acryl-router/src/core/utils/jwt/jwt.ts +3 -3
  387. package/plugins/acryl-router/src/core/utils/jwt/types.ts +1 -1
  388. package/plugins/acryl-router/src/core/utils/types.ts +42 -0
  389. package/plugins/acryl-router/src/core/utils/url.test.ts +2 -2
  390. package/plugins/acryl-router/src/core/validator/index.ts +1 -1
  391. package/plugins/acryl-router/src/core/validator/validator.test.ts +28 -28
  392. package/plugins/acryl-router/src/deprecated.ts +15 -0
  393. package/plugins/acryl-router/src/index.ts +3 -2
  394. package/plugins/acryl-router/src/middleware/index.ts +1 -1
  395. package/plugins/acryl-router/src/middleware/loopback-only.ts +34 -1
  396. package/plugins/acryl-router/src/service.ts +19 -13
  397. package/plugins/acryl-router/tests/docs-examples.spec.ts +11 -11
  398. package/plugins/acryl-router/tests/live-install.spec.ts +2 -2
  399. package/plugins/acryl-router/tests/loader.spec.ts +3 -3
  400. package/plugins/acryl-router/tests/loopback-only.spec.ts +80 -0
  401. package/plugins/acryl-router/tests/no-dom/consumer.ts +11 -0
  402. package/plugins/acryl-router/tests/no-dom/tsconfig.json +13 -0
  403. package/plugins/acryl-router/tests/service.spec.ts +39 -22
  404. package/plugins/acryl-router/upstream.json +3 -3
  405. package/plugins/acryl-router-http/tests/adapter.spec.ts +3 -3
  406. package/plugins/acryl-router-http/tests/surfaces.spec.ts +2 -2
  407. package/plugins/acryl-router-http/upstream.json +2 -2
  408. package/plugins/acryl-state/src/service.ts +2 -2
  409. package/plugins/acryl-state/upstream.json +2 -2
  410. package/plugins/builder/script.ts +3 -3
  411. package/plugins/extensions/index.ts +4 -3
  412. package/plugins/extensions/resolve.ts +70 -10
  413. package/plugins/openai/prompt.ts +7 -7
  414. package/shared/AGENTS.core.md +61 -0
  415. package/templates/agent/AGENTS.md +6 -0
  416. package/templates/agent/README.md +2 -2
  417. package/templates/agent/blend.yaml +1 -1
  418. package/templates/agent/src/routes.ts +2 -2
  419. package/templates/agent/test/model.test.ts +2 -2
  420. package/templates/agent/tsconfig.json +40 -0
  421. package/templates/blank/AGENTS.md +5 -0
  422. package/templates/blank/README.md +1 -1
  423. package/templates/blank/src/routes.ts +2 -2
  424. package/templates/todo/AGENTS.md +5 -0
  425. package/templates/todo/src/todo.ts +6 -4
  426. package/templates/todo/upstream.json +2 -2
@@ -9,7 +9,7 @@ import { decodeBase64 } from '../encode.ts'
9
9
  import type { SignatureAlgorithm } from './jwa.ts'
10
10
  import { CryptoKeyUsage, JwtAlgorithmNotImplemented } from './types.ts'
11
11
  import { utf8Encoder } from './utf8.ts'
12
- import type { BufferSource } from '../types.ts'
12
+ import type { BufferSource, CryptoKey, JsonWebKey } from '../types.ts'
13
13
 
14
14
  type KeyImporterAlgorithm = Parameters<typeof crypto.subtle.importKey>[2]
15
15
  type KeyAlgorithm =
@@ -21,11 +21,11 @@ type KeyAlgorithm =
21
21
 
22
22
  // Extending the JsonWebKey interface to include the "kid" property.
23
23
  // https://datatracker.ietf.org/doc/html/rfc7515#section-4.1.4
24
- export interface AppJsonWebKey extends JsonWebKey {
24
+ export interface AcrylJsonWebKey extends JsonWebKey {
25
25
  kid?: string
26
26
  }
27
27
 
28
- export type SignatureKey = string | AppJsonWebKey | CryptoKey
28
+ export type SignatureKey = string | AcrylJsonWebKey | CryptoKey
29
29
 
30
30
  export async function signing(
31
31
  privateKey: SignatureKey,
@@ -2,7 +2,7 @@
2
2
  import { vi } from 'vitest'
3
3
  import { encodeBase64, encodeBase64Url } from '../encode.ts'
4
4
  import { AlgorithmTypes } from './jwa.ts'
5
- import type { AppJsonWebKey } from './jws.ts'
5
+ import type { AcrylJsonWebKey } from './jws.ts'
6
6
  import { signing } from './jws.ts'
7
7
  import * as JWT from './jwt.ts'
8
8
  import { verifyWithJwks } from './jwt.ts'
@@ -1475,7 +1475,7 @@ describe('verifyWithJwks algorithm whitelist', () => {
1475
1475
 
1476
1476
  describe('verifyWithJwks key handling', () => {
1477
1477
  it('Should not mutate provided keys when JWKS is fetched repeatedly', async () => {
1478
- const localKeys: AppJsonWebKey[] = [
1478
+ const localKeys: AcrylJsonWebKey[] = [
1479
1479
  {
1480
1480
  kty: 'RSA',
1481
1481
  kid: 'local-key',
@@ -8,7 +8,7 @@ import { decodeBase64Url, encodeBase64Url } from '../encode.ts'
8
8
  import { AlgorithmTypes } from './jwa.ts'
9
9
  import type { AsymmetricAlgorithm, SignatureAlgorithm, SymmetricAlgorithm } from './jwa.ts'
10
10
  import { signing, verifying } from './jws.ts'
11
- import type { AppJsonWebKey, SignatureKey } from './jws.ts'
11
+ import type { AcrylJsonWebKey, SignatureKey } from './jws.ts'
12
12
  import {
13
13
  JwtAlgorithmMismatch,
14
14
  JwtAlgorithmNotAllowed,
@@ -198,7 +198,7 @@ const symmetricAlgorithms: SymmetricAlgorithm[] = [
198
198
  export const verifyWithJwks = async (
199
199
  token: string,
200
200
  options: {
201
- keys?: AppJsonWebKey[]
201
+ keys?: AcrylJsonWebKey[]
202
202
  jwks_uri?: string
203
203
  verification?: VerifyOptions
204
204
  allowedAlgorithms: readonly AsymmetricAlgorithm[]
@@ -241,7 +241,7 @@ export const verifyWithJwks = async (
241
241
  throw new Error('invalid JWKS response. "keys" field is not an array')
242
242
  }
243
243
  verifyKeys ??= []
244
- verifyKeys.push(...(data.keys as AppJsonWebKey[]))
244
+ verifyKeys.push(...(data.keys as AcrylJsonWebKey[]))
245
245
  } else if (!verifyKeys) {
246
246
  throw new Error('verifyWithJwks requires options for either "keys" or "jwks_uri" or both')
247
247
  }
@@ -154,4 +154,4 @@ export type JWTPayload = {
154
154
  aud?: string | string[]
155
155
  }
156
156
 
157
- export type { AppJsonWebKey } from './jws.ts'
157
+ export type { AcrylJsonWebKey } from './jws.ts'
@@ -121,3 +121,45 @@ export type StringLiteralUnion<T> = T | (string & Record<never, never>)
121
121
 
122
122
  /** Bytes a Web Crypto call accepts; declared here so the public types do not need the DOM library. */
123
123
  export type BufferSource = ArrayBufferView<ArrayBuffer> | ArrayBuffer
124
+
125
+ /** A Web Crypto key, named from the runtime's own `crypto` so the public types do not need the DOM library. */
126
+ export type CryptoKey = Awaited<ReturnType<typeof crypto.subtle.importKey>>
127
+
128
+ /** How a WebSocket hands binary data to `onmessage`; declared here so the public types do not need the DOM library. */
129
+ export type BinaryType = 'arraybuffer' | 'blob'
130
+
131
+ /** The members of a WebSocket `message` event the helpers hand out (the Web `MessageEvent`, whose Node global is not generic); declared here so the public types do not need the DOM library. */
132
+ export interface MessageEvent<T = unknown> extends Event {
133
+ readonly data: T
134
+ readonly lastEventId: string
135
+ readonly origin: string
136
+ }
137
+
138
+ /** The members of a WebSocket `close` event the helpers hand out (the Web `CloseEvent`, which Node has no global type for); declared here so the public types do not need the DOM library. */
139
+ export interface CloseEvent extends Event {
140
+ readonly code: number
141
+ readonly reason: string
142
+ readonly wasClean: boolean
143
+ }
144
+
145
+ /** A JSON Web Key (RFC 7517), the same members as the Web Crypto dictionary; declared here so the public types do not need the DOM library. */
146
+ export interface JsonWebKey {
147
+ alg?: string
148
+ crv?: string
149
+ d?: string
150
+ dp?: string
151
+ dq?: string
152
+ e?: string
153
+ ext?: boolean
154
+ k?: string
155
+ key_ops?: string[]
156
+ kty?: string
157
+ n?: string
158
+ oth?: { d?: string; r?: string; t?: string }[]
159
+ p?: string
160
+ q?: string
161
+ qi?: string
162
+ use?: string
163
+ x?: string
164
+ y?: string
165
+ }
@@ -270,7 +270,7 @@ describe('url', () => {
270
270
  )
271
271
  expect(getQueryParam('http://example.com/?safe=1#&admin=true')).toEqual({ safe: '1' })
272
272
  expect(getQueryParam('http://example.com/?name=hey&age=20&tall=170', 'age')).toBe('20')
273
- expect(getQueryParam('http://example.com/?App+is=a+web+framework', 'App is')).toBe(
273
+ expect(getQueryParam('http://example.com/?Acryl+is=a+web+framework', 'Acryl is')).toBe(
274
274
  'a web framework'
275
275
  )
276
276
  expect(getQueryParam('http://example.com/?name=%E0%A4%A', 'name')).toBe('%E0%A4%A')
@@ -330,7 +330,7 @@ describe('url', () => {
330
330
  expect(
331
331
  getQueryParams('http://example.com/?name=hey&age=20&tall=170&name=foo&age=30', 'age')
332
332
  ).toEqual(['20', '30'])
333
- expect(getQueryParams('http://example.com/?App+is=a+web+framework', 'App is')).toEqual([
333
+ expect(getQueryParams('http://example.com/?Acryl+is=a+web+framework', 'Acryl is')).toEqual([
334
334
  'a web framework',
335
335
  ])
336
336
  expect(getQueryParams('http://example.com/?name=%E0%A4%A', 'name')).toEqual(['%E0%A4%A'])
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @module
3
- * Validator for App.
3
+ * Validator for Acryl.
4
4
  */
5
5
 
6
6
  export { validator } from './validator.ts'
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable @typescript-eslint/no-unused-vars */
2
2
  import * as z from 'zod'
3
3
  import type { Context } from '../context.ts'
4
- import { App } from '../app.ts'
4
+ import { Acryl } from '../app.ts'
5
5
  import { HTTPException } from '../http-exception.ts'
6
6
  import { cloneRawRequest } from '../request.ts'
7
7
  import type {
@@ -61,7 +61,7 @@ const zodValidator = <
61
61
  }
62
62
 
63
63
  describe('Basic', () => {
64
- const app = new App()
64
+ const app = new Acryl()
65
65
 
66
66
  const route = app.get(
67
67
  '/search',
@@ -124,7 +124,7 @@ const onErrorHandler: ErrorHandler = (e, c) => {
124
124
  }
125
125
 
126
126
  describe('JSON', () => {
127
- const app = new App()
127
+ const app = new Acryl()
128
128
  app.post(
129
129
  '/post',
130
130
  validator('json', (value) => value),
@@ -230,7 +230,7 @@ describe('JSON', () => {
230
230
  })
231
231
 
232
232
  describe('Malformed JSON', () => {
233
- const app = new App()
233
+ const app = new Acryl()
234
234
  app.post(
235
235
  '/post',
236
236
  validator('json', (value) => value),
@@ -254,7 +254,7 @@ describe('Malformed JSON', () => {
254
254
  })
255
255
 
256
256
  describe('FormData', () => {
257
- const app = new App()
257
+ const app = new Acryl()
258
258
  app.post(
259
259
  '/post',
260
260
  validator('form', (value) => value),
@@ -373,7 +373,7 @@ describe('FormData', () => {
373
373
  })
374
374
 
375
375
  describe('Malformed FormData request', () => {
376
- const app = new App()
376
+ const app = new Acryl()
377
377
  app.post(
378
378
  '/post',
379
379
  validator('form', (value) => value),
@@ -399,7 +399,7 @@ describe('Malformed FormData request', () => {
399
399
  })
400
400
 
401
401
  describe('JSON and FormData', () => {
402
- const app = new App()
402
+ const app = new Acryl()
403
403
  app.post(
404
404
  '/',
405
405
  validator('json', (value) => value),
@@ -442,7 +442,7 @@ describe('JSON and FormData', () => {
442
442
 
443
443
  describe('Cached contents', () => {
444
444
  describe('json', () => {
445
- const app = new App()
445
+ const app = new Acryl()
446
446
  const bodyTypes = ['json', 'text', 'arrayBuffer', 'blob']
447
447
 
448
448
  for (const type of bodyTypes) {
@@ -483,7 +483,7 @@ describe('Cached contents', () => {
483
483
  })
484
484
 
485
485
  describe('Cached content', () => {
486
- const app = new App()
486
+ const app = new Acryl()
487
487
  const bodyTypes = ['formData', 'text', 'arrayBuffer', 'blob']
488
488
 
489
489
  for (const type of bodyTypes) {
@@ -523,7 +523,7 @@ describe('Cached contents', () => {
523
523
  })
524
524
 
525
525
  describe('Validator middleware with a custom validation function', () => {
526
- const app = new App()
526
+ const app = new Acryl()
527
527
 
528
528
  const validationFunction: ValidationFunction<{ id: string }, { id: number }> = (v) => {
529
529
  return {
@@ -595,7 +595,7 @@ describe('Validator middleware with a custom validation function', () => {
595
595
  })
596
596
 
597
597
  describe('Validator middleware with Zod validates JSON', () => {
598
- const app = new App()
598
+ const app = new Acryl()
599
599
 
600
600
  const schema = z.object({
601
601
  id: z.number(),
@@ -688,7 +688,7 @@ describe('Validator middleware with Zod validates JSON', () => {
688
688
  })
689
689
 
690
690
  describe('Validator middleware with Zod validates Form data', () => {
691
- const app = new App()
691
+ const app = new Acryl()
692
692
 
693
693
  const schema = z.object({
694
694
  id: z.string(),
@@ -728,7 +728,7 @@ describe('Validator middleware with Zod validates Form data', () => {
728
728
  })
729
729
 
730
730
  describe('Validator middleware with Zod validates query params', () => {
731
- const app = new App()
731
+ const app = new Acryl()
732
732
 
733
733
  const schema = z.object({
734
734
  page: z
@@ -767,7 +767,7 @@ describe('Validator middleware with Zod validates query params', () => {
767
767
  })
768
768
 
769
769
  describe('Validator middleware with Zod validates param', () => {
770
- const app = new App()
770
+ const app = new Acryl()
771
771
 
772
772
  const schema = z.object({
773
773
  id: z
@@ -804,7 +804,7 @@ describe('Validator middleware with Zod validates param', () => {
804
804
  })
805
805
 
806
806
  describe('Validator middleware with Zod validates header values', () => {
807
- const app = new App()
807
+ const app = new Acryl()
808
808
 
809
809
  const schema = z.object({
810
810
  'x-request-id': z.string().uuid(),
@@ -842,7 +842,7 @@ describe('Validator middleware with Zod validates header values', () => {
842
842
  })
843
843
 
844
844
  describe('Validator middleware with Zod validates cookies', () => {
845
- const app = new App()
845
+ const app = new Acryl()
846
846
 
847
847
  const schema = z.object({
848
848
  debug: z.enum(['0', '1']),
@@ -879,7 +879,7 @@ describe('Validator middleware with Zod validates cookies', () => {
879
879
  })
880
880
 
881
881
  describe('Validator middleware with Zod multiple validators', () => {
882
- const app = new App<{ Variables: { id: number } }>()
882
+ const app = new Acryl<{ Variables: { id: number } }>()
883
883
  const route = app.post(
884
884
  '/posts',
885
885
  zodValidator(
@@ -977,7 +977,7 @@ describe('Validator middleware with Zod multiple validators', () => {
977
977
  })
978
978
 
979
979
  it('With path parameters', () => {
980
- const app = new App()
980
+ const app = new Acryl()
981
981
 
982
982
  const route = app.put(
983
983
  '/posts/:id',
@@ -1020,7 +1020,7 @@ it('With path parameters', () => {
1020
1020
  })
1021
1021
 
1022
1022
  it('`on`', () => {
1023
- const app = new App()
1023
+ const app = new Acryl()
1024
1024
 
1025
1025
  const route = app.on(
1026
1026
  'PURGE',
@@ -1068,7 +1068,7 @@ it('`on`', () => {
1068
1068
  })
1069
1069
 
1070
1070
  it('`app.on`', () => {
1071
- const app = new App()
1071
+ const app = new Acryl()
1072
1072
 
1073
1073
  const route = app
1074
1074
  .get(
@@ -1112,7 +1112,7 @@ it('`app.on`', () => {
1112
1112
 
1113
1113
  describe('Clone Request object', () => {
1114
1114
  describe('json', () => {
1115
- const app = new App()
1115
+ const app = new Acryl()
1116
1116
  app.post(
1117
1117
  '/',
1118
1118
  validator('json', () => {
@@ -1147,7 +1147,7 @@ describe('Clone Request object', () => {
1147
1147
  })
1148
1148
 
1149
1149
  describe('form', () => {
1150
- const app = new App()
1150
+ const app = new Acryl()
1151
1151
  app.post(
1152
1152
  '/',
1153
1153
  validator('form', () => {
@@ -1212,7 +1212,7 @@ describe('Clone Request object', () => {
1212
1212
  })
1213
1213
 
1214
1214
  describe('Async validator function', () => {
1215
- const app = new App()
1215
+ const app = new Acryl()
1216
1216
 
1217
1217
  app.get(
1218
1218
  '/posts',
@@ -1243,7 +1243,7 @@ describe('Validator with using Zod directly', () => {
1243
1243
  age: z.number(),
1244
1244
  type: z.enum(['a']),
1245
1245
  })
1246
- const app = new App()
1246
+ const app = new Acryl()
1247
1247
 
1248
1248
  const route = app.post(
1249
1249
  '/posts',
@@ -1308,7 +1308,7 @@ describe('Validator with using Zod directly', () => {
1308
1308
 
1309
1309
  describe('Transform', () => {
1310
1310
  it('Should be number when the type is transformed', () => {
1311
- const route = new App().get(
1311
+ const route = new Acryl().get(
1312
1312
  '/',
1313
1313
  validator('query', async () => {
1314
1314
  return {
@@ -1347,7 +1347,7 @@ describe('Transform', () => {
1347
1347
  })
1348
1348
 
1349
1349
  it('Should be number and union when the type is transformed', () => {
1350
- const app = new App()
1350
+ const app = new Acryl()
1351
1351
  const route = app.get(
1352
1352
  '/',
1353
1353
  validator('query', () => {
@@ -1400,7 +1400,7 @@ describe('Transform', () => {
1400
1400
 
1401
1401
  describe('Raw Request cloning after validation', () => {
1402
1402
  it('Should allow the `cloneRawRequest` util to clone the request object after validation', async () => {
1403
- const app = new App()
1403
+ const app = new Acryl()
1404
1404
 
1405
1405
  app.post(
1406
1406
  '/json-validation',
@@ -1469,7 +1469,7 @@ describe('Raw Request cloning after validation', () => {
1469
1469
 
1470
1470
  describe('Form validator prototype pollution prevention', () => {
1471
1471
  it('should store __proto__ as data and not misdetect inherited keys', async () => {
1472
- const app = new App()
1472
+ const app = new Acryl()
1473
1473
  app.post(
1474
1474
  '/form',
1475
1475
  validator('form', (value) => value),
@@ -0,0 +1,15 @@
1
+ /**
2
+ * The 0.4 names, kept for one release so code written against them keeps working: `App` is now `Acryl` and `AppRequest` is now `AcrylRequest`,
3
+ * the upstream names with the project renamed. Not part of the ported core; both the plugin's root and the public package's root export these.
4
+ */
5
+
6
+ import { Acryl } from './core/app.ts'
7
+ import type { AcrylRequest } from './core/request.ts'
8
+ import type { BlankEnv, BlankSchema, Env, Input, Schema } from './core/types.ts'
9
+
10
+ /** @deprecated Use `Acryl` (`new Acryl()`); `App` is the 0.4 name and goes away in the next release. */
11
+ export const App = Acryl
12
+ /** @deprecated Use `Acryl`; `App` is the 0.4 name and goes away in the next release. */
13
+ export type App<E extends Env = BlankEnv, S extends Schema = BlankSchema, BasePath extends string = '/'> = Acryl<E, S, BasePath>
14
+ /** @deprecated Use `AcrylRequest`; `AppRequest` is the 0.4 name and goes away in the next release. */
15
+ export type AppRequest<P extends string = '/', I extends Input['out'] = {}> = AcrylRequest<P, I>
@@ -1,6 +1,7 @@
1
1
  export { Router, Config, apply, name, type MountableApp, type RouterHttpService, type TrailingSlash } from './service.ts'
2
2
  export { connectionOf, getConnInfo, type ConnectionInfo, type RouterBindings, type RouterEnv } from './connection.ts'
3
- export { App, Context } from './core/index.ts'
4
- export type { AppRequest, ContextRenderer, ContextVariableMap, Env, ErrorHandler, ExecutionContext, Handler, Input, MiddlewareHandler, Next, NotFoundHandler, NotFoundResponse, Schema, ToSchema, TypedResponse, ValidationTargets } from './core/index.ts'
3
+ export { Acryl, Context } from './core/index.ts'
4
+ export { App, type AppRequest } from './deprecated.ts'
5
+ export type { AcrylRequest, ContextRenderer, ContextVariableMap, Env, ErrorHandler, ExecutionContext, Handler, Input, MiddlewareHandler, Next, NotFoundHandler, NotFoundResponse, Schema, ToSchema, TypedResponse, ValidationTargets } from './core/index.ts'
5
6
  export { HTTPException } from './core/http-exception.ts'
6
7
  export type { ContentfulStatusCode, StatusCode } from './core/utils/http-status.ts'
@@ -22,4 +22,4 @@ export { NONCE, secureHeaders, type SecureHeadersVariables } from '../core/middl
22
22
  export { timeout } from '../core/middleware/timeout/index.ts'
23
23
  export { endTime, setMetric, startTime, timing, wrapTime, type TimingVariables } from '../core/middleware/timing/index.ts'
24
24
  export { appendTrailingSlash, trimTrailingSlash } from '../core/middleware/trailing-slash/index.ts'
25
- export { LOOPBACK_HOSTNAMES, loopbackAuthority, loopbackOnly, sameOrigin, type LoopbackOptions } from './loopback-only.ts'
25
+ export { LOOPBACK_HOSTNAMES, fromOwnPage, loopbackAuthority, loopbackOnly, sameOrigin, type LoopbackOptions } from './loopback-only.ts'
@@ -19,6 +19,13 @@ export interface LoopbackOptions {
19
19
  * checked in full: only a call with no connection facts at all counts as in process.
20
20
  */
21
21
  readonly inProcess?: 'deny' | 'allow'
22
+ /**
23
+ * 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,
24
+ * 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
25
+ * `Sec-Fetch-Site` absent or `same-origin`), or, for a read (GET, HEAD, OPTIONS), which browsers often send without `Origin`, `Sec-Fetch-Site:
26
+ * same-origin` and a `Referer` from this authority. `mutations` is not consulted: every request is held to that rule.
27
+ */
28
+ readonly callers?: 'local' | 'own-page'
22
29
  }
23
30
 
24
31
  const loopback = new BlockList()
@@ -68,10 +75,31 @@ export function sameOrigin(c: Context, authority: URL): boolean {
68
75
  }
69
76
  }
70
77
 
71
- /** Only requests from this machine to this app: loopback peer, the real port, an allowed `Host`, and for mutations a matching `Origin`. Everything else gets a 403. */
78
+ function originOf(value: string | undefined): string | undefined {
79
+ if (value === undefined) return undefined
80
+ try {
81
+ return new URL(value).origin
82
+ } catch {
83
+ return undefined
84
+ }
85
+ }
86
+
87
+ /** Whether the request comes from a page served by this authority itself: the `own-page` rule of {@link LoopbackOptions.callers}. */
88
+ export function fromOwnPage(c: Context, authority: URL): boolean {
89
+ const origin = c.req.header('origin')
90
+ const fetchSite = c.req.header('sec-fetch-site')
91
+ if (origin !== undefined && originOf(origin) === origin && origin === authority.origin) return fetchSite === undefined || fetchSite === 'same-origin'
92
+ return SAFE_METHODS.has(c.req.method) && fetchSite === 'same-origin' && originOf(c.req.header('referer')) === authority.origin
93
+ }
94
+
95
+ /**
96
+ * Only requests from this machine to this app: loopback peer, the real port, an allowed `Host`, and for mutations a matching `Origin` (with
97
+ * `callers: 'own-page'`, every request from this app's own page). Everything else gets a 403.
98
+ */
72
99
  export function loopbackOnly(options: LoopbackOptions = {}): MiddlewareHandler {
73
100
  const mutations = options.mutations ?? 'same-origin'
74
101
  const inProcess = options.inProcess ?? 'deny'
102
+ const ownPage = options.callers === 'own-page'
75
103
  return async (c, next) => {
76
104
  const connection = connectionOf(c)
77
105
  if (inProcess === 'allow' && connection.remoteAddress === undefined && connection.localPort === undefined) {
@@ -80,6 +108,11 @@ export function loopbackOnly(options: LoopbackOptions = {}): MiddlewareHandler {
80
108
  }
81
109
  const authority = loopbackAuthority(c, options.hostnames)
82
110
  if (authority === undefined) return c.json({ error: 'request authority rejected' }, 403)
111
+ if (ownPage) {
112
+ if (!fromOwnPage(c, authority)) return c.json({ error: 'only this app\'s own page may call this' }, 403)
113
+ await next()
114
+ return
115
+ }
83
116
  if (mutations === 'same-origin' && !SAFE_METHODS.has(c.req.method) && !sameOrigin(c, authority)) {
84
117
  return c.json({ error: 'a change must come from this app\'s own origin' }, 403)
85
118
  }
@@ -1,7 +1,7 @@
1
1
  /**
2
- * The ACRYL router service (`ctx.router`): plugin-owned `App` mounts on Web-standard Request and Response.
2
+ * The ACRYL router service (`ctx.router`): plugin-owned `Acryl` mounts on Web-standard Request and Response.
3
3
  *
4
- * A plugin builds an ordinary `App` and mounts it with `ctx.router.route(path, app)` from its own context, so the mount disappears when that
4
+ * A plugin builds an ordinary `Acryl` and mounts it with `ctx.router.route(path, app)` from its own context, so the mount disappears when that
5
5
  * plugin unloads. `fetch(request)` runs a request in process: Web and Desktop serve it behind HTTP through an adapter, the terminal UI calls
6
6
  * it directly, so one handler serves every surface without opening a socket. Disposal refuses new requests, aborts in-flight ones, ends any
7
7
  * response body still streaming and waits for all of it to settle.
@@ -10,7 +10,7 @@
10
10
  import { Context, Service } from '@deepseek-ai/cordis'
11
11
  import z from '@deepseek-ai/schemastery'
12
12
  import type { ConnectionInfo, RouterBindings } from './connection.ts'
13
- import { App } from './core/app.ts'
13
+ import { Acryl } from './core/app.ts'
14
14
  import type { ExecutionContext } from './core/context.ts'
15
15
  import { HTTPException } from './core/http-exception.ts'
16
16
  import { TrieRouter } from './core/router/trie-router/index.ts'
@@ -54,9 +54,9 @@ declare module '@deepseek-ai/cordis' {
54
54
  /** Stable Cordis plugin name, equal to the package name and the Loader row id. */
55
55
  export const name = 'acryl-router'
56
56
 
57
- // Any `App`, whatever its Env and schema; the router only reads its routes.
57
+ // Any `Acryl`, whatever its Env and schema; the router only reads its routes.
58
58
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
59
- export type MountableApp = App<any, any, any>
59
+ export type MountableApp = Acryl<any, any, any>
60
60
 
61
61
  interface Mount {
62
62
  readonly path: string
@@ -68,7 +68,7 @@ interface RouterState {
68
68
  errorHandler: ErrorHandler | undefined
69
69
  notFoundHandler: NotFoundHandler | undefined
70
70
  /** The app composed from the live mounts; dropped on every change and composed again by the next request. */
71
- composed: App | undefined
71
+ composed: Acryl | undefined
72
72
  closing: boolean
73
73
  }
74
74
 
@@ -144,9 +144,15 @@ export class Router extends Service {
144
144
  this.state.composed = undefined
145
145
  return this.end([...this.flights].filter(flight => (flight.running.get(mount) ?? 0) > 0 || flight.producer === mount), `removing ${path}`)
146
146
  }
147
- // The label lists what the mount serves, so the inspector can report routes without asking the router (`ALL` is middleware or `all`).
148
- const served = app.routes.map(route => `${route.method} ${mergePath(path, route.path)}`).join(', ')
149
- this.ctx.effect(() => remove, `acryl-router: route ${path} (${served})`)
147
+ // Each route the mount serves is a child effect of it, labeled on its own, so the inspector can report routes without asking the
148
+ // router and no label grows with the size of the app (`ALL` is middleware or `all`). The children hold nothing: the mount does.
149
+ // (Cordis adopts an effect as a child only when the parent's body yields it.)
150
+ const served = new Set(app.routes.map(route => `${route.method} ${mergePath(path, route.path)}`))
151
+ const owner = this.ctx
152
+ owner.effect(function* () {
153
+ for (const route of served) yield owner.effect(() => () => {}, `acryl-router: serves ${route}`)
154
+ yield remove
155
+ }, `acryl-router: route ${path}`)
150
156
  return () => { void remove() }
151
157
  }
152
158
 
@@ -155,8 +161,8 @@ export class Router extends Service {
155
161
  * mount's code a request is in. The core's `app.route` runs first so a sub-app's own `onError` still applies to its routes.
156
162
  */
157
163
  private snapshot(path: string, app: MountableApp): Mount {
158
- const copy = new App().route('/', app)
159
- const tagged = new App()
164
+ const copy = new Acryl().route('/', app)
165
+ const tagged = new Acryl()
160
166
  const mount: Mount = { path, app: tagged }
161
167
  for (const route of copy.routes) {
162
168
  const inner = route.handler
@@ -285,12 +291,12 @@ export class Router extends Service {
285
291
  }
286
292
  }
287
293
 
288
- private app(): App {
294
+ private app(): Acryl {
289
295
  if (this.state.composed !== undefined) return this.state.composed
290
296
  // The trie router, because the composed app is rebuilt after every mount change: the default matcher compiles one regular expression
291
297
  // over all routes on its first request, which grows faster than the route count (measured: 22 ms at 1000 routes, 163 ms at 2000),
292
298
  // while the trie rebuilds in about 1 ms per 1000 routes and matches as fast (scripts/bench-remount.mjs).
293
- const root = new App({ strict: this.strict, router: new TrieRouter() })
299
+ const root = new Acryl({ strict: this.strict, router: new TrieRouter() })
294
300
  for (const mount of this.state.mounts) root.route(mount.path, mount.app)
295
301
  root.onError(this.state.errorHandler ?? this.logError)
296
302
  if (this.state.notFoundHandler !== undefined) root.notFound(this.state.notFoundHandler)