acrylblends 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +73 -0
- package/dist/index.js +56 -2
- 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/agents/index.md +24 -0
- package/docs/framework/api/acryl.md +259 -0
- package/docs/framework/api/context.md +527 -0
- package/docs/framework/api/exception.md +80 -0
- package/docs/framework/api/index.md +12 -0
- package/docs/framework/api/presets.md +65 -0
- package/docs/framework/api/request.md +396 -0
- package/docs/framework/api/routing.md +303 -0
- package/docs/framework/api/summary.md +140 -0
- package/docs/framework/concepts/benchmarks.md +26 -0
- package/docs/framework/concepts/developer-experience.md +5 -0
- package/docs/framework/concepts/middleware.md +21 -0
- package/docs/framework/concepts/motivation.md +14 -0
- package/docs/framework/concepts/routers.md +63 -0
- package/docs/framework/concepts/stacks.md +235 -0
- package/docs/framework/concepts/web-standard.md +37 -0
- package/docs/framework/cordis/acryl-in-a-cordis-app.md +146 -0
- package/docs/framework/cordis/concepts.md +105 -0
- package/docs/framework/cordis/middleware.md +8 -0
- package/docs/framework/cordis/migration-from-0-3.md +111 -0
- package/docs/framework/cordis/migration-from-0-4.md +14 -0
- package/docs/framework/cordis/migration-from-dsh-webserver.md +103 -0
- package/docs/framework/cordis/mounting.md +85 -0
- package/docs/framework/cordis/node-server.md +75 -0
- package/docs/framework/cordis/plugin-lifecycle.md +111 -0
- package/docs/framework/cordis/surfaces.md +71 -0
- package/docs/framework/cordis/transport-and-cancellation.md +57 -0
- package/docs/framework/cordis/validation.md +135 -0
- package/docs/framework/getting-started/basic.md +196 -0
- package/docs/framework/getting-started/bun.md +221 -0
- package/docs/framework/getting-started/nodejs.md +344 -0
- package/docs/framework/getting-started/other-runtimes.md +23 -0
- package/docs/framework/guides/best-practices.md +231 -0
- package/docs/framework/guides/create-acrylblends.md +79 -0
- package/docs/framework/guides/examples.md +3 -0
- package/docs/framework/guides/faq.md +19 -0
- package/docs/framework/guides/helpers.md +33 -0
- package/docs/framework/guides/jsx-dom.md +299 -0
- package/docs/framework/guides/jsx.md +440 -0
- package/docs/framework/guides/middleware.md +253 -0
- package/docs/framework/guides/rpc.md +886 -0
- package/docs/framework/guides/testing.md +133 -0
- package/docs/framework/guides/validation.md +383 -0
- package/docs/framework/helpers/accepts.md +60 -0
- package/docs/framework/helpers/adapter.md +87 -0
- package/docs/framework/helpers/conninfo.md +112 -0
- package/docs/framework/helpers/cookie.md +232 -0
- package/docs/framework/helpers/css.md +285 -0
- package/docs/framework/helpers/dev.md +67 -0
- package/docs/framework/helpers/factory.md +180 -0
- package/docs/framework/helpers/html.md +123 -0
- package/docs/framework/helpers/jwt.md +184 -0
- package/docs/framework/helpers/proxy.md +118 -0
- package/docs/framework/helpers/route.md +143 -0
- package/docs/framework/helpers/ssg.md +393 -0
- package/docs/framework/helpers/streaming.md +119 -0
- package/docs/framework/helpers/testing.md +101 -0
- package/docs/framework/helpers/websocket.md +215 -0
- package/docs/framework/middleware/builtin/basic-auth.md +165 -0
- package/docs/framework/middleware/builtin/bearer-auth.md +138 -0
- package/docs/framework/middleware/builtin/body-limit.md +71 -0
- package/docs/framework/middleware/builtin/cache.md +122 -0
- package/docs/framework/middleware/builtin/combine.md +94 -0
- package/docs/framework/middleware/builtin/compress.md +59 -0
- package/docs/framework/middleware/builtin/context-storage.md +78 -0
- package/docs/framework/middleware/builtin/cors.md +135 -0
- package/docs/framework/middleware/builtin/csrf.md +105 -0
- package/docs/framework/middleware/builtin/etag.md +54 -0
- package/docs/framework/middleware/builtin/ip-restriction.md +69 -0
- package/docs/framework/middleware/builtin/jsx-renderer.md +286 -0
- package/docs/framework/middleware/builtin/jwk.md +192 -0
- package/docs/framework/middleware/builtin/jwt.md +145 -0
- package/docs/framework/middleware/builtin/language.md +232 -0
- package/docs/framework/middleware/builtin/logger.md +74 -0
- package/docs/framework/middleware/builtin/loopback-only.md +31 -0
- package/docs/framework/middleware/builtin/method-not-allowed.md +48 -0
- package/docs/framework/middleware/builtin/method-override.md +80 -0
- package/docs/framework/middleware/builtin/mount.md +106 -0
- package/docs/framework/middleware/builtin/pretty-json.md +53 -0
- package/docs/framework/middleware/builtin/request-id.md +94 -0
- package/docs/framework/middleware/builtin/secure-headers.md +247 -0
- package/docs/framework/middleware/builtin/timeout.md +98 -0
- package/docs/framework/middleware/builtin/timing.md +101 -0
- package/docs/framework/middleware/builtin/trailing-slash.md +74 -0
- package/docs/framework/middleware/third-party.md +4 -0
- package/docs/framework/upstream.json +9 -0
- package/lib/accepts-XBuZPVRI.js +52 -0
- package/lib/accepts.d.ts +33 -0
- package/lib/accepts.js +2 -0
- package/lib/acryl-base.d.ts +2 -0
- package/lib/acryl-base.js +332 -0
- package/lib/adapter.d.ts +12 -0
- package/lib/adapter.js +37 -0
- package/lib/app-BM0rTCp7.js +26 -0
- package/lib/app-CmAYW1Al.d.ts +21 -0
- package/lib/basic-auth.d.ts +72 -0
- package/lib/basic-auth.js +95 -0
- package/lib/bearer-auth.d.ts +89 -0
- package/lib/bearer-auth.js +94 -0
- package/lib/body-limit.d.ts +42 -0
- package/lib/body-limit.js +66 -0
- package/lib/client-BHTr318g.js +266 -0
- package/lib/client.d.ts +3 -0
- package/lib/client.js +2 -0
- package/lib/combine.d.ts +85 -0
- package/lib/combine.js +137 -0
- package/lib/compose-BuW2B6PZ.js +50 -0
- package/lib/compress.d.ts +38 -0
- package/lib/compress.js +79 -0
- package/lib/connection-C7xgP1hP.js +24 -0
- package/lib/conninfo.d.ts +25 -0
- package/lib/conninfo.js +2 -0
- package/lib/constants-Dy7ZvN1H.js +4 -0
- package/lib/context-Bm7rI-oK.d.ts +1234 -0
- package/lib/context-DDO0cfuP.js +365 -0
- package/lib/context-storage.d.ts +38 -0
- package/lib/context-storage.js +52 -0
- package/lib/cookie-ClMaKDQf.d.ts +40 -0
- package/lib/cookie.d.ts +24 -0
- package/lib/cookie.js +82 -0
- package/lib/cors.d.ts +52 -0
- package/lib/cors.js +106 -0
- package/lib/csrf.d.ts +75 -0
- package/lib/csrf.js +101 -0
- package/lib/etag.d.ts +40 -0
- package/lib/etag.js +135 -0
- package/lib/factory.d.ts +35 -0
- package/lib/factory.js +30 -0
- package/lib/headers-tu2YYN8T.d.ts +11 -0
- package/lib/html.d.ts +6 -0
- package/lib/html.js +31 -0
- package/lib/http-exception.d.ts +57 -0
- package/lib/http-exception.js +54 -0
- package/lib/http-status-DaAwGAFL.d.ts +35 -0
- package/lib/index-B-3F4wt2.d.ts +12 -0
- package/lib/index-UTBmM3GX.d.ts +68 -0
- package/lib/index-oOClm_Xk.d.ts +45 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.js +28 -0
- package/lib/ip-restriction.d.ts +68 -0
- package/lib/ip-restriction.js +166 -0
- package/lib/jwk.d.ts +52 -0
- package/lib/jwk.js +117 -0
- package/lib/jwt-BGJBw5AF.js +403 -0
- package/lib/jwt-Dg493Tai.d.ts +51 -0
- package/lib/jwt.d.ts +72 -0
- package/lib/jwt.js +115 -0
- package/lib/language.d.ts +88 -0
- package/lib/language.js +198 -0
- package/lib/logger.d.ts +22 -0
- package/lib/logger.js +54 -0
- package/lib/loopback-only.d.ts +45 -0
- package/lib/loopback-only.js +90 -0
- package/lib/method-not-allowed.d.ts +47 -0
- package/lib/method-not-allowed.js +82 -0
- package/lib/method-override.d.ts +46 -0
- package/lib/method-override.js +103 -0
- package/lib/mime-BQOYHl-l.d.ts +72 -0
- package/lib/node-server/conninfo.d.ts +11 -0
- package/lib/node-server/conninfo.js +19 -0
- package/lib/node-server/serve-static.d.ts +19 -0
- package/lib/node-server/serve-static.js +2 -0
- package/lib/node-server.d.ts +103 -0
- package/lib/node-server.js +1325 -0
- package/lib/powered-by.d.ts +28 -0
- package/lib/powered-by.js +24 -0
- package/lib/pretty-json.d.ts +40 -0
- package/lib/pretty-json.js +39 -0
- package/lib/reg-exp-router-DC1R3qoY.js +363 -0
- package/lib/request-id.d.ts +45 -0
- package/lib/request-id.js +34 -0
- package/lib/request.d.ts +2 -0
- package/lib/request.js +323 -0
- package/lib/route.d.ts +78 -0
- package/lib/route.js +126 -0
- package/lib/router/linear-router.d.ts +11 -0
- package/lib/router/linear-router.js +96 -0
- package/lib/router/pattern-router.d.ts +11 -0
- package/lib/router/pattern-router.js +41 -0
- package/lib/router/reg-exp-router.d.ts +35 -0
- package/lib/router/reg-exp-router.js +2 -0
- package/lib/router/smart-router.d.ts +15 -0
- package/lib/router/smart-router.js +2 -0
- package/lib/router/trie-router.d.ts +11 -0
- package/lib/router/trie-router.js +2 -0
- package/lib/router-CvUxUTOq.d.ts +99 -0
- package/lib/router.d.ts +2 -0
- package/lib/router.js +35 -0
- package/lib/schema-validator.d.ts +28 -0
- package/lib/schema-validator.js +22 -0
- package/lib/secure-headers.d.ts +125 -0
- package/lib/secure-headers.js +163 -0
- package/lib/serve-static-Dw_m6KxR.js +213 -0
- package/lib/serve-static.d.ts +31 -0
- package/lib/serve-static.js +77 -0
- package/lib/smart-router-C5CZ5XSM.js +49 -0
- package/lib/stream-CPdqZ0Fp.d.ts +34 -0
- package/lib/streaming-DHST3Scg.js +96 -0
- package/lib/streaming.d.ts +23 -0
- package/lib/streaming.js +2 -0
- package/lib/testing.d.ts +10 -0
- package/lib/testing.js +17 -0
- package/lib/timeout.d.ts +30 -0
- package/lib/timeout.js +42 -0
- package/lib/timing.d.ts +130 -0
- package/lib/timing.js +183 -0
- package/lib/trailing-slash.d.ts +91 -0
- package/lib/trailing-slash.js +85 -0
- package/lib/trie-router-CfFbapzL.js +146 -0
- package/lib/types-CDO6I3B0.d.ts +40 -0
- package/lib/types-CHesD1KG.d.ts +195 -0
- package/lib/types-CwrQjlaM.d.ts +105 -0
- package/lib/types-DR95J00T.d.ts +29 -0
- package/lib/types.d.ts +2 -0
- package/lib/types.js +4 -0
- package/lib/utils/accept.d.ts +9 -0
- package/lib/utils/accept.js +193 -0
- package/lib/utils/basic-auth.d.ts +8 -0
- package/lib/utils/basic-auth.js +20 -0
- package/lib/utils/body.d.ts +2 -0
- package/lib/utils/body.js +94 -0
- package/lib/utils/buffer.d.ts +19 -0
- package/lib/utils/buffer.js +51 -0
- package/lib/utils/color.d.ts +24 -0
- package/lib/utils/color.js +37 -0
- package/lib/utils/compress.d.ts +11 -0
- package/lib/utils/compress.js +11 -0
- package/lib/utils/concurrent.d.ts +17 -0
- package/lib/utils/concurrent.js +30 -0
- package/lib/utils/constants.d.ts +7 -0
- package/lib/utils/constants.js +7 -0
- package/lib/utils/cookie.d.ts +2 -0
- package/lib/utils/cookie.js +125 -0
- package/lib/utils/crypto.d.ts +14 -0
- package/lib/utils/crypto.js +34 -0
- package/lib/utils/encode.d.ts +11 -0
- package/lib/utils/encode.js +33 -0
- package/lib/utils/filepath.d.ts +14 -0
- package/lib/utils/filepath.js +25 -0
- package/lib/utils/handler.d.ts +9 -0
- package/lib/utils/handler.js +12 -0
- package/lib/utils/headers.d.ts +2 -0
- package/lib/utils/headers.js +1 -0
- package/lib/utils/html.d.ts +46 -0
- package/lib/utils/html.js +103 -0
- package/lib/utils/http-status.d.ts +2 -0
- package/lib/utils/http-status.js +1 -0
- package/lib/utils/ipaddr.d.ts +56 -0
- package/lib/utils/ipaddr.js +238 -0
- package/lib/utils/jwt.d.ts +24 -0
- package/lib/utils/jwt.js +2 -0
- package/lib/utils/mime.d.ts +2 -0
- package/lib/utils/mime.js +77 -0
- package/lib/utils/stream.d.ts +2 -0
- package/lib/utils/stream.js +88 -0
- package/lib/utils/types.d.ts +2 -0
- package/lib/utils/types.js +1 -0
- package/lib/utils/url.d.ts +46 -0
- package/lib/utils/url.js +197 -0
- package/lib/utils-dw8lxqjL.js +4 -0
- package/lib/validator-D84mq-dO.js +65 -0
- package/lib/validator.d.ts +42 -0
- package/lib/validator.js +2 -0
- package/lib/ws.d.ts +2 -0
- package/lib/ws.js +53 -0
- package/package.json +315 -15
- package/plugins/acryl-inspect/src/report.ts +15 -10
- package/plugins/acryl-inspect/src/service.ts +2 -2
- package/plugins/acryl-inspect/tests/report.spec.ts +9 -3
- package/plugins/acryl-inspect/tests/service.spec.ts +3 -3
- package/plugins/acryl-inspect/upstream.json +2 -2
- package/plugins/acryl-node-server/tests/adapter/app.ts +2 -2
- package/plugins/acryl-node-server/tests/adapter/assets/static/acryl.html +1 -1
- package/plugins/acryl-node-server/tests/adapter/assets/static/index.html +1 -1
- package/plugins/acryl-node-server/tests/adapter/conninfo.test.ts +2 -2
- package/plugins/acryl-node-server/tests/adapter/content-length.test.ts +4 -4
- package/plugins/acryl-node-server/tests/adapter/early-hints.test.ts +5 -5
- package/plugins/acryl-node-server/tests/adapter/request-client-disconnect.test.ts +2 -2
- package/plugins/acryl-node-server/tests/adapter/serve-static.test.ts +20 -20
- package/plugins/acryl-node-server/tests/adapter/server-socket.test.ts +2 -2
- package/plugins/acryl-node-server/tests/adapter/server.test.ts +50 -50
- package/plugins/acryl-node-server/tests/adapter/utils/response.test.ts +4 -4
- package/plugins/acryl-node-server/tests/adapter/websocket.test.ts +9 -9
- package/plugins/acryl-node-server/tests/server.spec.ts +6 -6
- package/plugins/acryl-node-server/upstream.json +2 -2
- package/plugins/acryl-router/src/client.ts +1 -1
- package/plugins/acryl-router/src/connection.ts +2 -2
- package/plugins/acryl-router/src/core/app-base.ts +29 -29
- package/plugins/acryl-router/src/core/app.test.ts +175 -175
- package/plugins/acryl-router/src/core/app.ts +8 -8
- package/plugins/acryl-router/src/core/client/client.test.ts +76 -76
- package/plugins/acryl-router/src/core/client/client.ts +2 -2
- package/plugins/acryl-router/src/core/client/fetch-result-please.ts +1 -1
- package/plugins/acryl-router/src/core/client/index.ts +1 -1
- package/plugins/acryl-router/src/core/client/types.test.ts +6 -6
- package/plugins/acryl-router/src/core/client/types.ts +16 -16
- package/plugins/acryl-router/src/core/client/utils.test.ts +2 -2
- package/plugins/acryl-router/src/core/context.test.ts +4 -4
- package/plugins/acryl-router/src/core/context.ts +6 -6
- package/plugins/acryl-router/src/core/helper/accepts/accepts.test.ts +3 -3
- package/plugins/acryl-router/src/core/helper/accepts/index.ts +1 -1
- package/plugins/acryl-router/src/core/helper/adapter/index.test.ts +6 -6
- package/plugins/acryl-router/src/core/helper/adapter/index.ts +1 -1
- package/plugins/acryl-router/src/core/helper/conninfo/index.ts +1 -1
- package/plugins/acryl-router/src/core/helper/cookie/index.test.ts +8 -8
- package/plugins/acryl-router/src/core/helper/cookie/index.ts +1 -1
- package/plugins/acryl-router/src/core/helper/factory/index.test.ts +9 -9
- package/plugins/acryl-router/src/core/helper/factory/index.ts +10 -10
- package/plugins/acryl-router/src/core/helper/html/index.test.ts +4 -4
- package/plugins/acryl-router/src/core/helper/html/index.ts +1 -1
- package/plugins/acryl-router/src/core/helper/route/index.test.ts +7 -7
- package/plugins/acryl-router/src/core/helper/route/index.ts +8 -8
- package/plugins/acryl-router/src/core/helper/streaming/index.ts +1 -1
- package/plugins/acryl-router/src/core/helper/testing/index.test.ts +6 -6
- package/plugins/acryl-router/src/core/helper/testing/index.ts +4 -4
- package/plugins/acryl-router/src/core/helper/websocket/index.ts +2 -1
- package/plugins/acryl-router/src/core/http-exception.ts +1 -1
- package/plugins/acryl-router/src/core/index.ts +9 -9
- package/plugins/acryl-router/src/core/middleware/basic-auth/index.test.ts +6 -6
- package/plugins/acryl-router/src/core/middleware/basic-auth/index.ts +3 -3
- package/plugins/acryl-router/src/core/middleware/bearer-auth/index.test.ts +5 -5
- package/plugins/acryl-router/src/core/middleware/bearer-auth/index.ts +3 -3
- package/plugins/acryl-router/src/core/middleware/body-limit/index.test.ts +6 -6
- package/plugins/acryl-router/src/core/middleware/body-limit/index.ts +3 -3
- package/plugins/acryl-router/src/core/middleware/combine/index.test.ts +9 -9
- package/plugins/acryl-router/src/core/middleware/combine/index.ts +7 -7
- package/plugins/acryl-router/src/core/middleware/compress/index.test.ts +9 -9
- package/plugins/acryl-router/src/core/middleware/compress/index.ts +3 -3
- package/plugins/acryl-router/src/core/middleware/context-storage/index.test.ts +5 -5
- package/plugins/acryl-router/src/core/middleware/context-storage/index.ts +4 -4
- package/plugins/acryl-router/src/core/middleware/cors/index.test.ts +7 -7
- package/plugins/acryl-router/src/core/middleware/cors/index.ts +3 -3
- package/plugins/acryl-router/src/core/middleware/csrf/index.test.ts +10 -10
- package/plugins/acryl-router/src/core/middleware/csrf/index.ts +3 -3
- package/plugins/acryl-router/src/core/middleware/etag/index.test.ts +42 -42
- package/plugins/acryl-router/src/core/middleware/etag/index.ts +4 -4
- package/plugins/acryl-router/src/core/middleware/ip-restriction/index.test.ts +4 -4
- package/plugins/acryl-router/src/core/middleware/ip-restriction/index.ts +6 -6
- package/plugins/acryl-router/src/core/middleware/jwk/index.test.ts +16 -16
- package/plugins/acryl-router/src/core/middleware/jwk/jwk.ts +7 -6
- package/plugins/acryl-router/src/core/middleware/jwt/index.test.ts +16 -16
- package/plugins/acryl-router/src/core/middleware/jwt/jwt.ts +4 -3
- package/plugins/acryl-router/src/core/middleware/language/index.test.ts +3 -3
- package/plugins/acryl-router/src/core/middleware/language/language.ts +3 -3
- package/plugins/acryl-router/src/core/middleware/logger/index.test.ts +5 -5
- package/plugins/acryl-router/src/core/middleware/logger/index.ts +4 -4
- package/plugins/acryl-router/src/core/middleware/method-not-allowed/index.test.ts +24 -24
- package/plugins/acryl-router/src/core/middleware/method-not-allowed/index.ts +8 -8
- package/plugins/acryl-router/src/core/middleware/method-override/index.test.ts +5 -5
- package/plugins/acryl-router/src/core/middleware/method-override/index.ts +6 -6
- package/plugins/acryl-router/src/core/middleware/powered-by/index.test.ts +4 -4
- package/plugins/acryl-router/src/core/middleware/powered-by/index.ts +6 -6
- package/plugins/acryl-router/src/core/middleware/pretty-json/index.test.ts +30 -30
- package/plugins/acryl-router/src/core/middleware/pretty-json/index.ts +4 -4
- package/plugins/acryl-router/src/core/middleware/request-id/index.test.ts +15 -15
- package/plugins/acryl-router/src/core/middleware/request-id/request-id.ts +3 -3
- package/plugins/acryl-router/src/core/middleware/secure-headers/index.test.ts +35 -35
- package/plugins/acryl-router/src/core/middleware/secure-headers/secure-headers.ts +3 -3
- package/plugins/acryl-router/src/core/middleware/serve-static/index.test.ts +23 -23
- package/plugins/acryl-router/src/core/middleware/serve-static/index.ts +1 -1
- package/plugins/acryl-router/src/core/middleware/timeout/index.test.ts +2 -2
- package/plugins/acryl-router/src/core/middleware/timeout/index.ts +3 -3
- package/plugins/acryl-router/src/core/middleware/timing/index.test.ts +14 -14
- package/plugins/acryl-router/src/core/middleware/timing/timing.ts +3 -3
- package/plugins/acryl-router/src/core/middleware/trailing-slash/index.test.ts +7 -7
- package/plugins/acryl-router/src/core/middleware/trailing-slash/index.ts +7 -7
- package/plugins/acryl-router/src/core/request.test.ts +42 -42
- package/plugins/acryl-router/src/core/request.ts +6 -6
- package/plugins/acryl-router/src/core/router/linear-router/index.ts +1 -1
- package/plugins/acryl-router/src/core/router/pattern-router/index.ts +1 -1
- package/plugins/acryl-router/src/core/router/reg-exp-router/index.ts +1 -1
- package/plugins/acryl-router/src/core/router/smart-router/index.ts +1 -1
- package/plugins/acryl-router/src/core/router/trie-router/index.ts +1 -1
- package/plugins/acryl-router/src/core/types.test.ts +115 -115
- package/plugins/acryl-router/src/core/types.ts +72 -72
- package/plugins/acryl-router/src/core/utils/body.ts +8 -8
- package/plugins/acryl-router/src/core/utils/html.ts +1 -1
- package/plugins/acryl-router/src/core/utils/jwt/jws.ts +3 -3
- package/plugins/acryl-router/src/core/utils/jwt/jwt.test.ts +2 -2
- package/plugins/acryl-router/src/core/utils/jwt/jwt.ts +3 -3
- package/plugins/acryl-router/src/core/utils/jwt/types.ts +1 -1
- package/plugins/acryl-router/src/core/utils/types.ts +42 -0
- package/plugins/acryl-router/src/core/utils/url.test.ts +2 -2
- package/plugins/acryl-router/src/core/validator/index.ts +1 -1
- package/plugins/acryl-router/src/core/validator/validator.test.ts +28 -28
- package/plugins/acryl-router/src/deprecated.ts +15 -0
- package/plugins/acryl-router/src/index.ts +3 -2
- package/plugins/acryl-router/src/middleware/index.ts +1 -1
- package/plugins/acryl-router/src/middleware/loopback-only.ts +34 -1
- package/plugins/acryl-router/src/service.ts +19 -13
- package/plugins/acryl-router/tests/docs-examples.spec.ts +11 -11
- package/plugins/acryl-router/tests/live-install.spec.ts +2 -2
- package/plugins/acryl-router/tests/loader.spec.ts +3 -3
- package/plugins/acryl-router/tests/loopback-only.spec.ts +80 -0
- package/plugins/acryl-router/tests/no-dom/consumer.ts +11 -0
- package/plugins/acryl-router/tests/no-dom/tsconfig.json +13 -0
- package/plugins/acryl-router/tests/service.spec.ts +39 -22
- package/plugins/acryl-router/upstream.json +3 -3
- package/plugins/acryl-router-http/tests/adapter.spec.ts +3 -3
- package/plugins/acryl-router-http/tests/surfaces.spec.ts +2 -2
- package/plugins/acryl-router-http/upstream.json +2 -2
- package/plugins/acryl-state/src/service.ts +2 -2
- package/plugins/acryl-state/upstream.json +2 -2
- package/plugins/builder/script.ts +3 -3
- package/plugins/extensions/index.ts +4 -3
- package/plugins/extensions/resolve.ts +70 -10
- package/plugins/openai/prompt.ts +7 -7
- package/shared/AGENTS.core.md +61 -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 +2 -2
- package/templates/agent/test/model.test.ts +2 -2
- package/templates/agent/tsconfig.json +40 -0
- package/templates/blank/AGENTS.md +5 -0
- package/templates/blank/README.md +1 -1
- package/templates/blank/src/routes.ts +2 -2
- package/templates/todo/AGENTS.md +5 -0
- package/templates/todo/src/todo.ts +6 -4
- package/templates/todo/upstream.json +2 -2
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { $ as Acryl, J as Schema, K as ResponseFormat, N as KnownResponseFormat, g as Endpoint, x as ExtractSchema } from "./context-Bm7rI-oK.js";
|
|
2
|
+
import { i as METHOD_NAME_ALL_LOWERCASE, n as METHODS } from "./router-CvUxUTOq.js";
|
|
3
|
+
import { c as StatusCode, l as SuccessStatusCode } from "./http-status-DaAwGAFL.js";
|
|
4
|
+
import { s as HasRequiredKeys } from "./types-CwrQjlaM.js";
|
|
5
|
+
import { t as Acryl$1 } from "./app-CmAYW1Al.js";
|
|
6
|
+
|
|
7
|
+
//#region ../../plugins/acryl-router/src/core/client/types.d.ts
|
|
8
|
+
/**
|
|
9
|
+
* Type representing the '$all' method name
|
|
10
|
+
*/
|
|
11
|
+
type MethodNameAll = `$${typeof METHOD_NAME_ALL_LOWERCASE}`;
|
|
12
|
+
/**
|
|
13
|
+
* Type representing all standard HTTP methods prefixed with '$'
|
|
14
|
+
* e.g., '$get' | '$post' | '$put' | '$delete' | '$options' | '$patch' | '$query'
|
|
15
|
+
*/
|
|
16
|
+
type StandardMethods = `$${(typeof METHODS)[number]}`;
|
|
17
|
+
/**
|
|
18
|
+
* Expands '$all' into all standard HTTP methods.
|
|
19
|
+
* If the schema contains '$all', it creates a type where all standard HTTP methods
|
|
20
|
+
* point to the same endpoint definition as '$all', while removing '$all' itself.
|
|
21
|
+
*/
|
|
22
|
+
type ExpandAllMethod<S> = MethodNameAll extends keyof S ? { [M in StandardMethods]: S[MethodNameAll] } & Omit<S, MethodNameAll> : S;
|
|
23
|
+
type AcrylRequest = (typeof Acryl$1.prototype)['request'];
|
|
24
|
+
type BuildSearchParamsFn = (query: Record<string, string | string[]>) => URLSearchParams;
|
|
25
|
+
type ClientRequestOptions<T = unknown> = {
|
|
26
|
+
fetch?: typeof fetch | AcrylRequest;
|
|
27
|
+
webSocket?: (...args: ConstructorParameters<typeof WebSocket>) => WebSocket;
|
|
28
|
+
/**
|
|
29
|
+
* Standard `RequestInit`, caution that this take highest priority
|
|
30
|
+
* and could be used to overwrite things that Acryl sets for you, like `body | method | headers`.
|
|
31
|
+
*
|
|
32
|
+
* If you want to add some headers, use in `headers` instead of `init`
|
|
33
|
+
*/
|
|
34
|
+
init?: RequestInit;
|
|
35
|
+
/**
|
|
36
|
+
* Custom function to serialize query parameters into URLSearchParams.
|
|
37
|
+
* By default, arrays are serialized as multiple parameters with the same key (e.g., `key=a&key=b`).
|
|
38
|
+
* You can provide a custom function to change this behavior, for example to use bracket notation (e.g., `key[]=a&key[]=b`).
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* const client = hc('http://localhost', {
|
|
43
|
+
* buildSearchParams: (query) => {
|
|
44
|
+
* return new URLSearchParams(qs.stringify(query))
|
|
45
|
+
* }
|
|
46
|
+
* })
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
buildSearchParams?: BuildSearchParamsFn;
|
|
50
|
+
} & (keyof T extends never ? {
|
|
51
|
+
headers?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>);
|
|
52
|
+
} : {
|
|
53
|
+
headers: T | (() => T | Promise<T>);
|
|
54
|
+
});
|
|
55
|
+
type ClientRequest<Prefix extends string, Path extends string, S extends Schema> = { [M in keyof ExpandAllMethod<S>]: ExpandAllMethod<S>[M] extends Endpoint & {
|
|
56
|
+
input: infer R;
|
|
57
|
+
} ? R extends object ? HasRequiredKeys<R> extends true ? (args: R, options?: ClientRequestOptions) => Promise<ClientResponseOfEndpoint<ExpandAllMethod<S>[M]>> : (args?: R, options?: ClientRequestOptions) => Promise<ClientResponseOfEndpoint<ExpandAllMethod<S>[M]>> : never : never } & {
|
|
58
|
+
$url: <const Arg extends (S[keyof S] extends {
|
|
59
|
+
input: infer R;
|
|
60
|
+
} ? R extends {
|
|
61
|
+
param: infer P;
|
|
62
|
+
} ? R extends {
|
|
63
|
+
query: infer Q;
|
|
64
|
+
} ? {
|
|
65
|
+
param: P;
|
|
66
|
+
query: Q;
|
|
67
|
+
} : {
|
|
68
|
+
param: P;
|
|
69
|
+
} : R extends {
|
|
70
|
+
query: infer Q;
|
|
71
|
+
} ? {
|
|
72
|
+
query: Q;
|
|
73
|
+
} : {} : {}) | undefined = undefined>(arg?: Arg) => AcrylURL<Prefix, Path, Arg>;
|
|
74
|
+
$path: <const Arg extends (S[keyof S] extends {
|
|
75
|
+
input: infer R;
|
|
76
|
+
} ? R extends {
|
|
77
|
+
param: infer P;
|
|
78
|
+
} ? R extends {
|
|
79
|
+
query: infer Q;
|
|
80
|
+
} ? {
|
|
81
|
+
param: P;
|
|
82
|
+
query: Q;
|
|
83
|
+
} : {
|
|
84
|
+
param: P;
|
|
85
|
+
} : R extends {
|
|
86
|
+
query: infer Q;
|
|
87
|
+
} ? {
|
|
88
|
+
query: Q;
|
|
89
|
+
} : {} : {}) | undefined = undefined>(arg?: Arg) => BuildPath<Path, Arg>;
|
|
90
|
+
} & (S['$get'] extends {
|
|
91
|
+
outputFormat: 'ws';
|
|
92
|
+
} ? S['$get'] extends {
|
|
93
|
+
input: infer I;
|
|
94
|
+
} ? {
|
|
95
|
+
$ws: (args?: I) => WebSocket;
|
|
96
|
+
} : {} : {});
|
|
97
|
+
type ClientResponseOfEndpoint<T extends Endpoint = Endpoint> = T extends {
|
|
98
|
+
output: infer O;
|
|
99
|
+
outputFormat: infer F;
|
|
100
|
+
status: infer S;
|
|
101
|
+
} ? ClientResponse<O, S extends number ? S : never, F extends ResponseFormat ? F : never> : never;
|
|
102
|
+
interface ClientResponse<T, U extends number = StatusCode, F extends ResponseFormat = ResponseFormat> {
|
|
103
|
+
readonly body: ReadableStream | null;
|
|
104
|
+
readonly bodyUsed: boolean;
|
|
105
|
+
ok: U extends SuccessStatusCode ? true : U extends Exclude<StatusCode, SuccessStatusCode> ? false : boolean;
|
|
106
|
+
redirected: boolean;
|
|
107
|
+
status: U;
|
|
108
|
+
statusText: string;
|
|
109
|
+
type: 'basic' | 'cors' | 'default' | 'error' | 'opaque' | 'opaqueredirect';
|
|
110
|
+
headers: Headers;
|
|
111
|
+
url: string;
|
|
112
|
+
redirect(url: string, status: number): Response;
|
|
113
|
+
clone(): Response;
|
|
114
|
+
bytes(): Promise<Uint8Array<ArrayBuffer>>;
|
|
115
|
+
json(): F extends 'text' ? Promise<never> : F extends 'json' ? Promise<T> : Promise<unknown>;
|
|
116
|
+
text(): F extends 'text' ? (T extends string ? Promise<T> : Promise<never>) : Promise<string>;
|
|
117
|
+
blob(): Promise<Blob>;
|
|
118
|
+
formData(): Promise<FormData>;
|
|
119
|
+
arrayBuffer(): Promise<ArrayBuffer>;
|
|
120
|
+
}
|
|
121
|
+
type BuildSearch<Arg, Key extends 'query'> = Arg extends { [K in Key]: infer Query } ? IsEmptyObject<Query> extends true ? '' : `?${string}` : '';
|
|
122
|
+
type BuildPathname<P extends string, Arg> = Arg extends {
|
|
123
|
+
param: infer Param;
|
|
124
|
+
} ? `${ApplyParam<TrimStartSlash<P>, Param>}` : `/${TrimStartSlash<P>}`;
|
|
125
|
+
type BuildPath<P extends string, Arg> = `${BuildPathname<P, Arg>}${BuildSearch<Arg, 'query'>}`;
|
|
126
|
+
type BuildTypedURL<Protocol extends string, Host extends string, Port extends string, P extends string, Arg> = TypedURL<`${Protocol}:`, Host, Port, BuildPathname<P, Arg>, BuildSearch<Arg, 'query'>>;
|
|
127
|
+
type AcrylURL<Prefix extends string, Path extends string, Arg> = IsLiteral<Prefix> extends true ? TrimEndSlash<Prefix> extends `${infer Protocol}://${infer Rest}` ? Rest extends `${infer Hostname}/${infer P}` ? ParseHostName<Hostname> extends [infer Host extends string, infer Port extends string] ? BuildTypedURL<Protocol, Host, Port, P, Arg> : never : ParseHostName<Rest> extends [infer Host extends string, infer Port extends string] ? BuildTypedURL<Protocol, Host, Port, Path, Arg> : never : URL : URL;
|
|
128
|
+
type ParseHostName<T extends string> = T extends `${infer Host}:${infer Port}` ? [Host, Port] : [T, ''];
|
|
129
|
+
type TrimStartSlash<T extends string> = T extends `/${infer R}` ? TrimStartSlash<R> : T;
|
|
130
|
+
type TrimEndSlash<T extends string> = T extends `${infer R}/` ? TrimEndSlash<R> : T;
|
|
131
|
+
type IsLiteral<T extends string> = [T] extends [never] ? false : string extends T ? false : true;
|
|
132
|
+
type ApplyParam<Path extends string, P, Result extends string = ''> = Path extends `${infer Head}/${infer Rest}` ? Head extends `:${infer Param}` ? P extends Record<Param, infer Value extends string> ? IsLiteral<Value> extends true ? ApplyParam<Rest, P, `${Result}/${Value & string}`> : ApplyParam<Rest, P, `${Result}/${Head}`> : ApplyParam<Rest, P, `${Result}/${Head}`> : ApplyParam<Rest, P, `${Result}/${Head}`> : Path extends `:${infer Param}` ? P extends Record<Param, infer Value extends string> ? IsLiteral<Value> extends true ? `${Result}/${Value & string}` : `${Result}/${Path}` : `${Result}/${Path}` : `${Result}/${Path}`;
|
|
133
|
+
type IsEmptyObject<T> = keyof T extends never ? true : false;
|
|
134
|
+
interface TypedURL<Protocol extends string, Hostname extends string, Port extends string, Pathname extends string, Search extends string> extends URL {
|
|
135
|
+
protocol: Protocol;
|
|
136
|
+
hostname: Hostname;
|
|
137
|
+
port: Port;
|
|
138
|
+
host: Port extends '' ? Hostname : `${Hostname}:${Port}`;
|
|
139
|
+
origin: `${Protocol}//${Hostname}${Port extends '' ? '' : `:${Port}`}`;
|
|
140
|
+
pathname: Pathname;
|
|
141
|
+
search: Search;
|
|
142
|
+
href: `${Protocol}//${Hostname}${Port extends '' ? '' : `:${Port}`}${Pathname}${Search}`;
|
|
143
|
+
}
|
|
144
|
+
interface Response extends ClientResponse<unknown> {}
|
|
145
|
+
type Fetch<T> = (args?: InferRequestType<T>, opt?: ClientRequestOptions) => Promise<ClientResponseOfEndpoint<InferEndpointType<T>>>;
|
|
146
|
+
type InferEndpointType<T> = T extends ((args: infer R, options: any | undefined) => Promise<infer U>) ? U extends ClientResponse<infer O, infer S, infer F> ? {
|
|
147
|
+
input: NonNullable<R>;
|
|
148
|
+
output: O;
|
|
149
|
+
outputFormat: F;
|
|
150
|
+
status: S;
|
|
151
|
+
} extends Endpoint ? {
|
|
152
|
+
input: NonNullable<R>;
|
|
153
|
+
output: O;
|
|
154
|
+
outputFormat: F;
|
|
155
|
+
status: S;
|
|
156
|
+
} : never : never : never;
|
|
157
|
+
type InferResponseType<T, U extends StatusCode = StatusCode> = InferResponseTypeFromEndpoint<InferEndpointType<T>, U>;
|
|
158
|
+
type InferResponseTypeFromEndpoint<T extends Endpoint, U extends StatusCode> = T extends {
|
|
159
|
+
output: infer O;
|
|
160
|
+
status: infer S;
|
|
161
|
+
} ? S extends U ? O : never : never;
|
|
162
|
+
type InferRequestType<T> = T extends ((args: infer R, options: any | undefined) => Promise<ClientResponse<unknown>>) ? NonNullable<R> : never;
|
|
163
|
+
/**
|
|
164
|
+
* Filter a ClientResponse type so it only includes responses of specific status codes.
|
|
165
|
+
*/
|
|
166
|
+
type FilterClientResponseByStatusCode<T extends ClientResponse<any, any, any>, U extends number = StatusCode> = T extends ClientResponse<infer RT, infer RC, infer RF> ? RC extends U ? ClientResponse<RT, RC, RF> : never : never;
|
|
167
|
+
type PathToChain<Prefix extends string, Path extends string, E extends Schema, Original extends string = Path> = Path extends `/${infer P}` ? PathToChain<Prefix, P, E, Path> : Path extends `${infer P}/${infer R}` ? { [K in P]: PathToChain<Prefix, R, E, Original> } : { [K in Path extends '' ? 'index' : Path]: ClientRequest<Prefix, Original, E extends Record<string, unknown> ? E[Original] : never> };
|
|
168
|
+
type Client<T, Prefix extends string> = T extends Acryl<any, infer S, any> ? S extends Record<infer K, Schema> ? K extends string ? PathToChain<Prefix, K, S> : never : never : never;
|
|
169
|
+
type GlobalResponseDefinition = { [S in StatusCode]?: { [F in KnownResponseFormat]?: unknown } };
|
|
170
|
+
type ToEndpoints<Def extends GlobalResponseDefinition, R> = { [S in keyof Def & StatusCode]: { [F in keyof Def[S] & KnownResponseFormat]: Omit<R, 'output' | 'status' | 'outputFormat'> & {
|
|
171
|
+
output: Def[S][F];
|
|
172
|
+
status: S;
|
|
173
|
+
outputFormat: F;
|
|
174
|
+
} }[keyof Def[S] & KnownResponseFormat] }[keyof Def & StatusCode];
|
|
175
|
+
type ModRoute<R, Def extends GlobalResponseDefinition> = R extends Endpoint ? R | ToEndpoints<Def, R> : R;
|
|
176
|
+
type ModSchema<D, Def extends GlobalResponseDefinition> = { [K in keyof D]: { [M in keyof D[K]]: ModRoute<D[K][M], Def> } };
|
|
177
|
+
type ApplyGlobalResponse<App, Def extends GlobalResponseDefinition> = App extends Acryl<infer E, infer _ extends Schema, infer B> ? ModSchema<ExtractSchema<App>, Def> extends infer S extends Schema ? Acryl$1<E, S, B> : never : never;
|
|
178
|
+
type PickRoute<R, U extends StatusCode> = R extends Endpoint ? R extends {
|
|
179
|
+
status: U;
|
|
180
|
+
} ? R : never : R;
|
|
181
|
+
type PickSchema<D, U extends StatusCode> = { [K in keyof D]: { [M in keyof D[K]]: PickRoute<D[K][M], U> } };
|
|
182
|
+
/**
|
|
183
|
+
* Keep only specific status code responses from all routes of an app.
|
|
184
|
+
* Useful when error responses are handled centrally (e.g., via custom fetch)
|
|
185
|
+
* and you want the client to only expose success response types.
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* ```ts
|
|
189
|
+
* type AppSuccessOnly = PickResponseByStatusCode<typeof app, 200>
|
|
190
|
+
* const client = hc<AppSuccessOnly>('http://localhost')
|
|
191
|
+
* ```
|
|
192
|
+
*/
|
|
193
|
+
type PickResponseByStatusCode<App, U extends StatusCode> = App extends Acryl<infer E, infer _ extends Schema, infer B> ? PickSchema<ExtractSchema<App>, U> extends infer S extends Schema ? Acryl$1<E, S, B> : never : never;
|
|
194
|
+
//#endregion
|
|
195
|
+
export { ClientResponse as a, InferRequestType as c, ClientRequestOptions as i, InferResponseType as l, Client as n, Fetch as o, ClientRequest as r, FilterClientResponseByStatusCode as s, ApplyGlobalResponse as t, PickResponseByStatusCode as u };
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
//#region ../../plugins/acryl-router/src/core/utils/types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* @module
|
|
4
|
+
* Types utility.
|
|
5
|
+
*/
|
|
6
|
+
type Expect<T extends true> = T;
|
|
7
|
+
type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends (<T>() => T extends Y ? 1 : 2) ? true : false;
|
|
8
|
+
type NotEqual<X, Y> = true extends Equal<X, Y> ? false : true;
|
|
9
|
+
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
|
|
10
|
+
type RemoveBlankRecord<T> = T extends Record<infer K, unknown> ? (K extends string ? T : never) : never;
|
|
11
|
+
type IfAnyThenEmptyObject<T> = 0 extends 1 & T ? {} : T;
|
|
12
|
+
type JSONPrimitive = string | boolean | number | null;
|
|
13
|
+
type JSONArray = (JSONPrimitive | JSONObject | JSONArray)[];
|
|
14
|
+
type JSONObject = {
|
|
15
|
+
[key: string]: JSONPrimitive | JSONArray | JSONObject | object | InvalidJSONValue;
|
|
16
|
+
};
|
|
17
|
+
type InvalidJSONValue = undefined | symbol | ((...args: unknown[]) => unknown);
|
|
18
|
+
type InvalidToNull<T> = T extends InvalidJSONValue ? null : T;
|
|
19
|
+
type IsInvalid<T> = T extends InvalidJSONValue ? true : false;
|
|
20
|
+
/**
|
|
21
|
+
* symbol keys are omitted through `JSON.stringify`
|
|
22
|
+
*/
|
|
23
|
+
type OmitSymbolKeys<T> = { [K in keyof T as K extends symbol ? never : K]: T[K] };
|
|
24
|
+
type JSONValue = JSONObject | JSONArray | JSONPrimitive;
|
|
25
|
+
/**
|
|
26
|
+
* Convert a type to a JSON-compatible type.
|
|
27
|
+
*
|
|
28
|
+
* Non-JSON values such as `Date` implement `.toJSON()`,
|
|
29
|
+
* so they can be transformed to a value assignable to `JSONObject`
|
|
30
|
+
*
|
|
31
|
+
* `JSON.stringify()` throws a `TypeError` when it encounters a `bigint` value,
|
|
32
|
+
* unless a custom `replacer` function or `.toJSON()` method is provided.
|
|
33
|
+
*
|
|
34
|
+
* This behavior can be controlled by the `TError` generic type parameter,
|
|
35
|
+
* which defaults to `bigint | ReadonlyArray<bigint>`.
|
|
36
|
+
* You can set it to `never` to disable this check.
|
|
37
|
+
*/
|
|
38
|
+
type JSONParsed<T, TError = bigint | ReadonlyArray<bigint>> = T extends {
|
|
39
|
+
toJSON(): infer J;
|
|
40
|
+
} ? (() => J) extends (() => JSONPrimitive) ? J : (() => J) extends (() => {
|
|
41
|
+
toJSON(): unknown;
|
|
42
|
+
}) ? {} : JSONParsed<J, TError> : T extends JSONPrimitive ? T : T extends InvalidJSONValue ? never : T extends ReadonlyArray<unknown> ? { [K in keyof T]: JSONParsed<InvalidToNull<T[K]>, TError> } extends infer A ? A extends ReadonlyArray<unknown> ? A : JSONParsed<InvalidToNull<T[number]>, TError>[] : never : T extends Set<unknown> | Map<unknown, unknown> | Record<string, never> ? {} : T extends object ? T[keyof T] extends TError ? never : { [K in keyof OmitSymbolKeys<T> as IsInvalid<T[K]> extends true ? never : K]: boolean extends IsInvalid<T[K]> ? JSONParsed<T[K], TError> | undefined : JSONParsed<T[K], TError> } : T extends unknown ? T extends TError ? never : JSONValue : never;
|
|
43
|
+
/**
|
|
44
|
+
* Useful to flatten the type output to improve type hints shown in editors. And also to transform an interface into a type to aide with assignability.
|
|
45
|
+
* @copyright from sindresorhus/type-fest
|
|
46
|
+
*/
|
|
47
|
+
type Simplify<T> = { [KeyType in keyof T]: T[KeyType] } & {};
|
|
48
|
+
/**
|
|
49
|
+
* A simple extension of Simplify that will deeply traverse array elements.
|
|
50
|
+
*/
|
|
51
|
+
type SimplifyDeepArray<T> = T extends any[] ? { [E in keyof T]: SimplifyDeepArray<T[E]> } : Simplify<T>;
|
|
52
|
+
type InterfaceToType<T> = T extends Function ? T : { [K in keyof T]: InterfaceToType<T[K]> };
|
|
53
|
+
type RequiredKeysOf<BaseType extends object> = Exclude<{ [Key in keyof BaseType]: BaseType extends Record<Key, BaseType[Key]> ? Key : never }[keyof BaseType], undefined>;
|
|
54
|
+
type HasRequiredKeys<BaseType extends object> = RequiredKeysOf<BaseType> extends never ? false : true;
|
|
55
|
+
type IsAny<T> = boolean extends (T extends never ? true : false) ? true : false;
|
|
56
|
+
/**
|
|
57
|
+
* String literal types with auto-completion
|
|
58
|
+
* @see https://github.com/Microsoft/TypeScript/issues/29729
|
|
59
|
+
*/
|
|
60
|
+
type StringLiteralUnion<T> = T | (string & Record<never, never>);
|
|
61
|
+
/** Bytes a Web Crypto call accepts; declared here so the public types do not need the DOM library. */
|
|
62
|
+
type BufferSource = ArrayBufferView<ArrayBuffer> | ArrayBuffer;
|
|
63
|
+
/** A Web Crypto key, named from the runtime's own `crypto` so the public types do not need the DOM library. */
|
|
64
|
+
type CryptoKey = Awaited<ReturnType<typeof crypto.subtle.importKey>>;
|
|
65
|
+
/** How a WebSocket hands binary data to `onmessage`; declared here so the public types do not need the DOM library. */
|
|
66
|
+
type BinaryType = 'arraybuffer' | 'blob';
|
|
67
|
+
/** The members of a WebSocket `message` event the helpers hand out (the Web `MessageEvent`, whose Node global is not generic); declared here so the public types do not need the DOM library. */
|
|
68
|
+
interface MessageEvent<T = unknown> extends Event {
|
|
69
|
+
readonly data: T;
|
|
70
|
+
readonly lastEventId: string;
|
|
71
|
+
readonly origin: string;
|
|
72
|
+
}
|
|
73
|
+
/** The members of a WebSocket `close` event the helpers hand out (the Web `CloseEvent`, which Node has no global type for); declared here so the public types do not need the DOM library. */
|
|
74
|
+
interface CloseEvent extends Event {
|
|
75
|
+
readonly code: number;
|
|
76
|
+
readonly reason: string;
|
|
77
|
+
readonly wasClean: boolean;
|
|
78
|
+
}
|
|
79
|
+
/** A JSON Web Key (RFC 7517), the same members as the Web Crypto dictionary; declared here so the public types do not need the DOM library. */
|
|
80
|
+
interface JsonWebKey {
|
|
81
|
+
alg?: string;
|
|
82
|
+
crv?: string;
|
|
83
|
+
d?: string;
|
|
84
|
+
dp?: string;
|
|
85
|
+
dq?: string;
|
|
86
|
+
e?: string;
|
|
87
|
+
ext?: boolean;
|
|
88
|
+
k?: string;
|
|
89
|
+
key_ops?: string[];
|
|
90
|
+
kty?: string;
|
|
91
|
+
n?: string;
|
|
92
|
+
oth?: {
|
|
93
|
+
d?: string;
|
|
94
|
+
r?: string;
|
|
95
|
+
t?: string;
|
|
96
|
+
}[];
|
|
97
|
+
p?: string;
|
|
98
|
+
q?: string;
|
|
99
|
+
qi?: string;
|
|
100
|
+
use?: string;
|
|
101
|
+
x?: string;
|
|
102
|
+
y?: string;
|
|
103
|
+
}
|
|
104
|
+
//#endregion
|
|
105
|
+
export { SimplifyDeepArray as C, Simplify as S, UnionToIntersection as T, JsonWebKey as _, Equal as a, RemoveBlankRecord as b, IfAnyThenEmptyObject as c, IsAny as d, JSONArray as f, JSONValue as g, JSONPrimitive as h, CryptoKey as i, InterfaceToType as l, JSONParsed as m, BufferSource as n, Expect as o, JSONObject as p, CloseEvent as r, HasRequiredKeys as s, BinaryType as t, InvalidJSONValue as u, MessageEvent as v, StringLiteralUnion as w, RequiredKeysOf as x, NotEqual as y };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
//#region ../../plugins/acryl-router/src/core/utils/jwt/types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* JWT Payload
|
|
4
|
+
*/
|
|
5
|
+
type JWTPayload = {
|
|
6
|
+
[key: string]: unknown;
|
|
7
|
+
/**
|
|
8
|
+
* The token is checked to ensure it has not expired.
|
|
9
|
+
*/
|
|
10
|
+
exp?: number;
|
|
11
|
+
/**
|
|
12
|
+
* The token is checked to ensure it is not being used before a specified time.
|
|
13
|
+
*/
|
|
14
|
+
nbf?: number;
|
|
15
|
+
/**
|
|
16
|
+
* The token is checked to ensure it is not issued in the future.
|
|
17
|
+
*/
|
|
18
|
+
iat?: number;
|
|
19
|
+
/**
|
|
20
|
+
* The token is checked to ensure it has been issued by a trusted issuer.
|
|
21
|
+
*/
|
|
22
|
+
iss?: string;
|
|
23
|
+
/**
|
|
24
|
+
* The token is checked to ensure it is intended for a specific audience.
|
|
25
|
+
*/
|
|
26
|
+
aud?: string | string[];
|
|
27
|
+
};
|
|
28
|
+
//#endregion
|
|
29
|
+
export { JWTPayload as t };
|
package/lib/types.d.ts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { A as Input, B as NotFoundResponse, C as FetchEventLike, D as Handler, E as HTTPResponseError, F as MergeSchemaPath, G as RemoveQuestion, H as ParamKeyToRecord, I as MiddlewareHandler, J as Schema, K as ResponseFormat, L as MiddlewareHandlerInterface, M as IntersectNonAnyTypes, N as KnownResponseFormat, O as HandlerInterface, P as MergePath, Q as Variables, R as Next, S as ExtractSchemaForStatusCode, T as H, U as ParamKeys, V as OnHandlerInterface, W as ParsedFormValue, X as TypedResponse, Y as ToSchema, Z as ValidationTargets, _ as Env, b as ExtractInput, d as AddParam, f as Bindings, g as Endpoint, h as BlankSchema, j as InputToDataByTarget, k as HandlerResponse, m as BlankInput, p as BlankEnv, q as RouterRoute, v as ErrorHandler, w as FormValue, x as ExtractSchema, y as ExtractHandlerResponse, z as NotFoundHandler } from "./context-Bm7rI-oK.js";
|
|
2
|
+
export { AddParam, Bindings, BlankEnv, BlankInput, BlankSchema, Endpoint, Env, ErrorHandler, ExtractHandlerResponse, ExtractInput, ExtractSchema, ExtractSchemaForStatusCode, FetchEventLike, FormValue, H, HTTPResponseError, Handler, HandlerInterface, HandlerResponse, Input, InputToDataByTarget, IntersectNonAnyTypes, KnownResponseFormat, MergePath, MergeSchemaPath, MiddlewareHandler, MiddlewareHandlerInterface, Next, NotFoundHandler, NotFoundResponse, OnHandlerInterface, ParamKeyToRecord, ParamKeys, ParsedFormValue, RemoveQuestion, ResponseFormat, RouterRoute, Schema, ToSchema, TypedResponse, ValidationTargets, Variables };
|
package/lib/types.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region ../../plugins/acryl-router/src/core/utils/accept.d.ts
|
|
2
|
+
interface Accept {
|
|
3
|
+
type: string;
|
|
4
|
+
params: Record<string, string>;
|
|
5
|
+
q: number;
|
|
6
|
+
}
|
|
7
|
+
declare const parseAccept: (acceptHeader: string) => Accept[];
|
|
8
|
+
//#endregion
|
|
9
|
+
export { Accept, parseAccept };
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
//#region ../../plugins/acryl-router/src/core/utils/accept.ts
|
|
2
|
+
const isWhitespace = (char) => char === 32 || char === 9 || char === 10 || char === 13;
|
|
3
|
+
const consumeWhitespace = (acceptHeader, startIndex) => {
|
|
4
|
+
while (startIndex < acceptHeader.length) {
|
|
5
|
+
if (!isWhitespace(acceptHeader.charCodeAt(startIndex))) break;
|
|
6
|
+
startIndex++;
|
|
7
|
+
}
|
|
8
|
+
return startIndex;
|
|
9
|
+
};
|
|
10
|
+
const ignoreTrailingWhitespace = (acceptHeader, startIndex) => {
|
|
11
|
+
while (startIndex > 0) {
|
|
12
|
+
if (!isWhitespace(acceptHeader.charCodeAt(startIndex - 1))) break;
|
|
13
|
+
startIndex--;
|
|
14
|
+
}
|
|
15
|
+
return startIndex;
|
|
16
|
+
};
|
|
17
|
+
const skipInvalidParam = (acceptHeader, startIndex) => {
|
|
18
|
+
while (startIndex < acceptHeader.length) {
|
|
19
|
+
const char = acceptHeader.charCodeAt(startIndex);
|
|
20
|
+
if (char === 59) return [startIndex + 1, true];
|
|
21
|
+
if (char === 44) return [startIndex + 1, false];
|
|
22
|
+
startIndex++;
|
|
23
|
+
}
|
|
24
|
+
return [startIndex, false];
|
|
25
|
+
};
|
|
26
|
+
const skipInvalidAcceptValue = (acceptHeader, startIndex) => {
|
|
27
|
+
let i = startIndex;
|
|
28
|
+
let inQuotes = false;
|
|
29
|
+
while (i < acceptHeader.length) {
|
|
30
|
+
const char = acceptHeader.charCodeAt(i);
|
|
31
|
+
if (inQuotes && char === 92) i++;
|
|
32
|
+
else if (char === 34) inQuotes = !inQuotes;
|
|
33
|
+
else if (!inQuotes && char === 44) return i + 1;
|
|
34
|
+
i++;
|
|
35
|
+
}
|
|
36
|
+
return i;
|
|
37
|
+
};
|
|
38
|
+
const getNextParam = (acceptHeader, startIndex) => {
|
|
39
|
+
startIndex = consumeWhitespace(acceptHeader, startIndex);
|
|
40
|
+
let i = startIndex;
|
|
41
|
+
let key;
|
|
42
|
+
let value;
|
|
43
|
+
let hasNext = false;
|
|
44
|
+
while (i < acceptHeader.length) {
|
|
45
|
+
const char = acceptHeader.charCodeAt(i);
|
|
46
|
+
if (char === 61) {
|
|
47
|
+
key = acceptHeader.slice(startIndex, ignoreTrailingWhitespace(acceptHeader, i));
|
|
48
|
+
i++;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
if (char === 59) return [
|
|
52
|
+
i + 1,
|
|
53
|
+
void 0,
|
|
54
|
+
void 0,
|
|
55
|
+
true
|
|
56
|
+
];
|
|
57
|
+
if (char === 44) return [
|
|
58
|
+
i + 1,
|
|
59
|
+
void 0,
|
|
60
|
+
void 0,
|
|
61
|
+
false
|
|
62
|
+
];
|
|
63
|
+
i++;
|
|
64
|
+
}
|
|
65
|
+
if (key === void 0) return [
|
|
66
|
+
i,
|
|
67
|
+
void 0,
|
|
68
|
+
void 0,
|
|
69
|
+
false
|
|
70
|
+
];
|
|
71
|
+
i = consumeWhitespace(acceptHeader, i);
|
|
72
|
+
if (acceptHeader.charCodeAt(i) === 61) {
|
|
73
|
+
const skipResult = skipInvalidParam(acceptHeader, i + 1);
|
|
74
|
+
return [
|
|
75
|
+
skipResult[0],
|
|
76
|
+
key,
|
|
77
|
+
void 0,
|
|
78
|
+
skipResult[1]
|
|
79
|
+
];
|
|
80
|
+
}
|
|
81
|
+
let inQuotes = false;
|
|
82
|
+
const paramStartIndex = i;
|
|
83
|
+
while (i < acceptHeader.length) {
|
|
84
|
+
const char = acceptHeader.charCodeAt(i);
|
|
85
|
+
if (inQuotes && char === 92) i++;
|
|
86
|
+
else if (char === 34) {
|
|
87
|
+
if (inQuotes) {
|
|
88
|
+
let nextIndex = consumeWhitespace(acceptHeader, i + 1);
|
|
89
|
+
const nextChar = acceptHeader.charCodeAt(nextIndex);
|
|
90
|
+
if (nextIndex < acceptHeader.length && !(nextChar === 59 || nextChar === 44)) {
|
|
91
|
+
const skipResult = skipInvalidParam(acceptHeader, nextIndex);
|
|
92
|
+
return [
|
|
93
|
+
skipResult[0],
|
|
94
|
+
key,
|
|
95
|
+
void 0,
|
|
96
|
+
skipResult[1]
|
|
97
|
+
];
|
|
98
|
+
}
|
|
99
|
+
value = acceptHeader.slice(paramStartIndex + 1, i);
|
|
100
|
+
if (value.includes("\\")) value = value.replace(/\\(.)/g, "$1");
|
|
101
|
+
if (nextChar === 44) return [
|
|
102
|
+
nextIndex + 1,
|
|
103
|
+
key,
|
|
104
|
+
value,
|
|
105
|
+
false
|
|
106
|
+
];
|
|
107
|
+
if (nextChar === 59) {
|
|
108
|
+
hasNext = true;
|
|
109
|
+
nextIndex++;
|
|
110
|
+
}
|
|
111
|
+
i = nextIndex;
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
inQuotes = true;
|
|
115
|
+
} else if (!inQuotes && (char === 59 || char === 44)) {
|
|
116
|
+
value = acceptHeader.slice(paramStartIndex, ignoreTrailingWhitespace(acceptHeader, i));
|
|
117
|
+
if (char === 59) hasNext = true;
|
|
118
|
+
i++;
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
i++;
|
|
122
|
+
}
|
|
123
|
+
return [
|
|
124
|
+
i,
|
|
125
|
+
key,
|
|
126
|
+
value ?? acceptHeader.slice(paramStartIndex, ignoreTrailingWhitespace(acceptHeader, i)),
|
|
127
|
+
hasNext
|
|
128
|
+
];
|
|
129
|
+
};
|
|
130
|
+
const getNextAcceptValue = (acceptHeader, startIndex) => {
|
|
131
|
+
const accept = {
|
|
132
|
+
type: "",
|
|
133
|
+
params: Object.create(null),
|
|
134
|
+
q: 1
|
|
135
|
+
};
|
|
136
|
+
startIndex = consumeWhitespace(acceptHeader, startIndex);
|
|
137
|
+
let i = startIndex;
|
|
138
|
+
while (i < acceptHeader.length) {
|
|
139
|
+
const char = acceptHeader.charCodeAt(i);
|
|
140
|
+
if (char === 59 || char === 44) {
|
|
141
|
+
accept.type = acceptHeader.slice(startIndex, ignoreTrailingWhitespace(acceptHeader, i));
|
|
142
|
+
i++;
|
|
143
|
+
if (char === 44) return [i, accept.type ? accept : void 0];
|
|
144
|
+
if (!accept.type) return [skipInvalidAcceptValue(acceptHeader, i), void 0];
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
i++;
|
|
148
|
+
}
|
|
149
|
+
if (!accept.type) {
|
|
150
|
+
accept.type = acceptHeader.slice(startIndex, ignoreTrailingWhitespace(acceptHeader, acceptHeader.length));
|
|
151
|
+
return [acceptHeader.length, accept.type ? accept : void 0];
|
|
152
|
+
}
|
|
153
|
+
let param;
|
|
154
|
+
let value;
|
|
155
|
+
let hasNext;
|
|
156
|
+
while (i < acceptHeader.length) {
|
|
157
|
+
[i, param, value, hasNext] = getNextParam(acceptHeader, i);
|
|
158
|
+
if (param && value) accept.params[param] = value;
|
|
159
|
+
if (!hasNext) break;
|
|
160
|
+
}
|
|
161
|
+
return [i, accept];
|
|
162
|
+
};
|
|
163
|
+
const parseAccept = (acceptHeader) => {
|
|
164
|
+
if (!acceptHeader) return [];
|
|
165
|
+
const values = [];
|
|
166
|
+
let i = 0;
|
|
167
|
+
let accept;
|
|
168
|
+
let requiresSort = false;
|
|
169
|
+
let lastAccept;
|
|
170
|
+
while (i < acceptHeader.length) {
|
|
171
|
+
[i, accept] = getNextAcceptValue(acceptHeader, i);
|
|
172
|
+
if (accept) {
|
|
173
|
+
accept.q = parseQuality(accept.params.q ?? accept.params.Q);
|
|
174
|
+
values.push(accept);
|
|
175
|
+
if (lastAccept && lastAccept.q < accept.q) requiresSort = true;
|
|
176
|
+
lastAccept = accept;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (requiresSort) values.sort((a, b) => b.q - a.q);
|
|
180
|
+
return values;
|
|
181
|
+
};
|
|
182
|
+
const parseQuality = (qVal) => {
|
|
183
|
+
if (qVal === void 0) return 1;
|
|
184
|
+
if (qVal === "") return 1;
|
|
185
|
+
if (qVal === "NaN") return 0;
|
|
186
|
+
const num = Number(qVal);
|
|
187
|
+
if (Number.isNaN(num)) return 1;
|
|
188
|
+
if (num < 0) return 0;
|
|
189
|
+
if (num > 1) return 1;
|
|
190
|
+
return num;
|
|
191
|
+
};
|
|
192
|
+
//#endregion
|
|
193
|
+
export { parseAccept };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { decodeBase64 } from "./encode.js";
|
|
2
|
+
//#region ../../plugins/acryl-router/src/core/utils/basic-auth.ts
|
|
3
|
+
const CREDENTIALS_REGEXP = /^ *(?:[Bb][Aa][Ss][Ii][Cc]) +([A-Za-z0-9._~+/-]+=*) *$/;
|
|
4
|
+
const USER_PASS_REGEXP = /^([^:]*):(.*)$/;
|
|
5
|
+
const utf8Decoder = new TextDecoder();
|
|
6
|
+
const auth = (req) => {
|
|
7
|
+
const match = CREDENTIALS_REGEXP.exec(req.headers.get("Authorization") || "");
|
|
8
|
+
if (!match) return;
|
|
9
|
+
let userPass = void 0;
|
|
10
|
+
try {
|
|
11
|
+
userPass = USER_PASS_REGEXP.exec(utf8Decoder.decode(decodeBase64(match[1])));
|
|
12
|
+
} catch {}
|
|
13
|
+
if (!userPass) return;
|
|
14
|
+
return {
|
|
15
|
+
username: userPass[1],
|
|
16
|
+
password: userPass[2]
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
//#endregion
|
|
20
|
+
export { auth };
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { bufferToFormData } from "./buffer.js";
|
|
2
|
+
//#region ../../plugins/acryl-router/src/core/utils/body.ts
|
|
3
|
+
const MAX_NESTED_OBJECTS = 1e4;
|
|
4
|
+
const isRawRequest = (request) => "headers" in request;
|
|
5
|
+
const parseBody = async (request, options = Object.create(null)) => {
|
|
6
|
+
const { all = false, dot = false } = options;
|
|
7
|
+
const mediaType = (isRawRequest(request) ? request.headers : request.raw.headers).get("Content-Type")?.split(";")[0].trim().toLowerCase();
|
|
8
|
+
if (mediaType === "multipart/form-data" || mediaType === "application/x-www-form-urlencoded") return parseFormData(request, {
|
|
9
|
+
all,
|
|
10
|
+
dot
|
|
11
|
+
});
|
|
12
|
+
return {};
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Parses form data from a request.
|
|
16
|
+
*
|
|
17
|
+
* @template T - The type of the parsed body data.
|
|
18
|
+
* @param {AcrylRequest | Request} request - The request object containing form data.
|
|
19
|
+
* @param {ParseBodyOptions} options - Options for parsing the form data.
|
|
20
|
+
* @returns {Promise<T>} The parsed body data.
|
|
21
|
+
*/
|
|
22
|
+
async function parseFormData(request, options) {
|
|
23
|
+
if (!isRawRequest(request) && request.bodyCache.formData) return convertFormDataToBodyData(await request.bodyCache.formData, options);
|
|
24
|
+
const headers = isRawRequest(request) ? request.headers : request.raw.headers;
|
|
25
|
+
const formDataPromise = bufferToFormData(await request.arrayBuffer(), headers.get("Content-Type") || "");
|
|
26
|
+
if (!isRawRequest(request)) request.bodyCache.formData = formDataPromise;
|
|
27
|
+
const formData = await formDataPromise;
|
|
28
|
+
if (formData) return convertFormDataToBodyData(formData, options);
|
|
29
|
+
return {};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Converts form data to body data based on the provided options.
|
|
33
|
+
*
|
|
34
|
+
* @template T - The type of the parsed body data.
|
|
35
|
+
* @param {FormData} formData - The form data to convert.
|
|
36
|
+
* @param {ParseBodyOptions} options - Options for parsing the form data.
|
|
37
|
+
* @returns {T} The converted body data.
|
|
38
|
+
*/
|
|
39
|
+
function convertFormDataToBodyData(formData, options) {
|
|
40
|
+
const form = Object.create(null);
|
|
41
|
+
const nestingState = { count: 0 };
|
|
42
|
+
formData.forEach((value, key) => {
|
|
43
|
+
if (!(options.all || key.endsWith("[]"))) form[key] = value;
|
|
44
|
+
else handleParsingAllValues(form, key, value);
|
|
45
|
+
});
|
|
46
|
+
if (options.dot) Object.entries(form).forEach(([key, value]) => {
|
|
47
|
+
if (key.includes(".")) {
|
|
48
|
+
handleParsingNestedValues(form, key, value, nestingState);
|
|
49
|
+
delete form[key];
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
return form;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Handles parsing all values for a given key, supporting multiple values as arrays.
|
|
56
|
+
*
|
|
57
|
+
* @param {BodyData} form - The form data object.
|
|
58
|
+
* @param {string} key - The key to parse.
|
|
59
|
+
* @param {FormDataEntryValue} value - The value to assign.
|
|
60
|
+
*/
|
|
61
|
+
const handleParsingAllValues = (form, key, value) => {
|
|
62
|
+
if (form[key] !== void 0) if (Array.isArray(form[key])) form[key].push(value);
|
|
63
|
+
else form[key] = [form[key], value];
|
|
64
|
+
else if (!key.endsWith("[]")) form[key] = value;
|
|
65
|
+
else form[key] = [value];
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Handles parsing nested values using dot notation keys.
|
|
69
|
+
*
|
|
70
|
+
* @param {BodyData} form - The form data object.
|
|
71
|
+
* @param {string} key - The dot notation key.
|
|
72
|
+
* @param {BodyDataValue} value - The value to assign.
|
|
73
|
+
*/
|
|
74
|
+
const handleParsingNestedValues = (form, key, value, state) => {
|
|
75
|
+
if (/(?:^|\.)__proto__\./.test(key)) return;
|
|
76
|
+
let nestedForm = form;
|
|
77
|
+
const keys = key.split(".", 34);
|
|
78
|
+
if (keys.length > 33) throwNestingLimitExceeded();
|
|
79
|
+
keys.forEach((key, index) => {
|
|
80
|
+
if (index === keys.length - 1) nestedForm[key] = value;
|
|
81
|
+
else {
|
|
82
|
+
if (!nestedForm[key] || typeof nestedForm[key] !== "object" || Array.isArray(nestedForm[key]) || nestedForm[key] instanceof File) {
|
|
83
|
+
if (state.count++ >= MAX_NESTED_OBJECTS) throwNestingLimitExceeded();
|
|
84
|
+
nestedForm[key] = Object.create(null);
|
|
85
|
+
}
|
|
86
|
+
nestedForm = nestedForm[key];
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
const throwNestingLimitExceeded = () => {
|
|
91
|
+
throw new Error("Nesting limit exceeded");
|
|
92
|
+
};
|
|
93
|
+
//#endregion
|
|
94
|
+
export { parseBody };
|