@lovrozagar/honey 0.6.8 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +514 -192
- package/bin/honey.js +25 -0
- package/dist/accepts.d.ts +7 -1
- package/dist/accepts.d.ts.map +1 -1
- package/dist/accepts.js +126 -0
- package/dist/accepts.js.map +1 -0
- package/dist/body-kind.d.ts +26 -0
- package/dist/body-kind.d.ts.map +1 -0
- package/dist/body-kind.js +70 -0
- package/dist/body-kind.js.map +1 -0
- package/dist/body-limit.d.ts +5 -1
- package/dist/body-limit.d.ts.map +1 -1
- package/dist/body-limit.js +126 -0
- package/dist/body-limit.js.map +1 -0
- package/dist/build/index.d.ts +19 -3
- package/dist/build/index.d.ts.map +1 -1
- package/dist/build/index.js +173 -0
- package/dist/build/index.js.map +1 -0
- package/dist/cli-args.d.ts +33 -0
- package/dist/cli-args.d.ts.map +1 -0
- package/dist/cli-args.js +102 -0
- package/dist/cli-args.js.map +1 -0
- package/dist/cli-go/auth.go +26 -0
- package/dist/cli-go/config.go +192 -0
- package/dist/cli-go/errors.go +75 -0
- package/dist/cli-go/multipart.go +79 -0
- package/dist/cli-go/output.go +163 -0
- package/dist/cli-go/root.go +30 -0
- package/dist/cli-go/stream.go +88 -0
- package/dist/cli-go/version.go +5 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +209 -0
- package/dist/cli.js.map +1 -0
- package/dist/client/defaults.js +48 -0
- package/dist/client/defaults.js.map +1 -0
- package/dist/client/error.d.ts +35 -0
- package/dist/client/error.d.ts.map +1 -1
- package/dist/client/error.js +71 -0
- package/dist/client/error.js.map +1 -0
- package/dist/client/http.d.ts +67 -8
- package/dist/client/http.d.ts.map +1 -1
- package/dist/client/http.js +571 -0
- package/dist/client/http.js.map +1 -0
- package/dist/client/index.d.ts +3 -2
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +95 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/path.d.ts +26 -0
- package/dist/client/path.d.ts.map +1 -0
- package/dist/client/path.js +163 -0
- package/dist/client/path.js.map +1 -0
- package/dist/client/redirect-policy.d.ts +12 -0
- package/dist/client/redirect-policy.d.ts.map +1 -0
- package/dist/client/redirect-policy.js +20 -0
- package/dist/client/redirect-policy.js.map +1 -0
- package/dist/client/sdk.d.ts +36 -0
- package/dist/client/sdk.d.ts.map +1 -1
- package/dist/client/sdk.js +292 -0
- package/dist/client/sdk.js.map +1 -0
- package/dist/client/sse.d.ts +13 -0
- package/dist/client/sse.d.ts.map +1 -1
- package/dist/client/sse.js +129 -0
- package/dist/client/sse.js.map +1 -0
- package/dist/client/types.js +2 -0
- package/dist/client/types.js.map +1 -0
- package/dist/client/ws.d.ts +9 -2
- package/dist/client/ws.d.ts.map +1 -1
- package/dist/client/ws.js +112 -0
- package/dist/client/ws.js.map +1 -0
- package/dist/client-go/errors.go +236 -0
- package/dist/client-go/export.go +44 -0
- package/dist/client-go/invalidation.go +371 -0
- package/dist/client-go/nullable.go +62 -0
- package/dist/client-go/realtime.go +354 -0
- package/dist/client-go/result.go +20 -0
- package/dist/client-go/runtime.go +975 -0
- package/dist/client-go/sse.go +159 -0
- package/dist/client-go/transport.go +495 -0
- package/dist/client-go/ws.go +128 -0
- package/dist/client-info.d.ts +36 -0
- package/dist/client-info.d.ts.map +1 -0
- package/dist/client-info.js +53 -0
- package/dist/client-info.js.map +1 -0
- package/dist/client-mcp/README.md +10 -0
- package/dist/client-mcp/server.ts +221 -0
- package/dist/client-mcp/types.ts +19 -0
- package/dist/client-python/_errors.py +115 -0
- package/dist/client-python/_invalidation.py +494 -0
- package/dist/client-python/_realtime.py +179 -0
- package/dist/client-python/_runtime.py +860 -0
- package/dist/client-python/_sse.py +155 -0
- package/dist/client-python/_transport.py +366 -0
- package/dist/client-python/_ws.py +159 -0
- package/dist/client-python/py.typed +0 -0
- package/dist/client-rust/errors.rs +220 -0
- package/dist/client-rust/invalidation.rs +412 -0
- package/dist/client-rust/invalidation_sync.rs +93 -0
- package/dist/client-rust/nullable.rs +17 -0
- package/dist/client-rust/realtime.rs +702 -0
- package/dist/client-rust/result.rs +22 -0
- package/dist/client-rust/runtime.rs +980 -0
- package/dist/client-rust/runtime_sync.rs +484 -0
- package/dist/client-rust/sse.rs +188 -0
- package/dist/client-rust/ws.rs +167 -0
- package/dist/codegen-go-cli.d.ts.map +1 -1
- package/dist/codegen-go-cli.js +964 -0
- package/dist/codegen-go-cli.js.map +1 -0
- package/dist/codegen-go.d.ts +15 -3
- package/dist/codegen-go.d.ts.map +1 -1
- package/dist/codegen-go.js +872 -0
- package/dist/codegen-go.js.map +1 -0
- package/dist/codegen-hash.js +9 -0
- package/dist/codegen-hash.js.map +1 -0
- package/dist/codegen-ir.d.ts +69 -2
- package/dist/codegen-ir.d.ts.map +1 -1
- package/dist/codegen-ir.js +661 -0
- package/dist/codegen-ir.js.map +1 -0
- package/dist/codegen-lang.d.ts +65 -0
- package/dist/codegen-lang.d.ts.map +1 -0
- package/dist/codegen-lang.js +526 -0
- package/dist/codegen-lang.js.map +1 -0
- package/dist/codegen-load.d.ts +31 -0
- package/dist/codegen-load.d.ts.map +1 -0
- package/dist/codegen-load.js +138 -0
- package/dist/codegen-load.js.map +1 -0
- package/dist/codegen-loaders.js +55 -0
- package/dist/codegen-loaders.js.map +1 -0
- package/dist/codegen-mcp.d.ts.map +1 -1
- package/dist/codegen-mcp.js +368 -0
- package/dist/codegen-mcp.js.map +1 -0
- package/dist/codegen-python.d.ts +13 -1
- package/dist/codegen-python.d.ts.map +1 -1
- package/dist/codegen-python.js +828 -0
- package/dist/codegen-python.js.map +1 -0
- package/dist/codegen-route-tree-intern.d.ts +15 -5
- package/dist/codegen-route-tree-intern.d.ts.map +1 -1
- package/dist/codegen-route-tree-intern.js +221 -0
- package/dist/codegen-route-tree-intern.js.map +1 -0
- package/dist/codegen-rust.d.ts.map +1 -1
- package/dist/codegen-rust.js +1293 -0
- package/dist/codegen-rust.js.map +1 -0
- package/dist/codegen-sanitize.d.ts.map +1 -1
- package/dist/codegen-sanitize.js +56 -0
- package/dist/codegen-sanitize.js.map +1 -0
- package/dist/codegen-schema-naming.d.ts +5 -0
- package/dist/codegen-schema-naming.d.ts.map +1 -1
- package/dist/codegen-schema-naming.js +150 -0
- package/dist/codegen-schema-naming.js.map +1 -0
- package/dist/codegen-sdk-model.d.ts +71 -0
- package/dist/codegen-sdk-model.d.ts.map +1 -0
- package/dist/codegen-sdk-model.js +179 -0
- package/dist/codegen-sdk-model.js.map +1 -0
- package/dist/codegen.d.ts +41 -23
- package/dist/codegen.d.ts.map +1 -1
- package/dist/codegen.js +4610 -0
- package/dist/codegen.js.map +1 -0
- package/dist/context.d.ts +36 -6
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +242 -0
- package/dist/context.js.map +1 -0
- package/dist/cookie-sign.d.ts +16 -2
- package/dist/cookie-sign.d.ts.map +1 -1
- package/dist/cookie-sign.js +104 -0
- package/dist/cookie-sign.js.map +1 -0
- package/dist/cookie.d.ts +12 -0
- package/dist/cookie.d.ts.map +1 -1
- package/dist/cookie.js +138 -0
- package/dist/cookie.js.map +1 -0
- package/dist/cors.d.ts +1 -0
- package/dist/cors.d.ts.map +1 -1
- package/dist/cors.js +87 -0
- package/dist/cors.js.map +1 -0
- package/dist/crypto.d.ts +6 -1
- package/dist/crypto.d.ts.map +1 -1
- package/dist/crypto.js +38 -0
- package/dist/crypto.js.map +1 -0
- package/dist/csrf.d.ts +19 -0
- package/dist/csrf.d.ts.map +1 -1
- package/dist/csrf.js +79 -0
- package/dist/csrf.js.map +1 -0
- package/dist/curl-logger.d.ts +14 -3
- package/dist/curl-logger.d.ts.map +1 -1
- package/dist/curl-logger.js +199 -0
- package/dist/curl-logger.js.map +1 -0
- package/dist/detect-runtime.js +13 -0
- package/dist/detect-runtime.js.map +1 -0
- package/dist/dict.d.ts +11 -0
- package/dist/dict.d.ts.map +1 -0
- package/dist/dict.js +13 -0
- package/dist/dict.js.map +1 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +44 -0
- package/dist/error.js.map +1 -0
- package/dist/errors.js +39 -0
- package/dist/errors.js.map +1 -0
- package/dist/etag.d.ts +2 -0
- package/dist/etag.d.ts.map +1 -1
- package/dist/etag.js +82 -0
- package/dist/etag.js.map +1 -0
- package/dist/feature-detect.d.ts +25 -0
- package/dist/feature-detect.d.ts.map +1 -0
- package/dist/feature-detect.js +144 -0
- package/dist/feature-detect.js.map +1 -0
- package/dist/feature-load.js +36 -0
- package/dist/feature-load.js.map +1 -0
- package/dist/feature-slots.d.ts +44 -0
- package/dist/feature-slots.d.ts.map +1 -0
- package/dist/feature-slots.js +48 -0
- package/dist/feature-slots.js.map +1 -0
- package/dist/fetch-request.d.ts +10 -0
- package/dist/fetch-request.d.ts.map +1 -0
- package/dist/fetch-request.js +13 -0
- package/dist/fetch-request.js.map +1 -0
- package/dist/gen-process.d.ts +15 -0
- package/dist/gen-process.d.ts.map +1 -0
- package/dist/gen-process.js +43 -0
- package/dist/gen-process.js.map +1 -0
- package/dist/gen-write.d.ts +19 -0
- package/dist/gen-write.d.ts.map +1 -0
- package/dist/gen-write.js +120 -0
- package/dist/gen-write.js.map +1 -0
- package/dist/glob.d.ts +21 -0
- package/dist/glob.d.ts.map +1 -0
- package/dist/glob.js +115 -0
- package/dist/glob.js.map +1 -0
- package/dist/go-type-emitter.d.ts +18 -4
- package/dist/go-type-emitter.d.ts.map +1 -1
- package/dist/go-type-emitter.js +594 -0
- package/dist/go-type-emitter.js.map +1 -0
- package/dist/honey-response.d.ts.map +1 -1
- package/dist/honey-response.js +338 -0
- package/dist/honey-response.js.map +1 -0
- package/dist/i18n-slot.d.ts +8 -0
- package/dist/i18n-slot.d.ts.map +1 -1
- package/dist/i18n-slot.js +14 -0
- package/dist/i18n-slot.js.map +1 -0
- package/dist/i18n.d.ts +3 -0
- package/dist/i18n.d.ts.map +1 -1
- package/dist/i18n.js +250 -0
- package/dist/i18n.js.map +1 -0
- package/dist/index.d.ts +408 -148
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2324 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +3 -5
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +140 -0
- package/dist/init.js.map +1 -0
- package/dist/input.js +4 -0
- package/dist/input.js.map +1 -0
- package/dist/invalidate-check.d.ts +11 -0
- package/dist/invalidate-check.d.ts.map +1 -1
- package/dist/invalidate-check.js +163 -0
- package/dist/invalidate-check.js.map +1 -0
- package/dist/invoke-user.d.ts +35 -0
- package/dist/invoke-user.d.ts.map +1 -0
- package/dist/invoke-user.js +73 -0
- package/dist/invoke-user.js.map +1 -0
- package/dist/ip-restrict.d.ts +13 -1
- package/dist/ip-restrict.d.ts.map +1 -1
- package/dist/ip-restrict.js +60 -0
- package/dist/ip-restrict.js.map +1 -0
- package/dist/ip.d.ts +39 -0
- package/dist/ip.d.ts.map +1 -0
- package/dist/ip.js +209 -0
- package/dist/ip.js.map +1 -0
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +113 -0
- package/dist/logger.js.map +1 -0
- package/dist/media-type.d.ts +30 -0
- package/dist/media-type.d.ts.map +1 -0
- package/dist/media-type.js +97 -0
- package/dist/media-type.js.map +1 -0
- package/dist/meta-spec-merge.d.ts +32 -0
- package/dist/meta-spec-merge.d.ts.map +1 -0
- package/dist/meta-spec-merge.js +68 -0
- package/dist/meta-spec-merge.js.map +1 -0
- package/dist/meta-spec.d.ts +16 -3
- package/dist/meta-spec.d.ts.map +1 -1
- package/dist/meta-spec.js +535 -0
- package/dist/meta-spec.js.map +1 -0
- package/dist/middleware.d.ts +23 -6
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +253 -0
- package/dist/middleware.js.map +1 -0
- package/dist/node-request.d.ts +57 -12
- package/dist/node-request.d.ts.map +1 -1
- package/dist/node-request.js +407 -0
- package/dist/node-request.js.map +1 -0
- package/dist/node.d.ts +20 -3
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +396 -0
- package/dist/node.js.map +1 -0
- package/dist/openapi/collect.d.ts +6 -3
- package/dist/openapi/collect.d.ts.map +1 -1
- package/dist/openapi/collect.js +30 -0
- package/dist/openapi/collect.js.map +1 -0
- package/dist/openapi/docs-page.d.ts +42 -0
- package/dist/openapi/docs-page.d.ts.map +1 -0
- package/dist/openapi/docs-page.js +80 -0
- package/dist/openapi/docs-page.js.map +1 -0
- package/dist/openapi/document.d.ts +4 -0
- package/dist/openapi/document.d.ts.map +1 -1
- package/dist/openapi/document.js +785 -0
- package/dist/openapi/document.js.map +1 -0
- package/dist/openapi/json-schema-slot.d.ts +7 -0
- package/dist/openapi/json-schema-slot.d.ts.map +1 -1
- package/dist/openapi/json-schema-slot.js +38 -0
- package/dist/openapi/json-schema-slot.js.map +1 -0
- package/dist/openapi/register.d.ts.map +1 -1
- package/dist/openapi/register.js +20 -0
- package/dist/openapi/register.js.map +1 -0
- package/dist/openapi/scalar.d.ts +3 -1
- package/dist/openapi/scalar.d.ts.map +1 -1
- package/dist/openapi/scalar.js +21 -0
- package/dist/openapi/scalar.js.map +1 -0
- package/dist/openapi/serve.d.ts +9 -0
- package/dist/openapi/serve.d.ts.map +1 -0
- package/dist/openapi/serve.js +36 -0
- package/dist/openapi/serve.js.map +1 -0
- package/dist/openapi/spec-factory.d.ts +30 -1
- package/dist/openapi/spec-factory.d.ts.map +1 -1
- package/dist/openapi/spec-factory.js +52 -0
- package/dist/openapi/spec-factory.js.map +1 -0
- package/dist/openapi/spec.d.ts +14 -5
- package/dist/openapi/spec.d.ts.map +1 -1
- package/dist/openapi/spec.js +50 -0
- package/dist/openapi/spec.js.map +1 -0
- package/dist/openapi/swagger.d.ts +3 -1
- package/dist/openapi/swagger.d.ts.map +1 -1
- package/dist/openapi/swagger.js +22 -0
- package/dist/openapi/swagger.js.map +1 -0
- package/dist/pattern.d.ts +71 -0
- package/dist/pattern.d.ts.map +1 -0
- package/dist/pattern.js +239 -0
- package/dist/pattern.js.map +1 -0
- package/dist/peer.d.ts +17 -0
- package/dist/peer.d.ts.map +1 -0
- package/dist/peer.js +50 -0
- package/dist/peer.js.map +1 -0
- package/dist/plugin.d.ts +67 -16
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +649 -0
- package/dist/plugin.js.map +1 -0
- package/dist/powered-by.d.ts.map +1 -1
- package/dist/powered-by.js +11 -0
- package/dist/powered-by.js.map +1 -0
- package/dist/pretty-json.d.ts.map +1 -1
- package/dist/pretty-json.js +47 -0
- package/dist/pretty-json.js.map +1 -0
- package/dist/producer-stream.d.ts +47 -0
- package/dist/producer-stream.d.ts.map +1 -0
- package/dist/producer-stream.js +267 -0
- package/dist/producer-stream.js.map +1 -0
- package/dist/proxy.d.ts +47 -8
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js +274 -0
- package/dist/proxy.js.map +1 -0
- package/dist/python-type-emitter.d.ts +14 -1
- package/dist/python-type-emitter.d.ts.map +1 -1
- package/dist/python-type-emitter.js +157 -0
- package/dist/python-type-emitter.js.map +1 -0
- package/dist/realtime/bus.d.ts +17 -1
- package/dist/realtime/bus.d.ts.map +1 -1
- package/dist/realtime/bus.js +112 -0
- package/dist/realtime/bus.js.map +1 -0
- package/dist/realtime/register.d.ts +3 -0
- package/dist/realtime/register.d.ts.map +1 -0
- package/dist/realtime/register.js +10 -0
- package/dist/realtime/register.js.map +1 -0
- package/dist/realtime/route.d.ts +65 -26
- package/dist/realtime/route.d.ts.map +1 -1
- package/dist/realtime/route.js +72 -0
- package/dist/realtime/route.js.map +1 -0
- package/dist/realtime/server.d.ts +43 -0
- package/dist/realtime/server.d.ts.map +1 -0
- package/dist/realtime/server.js +255 -0
- package/dist/realtime/server.js.map +1 -0
- package/dist/request-id.d.ts +7 -0
- package/dist/request-id.d.ts.map +1 -1
- package/dist/request-id.js +16 -0
- package/dist/request-id.js.map +1 -0
- package/dist/request-limits.d.ts +3 -0
- package/dist/request-limits.d.ts.map +1 -0
- package/dist/request-limits.js +3 -0
- package/dist/request-limits.js.map +1 -0
- package/dist/request-path.d.ts +33 -0
- package/dist/request-path.d.ts.map +1 -0
- package/dist/request-path.js +178 -0
- package/dist/request-path.js.map +1 -0
- package/dist/request-to-curl.d.ts +7 -1
- package/dist/request-to-curl.d.ts.map +1 -1
- package/dist/request-to-curl.js +48 -0
- package/dist/request-to-curl.js.map +1 -0
- package/dist/response.d.ts +25 -2
- package/dist/response.d.ts.map +1 -1
- package/dist/response.js +313 -0
- package/dist/response.js.map +1 -0
- package/dist/rust-type-emitter.d.ts +14 -2
- package/dist/rust-type-emitter.d.ts.map +1 -1
- package/dist/rust-type-emitter.js +463 -0
- package/dist/rust-type-emitter.js.map +1 -0
- package/dist/secure-headers.d.ts.map +1 -1
- package/dist/secure-headers.js +53 -0
- package/dist/secure-headers.js.map +1 -0
- package/dist/serve-register.d.ts +4 -0
- package/dist/serve-register.d.ts.map +1 -1
- package/dist/serve-register.js +9 -0
- package/dist/serve-register.js.map +1 -0
- package/dist/serve-slot.d.ts +3 -0
- package/dist/serve-slot.d.ts.map +1 -1
- package/dist/serve-slot.js +52 -0
- package/dist/serve-slot.js.map +1 -0
- package/dist/serve.d.ts +18 -1
- package/dist/serve.d.ts.map +1 -1
- package/dist/serve.js +157 -0
- package/dist/serve.js.map +1 -0
- package/dist/server-timing.d.ts.map +1 -1
- package/dist/server-timing.js +51 -0
- package/dist/server-timing.js.map +1 -0
- package/dist/static.d.ts +9 -0
- package/dist/static.d.ts.map +1 -1
- package/dist/static.js +102 -0
- package/dist/static.js.map +1 -0
- package/dist/telemetry/otel.d.ts +2 -0
- package/dist/telemetry/otel.d.ts.map +1 -1
- package/dist/telemetry/otel.js +135 -0
- package/dist/telemetry/otel.js.map +1 -0
- package/dist/testing.d.ts +12 -0
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +124 -0
- package/dist/testing.js.map +1 -0
- package/dist/timeout.d.ts +6 -0
- package/dist/timeout.d.ts.map +1 -1
- package/dist/timeout.js +36 -0
- package/dist/timeout.js.map +1 -0
- package/dist/tree.d.ts +133 -36
- package/dist/tree.d.ts.map +1 -1
- package/dist/tree.js +437 -0
- package/dist/tree.js.map +1 -0
- package/dist/trust.d.ts +21 -0
- package/dist/trust.d.ts.map +1 -0
- package/dist/trust.js +100 -0
- package/dist/trust.js.map +1 -0
- package/dist/ts-type-emitter.d.ts.map +1 -1
- package/dist/ts-type-emitter.js +150 -0
- package/dist/ts-type-emitter.js.map +1 -0
- package/dist/type-emitter.d.ts +16 -2
- package/dist/type-emitter.d.ts.map +1 -1
- package/dist/type-emitter.js +729 -0
- package/dist/type-emitter.js.map +1 -0
- package/dist/type-extractor.d.ts +8 -4
- package/dist/type-extractor.d.ts.map +1 -1
- package/dist/type-extractor.js +819 -0
- package/dist/type-extractor.js.map +1 -0
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +96 -0
- package/dist/types.js.map +1 -0
- package/dist/validation.d.ts +14 -2
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +335 -0
- package/dist/validation.js.map +1 -0
- package/dist/with-headers.d.ts +15 -0
- package/dist/with-headers.d.ts.map +1 -0
- package/dist/with-headers.js +45 -0
- package/dist/with-headers.js.map +1 -0
- package/dist/ws/bun.d.ts +11 -5
- package/dist/ws/bun.d.ts.map +1 -1
- package/dist/ws/bun.js +82 -0
- package/dist/ws/bun.js.map +1 -0
- package/dist/ws/cloudflare.d.ts +25 -3
- package/dist/ws/cloudflare.d.ts.map +1 -1
- package/dist/ws/cloudflare.js +117 -0
- package/dist/ws/cloudflare.js.map +1 -0
- package/dist/ws/deno.d.ts +4 -4
- package/dist/ws/deno.d.ts.map +1 -1
- package/dist/ws/deno.js +133 -0
- package/dist/ws/deno.js.map +1 -0
- package/dist/ws/node.d.ts +20 -3
- package/dist/ws/node.d.ts.map +1 -1
- package/dist/ws/node.js +173 -0
- package/dist/ws/node.js.map +1 -0
- package/dist/ws/session.d.ts +11 -0
- package/dist/ws/session.d.ts.map +1 -0
- package/dist/ws/session.js +60 -0
- package/dist/ws/session.js.map +1 -0
- package/dist/ws/shared.d.ts +65 -0
- package/dist/ws/shared.d.ts.map +1 -0
- package/dist/ws/shared.js +103 -0
- package/dist/ws/shared.js.map +1 -0
- package/dist/ws-origin.d.ts +20 -0
- package/dist/ws-origin.d.ts.map +1 -0
- package/dist/ws-origin.js +41 -0
- package/dist/ws-origin.js.map +1 -0
- package/dist/yaml.d.ts +15 -1
- package/dist/yaml.d.ts.map +1 -1
- package/dist/yaml.js +101 -0
- package/dist/yaml.js.map +1 -0
- package/docs/invalidate-spec.md +13 -1
- package/docs/meta-spec.md +36 -12
- package/docs/packaging.md +43 -24
- package/docs/regression-matrix/README.md +32 -0
- package/docs/regression-matrix/review.md +44 -0
- package/docs/regression-matrix/ws1-3.md +97 -0
- package/docs/regression-matrix/ws4-8.md +107 -0
- package/docs/regression-matrix/ws9-12.md +266 -0
- package/docs/sdk.md +102 -52
- package/package.json +183 -52
- package/src/accepts.ts +91 -33
- package/src/body-kind.ts +67 -0
- package/src/body-limit.ts +102 -87
- package/src/build/index.ts +104 -54
- package/src/cli-args.ts +123 -0
- package/src/cli-go/auth.go +12 -1
- package/src/cli-go/config.go +29 -2
- package/src/cli-go/errors.go +28 -10
- package/src/cli-go/multipart.go +51 -27
- package/src/cli-go/output.go +58 -4
- package/src/cli-go/root.go +1 -1
- package/src/cli-go/version.go +2 -2
- package/src/cli.ts +154 -148
- package/src/client/error.ts +56 -1
- package/src/client/http.ts +479 -256
- package/src/client/index.ts +55 -17
- package/src/client/path.ts +169 -0
- package/src/client/redirect-policy.ts +19 -0
- package/src/client/sdk.ts +180 -101
- package/src/client/sse.ts +92 -66
- package/src/client/ws.ts +67 -31
- package/src/client-go/errors.go +41 -12
- package/src/client-go/export.go +44 -0
- package/src/client-go/invalidation.go +52 -54
- package/src/client-go/nullable.go +62 -0
- package/src/client-go/realtime.go +147 -110
- package/src/client-go/runtime.go +646 -88
- package/src/client-go/sse.go +104 -94
- package/src/client-go/transport.go +67 -27
- package/src/client-go/ws.go +49 -25
- package/src/client-info.ts +79 -0
- package/src/client-mcp/server.ts +133 -3
- package/src/client-python/_invalidation.py +207 -291
- package/src/client-python/_realtime.py +63 -40
- package/src/client-python/_runtime.py +501 -119
- package/src/client-python/_sse.py +130 -74
- package/src/client-python/_transport.py +37 -9
- package/src/client-python/_ws.py +50 -22
- package/src/client-rust/errors.rs +21 -1
- package/src/client-rust/invalidation.rs +202 -231
- package/src/client-rust/invalidation_sync.rs +16 -229
- package/src/client-rust/nullable.rs +17 -0
- package/src/client-rust/realtime.rs +217 -217
- package/src/client-rust/runtime.rs +602 -177
- package/src/client-rust/runtime_sync.rs +169 -145
- package/src/client-rust/sse.rs +142 -121
- package/src/client-rust/ws.rs +61 -37
- package/src/codegen-go-cli.ts +607 -728
- package/src/codegen-go.ts +710 -770
- package/src/codegen-ir.ts +381 -75
- package/src/codegen-lang.ts +517 -0
- package/src/codegen-load.ts +150 -0
- package/src/codegen-mcp.ts +207 -108
- package/src/codegen-python.ts +684 -816
- package/src/codegen-route-tree-intern.ts +51 -25
- package/src/codegen-rust.ts +946 -1240
- package/src/codegen-sanitize.ts +0 -4
- package/src/codegen-schema-naming.ts +19 -6
- package/src/codegen-sdk-model.ts +228 -0
- package/src/codegen.ts +1488 -1140
- package/src/context.ts +130 -11
- package/src/cookie-sign.ts +85 -16
- package/src/cookie.ts +66 -11
- package/src/cors.ts +55 -54
- package/src/crypto.ts +27 -5
- package/src/csrf.ts +57 -25
- package/src/curl-logger.ts +155 -114
- package/src/dict.ts +12 -0
- package/src/error.ts +4 -2
- package/src/etag.ts +58 -34
- package/src/feature-detect.ts +147 -0
- package/src/feature-slots.ts +70 -0
- package/src/fetch-request.ts +13 -0
- package/src/gen-process.ts +42 -0
- package/src/gen-write.ts +127 -0
- package/src/glob.ts +109 -0
- package/src/go-type-emitter.ts +406 -155
- package/src/honey-response.ts +36 -9
- package/src/i18n-slot.ts +10 -0
- package/src/i18n.ts +98 -23
- package/src/index.ts +1887 -1756
- package/src/init.ts +40 -28
- package/src/invalidate-check.ts +42 -4
- package/src/invoke-user.ts +95 -0
- package/src/ip-restrict.ts +47 -161
- package/src/ip.ts +194 -0
- package/src/logger.ts +65 -36
- package/src/media-type.ts +104 -0
- package/src/meta-spec-merge.ts +80 -0
- package/src/meta-spec.ts +0 -0
- package/src/middleware.ts +112 -12
- package/src/node-request.ts +242 -52
- package/src/node.ts +318 -75
- package/src/openapi/collect.ts +19 -44
- package/src/openapi/docs-page.ts +89 -0
- package/src/openapi/document.ts +503 -224
- package/src/openapi/json-schema-slot.ts +40 -0
- package/src/openapi/register.ts +7 -2
- package/src/openapi/scalar.ts +11 -10
- package/src/openapi/serve.ts +39 -0
- package/src/openapi/spec-factory.ts +50 -1
- package/src/openapi/spec.ts +53 -30
- package/src/openapi/swagger.ts +12 -11
- package/src/pattern.ts +245 -0
- package/src/peer.ts +53 -0
- package/src/plugin.ts +270 -185
- package/src/powered-by.ts +2 -2
- package/src/pretty-json.ts +25 -9
- package/src/producer-stream.ts +296 -0
- package/src/proxy.ts +253 -55
- package/src/python-type-emitter.ts +68 -56
- package/src/realtime/bus.ts +56 -9
- package/src/realtime/register.ts +13 -0
- package/src/realtime/route.ts +129 -80
- package/src/realtime/server.ts +298 -0
- package/src/request-id.ts +13 -3
- package/src/request-limits.ts +2 -0
- package/src/request-path.ts +165 -0
- package/src/request-to-curl.ts +28 -7
- package/src/response.ts +143 -103
- package/src/rust-type-emitter.ts +265 -170
- package/src/secure-headers.ts +8 -4
- package/src/serve-register.ts +4 -0
- package/src/serve-slot.ts +38 -0
- package/src/serve.ts +113 -25
- package/src/server-timing.ts +11 -7
- package/src/static.ts +85 -32
- package/src/telemetry/otel.ts +29 -7
- package/src/testing.ts +76 -14
- package/src/timeout.ts +15 -7
- package/src/tree.ts +405 -333
- package/src/trust.ts +117 -0
- package/src/ts-type-emitter.ts +18 -12
- package/src/type-emitter.ts +227 -89
- package/src/type-extractor.ts +603 -423
- package/src/types.ts +8 -0
- package/src/validation.ts +221 -96
- package/src/with-headers.ts +45 -0
- package/src/ws/bun.ts +53 -15
- package/src/ws/cloudflare.ts +81 -19
- package/src/ws/deno.ts +124 -36
- package/src/ws/node.ts +173 -79
- package/src/ws/session.ts +73 -0
- package/src/ws/shared.ts +140 -0
- package/src/ws-origin.ts +53 -0
- package/src/yaml.ts +45 -22
- package/dist/client-mcp/server.d.ts +0 -10
- package/dist/client-mcp/server.d.ts.map +0 -1
- package/dist/client-mcp/types.d.ts +0 -16
- package/dist/client-mcp/types.d.ts.map +0 -1
- package/dist/cloudflare/realtime.d.ts +0 -30
- package/dist/cloudflare/realtime.d.ts.map +0 -1
- package/dist/realtime/buffer.d.ts +0 -18
- package/dist/realtime/buffer.d.ts.map +0 -1
- package/dist/realtime/longpoll.d.ts +0 -23
- package/dist/realtime/longpoll.d.ts.map +0 -1
- package/dist/realtime/protocol.d.ts +0 -50
- package/dist/realtime/protocol.d.ts.map +0 -1
- package/dist/realtime/runtime.d.ts +0 -74
- package/dist/realtime/runtime.d.ts.map +0 -1
- package/src/cloudflare/realtime.ts +0 -234
- package/src/realtime/buffer.ts +0 -101
- package/src/realtime/longpoll.ts +0 -148
- package/src/realtime/protocol.ts +0 -128
- package/src/realtime/runtime.ts +0 -427
package/src/proxy.ts
CHANGED
|
@@ -1,19 +1,64 @@
|
|
|
1
|
+
import { clientInfo, type HoneyContext } from "./context.ts"
|
|
1
2
|
import { HoneyError } from "./error.ts"
|
|
3
|
+
import { registerFeature } from "./feature-slots.ts"
|
|
4
|
+
import { searchOfUrl } from "./request-path.ts"
|
|
2
5
|
import { EK, SK } from "./types.ts"
|
|
3
6
|
|
|
4
|
-
const BODY_METHODS = new Set(["POST", "PUT", "PATCH"])
|
|
5
|
-
|
|
6
7
|
/* Bodies up to this size with a declared length are forwarded as bytes; larger or unsized ones
|
|
7
8
|
stream (uploads). */
|
|
8
9
|
const MAX_BUFFERED_BODY_BYTES = 1024 * 1024
|
|
9
10
|
|
|
11
|
+
/** Default time allowed until the upstream's response headers arrive. */
|
|
12
|
+
const DEFAULT_TIMEOUT_MS = 60_000
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Hop-by-hop headers (RFC 9110 §7.6.1) describe one connection and never cross a proxy, in
|
|
16
|
+
* either direction. `proxy-connection` is the pre-standard spelling clients still send.
|
|
17
|
+
* Headers a `Connection` header names are hop-by-hop too, see `stripHopByHop`.
|
|
18
|
+
*/
|
|
19
|
+
const HOP_BY_HOP = [
|
|
20
|
+
"connection",
|
|
21
|
+
"keep-alive",
|
|
22
|
+
"proxy-authenticate",
|
|
23
|
+
"proxy-authorization",
|
|
24
|
+
"proxy-connection",
|
|
25
|
+
"te",
|
|
26
|
+
"trailer",
|
|
27
|
+
"transfer-encoding",
|
|
28
|
+
"upgrade",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Client-sent forwarding headers. The app's `trustProxy()` setting has already decided what is
|
|
33
|
+
* true about the client (`clientInfo`); what the client wrote is replaced, never passed on.
|
|
34
|
+
*/
|
|
35
|
+
const FORWARDING = ["forwarded", "x-forwarded-for", "x-forwarded-host", "x-forwarded-proto", "x-real-ip"]
|
|
36
|
+
|
|
37
|
+
/** Statuses whose response can never carry a body: rebuilding one with a body throws. */
|
|
38
|
+
const NULL_BODY = new Set([101, 103, 204, 205, 304])
|
|
39
|
+
|
|
40
|
+
function stripHopByHop(headers: Headers, keepUpgrade: boolean): void {
|
|
41
|
+
const named = headers.get("connection")
|
|
42
|
+
if (named !== null) {
|
|
43
|
+
for (const token of named.split(",")) {
|
|
44
|
+
const name = token.trim().toLowerCase()
|
|
45
|
+
if (name === "" || (keepUpgrade && name === "upgrade")) continue
|
|
46
|
+
headers.delete(name)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
for (const name of HOP_BY_HOP) {
|
|
50
|
+
if (keepUpgrade && name === "upgrade") continue
|
|
51
|
+
headers.delete(name)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
10
55
|
/**
|
|
11
56
|
* A streamed body that the destination never reads (a route without input that was sent `{}`)
|
|
12
57
|
* can keep the call open until it times out: a service binding does not settle while the
|
|
13
58
|
* request stream is unconsumed, and a stream teed by `request.clone()` (a body-logging
|
|
14
59
|
* middleware) has no known length. Bytes have neither problem.
|
|
15
60
|
*/
|
|
16
|
-
async function forwardBody(request: Request): Promise<
|
|
61
|
+
async function forwardBody(request: Request): Promise<ArrayBuffer | ReadableStream<Uint8Array> | null> {
|
|
17
62
|
if (request.body === null) return null
|
|
18
63
|
const declared = request.headers.get("content-length")
|
|
19
64
|
const length = declared === null ? Number.NaN : Number.parseInt(declared, 10)
|
|
@@ -21,33 +66,94 @@ async function forwardBody(request: Request): Promise<BodyInit | null> {
|
|
|
21
66
|
return request.body
|
|
22
67
|
}
|
|
23
68
|
|
|
69
|
+
/** Network-level codes runtimes put on errors when the upstream cannot be reached or drops. */
|
|
70
|
+
const NETWORK_CODES = /^(?:E[A-Z0-9_]+|Connection\w*|UND_ERR\w*|UNABLE_\w+|CERT_\w+|DEPTH_ZERO\w*)$/
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Whether `error` means the upstream failed (502), as opposed to a bug in user code (500).
|
|
74
|
+
* Fetch reports network failures as a `TypeError` — so does a typo in `destination` — and the
|
|
75
|
+
* runtimes tell them apart differently: undici and Deno say "fetch failed" (with a `cause`),
|
|
76
|
+
* Bun puts a `code` on the error (`ConnectionRefused`, `ENOTFOUND`), Workers say the network
|
|
77
|
+
* connection was lost. An invalid URL is the destination's bug.
|
|
78
|
+
*/
|
|
79
|
+
function isUpstreamFailure(error: unknown): boolean {
|
|
80
|
+
if (!(error instanceof Error)) return false
|
|
81
|
+
const code = (error as { code?: unknown }).code
|
|
82
|
+
if (typeof code === "string") return !code.startsWith("ERR_INVALID") && NETWORK_CODES.test(code)
|
|
83
|
+
if (!(error instanceof TypeError)) return false
|
|
84
|
+
const message = error.message
|
|
85
|
+
return /^fetch failed/i.test(message) || /network connection (?:was )?lost/i.test(message)
|
|
86
|
+
}
|
|
87
|
+
|
|
24
88
|
/**
|
|
25
89
|
* Proxy configuration — controls how requests are forwarded to downstream services.
|
|
26
90
|
*
|
|
27
|
-
* `destination` is the only required field.
|
|
91
|
+
* `destination` is the only required field. The framework builds the RequestInit
|
|
28
92
|
* (headers, body, signal, redirect) and passes it along with the resolved URL.
|
|
93
|
+
*
|
|
94
|
+
* What the framework does, both ways:
|
|
95
|
+
* - Hop-by-hop headers (`Connection`, `Keep-Alive`, `Transfer-Encoding`, `TE`, `Trailer`,
|
|
96
|
+
* `Upgrade`, `Proxy-*`, and every header `Connection` names) are dropped. A WebSocket upgrade
|
|
97
|
+
* keeps `Upgrade: websocket` and `Connection: upgrade`.
|
|
98
|
+
* - The client's `Host` is not sent: the upstream sees the destination's host.
|
|
99
|
+
* `X-Forwarded-For`, `-Proto` and `-Host` describe the client as the app's `trustProxy()`
|
|
100
|
+
* setting decided it (`clientInfo(ctx)`), with one `X-Forwarded-For` entry; whatever
|
|
101
|
+
* forwarding headers the client sent (`Forwarded`, `X-Forwarded-*`, `X-Real-IP`) are dropped.
|
|
102
|
+
* Configure the upstream to trust exactly one hop: this proxy.
|
|
103
|
+
* - `Expect` is dropped (the proxy reads the body itself).
|
|
104
|
+
* - Every method except GET and HEAD forwards its body (DELETE, OPTIONS, PROPFIND…).
|
|
105
|
+
* - The request follows `ctx.signal`: a client disconnect, `timeout()` or shutdown cancels the
|
|
106
|
+
* upstream call and its body.
|
|
107
|
+
* - Redirects are returned to the client, never followed.
|
|
29
108
|
*/
|
|
30
109
|
export type ProxyConfig<TCtx> = {
|
|
31
110
|
/**
|
|
32
111
|
* Where to send the request. Framework doesn't care how — CF service binding,
|
|
33
112
|
* URL fetch, Durable Object stub, anything that returns a Response.
|
|
34
113
|
*
|
|
114
|
+
* A network failure the runtime reports (connection refused, DNS, reset) answers 502; any
|
|
115
|
+
* other throw — a bug in this function included — is a 500.
|
|
116
|
+
*
|
|
35
117
|
* @param ctx - honey context (middleware additions available)
|
|
36
|
-
* @param url - path + query string, after rewriteUrl if provided
|
|
118
|
+
* @param url - normalized path + query string, after rewriteUrl if provided
|
|
37
119
|
* @param init - framework-prepared RequestInit (method, headers, body, signal, redirect)
|
|
38
120
|
*/
|
|
39
121
|
destination: (ctx: TCtx, url: string, init: RequestInit) => Response | Promise<Response>
|
|
40
122
|
|
|
123
|
+
/**
|
|
124
|
+
* Whether the destination's Response body is already decoded, as `fetch()` always returns
|
|
125
|
+
* it (the runtime decompresses gzip, br, zstd and keeps the `Content-Encoding` header).
|
|
126
|
+
* When true (the default), `Content-Encoding` and `Content-Length` are dropped from encoded
|
|
127
|
+
* responses so the headers describe the bytes the client gets. Set false when the
|
|
128
|
+
* destination returns bytes still encoded (a store of compressed objects), so the headers
|
|
129
|
+
* pass through.
|
|
130
|
+
*/
|
|
131
|
+
decoded?: boolean
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Add `X-Forwarded-For`, `-Proto` and `-Host`. Default true. Client-sent forwarding headers
|
|
135
|
+
* are dropped either way.
|
|
136
|
+
*/
|
|
137
|
+
forwardedHeaders?: boolean
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Most milliseconds the upstream may stay silent while the body streams: the time between
|
|
141
|
+
* two chunks. Omitted or non-positive: no limit (streams such as SSE may idle). A stall
|
|
142
|
+
* aborts the upstream and errors the body. Disabled for WebSocket upgrades.
|
|
143
|
+
*/
|
|
144
|
+
idleTimeout?: number | ((ctx: TCtx) => number)
|
|
145
|
+
|
|
41
146
|
/**
|
|
42
147
|
* Hook after downstream responds, before returning to client.
|
|
43
148
|
* Return void to passthrough, or return a new Response to replace.
|
|
44
|
-
*
|
|
149
|
+
* The response is the proxy's own copy, so its headers can be set in place.
|
|
45
150
|
* NOT called for 101 WebSocket upgrades (opaque response).
|
|
46
151
|
*/
|
|
47
152
|
onResponse?: (ctx: TCtx, response: Response) => void | Response | Promise<void | Response>
|
|
48
153
|
|
|
49
154
|
/**
|
|
50
|
-
* Set request headers before forwarding. Called after hop-by-hop
|
|
155
|
+
* Set request headers before forwarding. Called after hop-by-hop and forwarding headers
|
|
156
|
+
* are handled, so it can override any of them (including `Host` on runtimes that send it).
|
|
51
157
|
* Static record: entries are set on the headers object.
|
|
52
158
|
* Function: mutate headers in place.
|
|
53
159
|
*/
|
|
@@ -55,18 +161,87 @@ export type ProxyConfig<TCtx> = {
|
|
|
55
161
|
|
|
56
162
|
/**
|
|
57
163
|
* Rewrite URL before passing to destination.
|
|
58
|
-
* Receives path + query string, returns transformed URL.
|
|
164
|
+
* Receives the normalized path + query string, returns transformed URL.
|
|
59
165
|
*/
|
|
60
166
|
rewriteUrl?: (url: string, ctx: TCtx) => string
|
|
61
167
|
|
|
62
168
|
/**
|
|
63
|
-
*
|
|
64
|
-
* value: no
|
|
65
|
-
*
|
|
169
|
+
* Most milliseconds to wait for the upstream's response headers; a later answer is a 504.
|
|
170
|
+
* Default 60 000. `0` or a non-positive value: no limit. The body is not covered — see
|
|
171
|
+
* `idleTimeout`. Accepts a number or a function of ctx. Disabled for WebSocket upgrades.
|
|
66
172
|
*/
|
|
67
173
|
timeout?: number | ((ctx: TCtx) => number)
|
|
68
174
|
}
|
|
69
175
|
|
|
176
|
+
function resolveMs<TCtx>(opt: number | ((ctx: TCtx) => number) | undefined, ctx: TCtx, fallback?: number) {
|
|
177
|
+
const ms = typeof opt === "function" ? opt(ctx) : (opt ?? fallback)
|
|
178
|
+
return ms !== undefined && ms > 0 ? ms : undefined
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function timeoutError(): DOMException {
|
|
182
|
+
return new DOMException("upstream timed out", "TimeoutError")
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* The body, erroring (and aborting the upstream through `onIdle`) when the upstream sends
|
|
187
|
+
* nothing for `ms`. The clock runs only while a read is outstanding: a client that reads slowly
|
|
188
|
+
* is backpressure, not an idle upstream.
|
|
189
|
+
*/
|
|
190
|
+
function withIdleTimeout(body: ReadableStream<Uint8Array>, ms: number, onIdle: () => void): ReadableStream<Uint8Array> {
|
|
191
|
+
const reader = body.getReader()
|
|
192
|
+
return new ReadableStream<Uint8Array>({
|
|
193
|
+
async cancel(reason) {
|
|
194
|
+
await reader.cancel(reason)
|
|
195
|
+
},
|
|
196
|
+
async pull(controller) {
|
|
197
|
+
let timer: ReturnType<typeof setTimeout> | undefined
|
|
198
|
+
const idle = new Promise<"idle">((resolve) => {
|
|
199
|
+
timer = setTimeout(() => resolve("idle"), ms)
|
|
200
|
+
})
|
|
201
|
+
try {
|
|
202
|
+
const result = await Promise.race([reader.read(), idle])
|
|
203
|
+
if (result === "idle") {
|
|
204
|
+
onIdle()
|
|
205
|
+
const error = timeoutError()
|
|
206
|
+
/* the upstream may not react to the abort (a binding, a stub): drop it either way */
|
|
207
|
+
reader.cancel(error).catch(() => {})
|
|
208
|
+
controller.error(error)
|
|
209
|
+
} else if (result.done) {
|
|
210
|
+
controller.close()
|
|
211
|
+
} else {
|
|
212
|
+
controller.enqueue(result.value)
|
|
213
|
+
}
|
|
214
|
+
} catch (error) {
|
|
215
|
+
controller.error(error)
|
|
216
|
+
} finally {
|
|
217
|
+
clearTimeout(timer)
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
})
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* The response the client gets: hop-by-hop headers dropped, encoding headers made true for
|
|
225
|
+
* the bytes, in a copy whose headers are mutable (fetch() responses are immutable).
|
|
226
|
+
*/
|
|
227
|
+
function clientResponse(response: Response, decoded: boolean, body: ReadableStream<Uint8Array> | null): Response {
|
|
228
|
+
const headers = new Headers(response.headers)
|
|
229
|
+
stripHopByHop(headers, false)
|
|
230
|
+
if (decoded) {
|
|
231
|
+
const encoding = headers.get("content-encoding")
|
|
232
|
+
if (encoding !== null && encoding.trim().toLowerCase() !== "identity") {
|
|
233
|
+
headers.delete("content-encoding")
|
|
234
|
+
/* the length of the encoded bytes, not of the decoded body the client receives */
|
|
235
|
+
headers.delete("content-length")
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return new Response(NULL_BODY.has(response.status) ? null : body, {
|
|
239
|
+
headers,
|
|
240
|
+
status: response.status,
|
|
241
|
+
statusText: response.statusText,
|
|
242
|
+
})
|
|
243
|
+
}
|
|
244
|
+
|
|
70
245
|
/**
|
|
71
246
|
* Creates a proxy handler function from config.
|
|
72
247
|
* Used internally by RouteBuilder.proxy() — not meant for direct consumption.
|
|
@@ -76,39 +251,45 @@ export type ProxyConfig<TCtx> = {
|
|
|
76
251
|
* which has both fields — we access them via property access on the object.
|
|
77
252
|
*/
|
|
78
253
|
export function createProxyHandler<TCtx>(config: ProxyConfig<TCtx>): (ctx: TCtx) => Promise<Response> {
|
|
79
|
-
const
|
|
254
|
+
const decoded = config.decoded !== false
|
|
255
|
+
const forwarded = config.forwardedHeaders !== false
|
|
80
256
|
|
|
81
257
|
return async (ctx: TCtx) => {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const
|
|
85
|
-
const
|
|
86
|
-
const
|
|
87
|
-
const
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
/* URL
|
|
91
|
-
const
|
|
92
|
-
const
|
|
93
|
-
const pathStart = protoEnd === -1 ? 0 : rawUrl.indexOf("/", protoEnd + 2)
|
|
94
|
-
const qIdx = pathStart === -1 ? -1 : rawUrl.indexOf("?", pathStart)
|
|
95
|
-
const pathOnly = c["path"] as string
|
|
96
|
-
const rawPathQuery = qIdx === -1 ? pathOnly : pathOnly + rawUrl.substring(qIdx)
|
|
97
|
-
const url = config.rewriteUrl ? config.rewriteUrl(rawPathQuery, ctx) : rawPathQuery
|
|
98
|
-
|
|
99
|
-
/* headers — one copy (original is immutable), strip hop-by-hop */
|
|
100
|
-
const headers = new Headers(request.headers)
|
|
101
|
-
headers.delete("connection")
|
|
102
|
-
headers.delete("keep-alive")
|
|
103
|
-
headers.delete("transfer-encoding")
|
|
104
|
-
headers.delete("te")
|
|
105
|
-
headers.delete("trailer")
|
|
106
|
-
headers.delete("proxy-authenticate")
|
|
107
|
-
headers.delete("proxy-authorization")
|
|
258
|
+
/* HoneyContext always has path + req + signal — safe at runtime */
|
|
259
|
+
const c = ctx as unknown as HoneyContext
|
|
260
|
+
const request = c.req
|
|
261
|
+
const method = request.method.toUpperCase()
|
|
262
|
+
const isWs = request.headers.get("upgrade")?.trim().toLowerCase() === "websocket"
|
|
263
|
+
const headerMs = isWs ? undefined : resolveMs(config.timeout, ctx, DEFAULT_TIMEOUT_MS)
|
|
264
|
+
const idleMs = isWs ? undefined : resolveMs(config.idleTimeout, ctx)
|
|
265
|
+
|
|
266
|
+
/* URL: the normalized path the router matched, plus the raw query — no new URL() */
|
|
267
|
+
const pathQuery = c.path + searchOfUrl(request.url)
|
|
268
|
+
const url = config.rewriteUrl ? config.rewriteUrl(pathQuery, ctx) : pathQuery
|
|
108
269
|
|
|
270
|
+
/* headers — one copy (the original is immutable) */
|
|
271
|
+
const headers = new Headers(request.headers)
|
|
272
|
+
stripHopByHop(headers, isWs)
|
|
109
273
|
if (isWs) {
|
|
274
|
+
headers.set("upgrade", "websocket")
|
|
110
275
|
headers.set("connection", "upgrade")
|
|
111
276
|
}
|
|
277
|
+
headers.delete("host")
|
|
278
|
+
headers.delete("expect")
|
|
279
|
+
for (const name of FORWARDING) headers.delete(name)
|
|
280
|
+
if (forwarded) {
|
|
281
|
+
const client = clientInfo(c)
|
|
282
|
+
if (client.ip !== null) headers.set("x-forwarded-for", client.ip)
|
|
283
|
+
headers.set("x-forwarded-proto", client.protocol)
|
|
284
|
+
if (client.host !== null) headers.set("x-forwarded-host", client.host)
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/* body: every method that can carry one (fetch refuses a GET or HEAD body) */
|
|
288
|
+
const body = method === "GET" || method === "HEAD" ? null : await forwardBody(request)
|
|
289
|
+
if (body === null || body instanceof ArrayBuffer) {
|
|
290
|
+
/* no body, or bytes whose length fetch() computes itself */
|
|
291
|
+
headers.delete("content-length")
|
|
292
|
+
}
|
|
112
293
|
|
|
113
294
|
if (config.requestHeaders) {
|
|
114
295
|
if (typeof config.requestHeaders === "function") {
|
|
@@ -120,14 +301,17 @@ export function createProxyHandler<TCtx>(config: ProxyConfig<TCtx>): (ctx: TCtx)
|
|
|
120
301
|
}
|
|
121
302
|
}
|
|
122
303
|
|
|
123
|
-
/*
|
|
124
|
-
const
|
|
304
|
+
/* one controller for the proxy's own timeouts, following the request's signal */
|
|
305
|
+
const upstream = new AbortController()
|
|
306
|
+
const clientSignal = c.signal as AbortSignal | undefined
|
|
307
|
+
const signal = clientSignal ? AbortSignal.any([clientSignal, upstream.signal]) : upstream.signal
|
|
308
|
+
|
|
125
309
|
const init: RequestInit = {
|
|
126
310
|
body: body ?? undefined,
|
|
127
311
|
headers,
|
|
128
312
|
method,
|
|
129
313
|
redirect: "manual",
|
|
130
|
-
signal
|
|
314
|
+
signal,
|
|
131
315
|
}
|
|
132
316
|
|
|
133
317
|
/* duplex required for streaming body (Node needs it, CF handles implicitly) */
|
|
@@ -136,23 +320,29 @@ export function createProxyHandler<TCtx>(config: ProxyConfig<TCtx>): (ctx: TCtx)
|
|
|
136
320
|
}
|
|
137
321
|
|
|
138
322
|
/* forward */
|
|
323
|
+
let headerTimedOut = false
|
|
324
|
+
const headerTimer =
|
|
325
|
+
headerMs === undefined
|
|
326
|
+
? undefined
|
|
327
|
+
: setTimeout(() => {
|
|
328
|
+
headerTimedOut = true
|
|
329
|
+
upstream.abort(timeoutError())
|
|
330
|
+
}, headerMs)
|
|
139
331
|
let response: Response
|
|
140
332
|
try {
|
|
141
333
|
response = await config.destination(ctx, url, init)
|
|
142
334
|
} catch (error) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
status: SK.gateway_timeout,
|
|
147
|
-
})
|
|
335
|
+
/* ours, or the destination's own AbortSignal.timeout() */
|
|
336
|
+
if (headerTimedOut || (error instanceof DOMException && error.name === "TimeoutError")) {
|
|
337
|
+
throw new HoneyError({ errorKey: EK.gateway_timeout, status: SK.gateway_timeout })
|
|
148
338
|
}
|
|
149
|
-
if (
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
status: SK.bad_gateway,
|
|
153
|
-
})
|
|
339
|
+
if (clientSignal?.aborted) throw error
|
|
340
|
+
if (isUpstreamFailure(error)) {
|
|
341
|
+
throw new HoneyError({ errorKey: EK.bad_gateway, status: SK.bad_gateway })
|
|
154
342
|
}
|
|
155
343
|
throw error
|
|
344
|
+
} finally {
|
|
345
|
+
clearTimeout(headerTimer)
|
|
156
346
|
}
|
|
157
347
|
|
|
158
348
|
/* WS 101 — return immediately, opaque */
|
|
@@ -160,13 +350,21 @@ export function createProxyHandler<TCtx>(config: ProxyConfig<TCtx>): (ctx: TCtx)
|
|
|
160
350
|
return response
|
|
161
351
|
}
|
|
162
352
|
|
|
353
|
+
let responseBody: ReadableStream<Uint8Array> | null = response.body
|
|
354
|
+
if (responseBody !== null && idleMs !== undefined) {
|
|
355
|
+
responseBody = withIdleTimeout(responseBody, idleMs, () => upstream.abort(timeoutError()))
|
|
356
|
+
}
|
|
357
|
+
let result = clientResponse(response, decoded, responseBody)
|
|
358
|
+
|
|
163
359
|
/* response hook */
|
|
164
360
|
if (config.onResponse) {
|
|
165
|
-
const replaced = await config.onResponse(ctx,
|
|
166
|
-
if (replaced)
|
|
361
|
+
const replaced = await config.onResponse(ctx, result)
|
|
362
|
+
if (replaced) result = replaced
|
|
167
363
|
}
|
|
168
364
|
|
|
169
|
-
|
|
170
|
-
return response
|
|
365
|
+
return result
|
|
171
366
|
}
|
|
172
367
|
}
|
|
368
|
+
|
|
369
|
+
/* `import "@lovrozagar/honey/proxy"` is what makes `.proxy()` available; the core never imports this module */
|
|
370
|
+
registerFeature("proxy", { createProxyHandler })
|
|
@@ -1,50 +1,23 @@
|
|
|
1
1
|
import { schemaToIR } from "./codegen-ir.ts"
|
|
2
2
|
import type { IRField, IRSchema } from "./codegen-ir.ts"
|
|
3
|
+
import { cmpCodeUnit, pyClassName, pyString } from "./codegen-lang.ts"
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
"None",
|
|
7
|
-
"True",
|
|
8
|
-
"and",
|
|
9
|
-
"as",
|
|
10
|
-
"assert",
|
|
11
|
-
"async",
|
|
12
|
-
"await",
|
|
13
|
-
"break",
|
|
14
|
-
"class",
|
|
15
|
-
"continue",
|
|
16
|
-
"def",
|
|
17
|
-
"del",
|
|
18
|
-
"elif",
|
|
19
|
-
"else",
|
|
20
|
-
"except",
|
|
21
|
-
"finally",
|
|
22
|
-
"for",
|
|
23
|
-
"from",
|
|
24
|
-
"global",
|
|
25
|
-
"if",
|
|
26
|
-
"import",
|
|
27
|
-
"in",
|
|
28
|
-
"is",
|
|
29
|
-
"lambda",
|
|
30
|
-
"nonlocal",
|
|
31
|
-
"not",
|
|
32
|
-
"or",
|
|
33
|
-
"pass",
|
|
34
|
-
"raise",
|
|
35
|
-
"return",
|
|
36
|
-
"try",
|
|
37
|
-
"while",
|
|
38
|
-
"with",
|
|
39
|
-
"yield",
|
|
40
|
-
])
|
|
41
|
-
|
|
42
|
-
/** Suffix reserved words with `_` per PEP 8 convention. */
|
|
5
|
+
/** Attribute-safe name that keeps the original casing (`apiKeys` stays `apiKeys`).
|
|
6
|
+
* Non-identifier characters become `_`; keywords get a `_` suffix per PEP 8. */
|
|
43
7
|
export function pyIdent(name: string): string {
|
|
44
|
-
|
|
45
|
-
|
|
8
|
+
let out = name.replace(/[^A-Za-z0-9_]/g, "_")
|
|
9
|
+
if (out === "") out = "value"
|
|
10
|
+
if (/^[0-9]/.test(out)) out = `_${out}`
|
|
11
|
+
if (PY_HARD_KEYWORDS.has(out) || out === "self") return `${out}_`
|
|
12
|
+
return out
|
|
46
13
|
}
|
|
47
14
|
|
|
15
|
+
const PY_HARD_KEYWORDS = new Set(
|
|
16
|
+
"False None True and as assert async await break class continue def del elif else except finally for from global if import in is lambda nonlocal not or pass raise return try while with yield".split(
|
|
17
|
+
" ",
|
|
18
|
+
),
|
|
19
|
+
)
|
|
20
|
+
|
|
48
21
|
function primitiveToPy(t: string): string {
|
|
49
22
|
if (t === "string") return "str"
|
|
50
23
|
if (t === "integer") return "int"
|
|
@@ -55,34 +28,52 @@ function primitiveToPy(t: string): string {
|
|
|
55
28
|
}
|
|
56
29
|
|
|
57
30
|
function formatConstPy(v: string | number | boolean): string {
|
|
58
|
-
if (typeof v === "string") return
|
|
31
|
+
if (typeof v === "string") return pyString(v)
|
|
59
32
|
if (typeof v === "boolean") return v ? "True" : "False"
|
|
60
33
|
return String(v)
|
|
61
34
|
}
|
|
62
35
|
|
|
63
36
|
function emitScalarPy(ir: Extract<IRSchema, { kind: "scalar" }>): string {
|
|
64
37
|
if (ir.enum) {
|
|
65
|
-
const members = ir.enum
|
|
38
|
+
const members = ir.enum
|
|
39
|
+
.filter((v) => v !== null)
|
|
40
|
+
.map((v) => (typeof v === "string" ? pyString(v) : typeof v === "boolean" ? (v ? "True" : "False") : String(v)))
|
|
41
|
+
.join(", ")
|
|
42
|
+
if (members === "") return primitiveToPy(ir.type)
|
|
66
43
|
return `Literal[${members}]`
|
|
67
44
|
}
|
|
68
45
|
return primitiveToPy(ir.type)
|
|
69
46
|
}
|
|
70
47
|
|
|
71
|
-
|
|
48
|
+
/** Module-level naming for generated types. Without it, nested objects render inline. */
|
|
49
|
+
export type PyTypeNames = {
|
|
50
|
+
ref: (schemaName: string) => string
|
|
51
|
+
/** Hoists an object schema to a named TypedDict and returns its name. */
|
|
52
|
+
hoist: (key: string, base: string, schema: Extract<IRSchema, { kind: "object" }>) => string
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
type Ctx = { names?: PyTypeNames; parent: string; field: string }
|
|
56
|
+
|
|
57
|
+
function emitObjectPy(ir: Extract<IRSchema, { kind: "object" }>, depth: number, ctx: Ctx): string {
|
|
72
58
|
const { fields, additional } = ir
|
|
73
59
|
|
|
74
60
|
if (fields.length === 0) {
|
|
75
61
|
if (additional) {
|
|
76
|
-
return `dict[str, ${
|
|
62
|
+
return `dict[str, ${irToPythonCtx(additional, depth + 1, { ...ctx, field: `${ctx.field}Value` })}]`
|
|
77
63
|
}
|
|
78
64
|
return "dict[str, Any]"
|
|
79
65
|
}
|
|
80
66
|
|
|
81
|
-
|
|
67
|
+
if (ctx.names) {
|
|
68
|
+
const base = ctx.field === "" ? ctx.parent : `${ctx.parent}${pyClassName(ctx.field)}`
|
|
69
|
+
return ctx.names.hoist(`${ctx.parent}.${ctx.field}`, base, ir)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const sortedFields = fields.slice().sort((a, b) => cmpCodeUnit(a.name, b.name))
|
|
82
73
|
const entries = sortedFields.map((f) => {
|
|
83
|
-
const pyType =
|
|
74
|
+
const pyType = irToPythonCtx(f.schema, depth + 1, ctx)
|
|
84
75
|
const annotation = f.required ? pyType : `NotRequired[${pyType}]`
|
|
85
|
-
return `${
|
|
76
|
+
return `${pyString(f.name)}: ${annotation}`
|
|
86
77
|
})
|
|
87
78
|
|
|
88
79
|
return `TypedDict("X", {${entries.join(", ")}})`
|
|
@@ -93,6 +84,15 @@ function emitObjectPy(ir: Extract<IRSchema, { kind: "object" }>, depth: number):
|
|
|
93
84
|
* depth > 8 returns `Any` (mirrors TS `unknown` fallback).
|
|
94
85
|
*/
|
|
95
86
|
export function irToPython(ir: IRSchema, depth = 0): string {
|
|
87
|
+
return irToPythonCtx(ir, depth, { field: "Value", parent: "Model" })
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** `irToPython` with module naming: refs map to emitted class names, nested objects are hoisted. */
|
|
91
|
+
export function irToPythonNamed(ir: IRSchema, names: PyTypeNames, parent: string, field: string): string {
|
|
92
|
+
return irToPythonCtx(ir, 0, { field, names, parent })
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function irToPythonCtx(ir: IRSchema, depth: number, ctx: Ctx): string {
|
|
96
96
|
if (depth > 8) return "Any"
|
|
97
97
|
|
|
98
98
|
switch (ir.kind) {
|
|
@@ -103,13 +103,15 @@ export function irToPython(ir: IRSchema, depth = 0): string {
|
|
|
103
103
|
return `Literal[${formatConstPy(ir.value)}]`
|
|
104
104
|
|
|
105
105
|
case "object":
|
|
106
|
-
return emitObjectPy(ir, depth)
|
|
106
|
+
return emitObjectPy(ir, depth, ctx)
|
|
107
107
|
|
|
108
108
|
case "array":
|
|
109
|
-
return `list[${
|
|
109
|
+
return `list[${irToPythonCtx(ir.items, depth + 1, { ...ctx, field: `${ctx.field}Item` })}]`
|
|
110
110
|
|
|
111
111
|
case "tuple":
|
|
112
|
-
return
|
|
112
|
+
return ir.items.length === 0
|
|
113
|
+
? "tuple[()]"
|
|
114
|
+
: `tuple[${ir.items.map((i, n) => irToPythonCtx(i, depth + 1, { ...ctx, field: `${ctx.field}${n}` })).join(", ")}]`
|
|
113
115
|
|
|
114
116
|
case "union": {
|
|
115
117
|
/* union-of-const → single Literal[...] to match mixed enum behavior */
|
|
@@ -119,12 +121,17 @@ export function irToPython(ir: IRSchema, depth = 0): string {
|
|
|
119
121
|
.join(", ")
|
|
120
122
|
return `Literal[${members}]`
|
|
121
123
|
}
|
|
122
|
-
return ir.variants
|
|
124
|
+
return ir.variants
|
|
125
|
+
.map((v, n) => irToPythonCtx(v, depth + 1, { ...ctx, field: `${ctx.field}Variant${n}` }))
|
|
126
|
+
.join(" | ")
|
|
123
127
|
}
|
|
124
128
|
|
|
125
129
|
case "allOf": {
|
|
126
130
|
const allObjects = ir.parts.every((p) => p.kind === "object")
|
|
127
|
-
if (!allObjects)
|
|
131
|
+
if (!allObjects) {
|
|
132
|
+
if (ctx.names && ir.parts.length === 1) return irToPythonCtx(ir.parts[0], depth + 1, ctx)
|
|
133
|
+
return "Any"
|
|
134
|
+
}
|
|
128
135
|
/* later parts overwrite earlier (mirrors Object.assign semantics in old jsonSchemaToPy) */
|
|
129
136
|
const mergedMap = new Map<string, IRField>()
|
|
130
137
|
const requiredSet = new Set<string>()
|
|
@@ -140,14 +147,14 @@ export function irToPython(ir: IRSchema, depth = 0): string {
|
|
|
140
147
|
mf.required = requiredSet.has(f.name)
|
|
141
148
|
return mf
|
|
142
149
|
})
|
|
143
|
-
return emitObjectPy({ fields: mergedFields, kind: "object" }, depth)
|
|
150
|
+
return emitObjectPy({ fields: mergedFields, kind: "object" }, depth, ctx)
|
|
144
151
|
}
|
|
145
152
|
|
|
146
153
|
case "ref":
|
|
147
|
-
return ir.name
|
|
154
|
+
return ctx.names ? ctx.names.ref(ir.name) : ir.name
|
|
148
155
|
|
|
149
156
|
case "nullable":
|
|
150
|
-
return `${
|
|
157
|
+
return `${irToPythonCtx(ir.inner, depth + 1, ctx)} | None`
|
|
151
158
|
|
|
152
159
|
/*
|
|
153
160
|
* binary kind arises from {type:"string", format:"binary"}.
|
|
@@ -167,3 +174,8 @@ export function jsonSchemaToPy(schema: Record<string, unknown> | undefined, dept
|
|
|
167
174
|
if (!schema || depth > 8) return "Any"
|
|
168
175
|
return irToPython(schemaToIR(schema), depth)
|
|
169
176
|
}
|
|
177
|
+
|
|
178
|
+
/** A key usable as a TypedDict class-syntax attribute (else the functional syntax is used). */
|
|
179
|
+
export function isPyAttributeKey(key: string): boolean {
|
|
180
|
+
return /^[A-Za-z_][A-Za-z0-9_]*$/.test(key) && !PY_HARD_KEYWORDS.has(key) && !key.startsWith("__")
|
|
181
|
+
}
|