acrylblends 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +22 -16
- package/dist/index.js +65 -20
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/plugins/acryl-inspect/LICENSE +21 -0
- package/plugins/acryl-inspect/plugin.json +12 -0
- package/plugins/acryl-inspect/src/index.ts +3 -0
- package/plugins/acryl-inspect/src/report.ts +126 -0
- package/plugins/acryl-inspect/src/service.ts +68 -0
- package/plugins/acryl-inspect/tests/report.spec.ts +63 -0
- package/plugins/acryl-inspect/tests/service.spec.ts +121 -0
- package/plugins/acryl-inspect/upstream.json +18 -0
- package/plugins/acryl-node-server/LICENSE +47 -0
- package/plugins/acryl-node-server/plugin.json +13 -0
- 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 +107 -0
- 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 +141 -0
- package/plugins/acryl-node-server/upstream.json +18 -0
- package/plugins/acryl-router/LICENSE +47 -0
- package/plugins/acryl-router/plugin.json +13 -0
- 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 -0
- package/plugins/acryl-router/src/helpers/schema-validator.ts +35 -0
- package/plugins/acryl-router/src/index.ts +6 -0
- package/plugins/acryl-router/src/middleware/index.ts +25 -0
- package/plugins/acryl-router/src/middleware/loopback-only.ts +88 -0
- package/plugins/acryl-router/src/service.ts +356 -0
- package/plugins/acryl-router/tests/docs-examples.spec.ts +152 -0
- package/plugins/acryl-router/tests/live-install.spec.ts +64 -0
- package/plugins/acryl-router/tests/loader.spec.ts +72 -0
- package/plugins/acryl-router/tests/service.spec.ts +409 -0
- package/plugins/acryl-router/tests/shadow-state.spec.ts +79 -0
- package/plugins/acryl-router/upstream.json +20 -0
- package/plugins/acryl-router-http/LICENSE +21 -0
- package/plugins/acryl-router-http/plugin.json +12 -0
- package/plugins/acryl-router-http/src/bridge.ts +54 -0
- package/plugins/acryl-router-http/src/index.ts +63 -0
- package/plugins/acryl-router-http/src/serve.ts +24 -0
- package/plugins/acryl-router-http/tests/adapter.spec.ts +174 -0
- package/plugins/acryl-router-http/tests/stream.spec.ts +133 -0
- package/plugins/acryl-router-http/tests/surfaces.spec.ts +101 -0
- package/plugins/acryl-router-http/upstream.json +22 -0
- package/plugins/acryl-state/LICENSE +21 -0
- package/plugins/acryl-state/NOTICE +30 -0
- package/plugins/acryl-state/plugin.json +12 -0
- package/plugins/acryl-state/src/cell.ts +67 -0
- package/plugins/acryl-state/src/index.ts +3 -0
- package/plugins/acryl-state/src/react.ts +11 -0
- package/plugins/acryl-state/src/service.ts +119 -0
- package/plugins/acryl-state/tests/cell.spec.ts +71 -0
- package/plugins/acryl-state/tests/react.spec.ts +39 -0
- package/plugins/acryl-state/tests/service.spec.ts +132 -0
- package/plugins/acryl-state/upstream.json +22 -0
- package/plugins/builder/script.ts +6 -10
- package/plugins/extensions/index.ts +20 -3
- package/plugins/extensions/resolve.ts +28 -3
- package/plugins/openai/prompt.ts +12 -6
- package/plugins/tasks/index.ts +14 -0
- package/plugins/tsconfig.json +14 -5
- package/templates/agent/blend.yaml +5 -7
- package/templates/agent/src/app.ts +8 -8
- package/templates/agent/src/routes.ts +39 -38
- package/templates/agent/template.json +3 -3
- package/templates/agent/test/builder.test.ts +22 -14
- package/templates/agent/test/model.test.ts +3 -3
- package/templates/agent/tsconfig.json +8 -5
- package/templates/{app → blank}/blend.yaml +3 -3
- package/templates/{app → blank}/src/app.ts +5 -5
- package/templates/blank/src/routes.ts +16 -0
- package/templates/blank/template.json +1 -0
- package/templates/{app → blank}/test/app.test.ts +1 -1
- package/templates/{app → blank}/tsconfig.json +2 -4
- package/templates/todo/README.md +27 -0
- package/templates/todo/blend.yaml +25 -0
- package/templates/todo/gitignore +2 -0
- package/templates/todo/package.json +23 -0
- package/templates/todo/src/app.ts +71 -0
- package/templates/todo/src/main.ts +19 -0
- package/templates/todo/src/page.ts +28 -0
- package/templates/todo/src/todo.ts +123 -0
- package/templates/todo/template.json +1 -0
- package/templates/todo/test/todo.test.ts +145 -0
- package/templates/todo/tsconfig.json +17 -0
- package/templates/todo/upstream.json +12 -0
- package/plugins/events/index.ts +0 -42
- package/plugins/events/plugin.json +0 -9
- package/plugins/http/index.ts +0 -64
- package/plugins/http/plugin.json +0 -10
- package/plugins/server/index.ts +0 -138
- package/plugins/server/plugin.json +0 -10
- package/templates/app/src/routes.ts +0 -14
- package/templates/app/template.json +0 -1
- /package/templates/{app → blank}/README.md +0 -0
- /package/templates/{app → blank}/gitignore +0 -0
- /package/templates/{app → blank}/package.json +0 -0
- /package/templates/{app → blank}/src/main.ts +0 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { UnsupportedPathError } from '../../router.ts'
|
|
2
|
+
import { runTest } from '../common.case.test.ts'
|
|
3
|
+
import { LinearRouter } from './router.ts'
|
|
4
|
+
|
|
5
|
+
describe('LinearRouter', () => {
|
|
6
|
+
runTest({
|
|
7
|
+
skip: [
|
|
8
|
+
{
|
|
9
|
+
reason: 'UnsupportedPath',
|
|
10
|
+
tests: [
|
|
11
|
+
'Multi match > `params` per a handler > GET /entry/123/show',
|
|
12
|
+
'Capture regex pattern has trailing wildcard > GET /foo/bar/file.html',
|
|
13
|
+
'Capture regex param with trailing wildcard on empty remainder > GET /123',
|
|
14
|
+
'Capture regex param with trailing wildcard and sibling route > GET /regex-abc/123/ghi',
|
|
15
|
+
'Trailing wildcard after a label > GET /abc',
|
|
16
|
+
'Trailing wildcard after a label > GET /abc/sub',
|
|
17
|
+
'Trailing wildcard after a pattern label > GET /abc',
|
|
18
|
+
'Trailing wildcard after a pattern label > GET /reverse/abc in reverse registration order',
|
|
19
|
+
'Trailing wildcard after a pattern label > POST /all/abc with ALL middleware',
|
|
20
|
+
'Trailing wildcard after a pattern label > GET /posts/2024/comments with nested braces',
|
|
21
|
+
'Trailing wildcard after a pattern label > GET /files/foo/detail with regexp meta characters',
|
|
22
|
+
'Trailing wildcard after a pattern label > GET /user/123/profile with the default pattern',
|
|
23
|
+
'Trailing wildcard after a pattern label > GET /user/123/profile with the default pattern in reverse registration order',
|
|
24
|
+
'Complex > Parameter with {.*} regexp',
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
reason: 'LinearRouter allows trailing slashes',
|
|
29
|
+
tests: ['Trailing slash > GET /book/'],
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
newRouter: () => new LinearRouter(),
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
describe('Multi match', () => {
|
|
36
|
+
describe('`params` per a handler', () => {
|
|
37
|
+
const router = new LinearRouter<string>()
|
|
38
|
+
|
|
39
|
+
beforeEach(() => {
|
|
40
|
+
router.add('ALL', '*', 'middleware a')
|
|
41
|
+
router.add('GET', '/entry/:id/*', 'middleware b')
|
|
42
|
+
router.add('GET', '/entry/:id/:action', 'action')
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('GET /entry/123/show', () => {
|
|
46
|
+
expect(() => {
|
|
47
|
+
router.match('GET', '/entry/123/show')
|
|
48
|
+
}).toThrowError(UnsupportedPathError)
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
describe('Trailing slash', () => {
|
|
54
|
+
const router = new LinearRouter<string>()
|
|
55
|
+
|
|
56
|
+
beforeEach(() => {
|
|
57
|
+
router.add('GET', '/book', 'GET /book')
|
|
58
|
+
router.add('GET', '/book/:id', 'GET /book/:id')
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
it('GET /book/', () => {
|
|
62
|
+
const [res] = router.match('GET', '/book/')
|
|
63
|
+
expect(res.length).toBe(1)
|
|
64
|
+
expect(res[0][0]).toBe('GET /book')
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
describe('Skip part', () => {
|
|
69
|
+
const router = new LinearRouter<string>()
|
|
70
|
+
|
|
71
|
+
beforeEach(() => {
|
|
72
|
+
router.add('GET', '/products/:id{d+}', 'GET /products/:id{d+}')
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it('GET /products/list', () => {
|
|
76
|
+
const [res] = router.match('GET', '/products/list')
|
|
77
|
+
expect(res.length).toBe(0)
|
|
78
|
+
})
|
|
79
|
+
})
|
|
80
|
+
})
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import type { Params, Result, Router } from '../../router.ts'
|
|
2
|
+
import { METHOD_NAME_ALL, UnsupportedPathError } from '../../router.ts'
|
|
3
|
+
import { checkOptionalParameter } from '../../utils/url.ts'
|
|
4
|
+
|
|
5
|
+
type RegExpMatchArrayWithIndices = RegExpMatchArray & { indices: [number, number][] }
|
|
6
|
+
|
|
7
|
+
const emptyParams = Object.create(null)
|
|
8
|
+
|
|
9
|
+
const splitPathRe = /\/(:\w+(?:{(?:(?:{[\d,]+})|[^}])+})?)|\/[^\/\?]+|(\?)/g
|
|
10
|
+
const splitByStarRe = /\*/
|
|
11
|
+
export class LinearRouter<T> implements Router<T> {
|
|
12
|
+
name: string = 'LinearRouter'
|
|
13
|
+
#routes: [string, string, T][] = []
|
|
14
|
+
|
|
15
|
+
add(method: string, path: string, handler: T) {
|
|
16
|
+
for (
|
|
17
|
+
let i = 0, paths = checkOptionalParameter(path) || [path], len = paths.length;
|
|
18
|
+
i < len;
|
|
19
|
+
i++
|
|
20
|
+
) {
|
|
21
|
+
this.#routes.push([method, paths[i], handler])
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
match(method: string, path: string): Result<T> {
|
|
26
|
+
const handlers: [T, Params][] = []
|
|
27
|
+
ROUTES_LOOP: for (let i = 0, len = this.#routes.length; i < len; i++) {
|
|
28
|
+
const [routeMethod, routePath, handler] = this.#routes[i]
|
|
29
|
+
if (routeMethod === method || routeMethod === METHOD_NAME_ALL) {
|
|
30
|
+
if (routePath === '*' || routePath === '/*') {
|
|
31
|
+
handlers.push([handler, emptyParams])
|
|
32
|
+
continue
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const hasStar = routePath.indexOf('*') !== -1
|
|
36
|
+
const hasLabel = routePath.indexOf(':') !== -1
|
|
37
|
+
if (!hasStar && !hasLabel) {
|
|
38
|
+
if (routePath === path || routePath + '/' === path) {
|
|
39
|
+
handlers.push([handler, emptyParams])
|
|
40
|
+
}
|
|
41
|
+
} else if (hasStar && !hasLabel) {
|
|
42
|
+
const endsWithStar = routePath.charCodeAt(routePath.length - 1) === 42
|
|
43
|
+
const endsWithSlashStar = routePath.endsWith('/*')
|
|
44
|
+
const parts = (
|
|
45
|
+
endsWithStar ? routePath.slice(0, endsWithSlashStar ? -2 : -1) : routePath
|
|
46
|
+
).split(splitByStarRe)
|
|
47
|
+
|
|
48
|
+
const lastIndex = parts.length - 1
|
|
49
|
+
for (let j = 0, pos = 0, len = parts.length; j < len; j++) {
|
|
50
|
+
const part = parts[j]
|
|
51
|
+
const index = path.indexOf(part, pos)
|
|
52
|
+
if (index !== pos) {
|
|
53
|
+
continue ROUTES_LOOP
|
|
54
|
+
}
|
|
55
|
+
pos += part.length
|
|
56
|
+
if (j === lastIndex) {
|
|
57
|
+
if (endsWithSlashStar) {
|
|
58
|
+
if (pos !== path.length && path.charCodeAt(pos) !== 47) {
|
|
59
|
+
continue ROUTES_LOOP
|
|
60
|
+
}
|
|
61
|
+
} else if (
|
|
62
|
+
!endsWithStar &&
|
|
63
|
+
pos !== path.length &&
|
|
64
|
+
!(pos === path.length - 1 && path.charCodeAt(pos) === 47)
|
|
65
|
+
) {
|
|
66
|
+
continue ROUTES_LOOP
|
|
67
|
+
}
|
|
68
|
+
} else {
|
|
69
|
+
const index = path.indexOf('/', pos)
|
|
70
|
+
if (index === -1) {
|
|
71
|
+
continue ROUTES_LOOP
|
|
72
|
+
}
|
|
73
|
+
pos = index
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
handlers.push([handler, emptyParams])
|
|
77
|
+
} else if (hasLabel && !hasStar) {
|
|
78
|
+
const params: Record<string, string> = Object.create(null)
|
|
79
|
+
const parts = routePath.match(splitPathRe) as string[]
|
|
80
|
+
|
|
81
|
+
const lastIndex = parts.length - 1
|
|
82
|
+
for (let j = 0, pos = 0, len = parts.length; j < len; j++) {
|
|
83
|
+
if (pos === -1 || pos >= path.length) {
|
|
84
|
+
continue ROUTES_LOOP
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const part = parts[j]
|
|
88
|
+
if (part.charCodeAt(1) === 58) {
|
|
89
|
+
if (path.charCodeAt(pos) !== 47) {
|
|
90
|
+
continue ROUTES_LOOP
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// /:label
|
|
94
|
+
let name = part.slice(2)
|
|
95
|
+
let value
|
|
96
|
+
|
|
97
|
+
if (name.charCodeAt(name.length - 1) === 125) {
|
|
98
|
+
// :label{pattern}
|
|
99
|
+
const openBracePos = name.indexOf('{')
|
|
100
|
+
const next = parts[j + 1]
|
|
101
|
+
const lookahead = next && next[1] !== ':' && next[1] !== '*' ? `(?=${next})` : ''
|
|
102
|
+
const pattern = name.slice(openBracePos + 1, -1) + lookahead
|
|
103
|
+
const restPath = path.slice(pos + 1)
|
|
104
|
+
const match = new RegExp(pattern, 'd').exec(restPath) as RegExpMatchArrayWithIndices
|
|
105
|
+
if (!match || match.indices[0][0] !== 0 || match.indices[0][1] === 0) {
|
|
106
|
+
continue ROUTES_LOOP
|
|
107
|
+
}
|
|
108
|
+
name = name.slice(0, openBracePos)
|
|
109
|
+
value = restPath.slice(...match.indices[0])
|
|
110
|
+
pos += match.indices[0][1] + 1
|
|
111
|
+
} else {
|
|
112
|
+
let endValuePos = path.indexOf('/', pos + 1)
|
|
113
|
+
if (endValuePos === -1) {
|
|
114
|
+
endValuePos = path.length
|
|
115
|
+
}
|
|
116
|
+
if (endValuePos === pos + 1) {
|
|
117
|
+
// an empty segment, as in `/u/` or `/u//posts`
|
|
118
|
+
continue ROUTES_LOOP
|
|
119
|
+
}
|
|
120
|
+
value = path.slice(pos + 1, endValuePos)
|
|
121
|
+
pos = endValuePos
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
params[name] ||= value as string
|
|
125
|
+
} else {
|
|
126
|
+
const index = path.indexOf(part, pos)
|
|
127
|
+
if (index !== pos) {
|
|
128
|
+
continue ROUTES_LOOP
|
|
129
|
+
}
|
|
130
|
+
pos += part.length
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (j === lastIndex) {
|
|
134
|
+
if (
|
|
135
|
+
pos !== path.length &&
|
|
136
|
+
!(pos === path.length - 1 && path.charCodeAt(pos) === 47)
|
|
137
|
+
) {
|
|
138
|
+
continue ROUTES_LOOP
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
handlers.push([handler, params])
|
|
144
|
+
} else if (hasLabel && hasStar) {
|
|
145
|
+
throw new UnsupportedPathError()
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return [handlers]
|
|
151
|
+
}
|
|
152
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { UnsupportedPathError } from '../../router.ts'
|
|
2
|
+
import { runTest } from '../common.case.test.ts'
|
|
3
|
+
import { PatternRouter } from './router.ts'
|
|
4
|
+
|
|
5
|
+
describe('Pattern', () => {
|
|
6
|
+
runTest({
|
|
7
|
+
skip: [
|
|
8
|
+
{
|
|
9
|
+
reason: 'UnsupportedPath',
|
|
10
|
+
tests: [
|
|
11
|
+
'Duplicate param name > self',
|
|
12
|
+
'Duplicate param name > self with trailing static',
|
|
13
|
+
'Duplicate param name > self three times',
|
|
14
|
+
],
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
reason: 'PatternRouter allows trailing slashes',
|
|
18
|
+
tests: ['Trailing slash > GET /book/'],
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
newRouter: () => new PatternRouter(),
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
describe('Duplicate param name', () => {
|
|
25
|
+
it('self', () => {
|
|
26
|
+
const router = new PatternRouter<string>()
|
|
27
|
+
expect(() => {
|
|
28
|
+
router.add('GET', '/:id/:id', 'foo')
|
|
29
|
+
}).toThrowError(UnsupportedPathError)
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
describe('Trailing slash', () => {
|
|
33
|
+
const router = new PatternRouter<string>()
|
|
34
|
+
|
|
35
|
+
beforeEach(() => {
|
|
36
|
+
router.add('GET', '/book', 'GET /book')
|
|
37
|
+
router.add('GET', '/book/:id', 'GET /book/:id')
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('GET /book/', () => {
|
|
41
|
+
const [res] = router.match('GET', '/book/')
|
|
42
|
+
expect(res.length).toBe(1)
|
|
43
|
+
expect(res[0][0]).toBe('GET /book')
|
|
44
|
+
})
|
|
45
|
+
})
|
|
46
|
+
})
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { Params, Result, Router } from '../../router.ts'
|
|
2
|
+
import { METHOD_NAME_ALL, UnsupportedPathError } from '../../router.ts'
|
|
3
|
+
|
|
4
|
+
type Route<T> = [RegExp, string, T] // [pattern, method, handler]
|
|
5
|
+
|
|
6
|
+
const emptyParams = Object.create(null)
|
|
7
|
+
|
|
8
|
+
export class PatternRouter<T> implements Router<T> {
|
|
9
|
+
name: string = 'PatternRouter'
|
|
10
|
+
#routes: Route<T>[] = []
|
|
11
|
+
|
|
12
|
+
add(method: string, path: string, handler: T) {
|
|
13
|
+
const suffix = path.endsWith('/*') ? '(?:$|/)' : path.endsWith('*') ? '' : '/?$'
|
|
14
|
+
path = path.replace(/\*$/, '')
|
|
15
|
+
if (path.at(-1) === '?') {
|
|
16
|
+
path = path.slice(0, -1)
|
|
17
|
+
this.add(method, path.replace(/\/[^/]+$/, ''), handler)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const parts = (path.match(/\/?(:\w+(?:{(?:(?:{[\d,]+})|[^}])+})?)|\/?[^\/\?]+/g) || []).map(
|
|
21
|
+
(part) => {
|
|
22
|
+
const match = part.match(/^\/:([^{]+)(?:{(.*)})?/)
|
|
23
|
+
return match
|
|
24
|
+
? `/(?<${match[1]}>${match[2] || '[^/]+'})`
|
|
25
|
+
: part === '/*'
|
|
26
|
+
? '/[^/]+'
|
|
27
|
+
: part.replace(/[.\\+*[^\]$()]/g, '\\$&')
|
|
28
|
+
}
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
this.#routes.push([new RegExp(`^${parts.join('')}${suffix}`), method, handler])
|
|
33
|
+
} catch {
|
|
34
|
+
throw new UnsupportedPathError()
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
match(method: string, path: string): Result<T> {
|
|
39
|
+
const handlers: [T, Params][] = []
|
|
40
|
+
|
|
41
|
+
for (let i = 0, len = this.#routes.length; i < len; i++) {
|
|
42
|
+
const [pattern, routeMethod, handler] = this.#routes[i]
|
|
43
|
+
|
|
44
|
+
if (routeMethod === method || routeMethod === METHOD_NAME_ALL) {
|
|
45
|
+
const match = pattern.exec(path)
|
|
46
|
+
if (match) {
|
|
47
|
+
handlers.push([handler, match.groups || emptyParams])
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return [handlers]
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ParamIndexMap, Result, Router } from '../../router.ts'
|
|
2
|
+
import { METHOD_NAME_ALL } from '../../router.ts'
|
|
3
|
+
|
|
4
|
+
export type HandlerData<T> = [T, ParamIndexMap][]
|
|
5
|
+
export type StaticMap<T> = Record<string, Result<T>>
|
|
6
|
+
export type Matcher<T> = [RegExp, HandlerData<T>[], StaticMap<T>]
|
|
7
|
+
export type MatcherMap<T> = Record<string, Matcher<T> | null>
|
|
8
|
+
|
|
9
|
+
export const emptyParam: string[] = []
|
|
10
|
+
export function match<R extends Router<T>, T>(this: R, method: string, path: string): Result<T> {
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
|
+
const matchers: MatcherMap<T> = (this as any).buildAllMatchers()
|
|
13
|
+
|
|
14
|
+
const match = ((method, path) => {
|
|
15
|
+
const matcher = (matchers[method] || matchers[METHOD_NAME_ALL]) as Matcher<T>
|
|
16
|
+
|
|
17
|
+
const staticMatch = matcher[2][path]
|
|
18
|
+
if (staticMatch) {
|
|
19
|
+
return staticMatch
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const match = path.match(matcher[0])
|
|
23
|
+
if (!match) {
|
|
24
|
+
return [[], emptyParam]
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const index = match.indexOf('', 1)
|
|
28
|
+
return [matcher[1][index], match]
|
|
29
|
+
}) as Router<T>['match']
|
|
30
|
+
|
|
31
|
+
this.match = match
|
|
32
|
+
return match(method, path)
|
|
33
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { createNullObject } from '../utils.ts'
|
|
2
|
+
|
|
3
|
+
export const LABEL_REG_EXP_STR = '[^/]+'
|
|
4
|
+
export const ONLY_WILDCARD_REG_EXP_STR = '.*'
|
|
5
|
+
export const TAIL_WILDCARD_REG_EXP_STR = '(?:|/.*)'
|
|
6
|
+
export const PATH_ERROR = Symbol()
|
|
7
|
+
|
|
8
|
+
export type ParamAssocArray = [string, number][]
|
|
9
|
+
export interface Context {
|
|
10
|
+
varIndex: number
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const regExpMetaChars = new Set('.\\+*[^]$()')
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Sort order:
|
|
17
|
+
* 1. literal
|
|
18
|
+
* 2. special pattern (e.g. :label{[0-9]+})
|
|
19
|
+
* 3. common label pattern (e.g. :label)
|
|
20
|
+
* 4. wildcard
|
|
21
|
+
*/
|
|
22
|
+
function compareKey(a: string, b: string): number {
|
|
23
|
+
if (a.length === 1) {
|
|
24
|
+
return b.length === 1 ? (a < b ? -1 : 1) : -1
|
|
25
|
+
}
|
|
26
|
+
if (b.length === 1) {
|
|
27
|
+
return 1
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// wildcard: the only wildcard (.*) precedes the tail wildcard
|
|
31
|
+
if (a === ONLY_WILDCARD_REG_EXP_STR || a === TAIL_WILDCARD_REG_EXP_STR) {
|
|
32
|
+
return b === TAIL_WILDCARD_REG_EXP_STR ? -1 : 1
|
|
33
|
+
} else if (b === ONLY_WILDCARD_REG_EXP_STR || b === TAIL_WILDCARD_REG_EXP_STR) {
|
|
34
|
+
return -1
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// label
|
|
38
|
+
if (a === LABEL_REG_EXP_STR) {
|
|
39
|
+
return 1
|
|
40
|
+
} else if (b === LABEL_REG_EXP_STR) {
|
|
41
|
+
return -1
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return a.length === b.length ? (a < b ? -1 : 1) : b.length - a.length
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export class Node {
|
|
48
|
+
// handler index of a dynamic path, or -1 for a static path terminal
|
|
49
|
+
#index?: number
|
|
50
|
+
#varIndex?: number
|
|
51
|
+
#children: Record<string, Node> = createNullObject()
|
|
52
|
+
|
|
53
|
+
insert(
|
|
54
|
+
tokens: readonly string[],
|
|
55
|
+
index: number,
|
|
56
|
+
paramMap: ParamAssocArray,
|
|
57
|
+
context: Context,
|
|
58
|
+
isStatic: boolean
|
|
59
|
+
): void {
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
61
|
+
let node: Node = this
|
|
62
|
+
for (let i = 0, len = tokens.length; i < len; i++) {
|
|
63
|
+
const token = tokens[i]
|
|
64
|
+
const pattern =
|
|
65
|
+
token.length === 1
|
|
66
|
+
? token === '*'
|
|
67
|
+
? i === len - 1
|
|
68
|
+
? ['', '', ONLY_WILDCARD_REG_EXP_STR] // '*' matches to all the trailing paths
|
|
69
|
+
: ['', '', LABEL_REG_EXP_STR]
|
|
70
|
+
: null
|
|
71
|
+
: token === '/*'
|
|
72
|
+
? ['', '', TAIL_WILDCARD_REG_EXP_STR] // '/path/to/*' is /\/path\/to(?:|/.*)$
|
|
73
|
+
: token.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/)
|
|
74
|
+
|
|
75
|
+
let nextNode: Node
|
|
76
|
+
if (pattern) {
|
|
77
|
+
const name = pattern[1]
|
|
78
|
+
let regexpStr = pattern[2] || LABEL_REG_EXP_STR
|
|
79
|
+
if (name && pattern[2]) {
|
|
80
|
+
if (regexpStr === '.*') {
|
|
81
|
+
throw PATH_ERROR
|
|
82
|
+
}
|
|
83
|
+
regexpStr = regexpStr.replace(/^\((?!\?:)(?=[^)]+\)$)/, '(?:') // (a|b) => (?:a|b)
|
|
84
|
+
if (/\((?!\?:)/.test(regexpStr)) {
|
|
85
|
+
// prefix(?:a|b) is allowed, but prefix(a|b) is not
|
|
86
|
+
throw PATH_ERROR
|
|
87
|
+
}
|
|
88
|
+
if (regexpStr.length === 1 && regExpMetaChars.has(regexpStr)) {
|
|
89
|
+
// a single-char pattern like :x{.} is ambiguous with a literal character
|
|
90
|
+
throw PATH_ERROR
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
nextNode = node.#children[regexpStr]
|
|
95
|
+
if (!nextNode) {
|
|
96
|
+
if (regexpStr !== ONLY_WILDCARD_REG_EXP_STR && regexpStr !== TAIL_WILDCARD_REG_EXP_STR) {
|
|
97
|
+
for (const k in node.#children) {
|
|
98
|
+
if (
|
|
99
|
+
// a single-char pattern coexists with single-char literals as a literal does
|
|
100
|
+
(regexpStr.length > 1 || k.length > 1) &&
|
|
101
|
+
k !== ONLY_WILDCARD_REG_EXP_STR &&
|
|
102
|
+
k !== TAIL_WILDCARD_REG_EXP_STR
|
|
103
|
+
) {
|
|
104
|
+
throw PATH_ERROR
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
nextNode = node.#children[regexpStr] = new Node()
|
|
109
|
+
}
|
|
110
|
+
if (name !== '') {
|
|
111
|
+
nextNode.#varIndex ??= context.varIndex++
|
|
112
|
+
paramMap.push([name, nextNode.#varIndex])
|
|
113
|
+
}
|
|
114
|
+
} else {
|
|
115
|
+
nextNode = node.#children[token]
|
|
116
|
+
if (!nextNode) {
|
|
117
|
+
for (const k in node.#children) {
|
|
118
|
+
if (
|
|
119
|
+
k.length > 1 &&
|
|
120
|
+
k !== ONLY_WILDCARD_REG_EXP_STR &&
|
|
121
|
+
k !== TAIL_WILDCARD_REG_EXP_STR
|
|
122
|
+
) {
|
|
123
|
+
throw PATH_ERROR
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
nextNode = node.#children[token] = new Node()
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
node = nextNode
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (node.#index !== undefined) {
|
|
134
|
+
throw PATH_ERROR
|
|
135
|
+
}
|
|
136
|
+
node.#index = isStatic ? -1 : index
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
buildRegExpStr(): string {
|
|
140
|
+
const childKeys = Object.keys(this.#children).sort(compareKey)
|
|
141
|
+
|
|
142
|
+
const strList = childKeys
|
|
143
|
+
.map((k) => {
|
|
144
|
+
const c = this.#children[k]
|
|
145
|
+
const childStr = c.buildRegExpStr()
|
|
146
|
+
// an empty childStr means a static-only branch, which is handled by staticMap
|
|
147
|
+
return childStr === ''
|
|
148
|
+
? ''
|
|
149
|
+
: (typeof c.#varIndex === 'number'
|
|
150
|
+
? `(${k})@${c.#varIndex}`
|
|
151
|
+
: regExpMetaChars.has(k)
|
|
152
|
+
? `\\${k}`
|
|
153
|
+
: k) + childStr
|
|
154
|
+
})
|
|
155
|
+
.filter(Boolean)
|
|
156
|
+
|
|
157
|
+
if (typeof this.#index === 'number' && this.#index !== -1) {
|
|
158
|
+
strList.unshift(`#${this.#index}`)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (strList.length === 0) {
|
|
162
|
+
return ''
|
|
163
|
+
}
|
|
164
|
+
if (strList.length === 1) {
|
|
165
|
+
return strList[0]
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return '(?:' + strList.join('|') + ')'
|
|
169
|
+
}
|
|
170
|
+
}
|