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
|
@@ -12,21 +12,81 @@ import { registerHooks } from 'node:module'
|
|
|
12
12
|
import { join } from 'node:path'
|
|
13
13
|
import { fileURLToPath, pathToFileURL } from 'node:url'
|
|
14
14
|
|
|
15
|
+
const PACKAGE = 'acrylblends'
|
|
16
|
+
|
|
15
17
|
const isBare = (specifier: string) => !/^[./]/.test(specifier) && !specifier.includes(':')
|
|
16
18
|
|
|
17
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* The framework's specifiers, as files of the vendored router plugin that sits beside this one. A plugin written while the app runs (by the agent, from the docs in the app)
|
|
21
|
+
* imports `acrylblends` and `acrylblends/<subpath>` as the docs write them; the old `acryl-router` names keep working. Empty when the app has no router.
|
|
22
|
+
*/
|
|
23
|
+
const MIDDLEWARE = [
|
|
24
|
+
'basic-auth',
|
|
25
|
+
'bearer-auth',
|
|
26
|
+
'body-limit',
|
|
27
|
+
'combine',
|
|
28
|
+
'compress',
|
|
29
|
+
'context-storage',
|
|
30
|
+
'cors',
|
|
31
|
+
'csrf',
|
|
32
|
+
'etag',
|
|
33
|
+
'ip-restriction',
|
|
34
|
+
'jwk',
|
|
35
|
+
'jwt',
|
|
36
|
+
'language',
|
|
37
|
+
'logger',
|
|
38
|
+
'loopback-only',
|
|
39
|
+
'method-not-allowed',
|
|
40
|
+
'method-override',
|
|
41
|
+
'powered-by',
|
|
42
|
+
'pretty-json',
|
|
43
|
+
'request-id',
|
|
44
|
+
'secure-headers',
|
|
45
|
+
'serve-static',
|
|
46
|
+
'timeout',
|
|
47
|
+
'timing',
|
|
48
|
+
'trailing-slash',
|
|
49
|
+
]
|
|
50
|
+
const HELPERS = [
|
|
51
|
+
'accepts',
|
|
52
|
+
'cookie',
|
|
53
|
+
'factory',
|
|
54
|
+
'html',
|
|
55
|
+
'route',
|
|
56
|
+
'schema-validator',
|
|
57
|
+
'streaming',
|
|
58
|
+
'testing',
|
|
59
|
+
'validator',
|
|
60
|
+
'ws',
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
/** The `acrylblends/...` names a plugin installed live may import, with the file each resolves to under `acryl-router/src`. */
|
|
64
|
+
export function frameworkSpecifiers(): Record<string, string> {
|
|
65
|
+
const map: Record<string, string> = {
|
|
66
|
+
'': 'index.ts',
|
|
67
|
+
conninfo: 'index.ts',
|
|
68
|
+
'http-exception': 'index.ts',
|
|
69
|
+
types: 'index.ts',
|
|
70
|
+
client: 'client.ts',
|
|
71
|
+
}
|
|
72
|
+
for (const name of MIDDLEWARE) map[name] = 'middleware/index.ts'
|
|
73
|
+
for (const name of HELPERS) map[name] = 'helpers/index.ts'
|
|
74
|
+
return map
|
|
75
|
+
}
|
|
76
|
+
|
|
18
77
|
export function routerAliases(): Record<string, string> {
|
|
19
78
|
const src = new URL('../acryl-router/src/', import.meta.url)
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
79
|
+
const aliases: Record<string, string> = {}
|
|
80
|
+
const add = (specifier: string, file: string) => {
|
|
81
|
+
const path = fileURLToPath(new URL(file, src))
|
|
82
|
+
if (existsSync(path)) aliases[specifier] = path
|
|
24
83
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
)
|
|
84
|
+
for (const [sub, file] of Object.entries(frameworkSpecifiers()))
|
|
85
|
+
add(sub === '' ? PACKAGE : `${PACKAGE}/${sub}`, file)
|
|
86
|
+
add('acryl-router', 'index.ts')
|
|
87
|
+
add('acryl-router/middleware', 'middleware/index.ts')
|
|
88
|
+
add('acryl-router/helpers', 'helpers/index.ts')
|
|
89
|
+
return aliases
|
|
30
90
|
}
|
|
31
91
|
|
|
32
92
|
export function resolveFromApp(
|
package/plugins/openai/prompt.ts
CHANGED
|
@@ -10,21 +10,21 @@ To add a capability:
|
|
|
10
10
|
A plugin's index.ts is TypeScript that Node runs directly (erasable syntax only: no enums, no parameter properties):
|
|
11
11
|
|
|
12
12
|
import type { Context } from '@deepseek-ai/cordis'
|
|
13
|
-
import {
|
|
13
|
+
import { Acryl } from 'acrylblends'
|
|
14
14
|
export const name = 'hello' // must equal the folder name
|
|
15
15
|
export const inject = ['router'] // services it needs; it waits (pending) until they exist
|
|
16
16
|
export function apply(ctx: Context) {
|
|
17
|
-
ctx.router.route('/', new
|
|
17
|
+
ctx.router.route('/', new Acryl().get('/hello', (c) => c.json({ text: 'Hello' }))) // removed when the plugin is unloaded
|
|
18
18
|
}
|
|
19
19
|
export async function check(ctx: Context) { // optional: must pass, or the install is rolled back
|
|
20
|
-
const reply = await ctx.
|
|
20
|
+
const reply = await ctx.router.request('/hello')
|
|
21
21
|
if (!reply.ok) throw new Error('GET /hello failed')
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
The router: build an
|
|
24
|
+
The router: build an Acryl app (import { Acryl } from 'acrylblends'), register routes on it with app.get/post/put/patch/delete(path, handler) and mount it with
|
|
25
25
|
ctx.router.route(prefix, app). A path parameter is :id and is read with c.req.param('id'); c.json(body, status) answers JSON, c.text(...) answers text,
|
|
26
|
-
await c.req.json() reads a JSON body, throw new HTTPException(404, { message }) (also from '
|
|
27
|
-
after route() are not served: build the whole app first. ctx.
|
|
26
|
+
await c.req.json() reads a JSON body, throw new HTTPException(404, { message }) (also from 'acrylblends') answers an error. Routes added to an app
|
|
27
|
+
after route() are not served: build the whole app first. ctx.router.request('/path', { method: 'POST', body: ... }) calls a route in process (use it in
|
|
28
28
|
check). The mount goes away when the plugin is unloaded.
|
|
29
29
|
|
|
30
30
|
For a capability that is a pure function of data (parse, convert, compute), write a sandboxed TOOL instead of a plugin. It cannot touch the
|
|
@@ -32,6 +32,6 @@ host: it runs in a separate process that can read only its own folder. Files: in
|
|
|
32
32
|
{ "description": "what it does and its input", "examples": [ { "input": {...}, "output": {...} } ] }
|
|
33
33
|
The examples are run in the sandbox at install and must match exactly, or the install is refused. Use write_plugin and install_plugin for tools too.
|
|
34
34
|
|
|
35
|
-
Rules: import only relative files, node: built-ins, @deepseek-ai/cordis and
|
|
35
|
+
Rules: import only relative files, node: built-ins, @deepseek-ai/cordis and acrylblends (and its subpaths such as acrylblends/cors, whose docs are in docs/framework). Provide services with ctx.provide(name, value) and
|
|
36
36
|
use others with ctx.get(name). Put timers, listeners and routes inside ctx.effect(() => cleanup). Use list_plugins and
|
|
37
37
|
read_plugin to see what exists. When you are done, answer in one or two plain sentences saying what you built.`
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# __APP_NAME__
|
|
2
|
+
|
|
3
|
+
A Cordis app on the ACRYL framework: TypeScript that Node 22.19 or newer runs directly (no build step; erasable syntax only, so no enums and no
|
|
4
|
+
parameter properties). Every part of it is a Cordis plugin.
|
|
5
|
+
|
|
6
|
+
## The framework's API is in `docs/framework/`
|
|
7
|
+
|
|
8
|
+
Start at `docs/framework/README.md`; `api/summary.md` is the one-page summary. Read before you write routes: `api/routing.md` (the `Acryl` app), `api/request.md` (`c.req`),
|
|
9
|
+
`api/context.md` (`c`), `cordis/validation.md` and `guides/validation.md`, `guides/helpers.md` (`streamSSE`), `concepts/middleware.md`, `cordis/plugin-lifecycle.md` (what a plugin
|
|
10
|
+
owns and when it is unloaded), `cordis/mounting.md` and `cordis/node-server.md`. Pages marked "not yet available" describe parts that are not in this app.
|
|
11
|
+
|
|
12
|
+
The docs write `import { Acryl } from 'acrylblends'` and `from 'acrylblends/<subpath>'`. In this app the framework is the vendored plugin source in `src/plugins/acryl-router/src`
|
|
13
|
+
(read it, do not edit it: a change belongs in ACRYL, upstream), so from a file in `src/` import:
|
|
14
|
+
|
|
15
|
+
- `./plugins/acryl-router/src/index.ts` for `Acryl`, `Context`, `HTTPException`, `connectionOf`, `getConnInfo` and the types;
|
|
16
|
+
- `./plugins/acryl-router/src/middleware/index.ts` for every middleware (`cors`, `bodyLimit`, `trimTrailingSlash`, `loopbackOnly`, ...);
|
|
17
|
+
- `./plugins/acryl-router/src/helpers/index.ts` for the helpers and validators (`streamSSE`, `schemaValidator`, `validator`, cookies, `testClient`, ...).
|
|
18
|
+
|
|
19
|
+
A plugin written into `extensions/` while the app runs may use the docs' own names instead: `acrylblends` and `acrylblends/<subpath>` resolve to the same files. `App` is the
|
|
20
|
+
deprecated name of `Acryl`.
|
|
21
|
+
|
|
22
|
+
## How a feature is built
|
|
23
|
+
|
|
24
|
+
Routes are an ordinary `Acryl` app that a plugin mounts once with `ctx.router.route(prefix, app)`. The mount belongs to the plugin and goes away when it unloads.
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
28
|
+
import { Acryl, HTTPException } from './plugins/acryl-router/src/index.ts'
|
|
29
|
+
import { schemaValidator, type StandardSchema } from './plugins/acryl-router/src/helpers/index.ts'
|
|
30
|
+
|
|
31
|
+
export const name = 'notes' // a plugin's name; blend.yaml refers to it
|
|
32
|
+
export const inject = ['router'] // services it needs
|
|
33
|
+
export function apply(ctx: Context) {
|
|
34
|
+
const app = new Acryl()
|
|
35
|
+
.get('/', (c) => c.json({ ok: true }))
|
|
36
|
+
.get('/:id', (c) => c.json({ id: c.req.param('id') }))
|
|
37
|
+
.post('/', schemaValidator('json', NewNote), (c) => c.json(c.req.valid('json'), 201)) // NewNote is a Standard Schema
|
|
38
|
+
ctx.router.route('/notes', app) // build the whole app first: routes added after route() are not served
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
- A small route goes on the `App` in `src/routes.ts`. A new feature is a new plugin file: add it to `registry` in `src/app.ts`, add a row
|
|
43
|
+
(`- id: notes` / `name: notes`) to `blend.yaml` before the `acryl-node-server` row, and pass runtime values (a data file) as its config in `createApp`.
|
|
44
|
+
- State, when `src/plugins/acryl-state` exists: `const cell = ctx.state.cell<T>('notes.list', initial)` (add `'state'` to `inject`), then
|
|
45
|
+
`cell.get()`, `cell.set(value)`, `cell.update(fn)` and `cell.subscribe(fn)` (returns the unsubscribe). Every cell is also served as JSON at `/api/state/<key>`
|
|
46
|
+
and streamed at `/api/state/<key>/events`.
|
|
47
|
+
- Test a route without a socket: `await ctx.router.request('/notes')`, or boot the app as `test/app.test.ts` does and use `fetch`.
|
|
48
|
+
|
|
49
|
+
## Things that surprise people
|
|
50
|
+
|
|
51
|
+
- A page mounted at `/x` answers `/x`, not `/x/` (trailing slashes are strict); `trimTrailingSlash()` (middleware) redirects `/x/` to `/x` for GET and HEAD.
|
|
52
|
+
- `schemaValidator('json', ...)` needs a JSON `Content-Type`; without it the schema sees `{}`. A failure answers 400 with
|
|
53
|
+
`{ "error": "invalid json", "issues": [{ "message", "path" }] }`: the human text is `issues[0].message`. A `jsonOnly` recipe in `docs/framework/validation.md` answers 415 instead.
|
|
54
|
+
- Throw `new HTTPException(404, { message })` for an error response; the body is the message as plain text (use `c.json({ error }, status)` when a page expects JSON).
|
|
55
|
+
- Handlers get the request as `c.req`: `c.req.param('id')`, `c.req.query('q')`, `await c.req.json()`, `c.req.raw` for the Web `Request`.
|
|
56
|
+
- A server-sent stream is `streamSSE(c, async (stream) => { await stream.writeSSE({ data: JSON.stringify(x) }) ... })`; call `stream.onAbort(cleanup)`.
|
|
57
|
+
- `npm run dev` restarts the app whenever a file changes.
|
|
58
|
+
|
|
59
|
+
## Before you say you are done
|
|
60
|
+
|
|
61
|
+
`npm test` and `npm run check` (type-check) both pass. Put tests in `test/`, written with `node:test` like `test/app.test.ts`.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
|
|
2
|
+
## This app (agent)
|
|
3
|
+
|
|
4
|
+
Besides `src/routes.ts`, the app runs an agent (`POST /ask`) that can write plugins into `extensions/` while the app runs and install them with
|
|
5
|
+
rollback; `GET /extensions` and `GET /tasks` show what it did. A plugin there is a folder with an `index.ts` exporting `name`, `inject`, `apply(ctx)`
|
|
6
|
+
and an optional `check(ctx)` that receives the plugin's own context (so `ctx.router` reads as in `apply`). It may import `acryl-router`.
|
|
@@ -5,7 +5,7 @@ Cordis plugin.
|
|
|
5
5
|
|
|
6
6
|
```sh
|
|
7
7
|
npm install
|
|
8
|
-
npm run dev # prints its URL; data lives in .acrylblends
|
|
8
|
+
npm run dev # prints its URL; data lives in .acrylblends/; it restarts when a file changes (a new port if ACRYLBLENDS_PORT=0)
|
|
9
9
|
npm test
|
|
10
10
|
npm run check # type-check
|
|
11
11
|
|
|
@@ -41,7 +41,7 @@ curl <url>/tasks # every run as a durable task, with the tool calls
|
|
|
41
41
|
|
|
42
42
|
Other commands: `update route <name> <path> <text>`, `break plugin <name>` (shows the rollback), `remove plugin <name>`,
|
|
43
43
|
`list plugins`. What the agent writes lands in `extensions/`, is part of your app, and starts again at the next start.
|
|
44
|
-
- `src/routes.ts` is your own plugin:
|
|
44
|
+
- `src/routes.ts` is your own plugin: it builds an `App` (`import { App } from './plugins/acryl-router/src/index.ts'`) and mounts it with `ctx.router.route(prefix, app)`. Routes added to the app after it is mounted are not served. A page mounted at `/x` answers `/x`, not `/x/` (trailing slashes are strict). The router API is documented at https://acrylblends.github.io/docs/framework/the-acryl-framework and in `docs/framework` of the acrylblends repository.
|
|
45
45
|
- `src/plugins/` holds the plugins copied from the ACRYLBLENDS library. They are yours now; edit them freely.
|
|
46
46
|
Add more with `acrylblends add <plugin>`.
|
|
47
47
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# The app as data, in ACRYL's Blend format (blends.acryl.dev/v1alpha1): which plugins it mounts, in what order, with what config.
|
|
2
2
|
# Edit this, not app.ts, to switch a plugin off (disabled: true) or change its config. `npm run lock` records what the app is built from.
|
|
3
|
-
# Order matters:
|
|
3
|
+
# Order matters: acryl-router comes before extensions, because installed extensions start again at boot and may add routes.
|
|
4
4
|
apiVersion: blends.acryl.dev/v1alpha1
|
|
5
5
|
kind: Blueprint
|
|
6
6
|
metadata:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Context } from '@deepseek-ai/cordis'
|
|
2
|
-
import {
|
|
2
|
+
import { Acryl } from './plugins/acryl-router/src/index.ts'
|
|
3
3
|
import { bodyLimit } from './plugins/acryl-router/src/middleware/index.ts'
|
|
4
4
|
import type {} from './plugins/agent/index.ts'
|
|
5
5
|
import type {} from './plugins/extensions/index.ts'
|
|
@@ -23,7 +23,7 @@ export const routes = {
|
|
|
23
23
|
const body = await c.req.json().catch(() => undefined)
|
|
24
24
|
return typeof body === 'object' && body !== null ? (body as Record<string, unknown>) : {}
|
|
25
25
|
}
|
|
26
|
-
const app = new
|
|
26
|
+
const app = new Acryl()
|
|
27
27
|
.use(bodyLimit({ maxSize: 64 * 1024 }))
|
|
28
28
|
.get('/', (c) => c.json({ app: APP_NAME, ok: true }))
|
|
29
29
|
.get('/health', (c) => c.json({ ok: true }))
|
|
@@ -10,12 +10,12 @@ import { pinnedInstance, withPort } from '../src/plugins/instance/index.ts'
|
|
|
10
10
|
|
|
11
11
|
/** A plugin no scripted command knows: the model writes it from scratch. */
|
|
12
12
|
const COUNTER = `import type { Context } from '@deepseek-ai/cordis'
|
|
13
|
-
import {
|
|
13
|
+
import { Acryl } from 'acrylblends'
|
|
14
14
|
export const name = 'counter'
|
|
15
15
|
export const inject = ['router']
|
|
16
16
|
export function apply(ctx: Context) {
|
|
17
17
|
let count = 0
|
|
18
|
-
ctx.router.route('/', new
|
|
18
|
+
ctx.router.route('/', new Acryl().get('/count', (c) => c.json({ count: ++count })))
|
|
19
19
|
}
|
|
20
20
|
`
|
|
21
21
|
|
|
@@ -13,6 +13,46 @@
|
|
|
13
13
|
"skipLibCheck": true,
|
|
14
14
|
"types": ["node"],
|
|
15
15
|
"paths": {
|
|
16
|
+
"acrylblends": ["./src/plugins/acryl-router/src/index.ts"],
|
|
17
|
+
"acrylblends/conninfo": ["./src/plugins/acryl-router/src/index.ts"],
|
|
18
|
+
"acrylblends/http-exception": ["./src/plugins/acryl-router/src/index.ts"],
|
|
19
|
+
"acrylblends/types": ["./src/plugins/acryl-router/src/index.ts"],
|
|
20
|
+
"acrylblends/client": ["./src/plugins/acryl-router/src/client.ts"],
|
|
21
|
+
"acrylblends/basic-auth": ["./src/plugins/acryl-router/src/middleware/index.ts"],
|
|
22
|
+
"acrylblends/bearer-auth": ["./src/plugins/acryl-router/src/middleware/index.ts"],
|
|
23
|
+
"acrylblends/body-limit": ["./src/plugins/acryl-router/src/middleware/index.ts"],
|
|
24
|
+
"acrylblends/combine": ["./src/plugins/acryl-router/src/middleware/index.ts"],
|
|
25
|
+
"acrylblends/compress": ["./src/plugins/acryl-router/src/middleware/index.ts"],
|
|
26
|
+
"acrylblends/context-storage": ["./src/plugins/acryl-router/src/middleware/index.ts"],
|
|
27
|
+
"acrylblends/cors": ["./src/plugins/acryl-router/src/middleware/index.ts"],
|
|
28
|
+
"acrylblends/csrf": ["./src/plugins/acryl-router/src/middleware/index.ts"],
|
|
29
|
+
"acrylblends/etag": ["./src/plugins/acryl-router/src/middleware/index.ts"],
|
|
30
|
+
"acrylblends/ip-restriction": ["./src/plugins/acryl-router/src/middleware/index.ts"],
|
|
31
|
+
"acrylblends/jwk": ["./src/plugins/acryl-router/src/middleware/index.ts"],
|
|
32
|
+
"acrylblends/jwt": ["./src/plugins/acryl-router/src/middleware/index.ts"],
|
|
33
|
+
"acrylblends/language": ["./src/plugins/acryl-router/src/middleware/index.ts"],
|
|
34
|
+
"acrylblends/logger": ["./src/plugins/acryl-router/src/middleware/index.ts"],
|
|
35
|
+
"acrylblends/loopback-only": ["./src/plugins/acryl-router/src/middleware/index.ts"],
|
|
36
|
+
"acrylblends/method-not-allowed": ["./src/plugins/acryl-router/src/middleware/index.ts"],
|
|
37
|
+
"acrylblends/method-override": ["./src/plugins/acryl-router/src/middleware/index.ts"],
|
|
38
|
+
"acrylblends/powered-by": ["./src/plugins/acryl-router/src/middleware/index.ts"],
|
|
39
|
+
"acrylblends/pretty-json": ["./src/plugins/acryl-router/src/middleware/index.ts"],
|
|
40
|
+
"acrylblends/request-id": ["./src/plugins/acryl-router/src/middleware/index.ts"],
|
|
41
|
+
"acrylblends/secure-headers": ["./src/plugins/acryl-router/src/middleware/index.ts"],
|
|
42
|
+
"acrylblends/serve-static": ["./src/plugins/acryl-router/src/middleware/index.ts"],
|
|
43
|
+
"acrylblends/timeout": ["./src/plugins/acryl-router/src/middleware/index.ts"],
|
|
44
|
+
"acrylblends/timing": ["./src/plugins/acryl-router/src/middleware/index.ts"],
|
|
45
|
+
"acrylblends/trailing-slash": ["./src/plugins/acryl-router/src/middleware/index.ts"],
|
|
46
|
+
"acrylblends/accepts": ["./src/plugins/acryl-router/src/helpers/index.ts"],
|
|
47
|
+
"acrylblends/cookie": ["./src/plugins/acryl-router/src/helpers/index.ts"],
|
|
48
|
+
"acrylblends/factory": ["./src/plugins/acryl-router/src/helpers/index.ts"],
|
|
49
|
+
"acrylblends/html": ["./src/plugins/acryl-router/src/helpers/index.ts"],
|
|
50
|
+
"acrylblends/route": ["./src/plugins/acryl-router/src/helpers/index.ts"],
|
|
51
|
+
"acrylblends/schema-validator": ["./src/plugins/acryl-router/src/helpers/index.ts"],
|
|
52
|
+
"acrylblends/streaming": ["./src/plugins/acryl-router/src/helpers/index.ts"],
|
|
53
|
+
"acrylblends/testing": ["./src/plugins/acryl-router/src/helpers/index.ts"],
|
|
54
|
+
"acrylblends/validator": ["./src/plugins/acryl-router/src/helpers/index.ts"],
|
|
55
|
+
"acrylblends/ws": ["./src/plugins/acryl-router/src/helpers/index.ts"],
|
|
16
56
|
"acryl-router": ["./src/plugins/acryl-router/src/index.ts"],
|
|
17
57
|
"acryl-router/middleware": ["./src/plugins/acryl-router/src/middleware/index.ts"],
|
|
18
58
|
"acryl-router/helpers": ["./src/plugins/acryl-router/src/helpers/index.ts"]
|
|
@@ -15,7 +15,7 @@ npm run check # type-check
|
|
|
15
15
|
one off with `disabled: true`. `npm run lock` writes `blend.lock.json`: the manifest's digest and a digest of
|
|
16
16
|
every plugin folder, so a diff of the lock shows what changed.
|
|
17
17
|
- `src/app.ts` holds the registry of plugins the code provides, and mounts the manifest's rows.
|
|
18
|
-
- `src/routes.ts` is your own plugin:
|
|
18
|
+
- `src/routes.ts` is your own plugin: it builds an `App` (`import { App } from './plugins/acryl-router/src/index.ts'`) and mounts it with `ctx.router.route(prefix, app)`. Routes added to the app after it is mounted are not served. A page mounted at `/x` answers `/x`, not `/x/` (trailing slashes are strict). The router API is documented at https://acrylblends.github.io/docs/framework/the-acryl-framework and in `docs/framework` of the acrylblends repository.
|
|
19
19
|
- `src/plugins/` holds the plugins copied from the ACRYLBLENDS library. They are yours now; edit them freely.
|
|
20
20
|
Add more with `acrylblends add <plugin>`.
|
|
21
21
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Context } from '@deepseek-ai/cordis'
|
|
2
|
-
import {
|
|
2
|
+
import { Acryl } from './plugins/acryl-router/src/index.ts'
|
|
3
3
|
|
|
4
4
|
export const APP_NAME = '__APP_NAME__'
|
|
5
5
|
|
|
@@ -8,7 +8,7 @@ export const routes = {
|
|
|
8
8
|
name: 'routes',
|
|
9
9
|
inject: ['router'],
|
|
10
10
|
apply(ctx: Context) {
|
|
11
|
-
const app = new
|
|
11
|
+
const app = new Acryl()
|
|
12
12
|
.get('/', (c) => c.json({ app: APP_NAME, ok: true }))
|
|
13
13
|
.get('/health', (c) => c.json({ ok: true }))
|
|
14
14
|
ctx.router.route('/', app)
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
|
|
2
|
+
## This app (todo)
|
|
3
|
+
|
|
4
|
+
`src/todo.ts` is the whole feature: a plugin that mounts an `App` (CRUD, a page, a server-sent stream) and keeps the list in a state cell that it
|
|
5
|
+
also writes to a file in the app's home. Use it as the reference for a new plugin, and keep its tests passing when you change it.
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
import { mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'
|
|
7
7
|
import { dirname } from 'node:path'
|
|
8
8
|
import type { Context } from '@deepseek-ai/cordis'
|
|
9
|
-
import {
|
|
10
|
-
import { bodyLimit, loopbackOnly } from './plugins/acryl-router/src/middleware/index.ts'
|
|
9
|
+
import { Acryl, HTTPException } from './plugins/acryl-router/src/index.ts'
|
|
10
|
+
import { bodyLimit, loopbackOnly, trimTrailingSlash } from './plugins/acryl-router/src/middleware/index.ts'
|
|
11
11
|
import { schemaValidator, streamSSE, type StandardSchema } from './plugins/acryl-router/src/helpers/index.ts'
|
|
12
12
|
import type {} from './plugins/acryl-state/src/index.ts'
|
|
13
13
|
import { PAGE } from './page.ts'
|
|
@@ -84,8 +84,10 @@ export function apply(ctx: Context, config: Config = {}): void {
|
|
|
84
84
|
return todo
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
// `/todo/` is what people type: trimTrailingSlash answers a GET for an unknown path ending in `/` with a 301 to the path without it,
|
|
88
|
+
// so the page is found either way while each route keeps one canonical path (the router itself treats `/a` and `/a/` as different).
|
|
89
|
+
const api = new Acryl()
|
|
90
|
+
.use(loopbackOnly({ inProcess: 'allow' }), bodyLimit({ maxSize: MAX_BODY_BYTES }), trimTrailingSlash())
|
|
89
91
|
.get('/', c => c.html(PAGE))
|
|
90
92
|
.get('/api', c => c.json(todos.get()))
|
|
91
93
|
.post('/api', schemaValidator('json', NewTodo), c => {
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
"examples/acryl-todo/src/index.ts": "src/todo.ts",
|
|
6
6
|
"examples/acryl-todo/src/page.ts": "src/page.ts"
|
|
7
7
|
},
|
|
8
|
-
"commit": "
|
|
8
|
+
"commit": "f5151e7f0c4de3b81bddb5cc686b5ef329e48e1c"
|
|
9
9
|
},
|
|
10
10
|
"rewrittenSpecifiers": 4,
|
|
11
|
-
"digest": "sha256:
|
|
11
|
+
"digest": "sha256:9093704776563001f7f472f94cc5c2fdd79206342c1cb59c11fce62aa74df3ed"
|
|
12
12
|
}
|