stitchkit 0.94.0 → 0.94.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/CHANGELOG.md +64 -0
- package/dist/agent-runtime/coding-shell-process.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-listing.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-search-patch.d.ts.map +1 -1
- package/dist/agent-runtime/contained-darwin.d.ts +38 -0
- package/dist/agent-runtime/contained-darwin.d.ts.map +1 -0
- package/dist/agent-runtime/contained-files.d.ts +11 -26
- package/dist/agent-runtime/contained-files.d.ts.map +1 -1
- package/dist/agent-runtime/contained-scan.d.ts +21 -0
- package/dist/agent-runtime/contained-scan.d.ts.map +1 -0
- package/dist/agent-runtime/contained-write.d.ts +9 -0
- package/dist/agent-runtime/contained-write.d.ts.map +1 -0
- package/dist/agent-runtime/deferred-tool-types.d.ts +3 -2
- package/dist/agent-runtime/deferred-tool-types.d.ts.map +1 -1
- package/dist/agent-runtime/harness-control.d.ts +0 -1
- package/dist/agent-runtime/harness-control.d.ts.map +1 -1
- package/dist/agent-runtime/harness.d.ts +0 -5
- package/dist/agent-runtime/harness.d.ts.map +1 -1
- package/dist/agent-runtime/managed-tools.d.ts +3 -2
- package/dist/agent-runtime/managed-tools.d.ts.map +1 -1
- package/dist/agent-runtime/runtime.d.ts +1 -1
- package/dist/agent-runtime/runtime.d.ts.map +1 -1
- package/dist/agent-runtime/schedule-records.d.ts +34 -0
- package/dist/agent-runtime/schedule-records.d.ts.map +1 -0
- package/dist/agent-runtime/schedules.d.ts +34 -0
- package/dist/agent-runtime/schedules.d.ts.map +1 -1
- package/dist/agent-runtime/store-conformance-lifecycle.d.ts +434 -0
- package/dist/agent-runtime/store-conformance-lifecycle.d.ts.map +1 -0
- package/dist/agent-runtime/store-conformance-ordering.d.ts +18 -0
- package/dist/agent-runtime/store-conformance-ordering.d.ts.map +1 -0
- package/dist/agent-runtime/store-conformance-support.d.ts +130 -0
- package/dist/agent-runtime/store-conformance-support.d.ts.map +1 -0
- package/dist/agent-runtime/store-conformance-terminal.d.ts +12 -0
- package/dist/agent-runtime/store-conformance-terminal.d.ts.map +1 -0
- package/dist/agent-runtime/store-conformance.d.ts.map +1 -1
- package/dist/application/admission-rate.d.ts +21 -0
- package/dist/application/admission-rate.d.ts.map +1 -0
- package/dist/application/admission-run.d.ts +8 -0
- package/dist/application/admission-run.d.ts.map +1 -0
- package/dist/application/admission.d.ts.map +1 -1
- package/dist/application/diagnostic-journal-lock.d.ts +9 -34
- package/dist/application/diagnostic-journal-lock.d.ts.map +1 -1
- package/dist/application/diagnostic-journal-manager.d.ts.map +1 -1
- package/dist/application/diagnostic-journal-storage.d.ts.map +1 -1
- package/dist/application/kernel-resource-context.d.ts.map +1 -1
- package/dist/application/notification-outbox.d.ts.map +1 -1
- package/dist/application/schedule.d.ts +0 -1
- package/dist/application/schedule.d.ts.map +1 -1
- package/dist/application/watch-hub-core.d.ts +122 -0
- package/dist/application/watch-hub-core.d.ts.map +1 -0
- package/dist/application/watch-hub.d.ts +2 -2
- package/dist/application/watch-hub.d.ts.map +1 -1
- package/dist/browser/client-executors.d.ts +14 -0
- package/dist/browser/client-executors.d.ts.map +1 -0
- package/dist/browser/client-multipart.d.ts +1 -1
- package/dist/browser/client-multipart.d.ts.map +1 -1
- package/dist/browser/client.d.ts +3 -2
- package/dist/browser/client.d.ts.map +1 -1
- package/dist/browser/http-fetch.d.ts +22 -0
- package/dist/browser/http-fetch.d.ts.map +1 -0
- package/dist/browser/http.d.ts +1 -3
- package/dist/browser/http.d.ts.map +1 -1
- package/dist/browser/live-state-core.d.ts +63 -0
- package/dist/browser/live-state-core.d.ts.map +1 -0
- package/dist/browser/live-state.d.ts.map +1 -1
- package/dist/browser/realtime-client.d.ts +26 -0
- package/dist/browser/realtime-client.d.ts.map +1 -0
- package/dist/browser/socket-io-connection.d.ts +82 -0
- package/dist/browser/socket-io-connection.d.ts.map +1 -0
- package/dist/browser/socket-io-peer.d.ts +20 -0
- package/dist/browser/socket-io-peer.d.ts.map +1 -0
- package/dist/browser/socket-io-trace.d.ts +31 -0
- package/dist/browser/socket-io-trace.d.ts.map +1 -0
- package/dist/browser/socket-io.d.ts +2 -18
- package/dist/browser/socket-io.d.ts.map +1 -1
- package/dist/contract/client-types.d.ts +134 -0
- package/dist/contract/client-types.d.ts.map +1 -0
- package/dist/contract/define-validation.d.ts +30 -0
- package/dist/contract/define-validation.d.ts.map +1 -0
- package/dist/contract/define.d.ts +3 -357
- package/dist/contract/define.d.ts.map +1 -1
- package/dist/contract/runtime-context.d.ts +131 -0
- package/dist/contract/runtime-context.d.ts.map +1 -0
- package/dist/contract/tool-options.d.ts +105 -0
- package/dist/contract/tool-options.d.ts.map +1 -0
- package/dist/contract/tool-view.d.ts +15 -2
- package/dist/contract/tool-view.d.ts.map +1 -1
- package/dist/durability/contract.d.ts +83 -0
- package/dist/durability/contract.d.ts.map +1 -1
- package/dist/durability/effect.d.ts +24 -0
- package/dist/durability/effect.d.ts.map +1 -0
- package/dist/durability/engine.d.ts +2 -2
- package/dist/durability/engine.d.ts.map +1 -1
- package/dist/durability/events.d.ts +2 -0
- package/dist/durability/events.d.ts.map +1 -1
- package/dist/durability/ledger.d.ts +11 -0
- package/dist/durability/ledger.d.ts.map +1 -1
- package/dist/durability/parks.d.ts +22 -0
- package/dist/durability/parks.d.ts.map +1 -0
- package/dist/durability/scheduler.d.ts +1 -0
- package/dist/durability/scheduler.d.ts.map +1 -1
- package/dist/entrypoints/agent-runtime/coding-tools.js +4 -4
- package/dist/entrypoints/agent-runtime/harness.js +127 -116
- package/dist/entrypoints/agent-runtime/sandbox.js +4 -4
- package/dist/entrypoints/agent-runtime/sqlite/bun.js +3 -3
- package/dist/entrypoints/agent-runtime/sqlite/node.js +3 -3
- package/dist/entrypoints/agent-runtime/testing.js +246 -214
- package/dist/entrypoints/agent-runtime.js +224 -203
- package/dist/entrypoints/application/diagnostic-journal.js +63 -203
- package/dist/entrypoints/application/opentelemetry.js +1 -1
- package/dist/entrypoints/application.js +361 -324
- package/dist/entrypoints/cli.d.ts +4 -1
- package/dist/entrypoints/cli.d.ts.map +1 -1
- package/dist/entrypoints/cli.js +57 -35
- package/dist/entrypoints/contract.d.ts +5 -2
- package/dist/entrypoints/contract.d.ts.map +1 -1
- package/dist/entrypoints/contract.js +3 -2
- package/dist/entrypoints/files.d.ts +2 -0
- package/dist/entrypoints/files.d.ts.map +1 -1
- package/dist/entrypoints/files.js +98 -2
- package/dist/entrypoints/index.d.ts +4 -2
- package/dist/entrypoints/index.d.ts.map +1 -1
- package/dist/entrypoints/index.js +348 -282
- package/dist/entrypoints/live.js +89 -71
- package/dist/entrypoints/node.d.ts +2 -1
- package/dist/entrypoints/node.d.ts.map +1 -1
- package/dist/entrypoints/node.js +13 -12
- package/dist/entrypoints/react.js +1 -1
- package/dist/entrypoints/remote.js +4 -4
- package/dist/entrypoints/server.d.ts +4 -2
- package/dist/entrypoints/server.d.ts.map +1 -1
- package/dist/entrypoints/server.js +293 -79
- package/dist/entrypoints/testing.d.ts +2 -1
- package/dist/entrypoints/testing.d.ts.map +1 -1
- package/dist/entrypoints/testing.js +288 -281
- package/dist/entrypoints/tools/connections.js +2 -2
- package/dist/entrypoints/tools/invoker.js +4 -4
- package/dist/entrypoints/tools.d.ts +6 -3
- package/dist/entrypoints/tools.d.ts.map +1 -1
- package/dist/entrypoints/tools.js +245 -202
- package/dist/entrypoints/tracking.js +325 -274
- package/dist/files/boundary.d.ts.map +1 -1
- package/dist/files/file-io.d.ts +14 -0
- package/dist/files/file-io.d.ts.map +1 -0
- package/dist/index-1j8pm5t0.js +412 -0
- package/dist/{index-kvj7f4hq.js → index-2bxbyab0.js} +10 -2
- package/dist/{index-xnj9bgxe.js → index-2gxzjvyr.js} +2 -162
- package/dist/index-4gcnakhx.js +82 -0
- package/dist/{index-j05z5gn4.js → index-55hkhm67.js} +136 -119
- package/dist/{index-cq4qfycf.js → index-79z7m7dt.js} +227 -59
- package/dist/{index-97ac4gph.js → index-7f68ghdn.js} +3 -3
- package/dist/{index-r7nmqpsg.js → index-7p1f0vp2.js} +1 -1
- package/dist/{index-dcpdvjsc.js → index-863ea9jb.js} +4 -4
- package/dist/index-8p52kd5p.js +242 -0
- package/dist/{index-2qzskm8h.js → index-dce5wxcq.js} +1 -1
- package/dist/index-e01r054k.js +105 -0
- package/dist/{index-sees8yf8.js → index-ensd0r74.js} +118 -111
- package/dist/{index-1nd48tm9.js → index-gxrt5h6v.js} +2 -1
- package/dist/{index-e87kakm4.js → index-ham5sz8m.js} +112 -110
- package/dist/{index-kj2wbeta.js → index-het2he5g.js} +280 -196
- package/dist/{index-vcvkq30w.js → index-hmp4800j.js} +3 -3
- package/dist/{index-gyr48nzg.js → index-k30h66yd.js} +71 -151
- package/dist/{index-2cr1cqhn.js → index-khtgb21r.js} +2 -2
- package/dist/{index-x4799c19.js → index-ndddxtyx.js} +11 -11
- package/dist/{index-dydjcp8z.js → index-np4m8hd3.js} +38 -36
- package/dist/{index-p81267c2.js → index-p3vsv1fb.js} +621 -357
- package/dist/{index-mp5sn43f.js → index-p9e0w8hs.js} +2 -2
- package/dist/{index-rewkc2hj.js → index-p9sh0xx4.js} +3 -3
- package/dist/{index-70yj2ebz.js → index-paz6sgdp.js} +107 -103
- package/dist/{index-bn2cjajt.js → index-px2gm2jp.js} +26 -102
- package/dist/index-s812ycat.js +65 -0
- package/dist/{index-xsqjkha9.js → index-sp1tzwnb.js} +2 -2
- package/dist/{index-n6hxg8as.js → index-t9rhjr9f.js} +615 -566
- package/dist/{index-zeemqhqx.js → index-v260df89.js} +88 -80
- package/dist/{index-fdp6hdxn.js → index-w906953s.js} +5 -1
- package/dist/{index-mdzh02yc.js → index-wdkt63w3.js} +1 -1
- package/dist/{index-58k4fp34.js → index-wsm5w4ee.js} +1 -1
- package/dist/{index-v38qyerb.js → index-xw3s75nj.js} +1 -1
- package/dist/internal/atomic-file.d.ts +23 -2
- package/dist/internal/atomic-file.d.ts.map +1 -1
- package/dist/internal/exclusive-lock.d.ts +51 -0
- package/dist/internal/exclusive-lock.d.ts.map +1 -0
- package/dist/internal/process-identity.d.ts +47 -0
- package/dist/internal/process-identity.d.ts.map +1 -0
- package/dist/internal/with-exclusive-lock.d.ts +67 -0
- package/dist/internal/with-exclusive-lock.d.ts.map +1 -0
- package/dist/live/watch-client.d.ts.map +1 -1
- package/dist/observability/audit.d.ts +2 -2
- package/dist/observability/audit.d.ts.map +1 -1
- package/dist/observability/event.d.ts +2 -1
- package/dist/observability/event.d.ts.map +1 -1
- package/dist/primitives/export-operation.d.ts +1 -1
- package/dist/primitives/export-operation.d.ts.map +1 -1
- package/dist/realtime/registry.d.ts +0 -5
- package/dist/realtime/registry.d.ts.map +1 -1
- package/dist/server/bun.d.ts +0 -1
- package/dist/server/bun.d.ts.map +1 -1
- package/dist/server/context-contribution.d.ts +1 -1
- package/dist/server/context-contribution.d.ts.map +1 -1
- package/dist/server/context.d.ts +1 -1
- package/dist/server/context.d.ts.map +1 -1
- package/dist/server/endpoint-response.d.ts +2 -1
- package/dist/server/endpoint-response.d.ts.map +1 -1
- package/dist/server/error-dispatch.d.ts +1 -1
- package/dist/server/error-dispatch.d.ts.map +1 -1
- package/dist/server/error-hook.d.ts +1 -1
- package/dist/server/error-hook.d.ts.map +1 -1
- package/dist/server/handler-state.d.ts +1 -1
- package/dist/server/handler-state.d.ts.map +1 -1
- package/dist/server/implement-registry.d.ts +54 -0
- package/dist/server/implement-registry.d.ts.map +1 -0
- package/dist/server/implement.d.ts +9 -55
- package/dist/server/implement.d.ts.map +1 -1
- package/dist/server/middleware/auth.d.ts +1 -31
- package/dist/server/middleware/auth.d.ts.map +1 -1
- package/dist/server/middleware/jwt.d.ts +31 -0
- package/dist/server/middleware/jwt.d.ts.map +1 -0
- package/dist/server/multipart-reader.d.ts +22 -0
- package/dist/server/multipart-reader.d.ts.map +1 -0
- package/dist/server/multipart.d.ts +1 -1
- package/dist/server/multipart.d.ts.map +1 -1
- package/dist/server/oauth/cimd.d.ts +88 -0
- package/dist/server/oauth/cimd.d.ts.map +1 -0
- package/dist/server/oauth/endpoints.d.ts +39 -0
- package/dist/server/oauth/endpoints.d.ts.map +1 -0
- package/dist/server/oauth/provider.d.ts +1 -68
- package/dist/server/oauth/provider.d.ts.map +1 -1
- package/dist/server/streaming-pump.d.ts +66 -0
- package/dist/server/streaming-pump.d.ts.map +1 -0
- package/dist/server/streaming-route.d.ts +12 -5
- package/dist/server/streaming-route.d.ts.map +1 -1
- package/dist/server/types.d.ts +4 -1
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/unix-client-bun.d.ts.map +1 -1
- package/dist/server/unix-client-http1.d.ts +76 -0
- package/dist/server/unix-client-http1.d.ts.map +1 -0
- package/dist/server/unix-client.d.ts.map +1 -1
- package/dist/testing/handler-clients.d.ts +2 -1
- package/dist/testing/handler-clients.d.ts.map +1 -1
- package/dist/testing/realtime-probe.d.ts +33 -0
- package/dist/testing/realtime-probe.d.ts.map +1 -0
- package/dist/testing/surface-conformance.d.ts +0 -31
- package/dist/testing/surface-conformance.d.ts.map +1 -1
- package/dist/testing/surface-manifest-digest.d.ts +44 -0
- package/dist/testing/surface-manifest-digest.d.ts.map +1 -0
- package/dist/testing/surface-manifest.d.ts.map +1 -1
- package/dist/tools/agent.d.ts +1 -1
- package/dist/tools/agent.d.ts.map +1 -1
- package/dist/tools/cli/args-fields.d.ts +31 -0
- package/dist/tools/cli/args-fields.d.ts.map +1 -0
- package/dist/tools/cli/args-route.d.ts +42 -0
- package/dist/tools/cli/args-route.d.ts.map +1 -0
- package/dist/tools/cli/args-view.d.ts +32 -0
- package/dist/tools/cli/args-view.d.ts.map +1 -0
- package/dist/tools/cli/args.d.ts +2 -65
- package/dist/tools/cli/args.d.ts.map +1 -1
- package/dist/tools/cli/argument-error.d.ts +5 -0
- package/dist/tools/cli/argument-error.d.ts.map +1 -0
- package/dist/tools/cli/checkpoint.d.ts.map +1 -1
- package/dist/tools/cli/command.d.ts +1 -1
- package/dist/tools/cli/command.d.ts.map +1 -1
- package/dist/tools/cli/config.d.ts +1 -1
- package/dist/tools/cli/config.d.ts.map +1 -1
- package/dist/tools/cli/format.d.ts +2 -1
- package/dist/tools/cli/format.d.ts.map +1 -1
- package/dist/tools/cli/invoke.d.ts +2 -1
- package/dist/tools/cli/invoke.d.ts.map +1 -1
- package/dist/tools/cli/managed-surface.d.ts +1 -1
- package/dist/tools/cli/managed-surface.d.ts.map +1 -1
- package/dist/tools/cli/policy.d.ts +1 -1
- package/dist/tools/cli/policy.d.ts.map +1 -1
- package/dist/tools/cli/prepare.d.ts.map +1 -1
- package/dist/tools/cli/run-managed.d.ts.map +1 -1
- package/dist/tools/cli/session.d.ts +1 -1
- package/dist/tools/cli/session.d.ts.map +1 -1
- package/dist/tools/cli/update.d.ts +19 -0
- package/dist/tools/cli/update.d.ts.map +1 -1
- package/dist/tools/cli/view.d.ts +1 -1
- package/dist/tools/cli/view.d.ts.map +1 -1
- package/dist/tools/cli/wait.d.ts +1 -1
- package/dist/tools/cli/wait.d.ts.map +1 -1
- package/dist/tools/connections/runtime.d.ts +1 -1
- package/dist/tools/connections/runtime.d.ts.map +1 -1
- package/dist/tools/execute-args.d.ts +23 -0
- package/dist/tools/execute-args.d.ts.map +1 -0
- package/dist/tools/execute-hooks.d.ts +146 -0
- package/dist/tools/execute-hooks.d.ts.map +1 -0
- package/dist/tools/execute-result.d.ts +40 -0
- package/dist/tools/execute-result.d.ts.map +1 -0
- package/dist/tools/execute.d.ts +4 -193
- package/dist/tools/execute.d.ts.map +1 -1
- package/dist/tools/internal/surface-projector.d.ts +2 -1
- package/dist/tools/internal/surface-projector.d.ts.map +1 -1
- package/dist/tools/invoker.d.ts +2 -1
- package/dist/tools/invoker.d.ts.map +1 -1
- package/dist/tools/lifecycle.d.ts +1 -1
- package/dist/tools/lifecycle.d.ts.map +1 -1
- package/dist/tools/mcp/mount.d.ts +1 -1
- package/dist/tools/mcp/mount.d.ts.map +1 -1
- package/dist/tools/mcp/prepare.d.ts +2 -1
- package/dist/tools/mcp/prepare.d.ts.map +1 -1
- package/dist/tools/mcp/progress.d.ts +1 -1
- package/dist/tools/mcp/progress.d.ts.map +1 -1
- package/dist/tools/mcp/register.d.ts +3 -2
- package/dist/tools/mcp/register.d.ts.map +1 -1
- package/dist/tools/mcp/round-context.d.ts +38 -0
- package/dist/tools/mcp/round-context.d.ts.map +1 -0
- package/dist/tools/mcp/round-policy.d.ts +1 -1
- package/dist/tools/mcp/round-policy.d.ts.map +1 -1
- package/dist/tools/mcp/round.d.ts +3 -11
- package/dist/tools/mcp/round.d.ts.map +1 -1
- package/dist/tools/mcp/runtime-tools.d.ts +2 -1
- package/dist/tools/mcp/runtime-tools.d.ts.map +1 -1
- package/dist/tools/mount.d.ts +3 -1
- package/dist/tools/mount.d.ts.map +1 -1
- package/dist/tools/native-definition.d.ts +2 -1
- package/dist/tools/native-definition.d.ts.map +1 -1
- package/dist/tools/operations/async-operation-runtime-tools.d.ts +2 -1
- package/dist/tools/operations/async-operation-runtime-tools.d.ts.map +1 -1
- package/dist/tools/operations/async-operation-runtime-types.d.ts +2 -1
- package/dist/tools/operations/async-operation-runtime-types.d.ts.map +1 -1
- package/dist/tools/remote.d.ts.map +1 -1
- package/dist/tools/runtime-tool.d.ts +3 -1
- package/dist/tools/runtime-tool.d.ts.map +1 -1
- package/dist/tools/tool-logger.d.ts +1 -1
- package/dist/tools/tool-logger.d.ts.map +1 -1
- package/dist/tracking/client-listeners.d.ts +30 -0
- package/dist/tracking/client-listeners.d.ts.map +1 -0
- package/dist/tracking/client-visit.d.ts +61 -0
- package/dist/tracking/client-visit.d.ts.map +1 -0
- package/dist/tracking/client.d.ts +3 -2
- package/dist/tracking/client.d.ts.map +1 -1
- package/llms/application.2.txt +266 -2
- package/llms/application.txt +8 -266
- package/llms/cli.2.txt +80 -0
- package/llms/cli.txt +45 -74
- package/llms/contract.txt +3 -3
- package/llms/files.txt +3 -0
- package/llms/tools.2.txt +88 -279
- package/llms/tools.3.txt +288 -0
- package/llms/tools.txt +27 -65
- package/llms-full.txt +108 -12
- package/llms.txt +5 -5
- package/package.json +1 -1
- package/dist/index-e2z3ahw9.js +0 -325
- package/dist/index-mkm15s49.js +0 -394
|
@@ -10,15 +10,15 @@ import {
|
|
|
10
10
|
import {
|
|
11
11
|
createValidatedRealtimeSocket,
|
|
12
12
|
isModuleNotFound
|
|
13
|
-
} from "./index-
|
|
13
|
+
} from "./index-ndddxtyx.js";
|
|
14
14
|
import {
|
|
15
15
|
DEFAULT_CONTRACT_STREAM_FRAME_BYTES
|
|
16
16
|
} from "./index-wqgjfstn.js";
|
|
17
17
|
import {
|
|
18
18
|
DEFAULT_PROCESS_SIGNALS,
|
|
19
|
-
RUNTIME_CONTEXT_RESERVED_KEYS,
|
|
20
19
|
applyCors,
|
|
21
20
|
assertCorsConfig,
|
|
21
|
+
bindContract,
|
|
22
22
|
corsPreflightResponse,
|
|
23
23
|
defaultSignalSource,
|
|
24
24
|
guardSignalCallback,
|
|
@@ -26,11 +26,11 @@ import {
|
|
|
26
26
|
mediaTypeEssence,
|
|
27
27
|
reportSignalError,
|
|
28
28
|
requestCorsHeaders
|
|
29
|
-
} from "./index-
|
|
29
|
+
} from "./index-2gxzjvyr.js";
|
|
30
30
|
import {
|
|
31
31
|
joinRoutePath,
|
|
32
32
|
parseTrailingWildcard
|
|
33
|
-
} from "./index-
|
|
33
|
+
} from "./index-4gcnakhx.js";
|
|
34
34
|
import {
|
|
35
35
|
getRequestContext,
|
|
36
36
|
runWithRequestContext,
|
|
@@ -67,11 +67,8 @@ import {
|
|
|
67
67
|
transportResult
|
|
68
68
|
} from "./index-hffjpmq9.js";
|
|
69
69
|
|
|
70
|
-
// src/server/multipart.ts
|
|
71
|
-
var DEFAULT_MAX_REQUEST_BYTES = 25 * 1024 * 1024;
|
|
72
|
-
var DEFAULT_MAX_FIELD_BYTES = 1024 * 1024;
|
|
70
|
+
// src/server/multipart-reader.ts
|
|
73
71
|
var DEFAULT_MAX_HEADER_BYTES = 64 * 1024;
|
|
74
|
-
var DEFAULT_MAX_PARTS = 1000;
|
|
75
72
|
var CRLF = new Uint8Array([13, 10]);
|
|
76
73
|
var HEADER_END = new Uint8Array([13, 10, 13, 10]);
|
|
77
74
|
var decoder = new TextDecoder;
|
|
@@ -356,6 +353,11 @@ class MultipartStreamReader {
|
|
|
356
353
|
this.#buffer = this.#buffer.slice(length);
|
|
357
354
|
}
|
|
358
355
|
}
|
|
356
|
+
|
|
357
|
+
// src/server/multipart.ts
|
|
358
|
+
var DEFAULT_MAX_REQUEST_BYTES = 25 * 1024 * 1024;
|
|
359
|
+
var DEFAULT_MAX_FIELD_BYTES = 1024 * 1024;
|
|
360
|
+
var DEFAULT_MAX_PARTS = 1000;
|
|
359
361
|
function matchesContentType(contentType, accepted) {
|
|
360
362
|
const normalized = contentType.toLowerCase();
|
|
361
363
|
return accepted.some((candidate) => {
|
|
@@ -554,6 +556,45 @@ async function parseMultipart(req, descriptor, fieldsSchema, receivers) {
|
|
|
554
556
|
}
|
|
555
557
|
}
|
|
556
558
|
|
|
559
|
+
// src/server/streaming-pump.ts
|
|
560
|
+
async function pumpFrames(p) {
|
|
561
|
+
let sinceYield = 0;
|
|
562
|
+
try {
|
|
563
|
+
for (;; ) {
|
|
564
|
+
await p.awaitDemand();
|
|
565
|
+
if (p.isClosed())
|
|
566
|
+
return;
|
|
567
|
+
const next = await p.iterator.next();
|
|
568
|
+
if (p.isClosed())
|
|
569
|
+
return;
|
|
570
|
+
if (next.done)
|
|
571
|
+
break;
|
|
572
|
+
if (!p.send(p.framing.frame(next.value)))
|
|
573
|
+
return;
|
|
574
|
+
sinceYield += 1;
|
|
575
|
+
if (sinceYield >= MAX_BUFFERED_FRAMES) {
|
|
576
|
+
sinceYield = 0;
|
|
577
|
+
await new Promise((resolve) => {
|
|
578
|
+
setTimeout(resolve, 0);
|
|
579
|
+
});
|
|
580
|
+
if (p.isClosed())
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
if (p.framing.done)
|
|
585
|
+
p.send(p.framing.done);
|
|
586
|
+
} catch (error) {
|
|
587
|
+
if (p.isClosed()) {
|
|
588
|
+
if (!isStreamCancellation(error, p.departed))
|
|
589
|
+
p.pumped.reject(error);
|
|
590
|
+
} else
|
|
591
|
+
p.send(p.framing.frame(normalizeError(error).toJSON()));
|
|
592
|
+
} finally {
|
|
593
|
+
p.pumped.resolve();
|
|
594
|
+
p.end();
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
|
|
557
598
|
// src/server/streaming-route.ts
|
|
558
599
|
var DEFAULT_STREAM_HEARTBEAT_MS = 5000;
|
|
559
600
|
var FRAMINGS = {
|
|
@@ -603,7 +644,7 @@ function responseHeaders(framing, extra) {
|
|
|
603
644
|
headers.set("X-Accel-Buffering", "no");
|
|
604
645
|
return headers;
|
|
605
646
|
}
|
|
606
|
-
function
|
|
647
|
+
function streamingTimings(options) {
|
|
607
648
|
const heartbeatMs = options.heartbeatMs ?? DEFAULT_STREAM_HEARTBEAT_MS;
|
|
608
649
|
if (!Number.isFinite(heartbeatMs) || heartbeatMs <= 0) {
|
|
609
650
|
throw new TypeError("heartbeatMs must be a finite positive number of milliseconds");
|
|
@@ -612,6 +653,10 @@ function streamingRoute(options) {
|
|
|
612
653
|
if (!Number.isInteger(idleTimeoutSeconds) || idleTimeoutSeconds < 0) {
|
|
613
654
|
throw new TypeError("idleTimeoutSeconds must be a non-negative integer");
|
|
614
655
|
}
|
|
656
|
+
return { heartbeatMs, idleTimeoutSeconds };
|
|
657
|
+
}
|
|
658
|
+
function streamingRoute(options) {
|
|
659
|
+
const { heartbeatMs, idleTimeoutSeconds } = streamingTimings(options);
|
|
615
660
|
const framing = FRAMINGS[options.format ?? "ndjson"];
|
|
616
661
|
return {
|
|
617
662
|
method: options.method ?? "GET",
|
|
@@ -719,44 +764,19 @@ function streamingRoute(options) {
|
|
|
719
764
|
});
|
|
720
765
|
}
|
|
721
766
|
};
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
return;
|
|
732
|
-
if (next.done)
|
|
733
|
-
break;
|
|
734
|
-
if (!send(framing.frame(next.value)))
|
|
735
|
-
return;
|
|
736
|
-
sinceYield += 1;
|
|
737
|
-
if (sinceYield >= MAX_BUFFERED_FRAMES) {
|
|
738
|
-
sinceYield = 0;
|
|
739
|
-
await new Promise((resolve) => {
|
|
740
|
-
setTimeout(resolve, 0);
|
|
741
|
-
});
|
|
742
|
-
if (closed)
|
|
743
|
-
return;
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
if (framing.done)
|
|
747
|
-
send(framing.done);
|
|
748
|
-
} catch (error) {
|
|
749
|
-
if (closed) {
|
|
750
|
-
if (!isStreamCancellation(error, departed.signal))
|
|
751
|
-
pumped.reject(error);
|
|
752
|
-
} else
|
|
753
|
-
send(framing.frame(normalizeError(error).toJSON()));
|
|
754
|
-
} finally {
|
|
755
|
-
pumped.resolve();
|
|
767
|
+
pumpFrames({
|
|
768
|
+
iterator,
|
|
769
|
+
framing,
|
|
770
|
+
send,
|
|
771
|
+
awaitDemand,
|
|
772
|
+
isClosed: () => closed,
|
|
773
|
+
departed: departed.signal,
|
|
774
|
+
pumped,
|
|
775
|
+
end: () => {
|
|
756
776
|
release();
|
|
757
777
|
finish();
|
|
758
778
|
}
|
|
759
|
-
})
|
|
779
|
+
});
|
|
760
780
|
},
|
|
761
781
|
pull() {
|
|
762
782
|
signalDemand();
|
|
@@ -776,6 +796,101 @@ function sseRoute(options) {
|
|
|
776
796
|
return streamingRoute({ ...options, format: "sse" });
|
|
777
797
|
}
|
|
778
798
|
|
|
799
|
+
// src/server/context-contribution.ts
|
|
800
|
+
var RUNTIME_CONTEXT_RESERVED_KEYS = new Set([
|
|
801
|
+
"params",
|
|
802
|
+
"input",
|
|
803
|
+
"files",
|
|
804
|
+
"rawBody",
|
|
805
|
+
"source",
|
|
806
|
+
"req",
|
|
807
|
+
"url",
|
|
808
|
+
"headers",
|
|
809
|
+
"traceId",
|
|
810
|
+
"spanId",
|
|
811
|
+
"ipAddress",
|
|
812
|
+
"userAgent",
|
|
813
|
+
"signal",
|
|
814
|
+
"mcp",
|
|
815
|
+
"reportProgress"
|
|
816
|
+
]);
|
|
817
|
+
function contributionError(scope, reason) {
|
|
818
|
+
return new TypeError(`[stitchkit] auth: invalid context contribution for scope ${JSON.stringify(scope)}: ${reason}`);
|
|
819
|
+
}
|
|
820
|
+
function descriptorsEqual(left, right) {
|
|
821
|
+
if (!left || !right)
|
|
822
|
+
return left === right;
|
|
823
|
+
if (left.enumerable !== right.enumerable || left.configurable !== right.configurable || left.writable !== right.writable) {
|
|
824
|
+
return false;
|
|
825
|
+
}
|
|
826
|
+
if ("value" in left || "value" in right) {
|
|
827
|
+
return "value" in left && "value" in right && Object.is(left.value, right.value);
|
|
828
|
+
}
|
|
829
|
+
return left.get === right.get && left.set === right.set;
|
|
830
|
+
}
|
|
831
|
+
function contextContributionDelta(original, shadow, scope) {
|
|
832
|
+
if (Object.getPrototypeOf(shadow) !== Object.getPrototypeOf(original)) {
|
|
833
|
+
throw contributionError(scope, "context prototype changes are not supported");
|
|
834
|
+
}
|
|
835
|
+
const originalKeys = Reflect.ownKeys(original);
|
|
836
|
+
const shadowKeys = Reflect.ownKeys(shadow);
|
|
837
|
+
const shadowKeySet = new Set(shadowKeys);
|
|
838
|
+
for (const key of originalKeys) {
|
|
839
|
+
if (!shadowKeySet.has(key)) {
|
|
840
|
+
const printable = typeof key === "string" ? JSON.stringify(key) : "a symbol key";
|
|
841
|
+
throw contributionError(scope, `context key ${printable} may not be deleted`);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
const contribution = Object.create(null);
|
|
845
|
+
for (const key of shadowKeys) {
|
|
846
|
+
const originalDescriptor = Object.getOwnPropertyDescriptor(original, key);
|
|
847
|
+
const shadowDescriptor = Object.getOwnPropertyDescriptor(shadow, key);
|
|
848
|
+
if (!shadowDescriptor || descriptorsEqual(originalDescriptor, shadowDescriptor))
|
|
849
|
+
continue;
|
|
850
|
+
Object.defineProperty(contribution, key, shadowDescriptor);
|
|
851
|
+
}
|
|
852
|
+
return contribution;
|
|
853
|
+
}
|
|
854
|
+
function prepareContextContribution(value, scope) {
|
|
855
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
856
|
+
throw contributionError(scope, "expected a plain record");
|
|
857
|
+
}
|
|
858
|
+
let prototype;
|
|
859
|
+
let descriptors;
|
|
860
|
+
let keys;
|
|
861
|
+
try {
|
|
862
|
+
prototype = Object.getPrototypeOf(value);
|
|
863
|
+
descriptors = Object.getOwnPropertyDescriptors(value);
|
|
864
|
+
keys = Reflect.ownKeys(value);
|
|
865
|
+
} catch {
|
|
866
|
+
throw contributionError(scope, "record inspection failed");
|
|
867
|
+
}
|
|
868
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
869
|
+
throw contributionError(scope, "expected Object.prototype or null prototype");
|
|
870
|
+
}
|
|
871
|
+
const prepared = Object.create(null);
|
|
872
|
+
for (const key of keys) {
|
|
873
|
+
if (typeof key !== "string") {
|
|
874
|
+
throw contributionError(scope, "symbol keys are not supported");
|
|
875
|
+
}
|
|
876
|
+
if (isUnsafeKey(key)) {
|
|
877
|
+
throw contributionError(scope, `unsafe key ${JSON.stringify(key)}`);
|
|
878
|
+
}
|
|
879
|
+
if (RUNTIME_CONTEXT_RESERVED_KEYS.has(key)) {
|
|
880
|
+
throw contributionError(scope, `reserved key ${JSON.stringify(key)}`);
|
|
881
|
+
}
|
|
882
|
+
const descriptor = descriptors[key];
|
|
883
|
+
if (!descriptor?.enumerable || !("value" in descriptor)) {
|
|
884
|
+
throw contributionError(scope, `key ${JSON.stringify(key)} must be enumerable data`);
|
|
885
|
+
}
|
|
886
|
+
prepared[key] = descriptor.value;
|
|
887
|
+
}
|
|
888
|
+
return prepared;
|
|
889
|
+
}
|
|
890
|
+
function mergeContextContribution(ctx, value, scope) {
|
|
891
|
+
Object.assign(ctx, prepareContextContribution(value, scope));
|
|
892
|
+
}
|
|
893
|
+
|
|
779
894
|
// src/server/request-body.ts
|
|
780
895
|
function requestAbortReason(req) {
|
|
781
896
|
return req.signal.reason ?? new DOMException("The connection was closed", "AbortError");
|
|
@@ -2044,6 +2159,68 @@ async function dispatch(state, req, url, traceId, server, clientIp, startedAt) {
|
|
|
2044
2159
|
return dispatchEndpoint(state, request, match);
|
|
2045
2160
|
}
|
|
2046
2161
|
|
|
2162
|
+
// src/server/implement-registry.ts
|
|
2163
|
+
function createScopedImplementRegistry() {
|
|
2164
|
+
return (contracts, handlers, options) => transportResult(bindRegistry(contracts, handlers, options));
|
|
2165
|
+
}
|
|
2166
|
+
function isImplementationContract(value) {
|
|
2167
|
+
return isRecord(value) && isRecord(value.meta) && typeof value.meta.prefix === "string" && isRecord(value.endpoints);
|
|
2168
|
+
}
|
|
2169
|
+
function bindRegistry(contracts, handlers, options) {
|
|
2170
|
+
const contractKeys = Object.keys(contracts);
|
|
2171
|
+
const handlerKeys = Object.keys(handlers);
|
|
2172
|
+
const missing = contractKeys.filter((key) => !Object.hasOwn(handlers, key));
|
|
2173
|
+
const extra = handlerKeys.filter((key) => !Object.hasOwn(contracts, key));
|
|
2174
|
+
if (missing.length > 0 || extra.length > 0) {
|
|
2175
|
+
if (options?.onMissingHandler !== "stub") {
|
|
2176
|
+
throw new Error(`[stitchkit] implementRegistry: registry mismatch (missing: ${missing.join(", ") || "none"}; extra: ${extra.join(", ") || "none"})`);
|
|
2177
|
+
}
|
|
2178
|
+
console.warn(`[stitchkit] implementRegistry: registry mismatch (missing: ${missing.join(", ") || "none"}; extra: ${extra.join(", ") || "none"}) — missing contracts are mounted as 501 stubs and extra handlers are ignored`);
|
|
2179
|
+
}
|
|
2180
|
+
const prefixes = new Map;
|
|
2181
|
+
const services = [];
|
|
2182
|
+
const byKey = {};
|
|
2183
|
+
for (const [key, candidate] of Object.entries(contracts)) {
|
|
2184
|
+
if (!isImplementationContract(candidate)) {
|
|
2185
|
+
throw new TypeError(`[stitchkit] implementRegistry: registry entry "${key}" must be one contract; composed arrays and namespaces are not supported`);
|
|
2186
|
+
}
|
|
2187
|
+
const contract = candidate;
|
|
2188
|
+
const groupScope = contract.meta.scope ?? "public";
|
|
2189
|
+
const identity = `${groupScope}\x00${contract.meta.prefix}`;
|
|
2190
|
+
const previousKey = prefixes.get(identity);
|
|
2191
|
+
if (previousKey !== undefined) {
|
|
2192
|
+
throw new Error(`[stitchkit] implementRegistry: duplicate contract prefix "${contract.meta.prefix}" in scope "${groupScope}" at "${previousKey}" and "${key}"`);
|
|
2193
|
+
}
|
|
2194
|
+
prefixes.set(identity, key);
|
|
2195
|
+
const entryHandlers = handlers[key] === undefined && options?.onMissingHandler === "stub" ? {} : handlers[key];
|
|
2196
|
+
if (!isRecord(entryHandlers)) {
|
|
2197
|
+
throw new TypeError(`[stitchkit] implementRegistry: handlers for "${key}" must be an object`);
|
|
2198
|
+
}
|
|
2199
|
+
const endpointKeys = Object.keys(contract.endpoints);
|
|
2200
|
+
const handlerEntryKeys = Object.keys(entryHandlers);
|
|
2201
|
+
const missingEndpoints = endpointKeys.filter((endpointKey) => !Object.hasOwn(entryHandlers, endpointKey));
|
|
2202
|
+
const extraEndpoints = handlerEntryKeys.filter((endpointKey) => !Object.hasOwn(contract.endpoints, endpointKey));
|
|
2203
|
+
if (missingEndpoints.length > 0 || extraEndpoints.length > 0) {
|
|
2204
|
+
const detail = `handlers for "${key}" mismatch (missing: ${missingEndpoints.join(", ") || "none"}; extra: ${extraEndpoints.join(", ") || "none"})`;
|
|
2205
|
+
if (options?.onMissingHandler !== "stub") {
|
|
2206
|
+
throw new Error(`[stitchkit] implementRegistry: ${detail}`);
|
|
2207
|
+
}
|
|
2208
|
+
console.warn(`[stitchkit] implementRegistry: ${detail} — missing endpoints are mounted as 501 stubs and extra handlers are ignored`);
|
|
2209
|
+
}
|
|
2210
|
+
const service = bindContract(contract, entryHandlers, options);
|
|
2211
|
+
services.push(service);
|
|
2212
|
+
byKey[key] = service;
|
|
2213
|
+
}
|
|
2214
|
+
Object.defineProperty(services, "byKey", { value: byKey, enumerable: false });
|
|
2215
|
+
return transportResult(services);
|
|
2216
|
+
}
|
|
2217
|
+
function implementRegistry(contracts, handlers, options) {
|
|
2218
|
+
return transportResult(bindRegistry(contracts, handlers, options));
|
|
2219
|
+
}
|
|
2220
|
+
function createImplementRegistry() {
|
|
2221
|
+
return (contracts, handlers, options) => transportResult(bindRegistry(contracts, handlers, options));
|
|
2222
|
+
}
|
|
2223
|
+
|
|
2047
2224
|
// src/server/process-signals.ts
|
|
2048
2225
|
var bound = new WeakSet;
|
|
2049
2226
|
function bindProcessSignals(handle, options = {}) {
|
|
@@ -2556,20 +2733,11 @@ function incomingResponseBody(response, maxBytes, onDone) {
|
|
|
2556
2733
|
}, { highWaterMark: 1 });
|
|
2557
2734
|
}
|
|
2558
2735
|
|
|
2559
|
-
// src/server/unix-client-
|
|
2736
|
+
// src/server/unix-client-http1.ts
|
|
2560
2737
|
var MAX_BODY_CHUNK_BYTES = 64 * 1024;
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
return typeof Reflect.get(candidate, "connect") === "function";
|
|
2565
|
-
}
|
|
2566
|
-
function runtimeBun() {
|
|
2567
|
-
const candidate = Reflect.get(globalThis, "Bun");
|
|
2568
|
-
return isBunUnixRuntime(candidate) ? candidate : undefined;
|
|
2569
|
-
}
|
|
2570
|
-
function hasBunUnixRuntime() {
|
|
2571
|
-
return runtimeBun() !== undefined;
|
|
2572
|
-
}
|
|
2738
|
+
var MAX_CHUNK_HEADER_BYTES = 1024;
|
|
2739
|
+
var CRLF2 = [13, 10];
|
|
2740
|
+
var CRLFCRLF = [13, 10, 13, 10];
|
|
2573
2741
|
function concatBytes2(left, right) {
|
|
2574
2742
|
if (left.byteLength === 0)
|
|
2575
2743
|
return right.slice();
|
|
@@ -2589,6 +2757,27 @@ function indexOfSequence(bytes, sequence) {
|
|
|
2589
2757
|
}
|
|
2590
2758
|
return -1;
|
|
2591
2759
|
}
|
|
2760
|
+
|
|
2761
|
+
class WireBuffer {
|
|
2762
|
+
bytes = new Uint8Array;
|
|
2763
|
+
get byteLength() {
|
|
2764
|
+
return this.bytes.byteLength;
|
|
2765
|
+
}
|
|
2766
|
+
append(data) {
|
|
2767
|
+
this.bytes = concatBytes2(this.bytes, data);
|
|
2768
|
+
}
|
|
2769
|
+
take(count) {
|
|
2770
|
+
const value = this.bytes.slice(0, count);
|
|
2771
|
+
this.bytes = this.bytes.slice(count);
|
|
2772
|
+
return value;
|
|
2773
|
+
}
|
|
2774
|
+
indexOf(sequence) {
|
|
2775
|
+
return indexOfSequence(this.bytes, sequence);
|
|
2776
|
+
}
|
|
2777
|
+
startsWith(sequence) {
|
|
2778
|
+
return sequence.every((byte, index) => this.bytes[index] === byte);
|
|
2779
|
+
}
|
|
2780
|
+
}
|
|
2592
2781
|
function requestBytes(request, body) {
|
|
2593
2782
|
const url = new URL(request.url);
|
|
2594
2783
|
const headers = new Headers(request.headers);
|
|
@@ -2620,6 +2809,213 @@ function parseContentLength(headers) {
|
|
|
2620
2809
|
}
|
|
2621
2810
|
return value;
|
|
2622
2811
|
}
|
|
2812
|
+
function readResponseHead(wire, maxHeaderBytes) {
|
|
2813
|
+
const headerEnd = wire.indexOf(CRLFCRLF);
|
|
2814
|
+
if (headerEnd < 0) {
|
|
2815
|
+
return wire.byteLength > maxHeaderBytes ? { kind: "too-large" } : { kind: "more" };
|
|
2816
|
+
}
|
|
2817
|
+
if (headerEnd + 4 > maxHeaderBytes)
|
|
2818
|
+
return { kind: "too-large" };
|
|
2819
|
+
let text;
|
|
2820
|
+
try {
|
|
2821
|
+
text = new TextDecoder("utf-8", { fatal: true }).decode(wire.take(headerEnd));
|
|
2822
|
+
} catch (error) {
|
|
2823
|
+
return { kind: "malformed", error };
|
|
2824
|
+
}
|
|
2825
|
+
wire.take(4);
|
|
2826
|
+
const lines = text.split(`\r
|
|
2827
|
+
`);
|
|
2828
|
+
const statusLine = lines.shift() ?? "";
|
|
2829
|
+
const matched = /^HTTP\/1\.[01] (\d{3})(?: (.*))?$/.exec(statusLine);
|
|
2830
|
+
if (!matched) {
|
|
2831
|
+
return {
|
|
2832
|
+
kind: "malformed",
|
|
2833
|
+
error: new Error("Unix response has an invalid HTTP status line")
|
|
2834
|
+
};
|
|
2835
|
+
}
|
|
2836
|
+
const headers = new Headers;
|
|
2837
|
+
let contentLength;
|
|
2838
|
+
try {
|
|
2839
|
+
for (const line of lines) {
|
|
2840
|
+
const separator = line.indexOf(":");
|
|
2841
|
+
if (separator <= 0)
|
|
2842
|
+
throw new Error("Unix response has an invalid header line");
|
|
2843
|
+
headers.append(line.slice(0, separator).trim(), line.slice(separator + 1).trim());
|
|
2844
|
+
}
|
|
2845
|
+
contentLength = parseContentLength(headers);
|
|
2846
|
+
} catch (error) {
|
|
2847
|
+
return { kind: "malformed", error };
|
|
2848
|
+
}
|
|
2849
|
+
return {
|
|
2850
|
+
kind: "head",
|
|
2851
|
+
status: Number(matched[1]),
|
|
2852
|
+
statusText: matched[2] ?? "",
|
|
2853
|
+
headers,
|
|
2854
|
+
contentLength,
|
|
2855
|
+
chunked: headers.get("transfer-encoding")?.toLowerCase().includes("chunked") ?? false
|
|
2856
|
+
};
|
|
2857
|
+
}
|
|
2858
|
+
var malformed = (message) => ({
|
|
2859
|
+
kind: "malformed",
|
|
2860
|
+
error: new Error(message)
|
|
2861
|
+
});
|
|
2862
|
+
|
|
2863
|
+
class BodyDecoder {
|
|
2864
|
+
chunked;
|
|
2865
|
+
remainingLength;
|
|
2866
|
+
maxHeaderBytes;
|
|
2867
|
+
chunkRemaining;
|
|
2868
|
+
expectChunkCrlf = false;
|
|
2869
|
+
trailers = false;
|
|
2870
|
+
constructor(chunked, remainingLength, maxHeaderBytes) {
|
|
2871
|
+
this.chunked = chunked;
|
|
2872
|
+
this.remainingLength = remainingLength;
|
|
2873
|
+
this.maxHeaderBytes = maxHeaderBytes;
|
|
2874
|
+
}
|
|
2875
|
+
next(wire, peerEnded) {
|
|
2876
|
+
return this.chunked ? this.nextChunked(wire, peerEnded) : this.nextPlain(wire, peerEnded);
|
|
2877
|
+
}
|
|
2878
|
+
nextPlain(wire, peerEnded) {
|
|
2879
|
+
if (wire.byteLength > 0) {
|
|
2880
|
+
const permitted = this.remainingLength ?? wire.byteLength;
|
|
2881
|
+
const bytes = Math.min(permitted, wire.byteLength, MAX_BODY_CHUNK_BYTES);
|
|
2882
|
+
if (this.remainingLength !== undefined)
|
|
2883
|
+
this.remainingLength -= bytes;
|
|
2884
|
+
return { kind: "data", value: wire.take(bytes) };
|
|
2885
|
+
}
|
|
2886
|
+
if (this.remainingLength === 0)
|
|
2887
|
+
return { kind: "complete" };
|
|
2888
|
+
if (!peerEnded)
|
|
2889
|
+
return { kind: "more" };
|
|
2890
|
+
return this.remainingLength !== undefined && this.remainingLength > 0 ? malformed("Unix response ended before Content-Length bytes arrived") : { kind: "complete" };
|
|
2891
|
+
}
|
|
2892
|
+
get plainComplete() {
|
|
2893
|
+
return !this.chunked && this.remainingLength === 0;
|
|
2894
|
+
}
|
|
2895
|
+
nextChunked(wire, peerEnded) {
|
|
2896
|
+
for (;; ) {
|
|
2897
|
+
if (this.trailers)
|
|
2898
|
+
return this.readTrailers(wire, peerEnded);
|
|
2899
|
+
if (this.expectChunkCrlf) {
|
|
2900
|
+
if (wire.byteLength < 2) {
|
|
2901
|
+
return peerEnded ? malformed("Unix chunked response ended before chunk delimiter") : { kind: "more" };
|
|
2902
|
+
}
|
|
2903
|
+
if (!wire.startsWith(CRLF2)) {
|
|
2904
|
+
return malformed("Unix chunked response has an invalid chunk delimiter");
|
|
2905
|
+
}
|
|
2906
|
+
wire.take(2);
|
|
2907
|
+
this.expectChunkCrlf = false;
|
|
2908
|
+
}
|
|
2909
|
+
if (this.chunkRemaining === undefined) {
|
|
2910
|
+
const header = this.readChunkHeader(wire, peerEnded);
|
|
2911
|
+
if (header !== undefined)
|
|
2912
|
+
return header;
|
|
2913
|
+
if (this.trailers)
|
|
2914
|
+
continue;
|
|
2915
|
+
}
|
|
2916
|
+
const remaining = this.chunkRemaining ?? 0;
|
|
2917
|
+
if (wire.byteLength === 0) {
|
|
2918
|
+
return peerEnded ? malformed("Unix chunked response ended inside a chunk") : { kind: "more" };
|
|
2919
|
+
}
|
|
2920
|
+
const bytes = Math.min(remaining, wire.byteLength, MAX_BODY_CHUNK_BYTES);
|
|
2921
|
+
const value = wire.take(bytes);
|
|
2922
|
+
this.chunkRemaining = remaining - bytes;
|
|
2923
|
+
if (this.chunkRemaining === 0) {
|
|
2924
|
+
this.chunkRemaining = undefined;
|
|
2925
|
+
this.expectChunkCrlf = true;
|
|
2926
|
+
}
|
|
2927
|
+
return { kind: "data", value };
|
|
2928
|
+
}
|
|
2929
|
+
}
|
|
2930
|
+
readChunkHeader(wire, peerEnded) {
|
|
2931
|
+
const lineEnd = wire.indexOf(CRLF2);
|
|
2932
|
+
if (lineEnd < 0) {
|
|
2933
|
+
if (wire.byteLength > MAX_CHUNK_HEADER_BYTES)
|
|
2934
|
+
return malformed("Unix chunk header is too large");
|
|
2935
|
+
return peerEnded ? malformed("Unix chunked response ended inside chunk header") : { kind: "more" };
|
|
2936
|
+
}
|
|
2937
|
+
const line = new TextDecoder("ascii", { fatal: true }).decode(wire.take(lineEnd));
|
|
2938
|
+
wire.take(2);
|
|
2939
|
+
const sizeText = line.split(";", 1)[0]?.trim() ?? "";
|
|
2940
|
+
if (!/^[0-9a-f]+$/i.test(sizeText)) {
|
|
2941
|
+
return malformed("Unix chunked response has an invalid chunk size");
|
|
2942
|
+
}
|
|
2943
|
+
const size = Number.parseInt(sizeText, 16);
|
|
2944
|
+
if (!Number.isSafeInteger(size))
|
|
2945
|
+
return malformed("Unix chunk size is not a safe integer");
|
|
2946
|
+
if (size === 0)
|
|
2947
|
+
this.trailers = true;
|
|
2948
|
+
else
|
|
2949
|
+
this.chunkRemaining = size;
|
|
2950
|
+
return;
|
|
2951
|
+
}
|
|
2952
|
+
readTrailers(wire, peerEnded) {
|
|
2953
|
+
if (wire.byteLength >= 2 && wire.startsWith(CRLF2)) {
|
|
2954
|
+
wire.take(2);
|
|
2955
|
+
return { kind: "complete" };
|
|
2956
|
+
}
|
|
2957
|
+
const trailerEnd = wire.indexOf(CRLFCRLF);
|
|
2958
|
+
if (trailerEnd < 0) {
|
|
2959
|
+
if (wire.byteLength > this.maxHeaderBytes)
|
|
2960
|
+
return { kind: "trailers-too-large" };
|
|
2961
|
+
return peerEnded ? malformed("Unix chunked response ended inside trailers") : { kind: "more" };
|
|
2962
|
+
}
|
|
2963
|
+
wire.take(trailerEnd + 4);
|
|
2964
|
+
return { kind: "complete" };
|
|
2965
|
+
}
|
|
2966
|
+
}
|
|
2967
|
+
|
|
2968
|
+
// src/server/unix-client-bun.ts
|
|
2969
|
+
function isBunUnixRuntime(candidate) {
|
|
2970
|
+
if (typeof candidate !== "object" || candidate === null)
|
|
2971
|
+
return false;
|
|
2972
|
+
return typeof Reflect.get(candidate, "connect") === "function";
|
|
2973
|
+
}
|
|
2974
|
+
function runtimeBun() {
|
|
2975
|
+
const candidate = Reflect.get(globalThis, "Bun");
|
|
2976
|
+
return isBunUnixRuntime(candidate) ? candidate : undefined;
|
|
2977
|
+
}
|
|
2978
|
+
function hasBunUnixRuntime() {
|
|
2979
|
+
return runtimeBun() !== undefined;
|
|
2980
|
+
}
|
|
2981
|
+
function classifyTransportFailure(error, headersReceived, dispatched) {
|
|
2982
|
+
if (error instanceof UnixClientTransportError)
|
|
2983
|
+
return error;
|
|
2984
|
+
if (headersReceived) {
|
|
2985
|
+
return new UnixClientTransportError("UNIX_RESPONSE_ABORTED", "Unix response failed before completion", "response-received", { cause: error });
|
|
2986
|
+
}
|
|
2987
|
+
return new UnixClientTransportError(dispatched ? "UNIX_DELIVERY_UNCERTAIN" : "UNIX_CONNECT_FAILED", dispatched ? "Unix request transport failed after dispatch may have begun" : "Unix socket connection failed before request dispatch", dispatched ? "possibly-dispatched" : "not-dispatched", { cause: error });
|
|
2988
|
+
}
|
|
2989
|
+
function limitError(limit, what, bytes) {
|
|
2990
|
+
return limit === "body" ? new UnixClientTransportError("UNIX_RESPONSE_TOO_LARGE", `Unix response body exceeds the ${bytes} byte limit`, "response-received") : new UnixClientTransportError("UNIX_HEADERS_TOO_LARGE", `Unix response ${what} exceed the ${bytes} byte limit`, "response-received");
|
|
2991
|
+
}
|
|
2992
|
+
function socketHandlers(events) {
|
|
2993
|
+
return {
|
|
2994
|
+
binaryType: "uint8array",
|
|
2995
|
+
open: events.open,
|
|
2996
|
+
drain: events.flush,
|
|
2997
|
+
data(active, data) {
|
|
2998
|
+
active.pause();
|
|
2999
|
+
events.data(data);
|
|
3000
|
+
},
|
|
3001
|
+
end: () => events.ended(undefined, "ended"),
|
|
3002
|
+
close: (_active, error) => events.ended(error, "closed"),
|
|
3003
|
+
error: (_active, error) => events.failed(error),
|
|
3004
|
+
connectError: (_active, error) => events.failed(error)
|
|
3005
|
+
};
|
|
3006
|
+
}
|
|
3007
|
+
function writeAvailable(active, bytes, offset) {
|
|
3008
|
+
let written = offset;
|
|
3009
|
+
while (written < bytes.byteLength) {
|
|
3010
|
+
const count = active.write(bytes, written, bytes.byteLength - written);
|
|
3011
|
+
if (count < 0)
|
|
3012
|
+
return "closed";
|
|
3013
|
+
if (count === 0)
|
|
3014
|
+
break;
|
|
3015
|
+
written += count;
|
|
3016
|
+
}
|
|
3017
|
+
return written;
|
|
3018
|
+
}
|
|
2623
3019
|
function bunUnixRequest(options) {
|
|
2624
3020
|
const outgoing = requestBytes(options.request, options.body);
|
|
2625
3021
|
const bun = runtimeBun();
|
|
@@ -2627,17 +3023,13 @@ function bunUnixRequest(options) {
|
|
|
2627
3023
|
throw new Error("Bun Unix runtime is unavailable");
|
|
2628
3024
|
let socket;
|
|
2629
3025
|
let controller;
|
|
2630
|
-
|
|
3026
|
+
const wire = new WireBuffer;
|
|
3027
|
+
let decoder2;
|
|
2631
3028
|
let responseResolved = false;
|
|
2632
3029
|
let headersReceived = false;
|
|
2633
3030
|
let settled = false;
|
|
2634
3031
|
let bodyComplete = false;
|
|
2635
3032
|
let peerEnded = false;
|
|
2636
|
-
let chunked = false;
|
|
2637
|
-
let chunkRemaining;
|
|
2638
|
-
let expectChunkCrlf = false;
|
|
2639
|
-
let trailers = false;
|
|
2640
|
-
let remainingLength;
|
|
2641
3033
|
let received = 0;
|
|
2642
3034
|
let writeOffset = 0;
|
|
2643
3035
|
let resolveResponse = () => {
|
|
@@ -2650,15 +3042,7 @@ function bunUnixRequest(options) {
|
|
|
2650
3042
|
resolveResponse = resolve;
|
|
2651
3043
|
rejectResponse = reject;
|
|
2652
3044
|
});
|
|
2653
|
-
const transportFailure = (error) =>
|
|
2654
|
-
if (error instanceof UnixClientTransportError)
|
|
2655
|
-
return error;
|
|
2656
|
-
if (headersReceived) {
|
|
2657
|
-
return new UnixClientTransportError("UNIX_RESPONSE_ABORTED", "Unix response failed before completion", "response-received", { cause: error });
|
|
2658
|
-
}
|
|
2659
|
-
const dispatched = writeOffset > 0;
|
|
2660
|
-
return new UnixClientTransportError(dispatched ? "UNIX_DELIVERY_UNCERTAIN" : "UNIX_CONNECT_FAILED", dispatched ? "Unix request transport failed after dispatch may have begun" : "Unix socket connection failed before request dispatch", dispatched ? "possibly-dispatched" : "not-dispatched", { cause: error });
|
|
2661
|
-
};
|
|
3045
|
+
const transportFailure = (error) => classifyTransportFailure(error, headersReceived, writeOffset > 0);
|
|
2662
3046
|
const clearRegistration = options.registerAbort(() => {
|
|
2663
3047
|
fail(new UnixClientTransportError("UNIX_CLIENT_CLOSED", "Unix client transport is closed"));
|
|
2664
3048
|
});
|
|
@@ -2691,16 +3075,11 @@ function bunUnixRequest(options) {
|
|
|
2691
3075
|
function abortRequest() {
|
|
2692
3076
|
fail(options.request.signal.reason ?? new DOMException("Request aborted", "AbortError"));
|
|
2693
3077
|
}
|
|
2694
|
-
const takeWire = (bytes) => {
|
|
2695
|
-
const value = wire.slice(0, bytes);
|
|
2696
|
-
wire = wire.slice(bytes);
|
|
2697
|
-
return value;
|
|
2698
|
-
};
|
|
2699
3078
|
const enqueue = (value) => {
|
|
2700
3079
|
if (options.maxResponseBytes !== undefined)
|
|
2701
3080
|
received += value.byteLength;
|
|
2702
3081
|
if (options.maxResponseBytes !== undefined && received > options.maxResponseBytes) {
|
|
2703
|
-
fail(
|
|
3082
|
+
fail(limitError("body", "body", options.maxResponseBytes));
|
|
2704
3083
|
return;
|
|
2705
3084
|
}
|
|
2706
3085
|
controller?.enqueue(value);
|
|
@@ -2717,186 +3096,51 @@ function bunUnixRequest(options) {
|
|
|
2717
3096
|
return;
|
|
2718
3097
|
socket?.resume();
|
|
2719
3098
|
};
|
|
2720
|
-
const
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
for (;; ) {
|
|
3099
|
+
const headersTooLarge = (what) => limitError("headers", what, options.maxHeaderBytes);
|
|
3100
|
+
const pump = () => {
|
|
3101
|
+
while (controller && decoder2 && !settled && !bodyComplete) {
|
|
2724
3102
|
if ((controller.desiredSize ?? 1) <= 0)
|
|
2725
3103
|
return;
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
3104
|
+
const step = decoder2.next(wire, peerEnded);
|
|
3105
|
+
if (step.kind === "data") {
|
|
3106
|
+
enqueue(step.value);
|
|
3107
|
+
if (!settled && decoder2.plainComplete)
|
|
2729
3108
|
completeBody();
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
if (trailerEnd < 0) {
|
|
2734
|
-
if (wire.byteLength > options.maxHeaderBytes) {
|
|
2735
|
-
fail(new UnixClientTransportError("UNIX_HEADERS_TOO_LARGE", `Unix response trailers exceed the ${options.maxHeaderBytes} byte limit`, "response-received"));
|
|
2736
|
-
} else if (peerEnded) {
|
|
2737
|
-
fail(transportFailure(new Error("Unix chunked response ended inside trailers")));
|
|
2738
|
-
} else {
|
|
2739
|
-
resumeForData();
|
|
2740
|
-
}
|
|
2741
|
-
return;
|
|
2742
|
-
}
|
|
2743
|
-
takeWire(trailerEnd + 4);
|
|
3109
|
+
} else if (step.kind === "more")
|
|
3110
|
+
resumeForData();
|
|
3111
|
+
else if (step.kind === "complete")
|
|
2744
3112
|
completeBody();
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
if (peerEnded) {
|
|
2750
|
-
fail(transportFailure(new Error("Unix chunked response ended before chunk delimiter")));
|
|
2751
|
-
} else
|
|
2752
|
-
resumeForData();
|
|
2753
|
-
return;
|
|
2754
|
-
}
|
|
2755
|
-
if (wire[0] !== 13 || wire[1] !== 10) {
|
|
2756
|
-
fail(transportFailure(new Error("Unix chunked response has an invalid chunk delimiter")));
|
|
2757
|
-
return;
|
|
2758
|
-
}
|
|
2759
|
-
takeWire(2);
|
|
2760
|
-
expectChunkCrlf = false;
|
|
2761
|
-
}
|
|
2762
|
-
if (chunkRemaining === undefined) {
|
|
2763
|
-
const lineEnd = indexOfSequence(wire, [13, 10]);
|
|
2764
|
-
if (lineEnd < 0) {
|
|
2765
|
-
if (wire.byteLength > 1024) {
|
|
2766
|
-
fail(transportFailure(new Error("Unix chunk header is too large")));
|
|
2767
|
-
} else if (peerEnded) {
|
|
2768
|
-
fail(transportFailure(new Error("Unix chunked response ended inside chunk header")));
|
|
2769
|
-
} else
|
|
2770
|
-
resumeForData();
|
|
2771
|
-
return;
|
|
2772
|
-
}
|
|
2773
|
-
const line = new TextDecoder("ascii", { fatal: true }).decode(takeWire(lineEnd));
|
|
2774
|
-
takeWire(2);
|
|
2775
|
-
const sizeText = line.split(";", 1)[0]?.trim() ?? "";
|
|
2776
|
-
if (!/^[0-9a-f]+$/i.test(sizeText)) {
|
|
2777
|
-
fail(transportFailure(new Error("Unix chunked response has an invalid chunk size")));
|
|
2778
|
-
return;
|
|
2779
|
-
}
|
|
2780
|
-
chunkRemaining = Number.parseInt(sizeText, 16);
|
|
2781
|
-
if (!Number.isSafeInteger(chunkRemaining)) {
|
|
2782
|
-
fail(transportFailure(new Error("Unix chunk size is not a safe integer")));
|
|
2783
|
-
return;
|
|
2784
|
-
}
|
|
2785
|
-
if (chunkRemaining === 0) {
|
|
2786
|
-
chunkRemaining = undefined;
|
|
2787
|
-
trailers = true;
|
|
2788
|
-
continue;
|
|
2789
|
-
}
|
|
2790
|
-
}
|
|
2791
|
-
if (wire.byteLength === 0) {
|
|
2792
|
-
if (peerEnded) {
|
|
2793
|
-
fail(transportFailure(new Error("Unix chunked response ended inside a chunk")));
|
|
2794
|
-
} else
|
|
2795
|
-
resumeForData();
|
|
2796
|
-
return;
|
|
2797
|
-
}
|
|
2798
|
-
const bytes = Math.min(chunkRemaining, wire.byteLength, MAX_BODY_CHUNK_BYTES);
|
|
2799
|
-
const value = takeWire(bytes);
|
|
2800
|
-
chunkRemaining -= bytes;
|
|
2801
|
-
if (chunkRemaining === 0) {
|
|
2802
|
-
chunkRemaining = undefined;
|
|
2803
|
-
expectChunkCrlf = true;
|
|
2804
|
-
}
|
|
2805
|
-
enqueue(value);
|
|
2806
|
-
return;
|
|
2807
|
-
}
|
|
2808
|
-
};
|
|
2809
|
-
const pumpPlain = () => {
|
|
2810
|
-
if (!controller || settled || bodyComplete)
|
|
2811
|
-
return;
|
|
2812
|
-
if ((controller.desiredSize ?? 1) <= 0)
|
|
2813
|
-
return;
|
|
2814
|
-
if (wire.byteLength > 0) {
|
|
2815
|
-
const permitted = remainingLength ?? wire.byteLength;
|
|
2816
|
-
const bytes = Math.min(permitted, wire.byteLength, MAX_BODY_CHUNK_BYTES);
|
|
2817
|
-
enqueue(takeWire(bytes));
|
|
2818
|
-
if (settled)
|
|
2819
|
-
return;
|
|
2820
|
-
if (remainingLength !== undefined) {
|
|
2821
|
-
remainingLength -= bytes;
|
|
2822
|
-
if (remainingLength === 0) {
|
|
2823
|
-
completeBody();
|
|
2824
|
-
return;
|
|
2825
|
-
}
|
|
2826
|
-
}
|
|
2827
|
-
return;
|
|
2828
|
-
}
|
|
2829
|
-
if (peerEnded) {
|
|
2830
|
-
if (remainingLength !== undefined && remainingLength > 0) {
|
|
2831
|
-
fail(transportFailure(new Error("Unix response ended before Content-Length bytes arrived")));
|
|
2832
|
-
} else {
|
|
2833
|
-
completeBody();
|
|
2834
|
-
}
|
|
3113
|
+
else if (step.kind === "malformed")
|
|
3114
|
+
fail(transportFailure(step.error));
|
|
3115
|
+
else
|
|
3116
|
+
fail(headersTooLarge("trailers"));
|
|
2835
3117
|
return;
|
|
2836
3118
|
}
|
|
2837
|
-
resumeForData();
|
|
2838
|
-
};
|
|
2839
|
-
const pump = () => {
|
|
2840
|
-
if (chunked)
|
|
2841
|
-
pumpChunked();
|
|
2842
|
-
else
|
|
2843
|
-
pumpPlain();
|
|
2844
3119
|
};
|
|
2845
3120
|
const parseHeaders = () => {
|
|
2846
|
-
const
|
|
2847
|
-
if (
|
|
2848
|
-
if (
|
|
2849
|
-
|
|
2850
|
-
|
|
3121
|
+
const head = readResponseHead(wire, options.maxHeaderBytes);
|
|
3122
|
+
if (head.kind !== "head") {
|
|
3123
|
+
if (head.kind === "malformed")
|
|
3124
|
+
headersReceived = true;
|
|
3125
|
+
if (head.kind === "more")
|
|
2851
3126
|
socket?.resume();
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
fail(new UnixClientTransportError("UNIX_HEADERS_TOO_LARGE", `Unix response headers exceed the ${options.maxHeaderBytes} byte limit`, "response-received"));
|
|
3127
|
+
else if (head.kind === "too-large")
|
|
3128
|
+
fail(headersTooLarge("headers"));
|
|
3129
|
+
else
|
|
3130
|
+
fail(transportFailure(head.error));
|
|
2857
3131
|
return;
|
|
2858
3132
|
}
|
|
2859
3133
|
headersReceived = true;
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
} catch (error) {
|
|
2864
|
-
fail(transportFailure(error));
|
|
2865
|
-
return;
|
|
2866
|
-
}
|
|
2867
|
-
takeWire(4);
|
|
2868
|
-
const lines = text.split(`\r
|
|
2869
|
-
`);
|
|
2870
|
-
const statusLine = lines.shift() ?? "";
|
|
2871
|
-
const matched = /^HTTP\/1\.[01] (\d{3})(?: (.*))?$/.exec(statusLine);
|
|
2872
|
-
if (!matched) {
|
|
2873
|
-
fail(transportFailure(new Error("Unix response has an invalid HTTP status line")));
|
|
3134
|
+
const { status, statusText, headers, contentLength } = head;
|
|
3135
|
+
if (options.maxResponseBytes !== undefined && contentLength !== undefined && contentLength > options.maxResponseBytes) {
|
|
3136
|
+
fail(limitError("body", "body", options.maxResponseBytes));
|
|
2874
3137
|
return;
|
|
2875
3138
|
}
|
|
2876
|
-
|
|
2877
|
-
const statusText = matched[2] ?? "";
|
|
2878
|
-
const headers = new Headers;
|
|
2879
|
-
try {
|
|
2880
|
-
for (const line of lines) {
|
|
2881
|
-
const separator = line.indexOf(":");
|
|
2882
|
-
if (separator <= 0)
|
|
2883
|
-
throw new Error("Unix response has an invalid header line");
|
|
2884
|
-
headers.append(line.slice(0, separator).trim(), line.slice(separator + 1).trim());
|
|
2885
|
-
}
|
|
2886
|
-
remainingLength = parseContentLength(headers);
|
|
2887
|
-
} catch (error) {
|
|
2888
|
-
fail(transportFailure(error));
|
|
2889
|
-
return;
|
|
2890
|
-
}
|
|
2891
|
-
if (options.maxResponseBytes !== undefined && remainingLength !== undefined && remainingLength > options.maxResponseBytes) {
|
|
2892
|
-
fail(new UnixClientTransportError("UNIX_RESPONSE_TOO_LARGE", `Unix response body exceeds the ${options.maxResponseBytes} byte limit`, "response-received"));
|
|
2893
|
-
return;
|
|
2894
|
-
}
|
|
2895
|
-
chunked = headers.get("transfer-encoding")?.toLowerCase().includes("chunked") ?? false;
|
|
3139
|
+
decoder2 = new BodyDecoder(head.chunked, contentLength, options.maxHeaderBytes);
|
|
2896
3140
|
const bodyless = options.request.method === "HEAD" || status === 204 || status === 205 || status === 304;
|
|
2897
3141
|
clearTimeout(timer);
|
|
2898
3142
|
responseResolved = true;
|
|
2899
|
-
if (bodyless ||
|
|
3143
|
+
if (bodyless || contentLength === 0) {
|
|
2900
3144
|
resolveResponse(new Response(null, { status, statusText, headers }));
|
|
2901
3145
|
finish();
|
|
2902
3146
|
return;
|
|
@@ -2916,16 +3160,11 @@ function bunUnixRequest(options) {
|
|
|
2916
3160
|
resolveResponse(new Response(body, { status, statusText, headers }));
|
|
2917
3161
|
};
|
|
2918
3162
|
const flushRequest = (active) => {
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
}
|
|
2925
|
-
if (written === 0)
|
|
2926
|
-
return;
|
|
2927
|
-
writeOffset += written;
|
|
2928
|
-
}
|
|
3163
|
+
const next = writeAvailable(active, outgoing, writeOffset);
|
|
3164
|
+
if (next === "closed") {
|
|
3165
|
+
fail(transportFailure(new Error("Unix request socket closed while writing")));
|
|
3166
|
+
} else
|
|
3167
|
+
writeOffset = next;
|
|
2929
3168
|
};
|
|
2930
3169
|
if (options.request.signal.aborted) {
|
|
2931
3170
|
fail(options.request.signal.reason ?? new DOMException("Request aborted", "AbortError"));
|
|
@@ -2934,52 +3173,35 @@ function bunUnixRequest(options) {
|
|
|
2934
3173
|
options.request.signal.addEventListener("abort", abortRequest, { once: true });
|
|
2935
3174
|
bun.connect({
|
|
2936
3175
|
unix: options.socketPath,
|
|
2937
|
-
socket: {
|
|
2938
|
-
binaryType: "uint8array",
|
|
3176
|
+
socket: socketHandlers({
|
|
2939
3177
|
open(active) {
|
|
2940
3178
|
socket = active;
|
|
2941
|
-
if (settled)
|
|
3179
|
+
if (settled)
|
|
2942
3180
|
active.terminate();
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
flushRequest(active);
|
|
2946
|
-
},
|
|
2947
|
-
drain(active) {
|
|
2948
|
-
flushRequest(active);
|
|
3181
|
+
else
|
|
3182
|
+
flushRequest(active);
|
|
2949
3183
|
},
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
wire
|
|
3184
|
+
flush: flushRequest,
|
|
3185
|
+
data(data) {
|
|
3186
|
+
wire.append(data);
|
|
2953
3187
|
if (!responseResolved)
|
|
2954
3188
|
parseHeaders();
|
|
2955
3189
|
else
|
|
2956
3190
|
pump();
|
|
2957
3191
|
},
|
|
2958
|
-
|
|
2959
|
-
peerEnded = true;
|
|
2960
|
-
if (!responseResolved) {
|
|
2961
|
-
fail(transportFailure(new Error("Unix connection ended before response headers")));
|
|
2962
|
-
} else
|
|
2963
|
-
pump();
|
|
2964
|
-
},
|
|
2965
|
-
close(_active, error) {
|
|
3192
|
+
ended(error, how) {
|
|
2966
3193
|
peerEnded = true;
|
|
2967
3194
|
if (settled)
|
|
2968
3195
|
return;
|
|
2969
3196
|
if (error)
|
|
2970
3197
|
fail(transportFailure(error));
|
|
2971
3198
|
else if (!responseResolved) {
|
|
2972
|
-
fail(transportFailure(new Error(
|
|
3199
|
+
fail(transportFailure(new Error(`Unix connection ${how} before response headers`)));
|
|
2973
3200
|
} else
|
|
2974
3201
|
pump();
|
|
2975
3202
|
},
|
|
2976
|
-
error(
|
|
2977
|
-
|
|
2978
|
-
},
|
|
2979
|
-
connectError(_active, error) {
|
|
2980
|
-
fail(transportFailure(error));
|
|
2981
|
-
}
|
|
2982
|
-
}
|
|
3203
|
+
failed: (error) => fail(transportFailure(error))
|
|
3204
|
+
})
|
|
2983
3205
|
}).catch((error) => fail(transportFailure(error)));
|
|
2984
3206
|
return response;
|
|
2985
3207
|
}
|
|
@@ -3043,7 +3265,7 @@ function redirectedRequest(request, location, status, body) {
|
|
|
3043
3265
|
signal: request.signal
|
|
3044
3266
|
});
|
|
3045
3267
|
}
|
|
3046
|
-
function
|
|
3268
|
+
function resolveUnixClientLimits(config) {
|
|
3047
3269
|
if (!config.socketPath.startsWith("/") || config.socketPath.includes("\x00")) {
|
|
3048
3270
|
throw new TypeError("socketPath must be an absolute Unix socket path");
|
|
3049
3271
|
}
|
|
@@ -3056,6 +3278,92 @@ function createUnixClientTransport(config) {
|
|
|
3056
3278
|
const maxConnections = positiveInteger(config.maxConnections, DEFAULT_MAX_CONNECTIONS, "maxConnections");
|
|
3057
3279
|
const maxHeaderBytes = positiveInteger(config.maxHeaderBytes, DEFAULT_MAX_HEADER_BYTES2, "maxHeaderBytes");
|
|
3058
3280
|
const maxRedirects = nonNegativeInteger(config.maxRedirects, DEFAULT_MAX_REDIRECTS, "maxRedirects");
|
|
3281
|
+
return {
|
|
3282
|
+
maxRequestBytes,
|
|
3283
|
+
maxResponseBytes,
|
|
3284
|
+
headersTimeoutMs,
|
|
3285
|
+
maxConnections,
|
|
3286
|
+
maxHeaderBytes,
|
|
3287
|
+
maxRedirects
|
|
3288
|
+
};
|
|
3289
|
+
}
|
|
3290
|
+
function redirectStep(request, status, location, redirectCount, maxRedirects) {
|
|
3291
|
+
if (!location || !isRedirect(status))
|
|
3292
|
+
return "return";
|
|
3293
|
+
if (request.redirect === "error" || redirectCount >= maxRedirects) {
|
|
3294
|
+
throw new UnixClientTransportError("UNIX_REDIRECT_REFUSED", redirectCount >= maxRedirects ? `Unix redirect limit ${maxRedirects} exceeded` : "Unix request redirect mode is error", "response-received");
|
|
3295
|
+
}
|
|
3296
|
+
return request.redirect === "follow" ? "follow" : "return";
|
|
3297
|
+
}
|
|
3298
|
+
function nodeUnixRequest(input) {
|
|
3299
|
+
const { request, url, headersTimeoutMs, maxHeaderBytes, activeRequests } = input;
|
|
3300
|
+
return new Promise((resolve, reject) => {
|
|
3301
|
+
let settled = false;
|
|
3302
|
+
const resolveOnce = (response) => {
|
|
3303
|
+
if (settled)
|
|
3304
|
+
return;
|
|
3305
|
+
settled = true;
|
|
3306
|
+
resolve(response);
|
|
3307
|
+
};
|
|
3308
|
+
const rejectOnce = (error) => {
|
|
3309
|
+
if (settled)
|
|
3310
|
+
return;
|
|
3311
|
+
settled = true;
|
|
3312
|
+
reject(error);
|
|
3313
|
+
};
|
|
3314
|
+
const outgoing = httpRequest({
|
|
3315
|
+
socketPath: input.socketPath,
|
|
3316
|
+
path: `${url.pathname}${url.search}`,
|
|
3317
|
+
method: request.method,
|
|
3318
|
+
headers: input.headers,
|
|
3319
|
+
agent: input.agent,
|
|
3320
|
+
signal: request.signal,
|
|
3321
|
+
maxHeaderSize: maxHeaderBytes
|
|
3322
|
+
}, resolveOnce);
|
|
3323
|
+
let connected = false;
|
|
3324
|
+
let requestStartBytes = 0;
|
|
3325
|
+
outgoing.once("socket", (socket) => {
|
|
3326
|
+
requestStartBytes = socket.bytesWritten;
|
|
3327
|
+
if (!socket.connecting && !socket.destroyed)
|
|
3328
|
+
connected = true;
|
|
3329
|
+
else {
|
|
3330
|
+
socket.once("connect", () => {
|
|
3331
|
+
connected = true;
|
|
3332
|
+
});
|
|
3333
|
+
}
|
|
3334
|
+
});
|
|
3335
|
+
activeRequests.add(outgoing);
|
|
3336
|
+
const timer = setTimeout(() => {
|
|
3337
|
+
const error = new UnixClientTransportError("UNIX_HEADERS_TIMEOUT", `Unix response headers did not arrive within ${headersTimeoutMs}ms`);
|
|
3338
|
+
rejectOnce(error);
|
|
3339
|
+
outgoing.destroy(error);
|
|
3340
|
+
}, headersTimeoutMs);
|
|
3341
|
+
timer.unref();
|
|
3342
|
+
outgoing.once("response", () => clearTimeout(timer));
|
|
3343
|
+
outgoing.once("error", (error) => {
|
|
3344
|
+
if (isNodeHeaderOverflow(error)) {
|
|
3345
|
+
rejectOnce(new UnixClientTransportError("UNIX_HEADERS_TOO_LARGE", `Unix response headers exceed the ${maxHeaderBytes} byte limit`, "response-received", { cause: error }));
|
|
3346
|
+
return;
|
|
3347
|
+
}
|
|
3348
|
+
const dispatched = connected && (outgoing.socket?.bytesWritten ?? requestStartBytes) > requestStartBytes;
|
|
3349
|
+
rejectOnce(new UnixClientTransportError(dispatched ? "UNIX_DELIVERY_UNCERTAIN" : "UNIX_CONNECT_FAILED", dispatched ? "Unix request transport failed after dispatch may have begun" : "Unix socket connection failed before request dispatch", dispatched ? "possibly-dispatched" : "not-dispatched", { cause: error }));
|
|
3350
|
+
});
|
|
3351
|
+
outgoing.once("close", () => {
|
|
3352
|
+
clearTimeout(timer);
|
|
3353
|
+
activeRequests.delete(outgoing);
|
|
3354
|
+
});
|
|
3355
|
+
outgoing.end(input.body);
|
|
3356
|
+
});
|
|
3357
|
+
}
|
|
3358
|
+
function createUnixClientTransport(config) {
|
|
3359
|
+
const {
|
|
3360
|
+
maxRequestBytes,
|
|
3361
|
+
maxResponseBytes,
|
|
3362
|
+
headersTimeoutMs,
|
|
3363
|
+
maxConnections,
|
|
3364
|
+
maxHeaderBytes,
|
|
3365
|
+
maxRedirects
|
|
3366
|
+
} = resolveUnixClientLimits(config);
|
|
3059
3367
|
const agent = new Agent({ keepAlive: true, maxSockets: maxConnections });
|
|
3060
3368
|
const activeRequests = new Set;
|
|
3061
3369
|
const activeResponses = new Set;
|
|
@@ -3089,15 +3397,16 @@ function createUnixClientTransport(config) {
|
|
|
3089
3397
|
}
|
|
3090
3398
|
});
|
|
3091
3399
|
const location2 = response.headers.get("location");
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3400
|
+
let step2;
|
|
3401
|
+
try {
|
|
3402
|
+
step2 = redirectStep(request, response.status, location2, redirectCount, maxRedirects);
|
|
3403
|
+
} catch (error) {
|
|
3404
|
+
await response.body?.cancel();
|
|
3405
|
+
throw error;
|
|
3406
|
+
}
|
|
3407
|
+
if (step2 === "follow" && location2) {
|
|
3408
|
+
await response.body?.cancel();
|
|
3409
|
+
return dispatch2(redirectedRequest(request, location2, response.status, body), redirectCount + 1);
|
|
3101
3410
|
}
|
|
3102
3411
|
return response;
|
|
3103
3412
|
}
|
|
@@ -3105,62 +3414,16 @@ function createUnixClientTransport(config) {
|
|
|
3105
3414
|
if (!Object.keys(headers).some((name) => name.toLowerCase() === "host")) {
|
|
3106
3415
|
headers.host = url.host;
|
|
3107
3416
|
}
|
|
3108
|
-
const incoming = await
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
return;
|
|
3119
|
-
settled = true;
|
|
3120
|
-
reject(error);
|
|
3121
|
-
};
|
|
3122
|
-
const outgoing = httpRequest({
|
|
3123
|
-
socketPath: config.socketPath,
|
|
3124
|
-
path: `${url.pathname}${url.search}`,
|
|
3125
|
-
method: request.method,
|
|
3126
|
-
headers,
|
|
3127
|
-
agent,
|
|
3128
|
-
signal: request.signal,
|
|
3129
|
-
maxHeaderSize: maxHeaderBytes
|
|
3130
|
-
}, resolveOnce);
|
|
3131
|
-
let connected = false;
|
|
3132
|
-
let requestStartBytes = 0;
|
|
3133
|
-
outgoing.once("socket", (socket) => {
|
|
3134
|
-
requestStartBytes = socket.bytesWritten;
|
|
3135
|
-
if (!socket.connecting && !socket.destroyed)
|
|
3136
|
-
connected = true;
|
|
3137
|
-
else {
|
|
3138
|
-
socket.once("connect", () => {
|
|
3139
|
-
connected = true;
|
|
3140
|
-
});
|
|
3141
|
-
}
|
|
3142
|
-
});
|
|
3143
|
-
activeRequests.add(outgoing);
|
|
3144
|
-
const timer = setTimeout(() => {
|
|
3145
|
-
const error = new UnixClientTransportError("UNIX_HEADERS_TIMEOUT", `Unix response headers did not arrive within ${headersTimeoutMs}ms`);
|
|
3146
|
-
rejectOnce(error);
|
|
3147
|
-
outgoing.destroy(error);
|
|
3148
|
-
}, headersTimeoutMs);
|
|
3149
|
-
timer.unref();
|
|
3150
|
-
outgoing.once("response", () => clearTimeout(timer));
|
|
3151
|
-
outgoing.once("error", (error) => {
|
|
3152
|
-
if (isNodeHeaderOverflow(error)) {
|
|
3153
|
-
rejectOnce(new UnixClientTransportError("UNIX_HEADERS_TOO_LARGE", `Unix response headers exceed the ${maxHeaderBytes} byte limit`, "response-received", { cause: error }));
|
|
3154
|
-
return;
|
|
3155
|
-
}
|
|
3156
|
-
const dispatched = connected && (outgoing.socket?.bytesWritten ?? requestStartBytes) > requestStartBytes;
|
|
3157
|
-
rejectOnce(new UnixClientTransportError(dispatched ? "UNIX_DELIVERY_UNCERTAIN" : "UNIX_CONNECT_FAILED", dispatched ? "Unix request transport failed after dispatch may have begun" : "Unix socket connection failed before request dispatch", dispatched ? "possibly-dispatched" : "not-dispatched", { cause: error }));
|
|
3158
|
-
});
|
|
3159
|
-
outgoing.once("close", () => {
|
|
3160
|
-
clearTimeout(timer);
|
|
3161
|
-
activeRequests.delete(outgoing);
|
|
3162
|
-
});
|
|
3163
|
-
outgoing.end(body);
|
|
3417
|
+
const incoming = await nodeUnixRequest({
|
|
3418
|
+
socketPath: config.socketPath,
|
|
3419
|
+
url,
|
|
3420
|
+
request,
|
|
3421
|
+
headers,
|
|
3422
|
+
body,
|
|
3423
|
+
agent,
|
|
3424
|
+
maxHeaderBytes,
|
|
3425
|
+
headersTimeoutMs,
|
|
3426
|
+
activeRequests
|
|
3164
3427
|
});
|
|
3165
3428
|
activeResponses.add(incoming);
|
|
3166
3429
|
const releaseResponse = () => void activeResponses.delete(incoming);
|
|
@@ -3173,17 +3436,18 @@ function createUnixClientTransport(config) {
|
|
|
3173
3436
|
throw new UnixClientTransportError("UNIX_RESPONSE_TOO_LARGE", `Unix response body exceeds the ${maxResponseBytes} byte limit`, "response-received");
|
|
3174
3437
|
}
|
|
3175
3438
|
const location = responseHeadersValue.get("location");
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3439
|
+
let step;
|
|
3440
|
+
try {
|
|
3441
|
+
step = redirectStep(request, status, location, redirectCount, maxRedirects);
|
|
3442
|
+
} catch (error) {
|
|
3443
|
+
incoming.destroy();
|
|
3444
|
+
releaseResponse();
|
|
3445
|
+
throw error;
|
|
3446
|
+
}
|
|
3447
|
+
if (step === "follow" && location) {
|
|
3448
|
+
incoming.destroy();
|
|
3449
|
+
releaseResponse();
|
|
3450
|
+
return dispatch2(redirectedRequest(request, location, status, body), redirectCount + 1);
|
|
3187
3451
|
}
|
|
3188
3452
|
const bodyless = request.method === "HEAD" || status === 204 || status === 205 || status === 304;
|
|
3189
3453
|
if (bodyless) {
|
|
@@ -3226,4 +3490,4 @@ function createUnixClientTransport(config) {
|
|
|
3226
3490
|
};
|
|
3227
3491
|
}
|
|
3228
3492
|
|
|
3229
|
-
export { parseMultipart, DEFAULT_STREAM_HEARTBEAT_MS, streamingRoute, ndjsonRoute, sseRoute, createHandler, bindProcessSignals, bindRealtimeServer, webSocketLane, composeWebSocketHandlers, createSocketIOServer, socketIoLane, UnixClientTransportError, createUnixClientTransport };
|
|
3493
|
+
export { contextContributionDelta, prepareContextContribution, mergeContextContribution, parseMultipart, DEFAULT_STREAM_HEARTBEAT_MS, streamingRoute, ndjsonRoute, sseRoute, createHandler, createScopedImplementRegistry, implementRegistry, createImplementRegistry, bindProcessSignals, bindRealtimeServer, webSocketLane, composeWebSocketHandlers, createSocketIOServer, socketIoLane, UnixClientTransportError, createUnixClientTransport };
|