acrylblends 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +6 -1
- package/dist/index.js +28 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/plugins/acryl-inspect/plugin.json +2 -1
- package/plugins/acryl-inspect/src/report.ts +16 -13
- package/plugins/acryl-inspect/src/service.ts +9 -7
- package/plugins/acryl-inspect/tests/report.spec.ts +7 -8
- package/plugins/acryl-inspect/tests/service.spec.ts +11 -10
- package/plugins/acryl-inspect/upstream.json +2 -2
- package/plugins/acryl-node-server/LICENSE +26 -0
- package/plugins/acryl-node-server/plugin.json +2 -1
- package/plugins/acryl-node-server/src/adapter/conninfo.ts +23 -0
- package/plugins/acryl-node-server/src/adapter/early-hints.ts +55 -0
- package/plugins/acryl-node-server/src/adapter/error.ts +11 -0
- package/plugins/acryl-node-server/src/adapter/headers.ts +249 -0
- package/plugins/acryl-node-server/src/adapter/index.ts +6 -0
- package/plugins/acryl-node-server/src/adapter/listener.ts +540 -0
- package/plugins/acryl-node-server/src/adapter/request.ts +797 -0
- package/plugins/acryl-node-server/src/adapter/response.ts +186 -0
- package/plugins/acryl-node-server/src/adapter/serve-static.ts +238 -0
- package/plugins/acryl-node-server/src/adapter/server.ts +36 -0
- package/plugins/acryl-node-server/src/adapter/types.ts +82 -0
- package/plugins/acryl-node-server/src/adapter/url.ts +42 -0
- package/plugins/acryl-node-server/src/adapter/utils/response/constants.ts +1 -0
- package/plugins/acryl-node-server/src/adapter/utils/response.ts +4 -0
- package/plugins/acryl-node-server/src/adapter/utils/stream.ts +88 -0
- package/plugins/acryl-node-server/src/adapter/utils.ts +96 -0
- package/plugins/acryl-node-server/src/adapter/websocket-types.ts +45 -0
- package/plugins/acryl-node-server/src/adapter/websocket.ts +375 -0
- package/plugins/acryl-node-server/src/index.ts +19 -6
- package/plugins/acryl-node-server/tests/adapter/app.ts +76 -0
- package/plugins/acryl-node-server/tests/adapter/assets/.static/plain.txt +1 -0
- package/plugins/acryl-node-server/tests/adapter/assets/favicon.ico +0 -0
- package/plugins/acryl-node-server/tests/adapter/assets/secret.txt +1 -0
- package/plugins/acryl-node-server/tests/adapter/assets/static/acryl.html +1 -0
- package/plugins/acryl-node-server/tests/adapter/assets/static/admin/secret.txt +1 -0
- package/plugins/acryl-node-server/tests/adapter/assets/static/data.json +5 -0
- package/plugins/acryl-node-server/tests/adapter/assets/static/extensionless +1 -0
- package/plugins/acryl-node-server/tests/adapter/assets/static/foo..bar.txt +0 -0
- package/plugins/acryl-node-server/tests/adapter/assets/static/index.html +1 -0
- package/plugins/acryl-node-server/tests/adapter/assets/static/plain.txt +1 -0
- package/plugins/acryl-node-server/tests/adapter/assets/static-with-context-path/plain.txt +1 -0
- package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.bin +1 -0
- package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.bin.br +1 -0
- package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.txt +1 -0
- package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.txt.br +1 -0
- package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.txt.zst +1 -0
- package/plugins/acryl-node-server/tests/adapter/conninfo.test.ts +34 -0
- package/plugins/acryl-node-server/tests/adapter/content-length.test.ts +248 -0
- package/plugins/acryl-node-server/tests/adapter/early-hints.test.ts +457 -0
- package/plugins/acryl-node-server/tests/adapter/fixtures/keys/agent1-cert.pem +23 -0
- package/plugins/acryl-node-server/tests/adapter/fixtures/keys/agent1-key.pem +27 -0
- package/plugins/acryl-node-server/tests/adapter/headers.test.ts +252 -0
- package/plugins/acryl-node-server/tests/adapter/helpers/request.ts +190 -0
- package/plugins/acryl-node-server/tests/adapter/listener.test.ts +727 -0
- package/plugins/acryl-node-server/tests/adapter/request-client-disconnect.test.ts +189 -0
- package/plugins/acryl-node-server/tests/adapter/request.test.ts +1230 -0
- package/plugins/acryl-node-server/tests/adapter/response.test.ts +285 -0
- package/plugins/acryl-node-server/tests/adapter/serve-static.test.ts +849 -0
- package/plugins/acryl-node-server/tests/adapter/server-socket.test.ts +790 -0
- package/plugins/acryl-node-server/tests/adapter/server.test.ts +1302 -0
- package/plugins/acryl-node-server/tests/adapter/setup.ts +16 -0
- package/plugins/acryl-node-server/tests/adapter/url.test.ts +76 -0
- package/plugins/acryl-node-server/tests/adapter/utils/response.test.ts +23 -0
- package/plugins/acryl-node-server/tests/adapter/utils/stream.test.ts +75 -0
- package/plugins/acryl-node-server/tests/adapter/utils.test.ts +235 -0
- package/plugins/acryl-node-server/tests/adapter/websocket.test.ts +260 -0
- package/plugins/acryl-node-server/tests/server.spec.ts +44 -8
- package/plugins/acryl-node-server/upstream.json +3 -3
- package/plugins/acryl-router/LICENSE +26 -0
- package/plugins/acryl-router/plugin.json +2 -1
- package/plugins/acryl-router/src/client.ts +2 -0
- package/plugins/acryl-router/src/connection.ts +42 -0
- package/plugins/acryl-router/src/core/app-base.ts +544 -0
- package/plugins/acryl-router/src/core/app.test.ts +3833 -0
- package/plugins/acryl-router/src/core/app.ts +34 -0
- package/plugins/acryl-router/src/core/client/client.test.ts +2313 -0
- package/plugins/acryl-router/src/core/client/client.ts +249 -0
- package/plugins/acryl-router/src/core/client/fetch-result-please.ts +95 -0
- package/plugins/acryl-router/src/core/client/index.ts +17 -0
- package/plugins/acryl-router/src/core/client/types.test.ts +149 -0
- package/plugins/acryl-router/src/core/client/types.ts +393 -0
- package/plugins/acryl-router/src/core/client/utils.test.ts +405 -0
- package/plugins/acryl-router/src/core/client/utils.ts +117 -0
- package/plugins/acryl-router/src/core/compose.test.ts +751 -0
- package/plugins/acryl-router/src/core/compose.ts +73 -0
- package/plugins/acryl-router/src/core/context.test.ts +629 -0
- package/plugins/acryl-router/src/core/context.ts +781 -0
- package/plugins/acryl-router/src/core/helper/accepts/accepts.test.ts +344 -0
- package/plugins/acryl-router/src/core/helper/accepts/accepts.ts +96 -0
- package/plugins/acryl-router/src/core/helper/accepts/index.ts +6 -0
- package/plugins/acryl-router/src/core/helper/adapter/index.test.ts +55 -0
- package/plugins/acryl-router/src/core/helper/adapter/index.ts +90 -0
- package/plugins/acryl-router/src/core/helper/conninfo/index.ts +6 -0
- package/plugins/acryl-router/src/core/helper/conninfo/types.ts +45 -0
- package/plugins/acryl-router/src/core/helper/cookie/index.test.ts +510 -0
- package/plugins/acryl-router/src/core/helper/cookie/index.ts +146 -0
- package/plugins/acryl-router/src/core/helper/factory/index.test.ts +434 -0
- package/plugins/acryl-router/src/core/helper/factory/index.ts +375 -0
- package/plugins/acryl-router/src/core/helper/html/index.test.ts +78 -0
- package/plugins/acryl-router/src/core/helper/html/index.ts +57 -0
- package/plugins/acryl-router/src/core/helper/route/index.test.ts +259 -0
- package/plugins/acryl-router/src/core/helper/route/index.ts +144 -0
- package/plugins/acryl-router/src/core/helper/streaming/index.ts +9 -0
- package/plugins/acryl-router/src/core/helper/streaming/sse.ts +101 -0
- package/plugins/acryl-router/src/core/helper/streaming/stream.test.ts +128 -0
- package/plugins/acryl-router/src/core/helper/streaming/stream.ts +45 -0
- package/plugins/acryl-router/src/core/helper/streaming/text.test.ts +34 -0
- package/plugins/acryl-router/src/core/helper/streaming/text.ts +15 -0
- package/plugins/acryl-router/src/core/helper/streaming/utils.ts +11 -0
- package/plugins/acryl-router/src/core/helper/testing/index.test.ts +42 -0
- package/plugins/acryl-router/src/core/helper/testing/index.ts +28 -0
- package/plugins/acryl-router/src/core/helper/websocket/index.test.ts +124 -0
- package/plugins/acryl-router/src/core/helper/websocket/index.ts +140 -0
- package/plugins/acryl-router/src/core/http-exception.test.ts +45 -0
- package/plugins/acryl-router/src/core/http-exception.ts +77 -0
- package/plugins/acryl-router/src/core/index.ts +53 -0
- package/plugins/acryl-router/src/core/middleware/basic-auth/index.test.ts +434 -0
- package/plugins/acryl-router/src/core/middleware/basic-auth/index.ts +152 -0
- package/plugins/acryl-router/src/core/middleware/bearer-auth/index.test.ts +1018 -0
- package/plugins/acryl-router/src/core/middleware/bearer-auth/index.ts +220 -0
- package/plugins/acryl-router/src/core/middleware/body-limit/index.test.ts +273 -0
- package/plugins/acryl-router/src/core/middleware/body-limit/index.ts +110 -0
- package/plugins/acryl-router/src/core/middleware/combine/index.test.ts +355 -0
- package/plugins/acryl-router/src/core/middleware/combine/index.ts +171 -0
- package/plugins/acryl-router/src/core/middleware/compress/index.test.ts +535 -0
- package/plugins/acryl-router/src/core/middleware/compress/index.ts +142 -0
- package/plugins/acryl-router/src/core/middleware/context-storage/index.test.ts +43 -0
- package/plugins/acryl-router/src/core/middleware/context-storage/index.ts +58 -0
- package/plugins/acryl-router/src/core/middleware/cors/index.test.ts +532 -0
- package/plugins/acryl-router/src/core/middleware/cors/index.ts +163 -0
- package/plugins/acryl-router/src/core/middleware/csrf/index.test.ts +534 -0
- package/plugins/acryl-router/src/core/middleware/csrf/index.ts +150 -0
- package/plugins/acryl-router/src/core/middleware/etag/digest.test.ts +21 -0
- package/plugins/acryl-router/src/core/middleware/etag/digest.ts +95 -0
- package/plugins/acryl-router/src/core/middleware/etag/index.test.ts +503 -0
- package/plugins/acryl-router/src/core/middleware/etag/index.ts +135 -0
- package/plugins/acryl-router/src/core/middleware/ip-restriction/index.test.ts +217 -0
- package/plugins/acryl-router/src/core/middleware/ip-restriction/index.ts +278 -0
- package/plugins/acryl-router/src/core/middleware/jwk/index.test.ts +1135 -0
- package/plugins/acryl-router/src/core/middleware/jwk/index.ts +1 -0
- package/plugins/acryl-router/src/core/middleware/jwk/jwk.ts +195 -0
- package/plugins/acryl-router/src/core/middleware/jwk/keys.test.json +48 -0
- package/plugins/acryl-router/src/core/middleware/jwt/index.test.ts +802 -0
- package/plugins/acryl-router/src/core/middleware/jwt/index.ts +9 -0
- package/plugins/acryl-router/src/core/middleware/jwt/jwt.ts +189 -0
- package/plugins/acryl-router/src/core/middleware/language/index.test.ts +552 -0
- package/plugins/acryl-router/src/core/middleware/language/index.ts +12 -0
- package/plugins/acryl-router/src/core/middleware/language/language.ts +314 -0
- package/plugins/acryl-router/src/core/middleware/logger/index.test.ts +204 -0
- package/plugins/acryl-router/src/core/middleware/logger/index.ts +95 -0
- package/plugins/acryl-router/src/core/middleware/method-not-allowed/index.test.ts +292 -0
- package/plugins/acryl-router/src/core/middleware/method-not-allowed/index.ts +141 -0
- package/plugins/acryl-router/src/core/middleware/method-override/index.test.ts +221 -0
- package/plugins/acryl-router/src/core/middleware/method-override/index.ts +147 -0
- package/plugins/acryl-router/src/core/middleware/powered-by/index.test.ts +37 -0
- package/plugins/acryl-router/src/core/middleware/powered-by/index.ts +35 -0
- package/plugins/acryl-router/src/core/middleware/pretty-json/index.test.ts +218 -0
- package/plugins/acryl-router/src/core/middleware/pretty-json/index.ts +67 -0
- package/plugins/acryl-router/src/core/middleware/request-id/index.test.ts +168 -0
- package/plugins/acryl-router/src/core/middleware/request-id/index.ts +7 -0
- package/plugins/acryl-router/src/core/middleware/request-id/request-id.ts +59 -0
- package/plugins/acryl-router/src/core/middleware/secure-headers/index.test.ts +671 -0
- package/plugins/acryl-router/src/core/middleware/secure-headers/index.ts +8 -0
- package/plugins/acryl-router/src/core/middleware/secure-headers/permissions-policy.ts +101 -0
- package/plugins/acryl-router/src/core/middleware/secure-headers/secure-headers.ts +340 -0
- package/plugins/acryl-router/src/core/middleware/serve-static/index.test.ts +450 -0
- package/plugins/acryl-router/src/core/middleware/serve-static/index.ts +135 -0
- package/plugins/acryl-router/src/core/middleware/serve-static/path.test.ts +50 -0
- package/plugins/acryl-router/src/core/middleware/serve-static/path.ts +25 -0
- package/plugins/acryl-router/src/core/middleware/timeout/index.test.ts +70 -0
- package/plugins/acryl-router/src/core/middleware/timeout/index.ts +58 -0
- package/plugins/acryl-router/src/core/middleware/timing/index.test.ts +310 -0
- package/plugins/acryl-router/src/core/middleware/timing/index.ts +8 -0
- package/plugins/acryl-router/src/core/middleware/timing/timing.ts +256 -0
- package/plugins/acryl-router/src/core/middleware/trailing-slash/index.test.ts +381 -0
- package/plugins/acryl-router/src/core/middleware/trailing-slash/index.ts +156 -0
- package/plugins/acryl-router/src/core/request/constants.ts +1 -0
- package/plugins/acryl-router/src/core/request.test.ts +751 -0
- package/plugins/acryl-router/src/core/request.ts +502 -0
- package/plugins/acryl-router/src/core/router/common.case.test.ts +1132 -0
- package/plugins/acryl-router/src/core/router/linear-router/index.ts +6 -0
- package/plugins/acryl-router/src/core/router/linear-router/router.test.ts +80 -0
- package/plugins/acryl-router/src/core/router/linear-router/router.ts +152 -0
- package/plugins/acryl-router/src/core/router/pattern-router/index.ts +6 -0
- package/plugins/acryl-router/src/core/router/pattern-router/router.test.ts +46 -0
- package/plugins/acryl-router/src/core/router/pattern-router/router.ts +54 -0
- package/plugins/acryl-router/src/core/router/reg-exp-router/index.ts +7 -0
- package/plugins/acryl-router/src/core/router/reg-exp-router/matcher.ts +33 -0
- package/plugins/acryl-router/src/core/router/reg-exp-router/node.ts +170 -0
- package/plugins/acryl-router/src/core/router/reg-exp-router/prepared-router.test.ts +154 -0
- package/plugins/acryl-router/src/core/router/reg-exp-router/prepared-router.ts +165 -0
- package/plugins/acryl-router/src/core/router/reg-exp-router/router.test.ts +265 -0
- package/plugins/acryl-router/src/core/router/reg-exp-router/router.ts +174 -0
- package/plugins/acryl-router/src/core/router/reg-exp-router/trie.ts +84 -0
- package/plugins/acryl-router/src/core/router/smart-router/index.ts +6 -0
- package/plugins/acryl-router/src/core/router/smart-router/router.test.ts +13 -0
- package/plugins/acryl-router/src/core/router/smart-router/router.ts +70 -0
- package/plugins/acryl-router/src/core/router/trie-router/index.ts +6 -0
- package/plugins/acryl-router/src/core/router/trie-router/node.test.ts +896 -0
- package/plugins/acryl-router/src/core/router/trie-router/node.ts +221 -0
- package/plugins/acryl-router/src/core/router/trie-router/router.test.ts +8 -0
- package/plugins/acryl-router/src/core/router/trie-router/router.ts +18 -0
- package/plugins/acryl-router/src/core/router/utils.ts +1 -0
- package/plugins/acryl-router/src/core/router.ts +103 -0
- package/plugins/acryl-router/src/core/types.test.ts +4134 -0
- package/plugins/acryl-router/src/core/types.ts +2782 -0
- package/plugins/acryl-router/src/core/utils/accept.test.ts +299 -0
- package/plugins/acryl-router/src/core/utils/accept.ts +268 -0
- package/plugins/acryl-router/src/core/utils/basic-auth.test.ts +56 -0
- package/plugins/acryl-router/src/core/utils/basic-auth.ts +26 -0
- package/plugins/acryl-router/src/core/utils/body.test.ts +496 -0
- package/plugins/acryl-router/src/core/utils/body.ts +263 -0
- package/plugins/acryl-router/src/core/utils/buffer.test.ts +147 -0
- package/plugins/acryl-router/src/core/utils/buffer.ts +117 -0
- package/plugins/acryl-router/src/core/utils/color.test.ts +23 -0
- package/plugins/acryl-router/src/core/utils/color.ts +56 -0
- package/plugins/acryl-router/src/core/utils/compress.ts +10 -0
- package/plugins/acryl-router/src/core/utils/concurrent.test.ts +69 -0
- package/plugins/acryl-router/src/core/utils/concurrent.ts +55 -0
- package/plugins/acryl-router/src/core/utils/constants.ts +4 -0
- package/plugins/acryl-router/src/core/utils/cookie.test.ts +460 -0
- package/plugins/acryl-router/src/core/utils/cookie.ts +281 -0
- package/plugins/acryl-router/src/core/utils/crypto.test.ts +43 -0
- package/plugins/acryl-router/src/core/utils/crypto.ts +58 -0
- package/plugins/acryl-router/src/core/utils/encode.test.ts +61 -0
- package/plugins/acryl-router/src/core/utils/encode.ts +34 -0
- package/plugins/acryl-router/src/core/utils/filepath.test.ts +78 -0
- package/plugins/acryl-router/src/core/utils/filepath.ts +60 -0
- package/plugins/acryl-router/src/core/utils/handler.ts +15 -0
- package/plugins/acryl-router/src/core/utils/headers.ts +355 -0
- package/plugins/acryl-router/src/core/utils/html.test.ts +16 -0
- package/plugins/acryl-router/src/core/utils/html.ts +182 -0
- package/plugins/acryl-router/src/core/utils/http-status.ts +72 -0
- package/plugins/acryl-router/src/core/utils/ipaddr.test.ts +149 -0
- package/plugins/acryl-router/src/core/utils/ipaddr.ts +374 -0
- package/plugins/acryl-router/src/core/utils/jwt/index.ts +7 -0
- package/plugins/acryl-router/src/core/utils/jwt/jwa.test.ts +86 -0
- package/plugins/acryl-router/src/core/utils/jwt/jwa.ts +38 -0
- package/plugins/acryl-router/src/core/utils/jwt/jws.ts +235 -0
- package/plugins/acryl-router/src/core/utils/jwt/jwt.test.ts +1788 -0
- package/plugins/acryl-router/src/core/utils/jwt/jwt.ts +292 -0
- package/plugins/acryl-router/src/core/utils/jwt/types.ts +157 -0
- package/plugins/acryl-router/src/core/utils/jwt/utf8.ts +7 -0
- package/plugins/acryl-router/src/core/utils/mime.test.ts +64 -0
- package/plugins/acryl-router/src/core/utils/mime.ts +94 -0
- package/plugins/acryl-router/src/core/utils/stream.test.ts +212 -0
- package/plugins/acryl-router/src/core/utils/stream.ts +107 -0
- package/plugins/acryl-router/src/core/utils/types.test.ts +295 -0
- package/plugins/acryl-router/src/core/utils/types.ts +123 -0
- package/plugins/acryl-router/src/core/utils/url.test.ts +384 -0
- package/plugins/acryl-router/src/core/utils/url.ts +337 -0
- package/plugins/acryl-router/src/core/validator/index.ts +8 -0
- package/plugins/acryl-router/src/core/validator/utils.test.ts +82 -0
- package/plugins/acryl-router/src/core/validator/utils.ts +69 -0
- package/plugins/acryl-router/src/core/validator/validator.test.ts +1488 -0
- package/plugins/acryl-router/src/core/validator/validator.ts +185 -0
- package/plugins/acryl-router/src/helpers/index.ts +13 -3
- package/plugins/acryl-router/src/helpers/schema-validator.ts +35 -0
- package/plugins/acryl-router/src/index.ts +6 -6
- package/plugins/acryl-router/src/middleware/index.ts +25 -6
- package/plugins/acryl-router/src/middleware/loopback-only.ts +19 -13
- package/plugins/acryl-router/src/service.ts +256 -64
- package/plugins/acryl-router/tests/docs-examples.spec.ts +152 -0
- package/plugins/acryl-router/tests/live-install.spec.ts +2 -2
- package/plugins/acryl-router/tests/loader.spec.ts +3 -2
- package/plugins/acryl-router/tests/service.spec.ts +264 -66
- package/plugins/acryl-router/tests/shadow-state.spec.ts +79 -0
- package/plugins/acryl-router/upstream.json +2 -2
- package/plugins/acryl-router-http/plugin.json +2 -1
- package/plugins/acryl-router-http/src/bridge.ts +3 -1
- package/plugins/acryl-router-http/tests/adapter.spec.ts +16 -12
- package/plugins/acryl-router-http/tests/surfaces.spec.ts +12 -10
- package/plugins/acryl-router-http/upstream.json +3 -3
- package/plugins/acryl-state/NOTICE +30 -0
- package/plugins/acryl-state/plugin.json +1 -1
- package/plugins/acryl-state/src/cell.ts +1 -1
- package/plugins/acryl-state/src/service.ts +33 -15
- package/plugins/acryl-state/upstream.json +6 -4
- package/plugins/builder/script.ts +4 -7
- package/plugins/extensions/index.ts +2 -2
- package/plugins/extensions/resolve.ts +28 -3
- package/plugins/openai/prompt.ts +9 -7
- package/plugins/tsconfig.json +5 -4
- package/templates/agent/src/routes.ts +37 -27
- package/templates/agent/test/model.test.ts +2 -1
- package/templates/agent/tsconfig.json +8 -5
- package/templates/blank/src/routes.ts +6 -4
- package/templates/blank/tsconfig.json +2 -4
- package/templates/todo/src/page.ts +1 -1
- package/templates/todo/src/todo.ts +56 -29
- package/templates/todo/tsconfig.json +2 -4
- package/templates/todo/upstream.json +2 -2
- package/plugins/acryl-router/src/compose.ts +0 -21
- package/plugins/acryl-router/src/context.ts +0 -59
- package/plugins/acryl-router/src/helpers/read-body.ts +0 -59
- package/plugins/acryl-router/src/helpers/sse.ts +0 -83
- package/plugins/acryl-router/src/helpers/validate.ts +0 -44
- package/plugins/acryl-router/src/http-error.ts +0 -21
- package/plugins/acryl-router/src/middleware/body-limit.ts +0 -25
- package/plugins/acryl-router/src/middleware/cors.ts +0 -46
- package/plugins/acryl-router/src/middleware/logger.ts +0 -21
- package/plugins/acryl-router/src/middleware/request-id.ts +0 -24
- package/plugins/acryl-router/src/middleware/secure-headers.ts +0 -23
- package/plugins/acryl-router/src/pattern.ts +0 -89
- package/plugins/acryl-router/src/registrar.ts +0 -90
- package/plugins/acryl-router/src/table.ts +0 -156
- package/plugins/acryl-router/src/types.ts +0 -73
- package/plugins/acryl-router/src/util.ts +0 -23
- package/plugins/acryl-router/tests/api.spec.ts +0 -223
- package/plugins/acryl-router/tests/conformance.ts +0 -170
- package/plugins/acryl-router/tests/helpers.spec.ts +0 -172
- package/plugins/acryl-router/tests/middleware.spec.ts +0 -183
- package/plugins/acryl-router/tests/table.spec.ts +0 -47
|
@@ -0,0 +1,781 @@
|
|
|
1
|
+
import { AppRequest } from './request.ts'
|
|
2
|
+
import type { Result } from './router.ts'
|
|
3
|
+
import type {
|
|
4
|
+
Env,
|
|
5
|
+
FetchEventLike,
|
|
6
|
+
H,
|
|
7
|
+
Input,
|
|
8
|
+
NotFoundHandler,
|
|
9
|
+
RouterRoute,
|
|
10
|
+
TypedResponse,
|
|
11
|
+
} from './types.ts'
|
|
12
|
+
import type { ResponseHeader } from './utils/headers.ts'
|
|
13
|
+
import { HtmlEscapedCallbackPhase, resolveCallback } from './utils/html.ts'
|
|
14
|
+
import type { ContentfulStatusCode, RedirectStatusCode, StatusCode } from './utils/http-status.ts'
|
|
15
|
+
import type { BaseMime } from './utils/mime.ts'
|
|
16
|
+
import type { InvalidJSONValue, IsAny, JSONParsed, JSONValue } from './utils/types.ts'
|
|
17
|
+
|
|
18
|
+
type HeaderRecord =
|
|
19
|
+
| Record<'Content-Type', BaseMime>
|
|
20
|
+
| Record<ResponseHeader, string | string[]>
|
|
21
|
+
| Record<string, string | string[]>
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Data type can be a string, ArrayBuffer, Blob, Uint8Array (buffer), or ReadableStream.
|
|
25
|
+
*/
|
|
26
|
+
export type Data = string | ArrayBuffer | Blob | ReadableStream | Uint8Array<ArrayBuffer>
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Interface for the execution context in a web worker or similar environment.
|
|
30
|
+
*/
|
|
31
|
+
export interface ExecutionContext {
|
|
32
|
+
/**
|
|
33
|
+
* Extends the lifetime of the event callback until the promise is settled.
|
|
34
|
+
*
|
|
35
|
+
* @param promise - A promise to wait for.
|
|
36
|
+
*/
|
|
37
|
+
waitUntil(promise: Promise<unknown>): void
|
|
38
|
+
/**
|
|
39
|
+
* Allows the event to be passed through to subsequent event listeners.
|
|
40
|
+
*/
|
|
41
|
+
passThroughOnException(): void
|
|
42
|
+
/**
|
|
43
|
+
* For compatibility with Wrangler 4.x.
|
|
44
|
+
*/
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
46
|
+
props: any
|
|
47
|
+
/**
|
|
48
|
+
* For compatibility with Wrangler 4.x.
|
|
49
|
+
*/
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
51
|
+
exports?: any
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Interface for context variable mapping.
|
|
56
|
+
*/
|
|
57
|
+
export interface ContextVariableMap {}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Interface for context renderer.
|
|
61
|
+
*/
|
|
62
|
+
export interface ContextRenderer {}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Interface representing a renderer for content.
|
|
66
|
+
*
|
|
67
|
+
* @interface DefaultRenderer
|
|
68
|
+
* @param {string | Promise<string>} content - The content to be rendered, which can be either a string or a Promise resolving to a string.
|
|
69
|
+
* @returns {Response | Promise<Response>} - The response after rendering the content, which can be either a Response or a Promise resolving to a Response.
|
|
70
|
+
*/
|
|
71
|
+
interface DefaultRenderer {
|
|
72
|
+
(content: string | Promise<string>): Response | Promise<Response>
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Renderer type which can either be a ContextRenderer or DefaultRenderer.
|
|
77
|
+
*/
|
|
78
|
+
export type Renderer = ContextRenderer extends Function ? ContextRenderer : DefaultRenderer
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Extracts the props for the renderer.
|
|
82
|
+
*/
|
|
83
|
+
export type PropsForRenderer = [...Required<Parameters<Renderer>>] extends [unknown, infer Props]
|
|
84
|
+
? Props
|
|
85
|
+
: unknown
|
|
86
|
+
|
|
87
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
88
|
+
export type Layout<T = Record<string, any>> = (props: T) => any
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Interface for getting context variables.
|
|
92
|
+
*
|
|
93
|
+
* @template E - Environment type.
|
|
94
|
+
*/
|
|
95
|
+
interface Get<E extends Env> {
|
|
96
|
+
<Key extends keyof E['Variables']>(key: Key): E['Variables'][Key]
|
|
97
|
+
<Key extends keyof ContextVariableMap>(key: Key): ContextVariableMap[Key]
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Interface for setting context variables.
|
|
102
|
+
*
|
|
103
|
+
* @template E - Environment type.
|
|
104
|
+
*/
|
|
105
|
+
interface Set<E extends Env> {
|
|
106
|
+
<Key extends keyof E['Variables']>(key: Key, value: E['Variables'][Key]): void
|
|
107
|
+
<Key extends keyof ContextVariableMap>(key: Key, value: ContextVariableMap[Key]): void
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Interface for creating a new response.
|
|
112
|
+
*/
|
|
113
|
+
interface NewResponse {
|
|
114
|
+
(data: Data | null, status?: StatusCode, headers?: HeaderRecord): Response
|
|
115
|
+
(data: Data | null, init?: ResponseOrInit): Response
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Interface for responding with a body.
|
|
120
|
+
*/
|
|
121
|
+
interface BodyRespond {
|
|
122
|
+
// if we return content, only allow the status codes that allow for returning the body
|
|
123
|
+
<T extends Data, U extends ContentfulStatusCode>(
|
|
124
|
+
data: T,
|
|
125
|
+
status?: U,
|
|
126
|
+
headers?: HeaderRecord
|
|
127
|
+
): Response & TypedResponse<T, U, 'body'>
|
|
128
|
+
<T extends Data, U extends ContentfulStatusCode>(
|
|
129
|
+
data: T,
|
|
130
|
+
init?: ResponseOrInit<U>
|
|
131
|
+
): Response & TypedResponse<T, U, 'body'>
|
|
132
|
+
<T extends null, U extends StatusCode>(
|
|
133
|
+
data: T,
|
|
134
|
+
status?: U,
|
|
135
|
+
headers?: HeaderRecord
|
|
136
|
+
): Response & TypedResponse<null, U, 'body'>
|
|
137
|
+
<T extends null, U extends StatusCode>(
|
|
138
|
+
data: T,
|
|
139
|
+
init?: ResponseOrInit<U>
|
|
140
|
+
): Response & TypedResponse<null, U, 'body'>
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Interface for responding with text.
|
|
145
|
+
*
|
|
146
|
+
* @interface TextRespond
|
|
147
|
+
* @template T - The type of the text content.
|
|
148
|
+
* @template U - The type of the status code.
|
|
149
|
+
*
|
|
150
|
+
* @param {T} text - The text content to be included in the response.
|
|
151
|
+
* @param {U} [status] - An optional status code for the response.
|
|
152
|
+
* @param {HeaderRecord} [headers] - An optional record of headers to include in the response.
|
|
153
|
+
*
|
|
154
|
+
* @returns {Response & TypedResponse<T, U, 'text'>} - The response after rendering the text content, typed with the provided text and status code types.
|
|
155
|
+
*/
|
|
156
|
+
interface TextRespond {
|
|
157
|
+
<T extends string, U extends ContentfulStatusCode = ContentfulStatusCode>(
|
|
158
|
+
text: T,
|
|
159
|
+
status?: U,
|
|
160
|
+
headers?: HeaderRecord
|
|
161
|
+
): Response & TypedResponse<T, U, 'text'>
|
|
162
|
+
<T extends string, U extends ContentfulStatusCode = ContentfulStatusCode>(
|
|
163
|
+
text: T,
|
|
164
|
+
init?: ResponseOrInit<U>
|
|
165
|
+
): Response & TypedResponse<T, U, 'text'>
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Interface for responding with JSON.
|
|
170
|
+
*
|
|
171
|
+
* @interface JSONRespond
|
|
172
|
+
* @template T - The type of the JSON value or simplified unknown type.
|
|
173
|
+
* @template U - The type of the status code.
|
|
174
|
+
*
|
|
175
|
+
* @param {T} object - The JSON object to be included in the response.
|
|
176
|
+
* @param {U} [status] - An optional status code for the response.
|
|
177
|
+
* @param {HeaderRecord} [headers] - An optional record of headers to include in the response.
|
|
178
|
+
*
|
|
179
|
+
* @returns {JSONRespondReturn<T, U>} - The response after rendering the JSON object, typed with the provided object and status code types.
|
|
180
|
+
*/
|
|
181
|
+
interface JSONRespond {
|
|
182
|
+
<
|
|
183
|
+
T extends JSONValue | {} | InvalidJSONValue,
|
|
184
|
+
U extends ContentfulStatusCode = ContentfulStatusCode,
|
|
185
|
+
>(
|
|
186
|
+
object: T,
|
|
187
|
+
status?: U,
|
|
188
|
+
headers?: HeaderRecord
|
|
189
|
+
): JSONRespondReturn<T, U>
|
|
190
|
+
<
|
|
191
|
+
T extends JSONValue | {} | InvalidJSONValue,
|
|
192
|
+
U extends ContentfulStatusCode = ContentfulStatusCode,
|
|
193
|
+
>(
|
|
194
|
+
object: T,
|
|
195
|
+
init?: ResponseOrInit<U>
|
|
196
|
+
): JSONRespondReturn<T, U>
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* @template T - The type of the JSON value or simplified unknown type.
|
|
201
|
+
* @template U - The type of the status code.
|
|
202
|
+
*
|
|
203
|
+
* @returns {Response & TypedResponse<JSONParsed<T>, U, 'json'>} - The response after rendering the JSON object, typed with the provided object and status code types.
|
|
204
|
+
*/
|
|
205
|
+
type JSONRespondReturn<
|
|
206
|
+
T extends JSONValue | {} | InvalidJSONValue,
|
|
207
|
+
U extends ContentfulStatusCode,
|
|
208
|
+
> = Response & TypedResponse<JSONParsed<T>, U, 'json'>
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Interface representing a function that responds with HTML content.
|
|
212
|
+
*
|
|
213
|
+
* @param html - The HTML content to respond with, which can be a string or a Promise that resolves to a string.
|
|
214
|
+
* @param status - (Optional) The HTTP status code for the response.
|
|
215
|
+
* @param headers - (Optional) A record of headers to include in the response.
|
|
216
|
+
* @param init - (Optional) The response initialization object.
|
|
217
|
+
*
|
|
218
|
+
* @returns A Response object or a Promise that resolves to a Response object.
|
|
219
|
+
*/
|
|
220
|
+
interface HTMLRespond {
|
|
221
|
+
<T extends string | Promise<string>>(
|
|
222
|
+
html: T,
|
|
223
|
+
status?: ContentfulStatusCode,
|
|
224
|
+
headers?: HeaderRecord
|
|
225
|
+
): T extends string ? Response : Promise<Response>
|
|
226
|
+
<T extends string | Promise<string>>(
|
|
227
|
+
html: T,
|
|
228
|
+
init?: ResponseOrInit<ContentfulStatusCode>
|
|
229
|
+
): T extends string ? Response : Promise<Response>
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Options for configuring the context.
|
|
234
|
+
*
|
|
235
|
+
* @template E - Environment type.
|
|
236
|
+
*/
|
|
237
|
+
type ContextOptions<E extends Env> = {
|
|
238
|
+
/**
|
|
239
|
+
* Bindings for the environment.
|
|
240
|
+
*/
|
|
241
|
+
env: E['Bindings']
|
|
242
|
+
/**
|
|
243
|
+
* Execution context for the request.
|
|
244
|
+
*/
|
|
245
|
+
executionCtx?: FetchEventLike | ExecutionContext | undefined
|
|
246
|
+
/**
|
|
247
|
+
* Handler for not found responses.
|
|
248
|
+
*/
|
|
249
|
+
notFoundHandler?: NotFoundHandler<E>
|
|
250
|
+
matchResult?: Result<[H, RouterRoute]>
|
|
251
|
+
path?: string
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
interface SetHeadersOptions {
|
|
255
|
+
append?: boolean
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
interface SetHeaders {
|
|
259
|
+
(name: 'Content-Type', value?: BaseMime, options?: SetHeadersOptions): void
|
|
260
|
+
(name: ResponseHeader, value?: string, options?: SetHeadersOptions): void
|
|
261
|
+
(name: string, value?: string, options?: SetHeadersOptions): void
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
type ResponseHeadersInit =
|
|
265
|
+
| [string, string][]
|
|
266
|
+
| Record<'Content-Type', BaseMime>
|
|
267
|
+
| Record<ResponseHeader, string>
|
|
268
|
+
| Record<string, string>
|
|
269
|
+
| Headers
|
|
270
|
+
|
|
271
|
+
interface ResponseInit<T extends StatusCode = StatusCode> {
|
|
272
|
+
headers?: ResponseHeadersInit
|
|
273
|
+
status?: T
|
|
274
|
+
statusText?: string
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
type ResponseOrInit<T extends StatusCode = StatusCode> = ResponseInit<T> | Response
|
|
278
|
+
|
|
279
|
+
export const TEXT_PLAIN = 'text/plain; charset=UTF-8'
|
|
280
|
+
|
|
281
|
+
const setDefaultContentType = (contentType: string, headers?: HeaderRecord): HeaderRecord => {
|
|
282
|
+
return {
|
|
283
|
+
'Content-Type': contentType,
|
|
284
|
+
...headers,
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const createResponseInstance = (
|
|
289
|
+
body?: BodyInit | null | undefined,
|
|
290
|
+
init?: globalThis.ResponseInit
|
|
291
|
+
): Response => new Response(body, init)
|
|
292
|
+
|
|
293
|
+
export class Context<
|
|
294
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
295
|
+
E extends Env = any,
|
|
296
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
297
|
+
P extends string = any,
|
|
298
|
+
I extends Input = {},
|
|
299
|
+
> {
|
|
300
|
+
#rawRequest: Request
|
|
301
|
+
#req: AppRequest<P, I['out']> | undefined
|
|
302
|
+
/**
|
|
303
|
+
* `.env` can get bindings (environment variables, secrets, KV namespaces, D1 database, R2 bucket etc.) in Cloudflare Workers.
|
|
304
|
+
*
|
|
305
|
+
*
|
|
306
|
+
* @example
|
|
307
|
+
* ```ts
|
|
308
|
+
* // Environment object for Cloudflare Workers
|
|
309
|
+
* app.get('*', async c => {
|
|
310
|
+
* const counter = c.env.COUNTER
|
|
311
|
+
* })
|
|
312
|
+
* ```
|
|
313
|
+
*/
|
|
314
|
+
env: E['Bindings'] = {}
|
|
315
|
+
#var: Map<unknown, unknown> | undefined
|
|
316
|
+
finalized: boolean = false
|
|
317
|
+
/**
|
|
318
|
+
* `.error` can get the error object from the middleware if the Handler throws an error.
|
|
319
|
+
*
|
|
320
|
+
*
|
|
321
|
+
* @example
|
|
322
|
+
* ```ts
|
|
323
|
+
* app.use('*', async (c, next) => {
|
|
324
|
+
* await next()
|
|
325
|
+
* if (c.error) {
|
|
326
|
+
* // do something...
|
|
327
|
+
* }
|
|
328
|
+
* })
|
|
329
|
+
* ```
|
|
330
|
+
*/
|
|
331
|
+
error: Error | undefined
|
|
332
|
+
|
|
333
|
+
#status: StatusCode | undefined
|
|
334
|
+
#executionCtx: FetchEventLike | ExecutionContext | undefined
|
|
335
|
+
#res: Response | undefined
|
|
336
|
+
#layout: Layout<PropsForRenderer & { Layout: Layout }> | undefined
|
|
337
|
+
#renderer: Renderer | undefined
|
|
338
|
+
#notFoundHandler: NotFoundHandler<E> | undefined
|
|
339
|
+
#preparedHeaders: Headers | undefined
|
|
340
|
+
|
|
341
|
+
#matchResult: Result<[H, RouterRoute]> | undefined
|
|
342
|
+
#path: string | undefined
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Creates an instance of the Context class.
|
|
346
|
+
*
|
|
347
|
+
* @param req - The Request object.
|
|
348
|
+
* @param options - Optional configuration options for the context.
|
|
349
|
+
*/
|
|
350
|
+
constructor(req: Request, options?: ContextOptions<E>) {
|
|
351
|
+
this.#rawRequest = req
|
|
352
|
+
if (options) {
|
|
353
|
+
this.#executionCtx = options.executionCtx
|
|
354
|
+
this.env = options.env
|
|
355
|
+
this.#notFoundHandler = options.notFoundHandler
|
|
356
|
+
this.#path = options.path
|
|
357
|
+
this.#matchResult = options.matchResult
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* `.req` is the instance of {@link AppRequest}.
|
|
363
|
+
*/
|
|
364
|
+
get req(): AppRequest<P, I['out']> {
|
|
365
|
+
this.#req ??= new AppRequest(this.#rawRequest, this.#path, this.#matchResult)
|
|
366
|
+
return this.#req
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* The FetchEvent associated with the current request.
|
|
371
|
+
*
|
|
372
|
+
* @throws Will throw an error if the context does not have a FetchEvent.
|
|
373
|
+
*/
|
|
374
|
+
get event(): FetchEventLike {
|
|
375
|
+
if (this.#executionCtx && 'respondWith' in this.#executionCtx) {
|
|
376
|
+
return this.#executionCtx
|
|
377
|
+
} else {
|
|
378
|
+
throw Error('This context has no FetchEvent')
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* The ExecutionContext associated with the current request.
|
|
384
|
+
*
|
|
385
|
+
* @throws Will throw an error if the context does not have an ExecutionContext.
|
|
386
|
+
*/
|
|
387
|
+
get executionCtx(): ExecutionContext {
|
|
388
|
+
if (this.#executionCtx) {
|
|
389
|
+
return this.#executionCtx as ExecutionContext
|
|
390
|
+
} else {
|
|
391
|
+
throw Error('This context has no ExecutionContext')
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* The Response object for the current request.
|
|
397
|
+
*/
|
|
398
|
+
get res(): Response {
|
|
399
|
+
return (this.#res ||= createResponseInstance(null, {
|
|
400
|
+
headers: (this.#preparedHeaders ??= new Headers()),
|
|
401
|
+
}))
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Sets the Response object for the current request.
|
|
406
|
+
*
|
|
407
|
+
* @param _res - The Response object to set.
|
|
408
|
+
*/
|
|
409
|
+
set res(_res: Response | undefined) {
|
|
410
|
+
if (this.#res && _res) {
|
|
411
|
+
_res = createResponseInstance(_res.body, _res)
|
|
412
|
+
for (const [k, v] of this.#res.headers.entries()) {
|
|
413
|
+
if (k === 'content-type') {
|
|
414
|
+
continue
|
|
415
|
+
}
|
|
416
|
+
if (k === 'set-cookie') {
|
|
417
|
+
const cookies = this.#res.headers.getSetCookie()
|
|
418
|
+
_res.headers.delete('set-cookie')
|
|
419
|
+
for (const cookie of cookies) {
|
|
420
|
+
_res.headers.append('set-cookie', cookie)
|
|
421
|
+
}
|
|
422
|
+
} else {
|
|
423
|
+
_res.headers.set(k, v)
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
this.#res = _res
|
|
428
|
+
this.finalized = true
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* `.render()` can create a response within a layout.
|
|
433
|
+
*
|
|
434
|
+
*
|
|
435
|
+
* @example
|
|
436
|
+
* ```ts
|
|
437
|
+
* app.get('/', (c) => {
|
|
438
|
+
* return c.render('Hello!')
|
|
439
|
+
* })
|
|
440
|
+
* ```
|
|
441
|
+
*/
|
|
442
|
+
render: Renderer = (...args) => {
|
|
443
|
+
this.#renderer ??= (content: string | Promise<string>) => this.html(content)
|
|
444
|
+
return this.#renderer(...args)
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Sets the layout for the response.
|
|
449
|
+
*
|
|
450
|
+
* @param layout - The layout to set.
|
|
451
|
+
* @returns The layout function.
|
|
452
|
+
*/
|
|
453
|
+
setLayout = (
|
|
454
|
+
layout: Layout<PropsForRenderer & { Layout: Layout }>
|
|
455
|
+
): Layout<
|
|
456
|
+
PropsForRenderer & {
|
|
457
|
+
Layout: Layout
|
|
458
|
+
}
|
|
459
|
+
> => (this.#layout = layout)
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Gets the current layout for the response.
|
|
463
|
+
*
|
|
464
|
+
* @returns The current layout function.
|
|
465
|
+
*/
|
|
466
|
+
getLayout = (): Layout<PropsForRenderer & { Layout: Layout }> | undefined => this.#layout
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* `.setRenderer()` can set the layout in the custom middleware.
|
|
470
|
+
*
|
|
471
|
+
*
|
|
472
|
+
* @example
|
|
473
|
+
* ```tsx
|
|
474
|
+
* app.use('*', async (c, next) => {
|
|
475
|
+
* c.setRenderer((content) => {
|
|
476
|
+
* return c.html(
|
|
477
|
+
* <html>
|
|
478
|
+
* <body>
|
|
479
|
+
* <p>{content}</p>
|
|
480
|
+
* </body>
|
|
481
|
+
* </html>
|
|
482
|
+
* )
|
|
483
|
+
* })
|
|
484
|
+
* await next()
|
|
485
|
+
* })
|
|
486
|
+
* ```
|
|
487
|
+
*/
|
|
488
|
+
setRenderer = (renderer: Renderer): void => {
|
|
489
|
+
this.#renderer = renderer
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* `.header()` can set headers.
|
|
494
|
+
*
|
|
495
|
+
*
|
|
496
|
+
* @example
|
|
497
|
+
* ```ts
|
|
498
|
+
* app.get('/welcome', (c) => {
|
|
499
|
+
* // Set headers
|
|
500
|
+
* c.header('X-Message', 'Hello!')
|
|
501
|
+
* c.header('Content-Type', 'text/plain')
|
|
502
|
+
*
|
|
503
|
+
* // Append multiple headers using the append option (e.g. Vary)
|
|
504
|
+
* c.header('Vary', 'Accept-Encoding', { append: true })
|
|
505
|
+
* c.header('Vary', 'User-Agent', { append: true })
|
|
506
|
+
*
|
|
507
|
+
* return c.body('Thank you for coming')
|
|
508
|
+
* })
|
|
509
|
+
* ```
|
|
510
|
+
*/
|
|
511
|
+
header: SetHeaders = (name, value, options): void => {
|
|
512
|
+
if (this.finalized) {
|
|
513
|
+
this.#res = createResponseInstance((this.#res as Response).body, this.#res)
|
|
514
|
+
}
|
|
515
|
+
const headers = this.#res ? this.#res.headers : (this.#preparedHeaders ??= new Headers())
|
|
516
|
+
if (value === undefined) {
|
|
517
|
+
headers.delete(name)
|
|
518
|
+
} else if (options?.append) {
|
|
519
|
+
headers.append(name, value)
|
|
520
|
+
} else {
|
|
521
|
+
headers.set(name, value)
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
status = (status: StatusCode): void => {
|
|
526
|
+
this.#status = status
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* `.set()` can set the value specified by the key.
|
|
531
|
+
*
|
|
532
|
+
*
|
|
533
|
+
* @example
|
|
534
|
+
* ```ts
|
|
535
|
+
* app.use('*', async (c, next) => {
|
|
536
|
+
* c.set('message', 'App is hot!!')
|
|
537
|
+
* await next()
|
|
538
|
+
* })
|
|
539
|
+
* ```
|
|
540
|
+
*/
|
|
541
|
+
set: Set<
|
|
542
|
+
IsAny<E> extends true
|
|
543
|
+
? {
|
|
544
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
545
|
+
Variables: ContextVariableMap & Record<PropertyKey, any>
|
|
546
|
+
}
|
|
547
|
+
: E
|
|
548
|
+
> = (key: PropertyKey, value: unknown) => {
|
|
549
|
+
this.#var ??= new Map()
|
|
550
|
+
this.#var.set(key, value)
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* `.get()` can use the value specified by the key.
|
|
555
|
+
*
|
|
556
|
+
*
|
|
557
|
+
* @example
|
|
558
|
+
* ```ts
|
|
559
|
+
* app.get('/', (c) => {
|
|
560
|
+
* const message = c.get('message')
|
|
561
|
+
* return c.text(`The message is "${message}"`)
|
|
562
|
+
* })
|
|
563
|
+
* ```
|
|
564
|
+
*/
|
|
565
|
+
get: Get<
|
|
566
|
+
IsAny<E> extends true
|
|
567
|
+
? {
|
|
568
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
569
|
+
Variables: ContextVariableMap & Record<PropertyKey, any>
|
|
570
|
+
}
|
|
571
|
+
: E
|
|
572
|
+
> = (key: PropertyKey) => {
|
|
573
|
+
return this.#var ? this.#var.get(key) : undefined
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* `.var` can access the value of a variable.
|
|
578
|
+
*
|
|
579
|
+
*
|
|
580
|
+
* @example
|
|
581
|
+
* ```ts
|
|
582
|
+
* const result = c.var.client.oneMethod()
|
|
583
|
+
* ```
|
|
584
|
+
*/
|
|
585
|
+
// c.var.propName is a read-only
|
|
586
|
+
get var(): Readonly<
|
|
587
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
588
|
+
ContextVariableMap & (IsAny<E['Variables']> extends true ? Record<string, any> : E['Variables'])
|
|
589
|
+
> {
|
|
590
|
+
if (!this.#var) {
|
|
591
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
592
|
+
return {} as any
|
|
593
|
+
}
|
|
594
|
+
return Object.fromEntries(this.#var)
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
#newResponse(
|
|
598
|
+
data: Data | null,
|
|
599
|
+
arg?: StatusCode | ResponseOrInit,
|
|
600
|
+
headers?: HeaderRecord
|
|
601
|
+
): Response {
|
|
602
|
+
let responseHeaders = this.#res ? new Headers(this.#res.headers) : this.#preparedHeaders
|
|
603
|
+
|
|
604
|
+
if (typeof arg === 'object' && arg.headers) {
|
|
605
|
+
responseHeaders ??= new Headers()
|
|
606
|
+
for (const [key, value] of new Headers(arg.headers)) {
|
|
607
|
+
if (key === 'set-cookie') {
|
|
608
|
+
responseHeaders.append(key, value)
|
|
609
|
+
} else {
|
|
610
|
+
responseHeaders.set(key, value)
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
if (headers) {
|
|
616
|
+
if (!responseHeaders) {
|
|
617
|
+
let count = 0
|
|
618
|
+
for (const k in headers) {
|
|
619
|
+
if (++count > 1 || typeof headers[k as keyof HeaderRecord] !== 'string') {
|
|
620
|
+
responseHeaders = new Headers()
|
|
621
|
+
break
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
if (responseHeaders) {
|
|
626
|
+
for (const k in headers) {
|
|
627
|
+
const v = headers[k as keyof HeaderRecord]
|
|
628
|
+
if (typeof v === 'string') {
|
|
629
|
+
responseHeaders.set(k, v)
|
|
630
|
+
} else {
|
|
631
|
+
responseHeaders.delete(k)
|
|
632
|
+
for (const v2 of v) {
|
|
633
|
+
responseHeaders.append(k, v2)
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
const status = typeof arg === 'number' ? arg : (arg?.status ?? this.#status)
|
|
641
|
+
return createResponseInstance(data, {
|
|
642
|
+
status,
|
|
643
|
+
headers: responseHeaders ?? (headers as Record<string, string> | undefined),
|
|
644
|
+
})
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
newResponse: NewResponse = (...args) => this.#newResponse(...(args as Parameters<NewResponse>))
|
|
648
|
+
|
|
649
|
+
/**
|
|
650
|
+
* `.body()` can return the HTTP response.
|
|
651
|
+
* You can set headers with `.header()` and set HTTP status code with `.status`.
|
|
652
|
+
* This can also be set in `.text()`, `.json()` and so on.
|
|
653
|
+
*
|
|
654
|
+
*
|
|
655
|
+
* @example
|
|
656
|
+
* ```ts
|
|
657
|
+
* app.get('/welcome', (c) => {
|
|
658
|
+
* // Set headers
|
|
659
|
+
* c.header('X-Message', 'Hello!')
|
|
660
|
+
* c.header('Content-Type', 'text/plain')
|
|
661
|
+
* // Set HTTP status code
|
|
662
|
+
* c.status(201)
|
|
663
|
+
*
|
|
664
|
+
* // Return the response body
|
|
665
|
+
* return c.body('Thank you for coming')
|
|
666
|
+
* })
|
|
667
|
+
* ```
|
|
668
|
+
*/
|
|
669
|
+
body: BodyRespond = (
|
|
670
|
+
data: Data | null,
|
|
671
|
+
arg?: StatusCode | RequestInit,
|
|
672
|
+
headers?: HeaderRecord
|
|
673
|
+
): ReturnType<BodyRespond> => this.#newResponse(data, arg, headers) as ReturnType<BodyRespond>
|
|
674
|
+
|
|
675
|
+
/**
|
|
676
|
+
* `.text()` can render text as `Content-Type:text/plain`.
|
|
677
|
+
*
|
|
678
|
+
*
|
|
679
|
+
* @example
|
|
680
|
+
* ```ts
|
|
681
|
+
* app.get('/say', (c) => {
|
|
682
|
+
* return c.text('Hello!')
|
|
683
|
+
* })
|
|
684
|
+
* ```
|
|
685
|
+
*/
|
|
686
|
+
text: TextRespond = (
|
|
687
|
+
text: string,
|
|
688
|
+
arg?: ContentfulStatusCode | ResponseOrInit,
|
|
689
|
+
headers?: HeaderRecord
|
|
690
|
+
): ReturnType<TextRespond> => {
|
|
691
|
+
return !this.#preparedHeaders && !this.#status && !arg && !headers && !this.finalized
|
|
692
|
+
? (new Response(text) as ReturnType<TextRespond>)
|
|
693
|
+
: (this.#newResponse(
|
|
694
|
+
text,
|
|
695
|
+
arg,
|
|
696
|
+
setDefaultContentType(TEXT_PLAIN, headers)
|
|
697
|
+
) as ReturnType<TextRespond>)
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
/**
|
|
701
|
+
* `.json()` can render JSON as `Content-Type:application/json`.
|
|
702
|
+
*
|
|
703
|
+
*
|
|
704
|
+
* @example
|
|
705
|
+
* ```ts
|
|
706
|
+
* app.get('/api', (c) => {
|
|
707
|
+
* return c.json({ message: 'Hello!' })
|
|
708
|
+
* })
|
|
709
|
+
* ```
|
|
710
|
+
*/
|
|
711
|
+
json: JSONRespond = <
|
|
712
|
+
T extends JSONValue | {} | InvalidJSONValue,
|
|
713
|
+
U extends ContentfulStatusCode = ContentfulStatusCode,
|
|
714
|
+
>(
|
|
715
|
+
object: T,
|
|
716
|
+
arg?: U | ResponseOrInit<U>,
|
|
717
|
+
headers?: HeaderRecord
|
|
718
|
+
): JSONRespondReturn<T, U> => {
|
|
719
|
+
return this.#newResponse(
|
|
720
|
+
JSON.stringify(object),
|
|
721
|
+
arg,
|
|
722
|
+
setDefaultContentType('application/json', headers)
|
|
723
|
+
) /* eslint-disable @typescript-eslint/no-explicit-any */ as any
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
html: HTMLRespond = (
|
|
727
|
+
html: string | Promise<string>,
|
|
728
|
+
arg?: ContentfulStatusCode | ResponseOrInit<ContentfulStatusCode>,
|
|
729
|
+
headers?: HeaderRecord
|
|
730
|
+
): Response | Promise<Response> => {
|
|
731
|
+
const res = (html: string) =>
|
|
732
|
+
this.#newResponse(html, arg, setDefaultContentType('text/html; charset=UTF-8', headers))
|
|
733
|
+
return typeof html === 'object'
|
|
734
|
+
? resolveCallback(html, HtmlEscapedCallbackPhase.Stringify, false, {}).then(res)
|
|
735
|
+
: res(html)
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
/**
|
|
739
|
+
* `.redirect()` can Redirect, default status code is 302.
|
|
740
|
+
*
|
|
741
|
+
*
|
|
742
|
+
* @example
|
|
743
|
+
* ```ts
|
|
744
|
+
* app.get('/redirect', (c) => {
|
|
745
|
+
* return c.redirect('/')
|
|
746
|
+
* })
|
|
747
|
+
* app.get('/redirect-permanently', (c) => {
|
|
748
|
+
* return c.redirect('/', 301)
|
|
749
|
+
* })
|
|
750
|
+
* ```
|
|
751
|
+
*/
|
|
752
|
+
redirect = <T extends RedirectStatusCode = 302>(
|
|
753
|
+
location: string | URL,
|
|
754
|
+
status?: T
|
|
755
|
+
): Response & TypedResponse<undefined, T, 'redirect'> => {
|
|
756
|
+
const locationString = String(location)
|
|
757
|
+
this.header(
|
|
758
|
+
'Location',
|
|
759
|
+
// Multibytes should be encoded
|
|
760
|
+
// eslint-disable-next-line no-control-regex
|
|
761
|
+
!/[^\x00-\xFF]/.test(locationString) ? locationString : encodeURI(locationString)
|
|
762
|
+
)
|
|
763
|
+
return this.newResponse(null, status ?? 302) as any
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
/**
|
|
767
|
+
* `.notFound()` can return the Not Found Response.
|
|
768
|
+
*
|
|
769
|
+
*
|
|
770
|
+
* @example
|
|
771
|
+
* ```ts
|
|
772
|
+
* app.get('/notfound', (c) => {
|
|
773
|
+
* return c.notFound()
|
|
774
|
+
* })
|
|
775
|
+
* ```
|
|
776
|
+
*/
|
|
777
|
+
notFound = (): ReturnType<NotFoundHandler> => {
|
|
778
|
+
this.#notFoundHandler ??= () => createResponseInstance()
|
|
779
|
+
return this.#notFoundHandler(this)
|
|
780
|
+
}
|
|
781
|
+
}
|