acrylblends 0.3.0 → 0.4.1
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 +84 -5
- package/dist/index.js.map +1 -1
- package/docs/framework/LICENSE +23 -0
- package/docs/framework/README.md +63 -0
- package/docs/framework/UPSTREAM.md +3 -0
- package/docs/framework/api-summary.md +138 -0
- package/docs/framework/concepts.md +105 -0
- package/docs/framework/context.md +129 -0
- package/docs/framework/getting-started.md +146 -0
- package/docs/framework/helpers.md +118 -0
- package/docs/framework/middleware.md +154 -0
- package/docs/framework/migration-from-0-3.md +108 -0
- package/docs/framework/migration-from-dsh-webserver.md +103 -0
- package/docs/framework/node-server.md +75 -0
- package/docs/framework/plugin-lifecycle.md +111 -0
- package/docs/framework/request.md +106 -0
- package/docs/framework/routing.md +188 -0
- package/docs/framework/surfaces.md +71 -0
- package/docs/framework/upstream.json +9 -0
- package/docs/framework/validation.md +135 -0
- package/package.json +4 -2
- package/plugins/acryl-inspect/plugin.json +2 -1
- package/plugins/acryl-inspect/src/report.ts +21 -13
- package/plugins/acryl-inspect/src/service.ts +9 -7
- package/plugins/acryl-inspect/tests/report.spec.ts +13 -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 +53 -14
- package/plugins/acryl-router/src/service.ts +262 -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/loopback-only.spec.ts +80 -0
- package/plugins/acryl-router/tests/service.spec.ts +281 -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 +6 -5
- package/plugins/extensions/resolve.ts +28 -3
- package/plugins/openai/prompt.ts +9 -7
- package/plugins/tsconfig.json +5 -4
- package/shared/AGENTS.core.md +54 -0
- package/templates/agent/AGENTS.md +6 -0
- package/templates/agent/README.md +2 -2
- package/templates/agent/blend.yaml +1 -1
- 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/AGENTS.md +5 -0
- package/templates/blank/README.md +1 -1
- package/templates/blank/src/routes.ts +6 -4
- package/templates/blank/tsconfig.json +2 -4
- package/templates/todo/AGENTS.md +5 -0
- package/templates/todo/src/page.ts +1 -1
- package/templates/todo/src/todo.ts +58 -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,34 @@
|
|
|
1
|
+
import { streamText } from './index.ts'
|
|
2
|
+
import { Context } from '../../context.ts'
|
|
3
|
+
|
|
4
|
+
describe('Text Streaming Helper', () => {
|
|
5
|
+
const req = new Request('http://localhost/')
|
|
6
|
+
let c: Context
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
c = new Context(req)
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
it('Check streamText Response', async () => {
|
|
12
|
+
const res = streamText(c, async (stream) => {
|
|
13
|
+
for (let i = 0; i < 3; i++) {
|
|
14
|
+
await stream.write(`${i}`)
|
|
15
|
+
await stream.sleep(1)
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
expect(res.status).toBe(200)
|
|
20
|
+
expect(res.headers.get('content-type')).toMatch(/^text\/plain/)
|
|
21
|
+
expect(res.headers.get('x-content-type-options')).toBe('nosniff')
|
|
22
|
+
expect(res.headers.get('transfer-encoding')).toBe('chunked')
|
|
23
|
+
|
|
24
|
+
if (!res.body) {
|
|
25
|
+
throw new Error('Body is null')
|
|
26
|
+
}
|
|
27
|
+
const reader = res.body.getReader()
|
|
28
|
+
const decoder = new TextDecoder()
|
|
29
|
+
for (let i = 0; i < 3; i++) {
|
|
30
|
+
const { value } = await reader.read()
|
|
31
|
+
expect(decoder.decode(value)).toEqual(`${i}`)
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
})
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Context } from '../../context.ts'
|
|
2
|
+
import { TEXT_PLAIN } from '../../context.ts'
|
|
3
|
+
import type { StreamingApi } from '../../utils/stream.ts'
|
|
4
|
+
import { stream } from './index.ts'
|
|
5
|
+
|
|
6
|
+
export const streamText = (
|
|
7
|
+
c: Context,
|
|
8
|
+
cb: (stream: StreamingApi) => Promise<void>,
|
|
9
|
+
onError?: (e: Error, stream: StreamingApi) => Promise<void>
|
|
10
|
+
): Response => {
|
|
11
|
+
c.header('Content-Type', TEXT_PLAIN)
|
|
12
|
+
c.header('X-Content-Type-Options', 'nosniff')
|
|
13
|
+
c.header('Transfer-Encoding', 'chunked')
|
|
14
|
+
return stream(c, cb, onError)
|
|
15
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export let isOldBunVersion = (): boolean => {
|
|
2
|
+
// @ts-expect-error @types/bun is not installed
|
|
3
|
+
const version: string = typeof Bun !== 'undefined' ? Bun.version : undefined
|
|
4
|
+
if (version === undefined) {
|
|
5
|
+
return false
|
|
6
|
+
}
|
|
7
|
+
const result = version.startsWith('1.1') || version.startsWith('1.0') || version.startsWith('0.')
|
|
8
|
+
// Avoid running this check on every call
|
|
9
|
+
isOldBunVersion = () => result
|
|
10
|
+
return result
|
|
11
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { testClient } from './index.ts'
|
|
2
|
+
import { App } from '../../app.ts'
|
|
3
|
+
|
|
4
|
+
describe('acryl testClient', () => {
|
|
5
|
+
it('Should return the correct search result', async () => {
|
|
6
|
+
const app = new App().get('/search', (c) => c.json({ hello: 'world' }))
|
|
7
|
+
const res = await testClient(app).search.$get()
|
|
8
|
+
expect(await res.json()).toEqual({ hello: 'world' })
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
it('Should return the correct environment variables value', async () => {
|
|
12
|
+
type Bindings = { hello: string }
|
|
13
|
+
const app = new App<{ Bindings: Bindings }>().get('/search', (c) => {
|
|
14
|
+
return c.json({ hello: c.env.hello })
|
|
15
|
+
})
|
|
16
|
+
const res = await testClient(app, { hello: 'world' }).search.$get()
|
|
17
|
+
expect(await res.json()).toEqual({ hello: 'world' })
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('Should use the passed in headers', async () => {
|
|
21
|
+
const app = new App().get('/search', (c) => {
|
|
22
|
+
return c.json({ query: c.req.header('x-query') })
|
|
23
|
+
})
|
|
24
|
+
const res = await testClient(app, undefined, undefined, {
|
|
25
|
+
headers: { 'x-query': 'abc' },
|
|
26
|
+
}).search.$get()
|
|
27
|
+
expect(await res.json()).toEqual({ query: 'abc' })
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('Should return a correct URL with out throwing an error', async () => {
|
|
31
|
+
const app = new App().get('/abc', (c) => c.json(0))
|
|
32
|
+
const url = testClient(app).abc.$url()
|
|
33
|
+
expect(url.pathname).toBe('/abc')
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('Should not throw an error with $ws()', async () => {
|
|
37
|
+
vi.stubGlobal('WebSocket', class {})
|
|
38
|
+
const app = new App().get('/ws', (c) => c.text('Fake response of a WebSocket'))
|
|
39
|
+
// @ts-expect-error $ws is not typed correctly
|
|
40
|
+
expect(() => testClient(app).ws.$ws()).not.toThrowError()
|
|
41
|
+
})
|
|
42
|
+
})
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module
|
|
3
|
+
* Testing Helper for App.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { hc } from '../../client/index.ts'
|
|
7
|
+
import type { ClientRequestOptions } from '../../client/index.ts'
|
|
8
|
+
import type { Client } from '../../client/types.ts'
|
|
9
|
+
import type { ExecutionContext } from '../../context.ts'
|
|
10
|
+
import type { App } from '../../app.ts'
|
|
11
|
+
import type { Schema } from '../../types.ts'
|
|
12
|
+
import type { UnionToIntersection } from '../../utils/types.ts'
|
|
13
|
+
|
|
14
|
+
type ExtractEnv<T> = T extends App<infer E, Schema, string> ? E : never
|
|
15
|
+
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
17
|
+
export const testClient = <T extends App<any, Schema, string>>(
|
|
18
|
+
app: T,
|
|
19
|
+
Env?: ExtractEnv<T>['Bindings'] | {},
|
|
20
|
+
executionCtx?: ExecutionContext,
|
|
21
|
+
options?: Omit<ClientRequestOptions, 'fetch'>
|
|
22
|
+
): UnionToIntersection<Client<T, 'http://localhost'>> => {
|
|
23
|
+
const customFetch = (input: RequestInfo | URL, init?: RequestInit) => {
|
|
24
|
+
return app.request(input, init, Env, executionCtx)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return hc<typeof app, 'http://localhost'>('http://localhost', { ...options, fetch: customFetch })
|
|
28
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import type { WSContextInit } from './index.ts'
|
|
2
|
+
import { WSContext, createWSMessageEvent, defineWebSocketHelper } from './index.ts'
|
|
3
|
+
import { Context } from '../../context.ts'
|
|
4
|
+
|
|
5
|
+
describe('`createWSMessageEvent`', () => {
|
|
6
|
+
it('Should `createWSMessageEvent` is working for string', () => {
|
|
7
|
+
const randomString = Math.random().toString()
|
|
8
|
+
const event = createWSMessageEvent(randomString)
|
|
9
|
+
|
|
10
|
+
expect(event.data).toBe(randomString)
|
|
11
|
+
})
|
|
12
|
+
it('Should `createWSMessageEvent` type is `message`', () => {
|
|
13
|
+
const event = createWSMessageEvent('')
|
|
14
|
+
expect(event.type).toBe('message')
|
|
15
|
+
})
|
|
16
|
+
})
|
|
17
|
+
describe('defineWebSocketHelper', () => {
|
|
18
|
+
it('defineWebSocketHelper should work', async () => {
|
|
19
|
+
const upgradeWebSocket = defineWebSocketHelper(() => {
|
|
20
|
+
return new Response('Hello World', {
|
|
21
|
+
status: 200,
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
const response = await upgradeWebSocket(() => ({}))(
|
|
25
|
+
new Context(new Request('http://localhost')),
|
|
26
|
+
() => Promise.resolve()
|
|
27
|
+
)
|
|
28
|
+
expect(response).toBeTruthy()
|
|
29
|
+
expect((response as Response).status).toBe(200)
|
|
30
|
+
})
|
|
31
|
+
it('When response is undefined, should call next()', async () => {
|
|
32
|
+
const upgradeWebSocket = defineWebSocketHelper(() => {
|
|
33
|
+
return
|
|
34
|
+
})
|
|
35
|
+
const next = vi.fn()
|
|
36
|
+
await upgradeWebSocket(() => ({}))(new Context(new Request('http://localhost')), next)
|
|
37
|
+
expect(next).toBeCalled()
|
|
38
|
+
})
|
|
39
|
+
it('Use upgradeWebSocket in return', async () => {
|
|
40
|
+
const upgradeWebSocket = defineWebSocketHelper(() => {
|
|
41
|
+
return new Response('Hello World', {
|
|
42
|
+
status: 200,
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
const c = new Context(new Request('http://localhost'))
|
|
46
|
+
const res = await upgradeWebSocket(c, {})
|
|
47
|
+
expect(res.status).toBe(200)
|
|
48
|
+
})
|
|
49
|
+
it('When upgrading failed and use it in handler, it should throw error', async () => {
|
|
50
|
+
const upgradeWebSocket = defineWebSocketHelper(() => {
|
|
51
|
+
return
|
|
52
|
+
})
|
|
53
|
+
const c = new Context(new Request('http://localhost'))
|
|
54
|
+
await expect(() => upgradeWebSocket(c, {})).rejects.toThrow()
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
describe('WSContext', () => {
|
|
58
|
+
it('Should close() works', async () => {
|
|
59
|
+
type Result = [number | undefined, string | undefined]
|
|
60
|
+
let ws!: WSContext
|
|
61
|
+
const promise = new Promise<Result>((resolve) => {
|
|
62
|
+
ws = new WSContext({
|
|
63
|
+
close(code, reason) {
|
|
64
|
+
resolve([code, reason])
|
|
65
|
+
},
|
|
66
|
+
} as WSContextInit)
|
|
67
|
+
})
|
|
68
|
+
ws.close(0, 'reason')
|
|
69
|
+
const [code, reason] = await promise
|
|
70
|
+
expect(code).toBe(0)
|
|
71
|
+
expect(reason).toBe('reason')
|
|
72
|
+
})
|
|
73
|
+
it('Should send() works', async () => {
|
|
74
|
+
let ws!: WSContext
|
|
75
|
+
const promise = new Promise<string | ArrayBuffer | Uint8Array<ArrayBuffer>>((resolve) => {
|
|
76
|
+
ws = new WSContext({
|
|
77
|
+
send(data: string | ArrayBuffer | Uint8Array<ArrayBuffer>, _options) {
|
|
78
|
+
resolve(data)
|
|
79
|
+
},
|
|
80
|
+
} as WSContextInit)
|
|
81
|
+
})
|
|
82
|
+
ws.send('Hello')
|
|
83
|
+
expect(await promise).toBe('Hello')
|
|
84
|
+
})
|
|
85
|
+
it('Should readyState works', () => {
|
|
86
|
+
const ws = new WSContext({
|
|
87
|
+
readyState: 0,
|
|
88
|
+
} as WSContextInit)
|
|
89
|
+
expect(ws.readyState).toBe(0)
|
|
90
|
+
})
|
|
91
|
+
it('Should normalize URL', () => {
|
|
92
|
+
const stringURLWS = new WSContext({
|
|
93
|
+
url: 'http://localhost',
|
|
94
|
+
} as WSContextInit)
|
|
95
|
+
expect(stringURLWS.url).toBeInstanceOf(URL)
|
|
96
|
+
|
|
97
|
+
const urlURLWS = new WSContext({
|
|
98
|
+
url: new URL('http://localhost'),
|
|
99
|
+
} as WSContextInit)
|
|
100
|
+
expect(urlURLWS.url).toBeInstanceOf(URL)
|
|
101
|
+
|
|
102
|
+
const nullURLWS = new WSContext({
|
|
103
|
+
url: undefined,
|
|
104
|
+
} as WSContextInit)
|
|
105
|
+
expect(nullURLWS.url).toBeNull()
|
|
106
|
+
})
|
|
107
|
+
it('Should normalize message in send()', () => {
|
|
108
|
+
let data: string | ArrayBuffer | Uint8Array | null = null
|
|
109
|
+
const wsContext = new WSContext({
|
|
110
|
+
send(received, _options) {
|
|
111
|
+
data = received
|
|
112
|
+
},
|
|
113
|
+
} as WSContextInit)
|
|
114
|
+
|
|
115
|
+
wsContext.send('string')
|
|
116
|
+
expect(data).toBe('string')
|
|
117
|
+
|
|
118
|
+
wsContext.send(new ArrayBuffer(16))
|
|
119
|
+
expect(data).toBeInstanceOf(ArrayBuffer)
|
|
120
|
+
|
|
121
|
+
wsContext.send(new Uint8Array(16))
|
|
122
|
+
expect(data).toBeInstanceOf(Uint8Array)
|
|
123
|
+
})
|
|
124
|
+
})
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module
|
|
3
|
+
* WebSocket Helper for App.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
7
|
+
import type { Context } from '../../context.ts'
|
|
8
|
+
import type { MiddlewareHandler, TypedResponse } from '../../types.ts'
|
|
9
|
+
import type { StatusCode } from '../../utils/http-status.ts'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* WebSocket Event Listeners type
|
|
13
|
+
*/
|
|
14
|
+
export interface WSEvents<T = unknown> {
|
|
15
|
+
onOpen?: (evt: Event, ws: WSContext<T>) => void
|
|
16
|
+
onMessage?: (evt: MessageEvent<WSMessageReceive>, ws: WSContext<T>) => void
|
|
17
|
+
onClose?: (evt: CloseEvent, ws: WSContext<T>) => void
|
|
18
|
+
onError?: (evt: Event, ws: WSContext<T>) => void
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Upgrade WebSocket Type
|
|
23
|
+
*/
|
|
24
|
+
export interface UpgradeWebSocket<T = unknown, U = any, _WSEvents = WSEvents<T>> {
|
|
25
|
+
(
|
|
26
|
+
createEvents: (c: Context) => _WSEvents | Promise<_WSEvents>,
|
|
27
|
+
options?: U
|
|
28
|
+
): MiddlewareHandler<
|
|
29
|
+
any,
|
|
30
|
+
string,
|
|
31
|
+
{
|
|
32
|
+
outputFormat: 'ws'
|
|
33
|
+
}
|
|
34
|
+
>
|
|
35
|
+
(
|
|
36
|
+
c: Context,
|
|
37
|
+
events: _WSEvents,
|
|
38
|
+
options?: U
|
|
39
|
+
): Promise<Response & TypedResponse<{}, StatusCode, 'ws'>>
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* ReadyState for WebSocket
|
|
44
|
+
*/
|
|
45
|
+
export type WSReadyState = 0 | 1 | 2 | 3
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* An argument for WSContext class
|
|
49
|
+
*/
|
|
50
|
+
export interface WSContextInit<T = unknown> {
|
|
51
|
+
send(data: string | ArrayBuffer | Uint8Array<ArrayBuffer>, options: SendOptions): void
|
|
52
|
+
close(code?: number, reason?: string): void
|
|
53
|
+
|
|
54
|
+
raw?: T
|
|
55
|
+
readyState: WSReadyState
|
|
56
|
+
url?: string | URL | null
|
|
57
|
+
protocol?: string | null
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Options for sending message
|
|
62
|
+
*/
|
|
63
|
+
export interface SendOptions {
|
|
64
|
+
compress?: boolean
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* A context for controlling WebSockets
|
|
69
|
+
*/
|
|
70
|
+
export class WSContext<T = unknown> {
|
|
71
|
+
#init: WSContextInit<T>
|
|
72
|
+
constructor(init: WSContextInit<T>) {
|
|
73
|
+
this.#init = init
|
|
74
|
+
this.raw = init.raw
|
|
75
|
+
this.url = init.url ? new URL(init.url) : null
|
|
76
|
+
this.protocol = init.protocol ?? null
|
|
77
|
+
}
|
|
78
|
+
send(source: string | ArrayBuffer | Uint8Array<ArrayBuffer>, options?: SendOptions): void {
|
|
79
|
+
this.#init.send(source, options ?? {})
|
|
80
|
+
}
|
|
81
|
+
raw?: T
|
|
82
|
+
binaryType: BinaryType = 'arraybuffer'
|
|
83
|
+
get readyState(): WSReadyState {
|
|
84
|
+
return this.#init.readyState
|
|
85
|
+
}
|
|
86
|
+
url: URL | null
|
|
87
|
+
protocol: string | null
|
|
88
|
+
close(code?: number, reason?: string) {
|
|
89
|
+
this.#init.close(code, reason)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export type WSMessageReceive = string | Blob | ArrayBufferLike
|
|
94
|
+
|
|
95
|
+
export const createWSMessageEvent = (source: WSMessageReceive): MessageEvent<WSMessageReceive> => {
|
|
96
|
+
return new MessageEvent<WSMessageReceive>('message', {
|
|
97
|
+
data: source,
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export interface WebSocketHelperDefineContext {}
|
|
102
|
+
export type WebSocketHelperDefineHandler<T, U> = (
|
|
103
|
+
c: Context,
|
|
104
|
+
events: WSEvents<T>,
|
|
105
|
+
options?: U
|
|
106
|
+
) => Promise<Response | void> | Response | void
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Create a WebSocket adapter/helper
|
|
110
|
+
*/
|
|
111
|
+
export const defineWebSocketHelper = <T = unknown, U = any>(
|
|
112
|
+
handler: WebSocketHelperDefineHandler<T, U>
|
|
113
|
+
): UpgradeWebSocket<T, U> => {
|
|
114
|
+
return ((
|
|
115
|
+
...args:
|
|
116
|
+
| [createEvents: (c: Context) => WSEvents<T> | Promise<WSEvents<T>>, options?: U]
|
|
117
|
+
| [c: Context, events: WSEvents<T>, options?: U]
|
|
118
|
+
) => {
|
|
119
|
+
if (typeof args[0] === 'function') {
|
|
120
|
+
const [createEvents, options] = args
|
|
121
|
+
return async function upgradeWebSocket(c, next) {
|
|
122
|
+
const events = await createEvents(c)
|
|
123
|
+
const result = await handler(c, events, options as U)
|
|
124
|
+
if (result) {
|
|
125
|
+
return result
|
|
126
|
+
}
|
|
127
|
+
await next()
|
|
128
|
+
}
|
|
129
|
+
} else {
|
|
130
|
+
const [c, events, options] = args as [c: Context, events: WSEvents<T>, options?: U]
|
|
131
|
+
return (async () => {
|
|
132
|
+
const upgraded = await handler(c, events, options as U)
|
|
133
|
+
if (!upgraded) {
|
|
134
|
+
throw new Error('Failed to upgrade WebSocket')
|
|
135
|
+
}
|
|
136
|
+
return upgraded
|
|
137
|
+
})()
|
|
138
|
+
}
|
|
139
|
+
}) as UpgradeWebSocket<T, U>
|
|
140
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { HTTPException } from './http-exception.ts'
|
|
2
|
+
|
|
3
|
+
describe('HTTPException', () => {
|
|
4
|
+
it('Should be 401 HTTP exception object', async () => {
|
|
5
|
+
// We should throw an exception if is not authorized
|
|
6
|
+
// because next handlers should not be fired.
|
|
7
|
+
const exception = new HTTPException(401, {
|
|
8
|
+
message: 'Unauthorized',
|
|
9
|
+
})
|
|
10
|
+
const res = exception.getResponse()
|
|
11
|
+
|
|
12
|
+
expect(res.status).toBe(401)
|
|
13
|
+
expect(await res.text()).toBe('Unauthorized')
|
|
14
|
+
expect(exception.status).toBe(401)
|
|
15
|
+
expect(exception.message).toBe('Unauthorized')
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
it('Should be accessible to the object causing the exception', async () => {
|
|
19
|
+
// We should pass the cause of the error to the cause option
|
|
20
|
+
// because it makes debugging easier.
|
|
21
|
+
const error = new Error('Server Error')
|
|
22
|
+
const exception = new HTTPException(500, {
|
|
23
|
+
message: 'Internal Server Error',
|
|
24
|
+
cause: error,
|
|
25
|
+
})
|
|
26
|
+
const res = exception.getResponse()
|
|
27
|
+
|
|
28
|
+
expect(res.status).toBe(500)
|
|
29
|
+
expect(await res.text()).toBe('Internal Server Error')
|
|
30
|
+
expect(exception.status).toBe(500)
|
|
31
|
+
expect(exception.message).toBe('Internal Server Error')
|
|
32
|
+
expect(exception.cause).toBe(error)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
it('Should prioritize the status code over the code in the response', async () => {
|
|
36
|
+
const exception = new HTTPException(400, {
|
|
37
|
+
res: new Response('An exception', {
|
|
38
|
+
status: 200,
|
|
39
|
+
}),
|
|
40
|
+
})
|
|
41
|
+
const res = exception.getResponse()
|
|
42
|
+
expect(res.status).toBe(400)
|
|
43
|
+
expect(await res.text()).toBe('An exception')
|
|
44
|
+
})
|
|
45
|
+
})
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module
|
|
3
|
+
* This module provides the `HTTPException` class.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { ContentfulStatusCode } from './utils/http-status.ts'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Options for creating an `HTTPException`.
|
|
10
|
+
* @property res - Optional response object to use.
|
|
11
|
+
* @property message - Optional custom error message.
|
|
12
|
+
* @property cause - Optional cause of the error.
|
|
13
|
+
*/
|
|
14
|
+
type HTTPExceptionOptions = {
|
|
15
|
+
res?: Response
|
|
16
|
+
message?: string
|
|
17
|
+
cause?: unknown
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* `HTTPException` must be used when a fatal error such as authentication failure occurs.
|
|
22
|
+
*
|
|
23
|
+
*
|
|
24
|
+
* @param {StatusCode} status - status code of HTTPException
|
|
25
|
+
* @param {HTTPExceptionOptions} options - options of HTTPException
|
|
26
|
+
* @param {HTTPExceptionOptions["res"]} options.res - response of options of HTTPException
|
|
27
|
+
* @param {HTTPExceptionOptions["message"]} options.message - message of options of HTTPException
|
|
28
|
+
* @param {HTTPExceptionOptions["cause"]} options.cause - cause of options of HTTPException
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* import { HTTPException } from 'acryl-router'
|
|
33
|
+
*
|
|
34
|
+
* // ...
|
|
35
|
+
*
|
|
36
|
+
* app.post('/auth', async (c, next) => {
|
|
37
|
+
* // authentication
|
|
38
|
+
* if (authorized === false) {
|
|
39
|
+
* throw new HTTPException(401, { message: 'Custom error message' })
|
|
40
|
+
* }
|
|
41
|
+
* await next()
|
|
42
|
+
* })
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export class HTTPException extends Error {
|
|
46
|
+
readonly res?: Response
|
|
47
|
+
readonly status: ContentfulStatusCode
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Creates an instance of `HTTPException`.
|
|
51
|
+
* @param status - HTTP status code for the exception. Defaults to 500.
|
|
52
|
+
* @param options - Additional options for the exception.
|
|
53
|
+
*/
|
|
54
|
+
constructor(status: ContentfulStatusCode = 500, options?: HTTPExceptionOptions) {
|
|
55
|
+
super(options?.message, { cause: options?.cause })
|
|
56
|
+
this.res = options?.res
|
|
57
|
+
this.status = status
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Returns the response object associated with the exception.
|
|
62
|
+
* If a response object is not provided, a new response is created with the error message and status code.
|
|
63
|
+
* @returns The response object.
|
|
64
|
+
*/
|
|
65
|
+
getResponse(): Response {
|
|
66
|
+
if (this.res) {
|
|
67
|
+
const newResponse = new Response(this.res.body, {
|
|
68
|
+
status: this.status,
|
|
69
|
+
headers: this.res.headers,
|
|
70
|
+
})
|
|
71
|
+
return newResponse
|
|
72
|
+
}
|
|
73
|
+
return new Response(this.message, {
|
|
74
|
+
status: this.status,
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module
|
|
3
|
+
*
|
|
4
|
+
* App - Web Framework built on Web Standards
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { App } from 'acryl-router'
|
|
9
|
+
* const app = new App()
|
|
10
|
+
*
|
|
11
|
+
* app.get('/', (c) => c.text('App!'))
|
|
12
|
+
*
|
|
13
|
+
* export default app
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { App } from './app.ts'
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Types for environment variables, error handlers, handlers, middleware handlers, and more.
|
|
21
|
+
*/
|
|
22
|
+
export type {
|
|
23
|
+
Env,
|
|
24
|
+
ErrorHandler,
|
|
25
|
+
Handler,
|
|
26
|
+
MiddlewareHandler,
|
|
27
|
+
Next,
|
|
28
|
+
NotFoundResponse,
|
|
29
|
+
NotFoundHandler,
|
|
30
|
+
ValidationTargets,
|
|
31
|
+
Input,
|
|
32
|
+
Schema,
|
|
33
|
+
ToSchema,
|
|
34
|
+
TypedResponse,
|
|
35
|
+
} from './types.ts'
|
|
36
|
+
/**
|
|
37
|
+
* Types for context, context variable map, context renderer, and execution context.
|
|
38
|
+
*/
|
|
39
|
+
export { Context } from './context.ts'
|
|
40
|
+
export type { ContextVariableMap, ContextRenderer, ExecutionContext } from './context.ts'
|
|
41
|
+
/**
|
|
42
|
+
* Type for AppRequest.
|
|
43
|
+
*/
|
|
44
|
+
export type { AppRequest } from './request.ts'
|
|
45
|
+
/**
|
|
46
|
+
* Types for inferring request and response types and client request options.
|
|
47
|
+
*/
|
|
48
|
+
export type { InferRequestType, InferResponseType, ClientRequestOptions } from './client/index.ts'
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* App framework for building web applications.
|
|
52
|
+
*/
|
|
53
|
+
export { App }
|