@cloudflare/sandbox 0.8.5 → 0.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +80 -38
- package/dist/index.js.map +1 -1
- package/dist/sandbox-DW5aQ1lD.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -773,6 +773,44 @@ var BaseTransport = class {
|
|
|
773
773
|
}
|
|
774
774
|
}
|
|
775
775
|
/**
|
|
776
|
+
* Build a URL targeting the container's HTTP server.
|
|
777
|
+
*/
|
|
778
|
+
buildContainerUrl(path$1) {
|
|
779
|
+
if (this.config.stub) return `http://localhost:${this.config.port || 3e3}${path$1}`;
|
|
780
|
+
return `${this.config.baseUrl ?? `http://localhost:${this.config.port || 3e3}`}${path$1}`;
|
|
781
|
+
}
|
|
782
|
+
/**
|
|
783
|
+
* Single HTTP request to the container — no WebSocket, no 503 retry.
|
|
784
|
+
*/
|
|
785
|
+
httpFetch(path$1, options) {
|
|
786
|
+
const url = this.buildContainerUrl(path$1);
|
|
787
|
+
if (this.config.stub) return this.config.stub.containerFetch(url, options || {}, this.config.port);
|
|
788
|
+
return globalThis.fetch(url, options);
|
|
789
|
+
}
|
|
790
|
+
/**
|
|
791
|
+
* Streaming HTTP request to the container — no WebSocket, no 503 retry.
|
|
792
|
+
*/
|
|
793
|
+
async httpFetchStream(path$1, body, method = "POST", headers) {
|
|
794
|
+
const url = this.buildContainerUrl(path$1);
|
|
795
|
+
const init = {
|
|
796
|
+
method,
|
|
797
|
+
headers: body && method === "POST" ? {
|
|
798
|
+
...headers,
|
|
799
|
+
"Content-Type": "application/json"
|
|
800
|
+
} : headers,
|
|
801
|
+
body: body && method === "POST" ? JSON.stringify(body) : void 0
|
|
802
|
+
};
|
|
803
|
+
let response;
|
|
804
|
+
if (this.config.stub) response = await this.config.stub.containerFetch(url, init, this.config.port);
|
|
805
|
+
else response = await globalThis.fetch(url, init);
|
|
806
|
+
if (!response.ok) {
|
|
807
|
+
const errorBody = await response.text();
|
|
808
|
+
throw new Error(`HTTP error! status: ${response.status} - ${errorBody}`);
|
|
809
|
+
}
|
|
810
|
+
if (!response.body) throw new Error("No response body for streaming");
|
|
811
|
+
return response.body;
|
|
812
|
+
}
|
|
813
|
+
/**
|
|
776
814
|
* Sleep utility for retry delays
|
|
777
815
|
*/
|
|
778
816
|
sleep(ms) {
|
|
@@ -787,13 +825,12 @@ var BaseTransport = class {
|
|
|
787
825
|
*
|
|
788
826
|
* Uses standard fetch API for communication with the container.
|
|
789
827
|
* HTTP is stateless, so connect/disconnect are no-ops.
|
|
828
|
+
*
|
|
829
|
+
* All HTTP request logic lives in {@link BaseTransport.httpFetch} and
|
|
830
|
+
* {@link BaseTransport.httpFetchStream}; this subclass simply wires
|
|
831
|
+
* the abstract `doFetch` / `fetchStream` hooks to those shared helpers.
|
|
790
832
|
*/
|
|
791
833
|
var HttpTransport = class extends BaseTransport {
|
|
792
|
-
baseUrl;
|
|
793
|
-
constructor(config) {
|
|
794
|
-
super(config);
|
|
795
|
-
this.baseUrl = config.baseUrl ?? "http://localhost:3000";
|
|
796
|
-
}
|
|
797
834
|
getMode() {
|
|
798
835
|
return "http";
|
|
799
836
|
}
|
|
@@ -803,36 +840,10 @@ var HttpTransport = class extends BaseTransport {
|
|
|
803
840
|
return true;
|
|
804
841
|
}
|
|
805
842
|
async doFetch(path$1, options) {
|
|
806
|
-
|
|
807
|
-
if (this.config.stub) return this.config.stub.containerFetch(url, options || {}, this.config.port);
|
|
808
|
-
return globalThis.fetch(url, options);
|
|
843
|
+
return this.httpFetch(path$1, options);
|
|
809
844
|
}
|
|
810
845
|
async fetchStream(path$1, body, method = "POST", headers) {
|
|
811
|
-
|
|
812
|
-
const options = this.buildStreamOptions(body, method, headers);
|
|
813
|
-
let response;
|
|
814
|
-
if (this.config.stub) response = await this.config.stub.containerFetch(url, options, this.config.port);
|
|
815
|
-
else response = await globalThis.fetch(url, options);
|
|
816
|
-
if (!response.ok) {
|
|
817
|
-
const errorBody = await response.text();
|
|
818
|
-
throw new Error(`HTTP error! status: ${response.status} - ${errorBody}`);
|
|
819
|
-
}
|
|
820
|
-
if (!response.body) throw new Error("No response body for streaming");
|
|
821
|
-
return response.body;
|
|
822
|
-
}
|
|
823
|
-
buildUrl(path$1) {
|
|
824
|
-
if (this.config.stub) return `http://localhost:${this.config.port}${path$1}`;
|
|
825
|
-
return `${this.baseUrl}${path$1}`;
|
|
826
|
-
}
|
|
827
|
-
buildStreamOptions(body, method, headers) {
|
|
828
|
-
return {
|
|
829
|
-
method,
|
|
830
|
-
headers: body && method === "POST" ? {
|
|
831
|
-
...headers,
|
|
832
|
-
"Content-Type": "application/json"
|
|
833
|
-
} : headers,
|
|
834
|
-
body: body && method === "POST" ? JSON.stringify(body) : void 0
|
|
835
|
-
};
|
|
846
|
+
return this.httpFetchStream(path$1, body, method, headers);
|
|
836
847
|
}
|
|
837
848
|
};
|
|
838
849
|
|
|
@@ -899,10 +910,30 @@ var WebSocketTransport = class extends BaseTransport {
|
|
|
899
910
|
this.cleanup();
|
|
900
911
|
}
|
|
901
912
|
/**
|
|
902
|
-
*
|
|
913
|
+
* Whether a WebSocket connection is currently being established.
|
|
914
|
+
*
|
|
915
|
+
* When true, awaiting `connectPromise` from a nested call would deadlock:
|
|
916
|
+
* the outer `connectViaFetch → stub.fetch → containerFetch →
|
|
917
|
+
* startAndWaitForPorts → blockConcurrencyWhile(onStart)` chain may call
|
|
918
|
+
* back into the SDK (e.g. `exec()`), which would await the same
|
|
919
|
+
* `connectPromise` that cannot resolve until `onStart` returns.
|
|
920
|
+
*
|
|
921
|
+
* Callers use this to fall back to a direct HTTP request, which is safe
|
|
922
|
+
* because `startAndWaitForPorts()` calls `setHealthy()` before invoking
|
|
923
|
+
* `onStart()`, so `containerFetch()` routes directly to the container.
|
|
924
|
+
*/
|
|
925
|
+
isWebSocketConnecting() {
|
|
926
|
+
return this.state === "connecting";
|
|
927
|
+
}
|
|
928
|
+
/**
|
|
929
|
+
* Transport-specific fetch implementation.
|
|
903
930
|
* Converts WebSocket response to standard Response object.
|
|
931
|
+
*
|
|
932
|
+
* Falls back to HTTP while a WebSocket connection is being established
|
|
933
|
+
* to avoid the re-entrant deadlock described in `isWebSocketConnecting()`.
|
|
904
934
|
*/
|
|
905
935
|
async doFetch(path$1, options) {
|
|
936
|
+
if (this.isWebSocketConnecting()) return this.httpFetch(path$1, options);
|
|
906
937
|
await this.connect();
|
|
907
938
|
const method = options?.method || "GET";
|
|
908
939
|
const body = this.parseBody(options?.body);
|
|
@@ -914,7 +945,9 @@ var WebSocketTransport = class extends BaseTransport {
|
|
|
914
945
|
});
|
|
915
946
|
}
|
|
916
947
|
/**
|
|
917
|
-
* Streaming fetch implementation
|
|
948
|
+
* Streaming fetch implementation.
|
|
949
|
+
*
|
|
950
|
+
* Delegates to `requestStream()`, which applies the re-entrancy guard.
|
|
918
951
|
*/
|
|
919
952
|
async fetchStream(path$1, body, method = "POST", headers) {
|
|
920
953
|
return this.requestStream(method, path$1, body, headers);
|
|
@@ -1054,7 +1087,12 @@ var WebSocketTransport = class extends BaseTransport {
|
|
|
1054
1087
|
});
|
|
1055
1088
|
}
|
|
1056
1089
|
/**
|
|
1057
|
-
* Send a request and wait for response
|
|
1090
|
+
* Send a request and wait for response.
|
|
1091
|
+
*
|
|
1092
|
+
* Only reachable from `doFetch()`, which already applies the re-entrancy
|
|
1093
|
+
* guard via `isWebSocketConnecting()`. The `connect()` call here handles
|
|
1094
|
+
* the case where the WebSocket was closed between `doFetch` and `request`
|
|
1095
|
+
* (idle disconnect).
|
|
1058
1096
|
*/
|
|
1059
1097
|
async request(method, path$1, body, headers) {
|
|
1060
1098
|
await this.connect();
|
|
@@ -1105,7 +1143,7 @@ var WebSocketTransport = class extends BaseTransport {
|
|
|
1105
1143
|
});
|
|
1106
1144
|
}
|
|
1107
1145
|
/**
|
|
1108
|
-
* Send a streaming request and return a ReadableStream
|
|
1146
|
+
* Send a streaming request and return a ReadableStream.
|
|
1109
1147
|
*
|
|
1110
1148
|
* The stream will receive data chunks as they arrive over the WebSocket.
|
|
1111
1149
|
* Format matches SSE for compatibility with existing streaming code.
|
|
@@ -1117,8 +1155,12 @@ var WebSocketTransport = class extends BaseTransport {
|
|
|
1117
1155
|
* Uses an inactivity timeout instead of a total-duration timeout so that
|
|
1118
1156
|
* long-running streams (e.g. execStream from an agent) stay alive as long
|
|
1119
1157
|
* as data is flowing. The timer resets on every chunk or response message.
|
|
1158
|
+
*
|
|
1159
|
+
* Falls back to HTTP while a WebSocket connection is being established
|
|
1160
|
+
* to avoid the re-entrant deadlock described in `isWebSocketConnecting()`.
|
|
1120
1161
|
*/
|
|
1121
1162
|
async requestStream(method, path$1, body, headers) {
|
|
1163
|
+
if (this.isWebSocketConnecting()) return this.httpFetchStream(path$1, body, method, headers);
|
|
1122
1164
|
await this.connect();
|
|
1123
1165
|
this.clearIdleDisconnectTimer();
|
|
1124
1166
|
const id = generateRequestId();
|
|
@@ -3645,7 +3687,7 @@ function buildS3fsSource(bucket, prefix) {
|
|
|
3645
3687
|
* This file is auto-updated by .github/changeset-version.ts during releases
|
|
3646
3688
|
* DO NOT EDIT MANUALLY - Changes will be overwritten on the next version bump
|
|
3647
3689
|
*/
|
|
3648
|
-
const SDK_VERSION = "0.8.
|
|
3690
|
+
const SDK_VERSION = "0.8.6";
|
|
3649
3691
|
|
|
3650
3692
|
//#endregion
|
|
3651
3693
|
//#region src/sandbox.ts
|