@phpsandbox/sdk 0.0.33 → 0.0.35

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.
@@ -3102,6 +3102,89 @@ var ReconnectingWebSocket = (
3102
3102
  );
3103
3103
  var reconnecting_websocket_mjs_default = ReconnectingWebSocket;
3104
3104
 
3105
+ // src/utils/websocket.ts
3106
+ var getReadyStateLabel = (state) => {
3107
+ if (typeof state !== "number") {
3108
+ return void 0;
3109
+ }
3110
+ return {
3111
+ 0: "CONNECTING",
3112
+ 1: "OPEN",
3113
+ 2: "CLOSING",
3114
+ 3: "CLOSED"
3115
+ }[state] ?? `STATE_${state}`;
3116
+ };
3117
+ var sanitizeWebSocketUrl = (value) => {
3118
+ try {
3119
+ const url = new URL(value);
3120
+ return `${url.origin}${url.pathname}`;
3121
+ } catch {
3122
+ return value;
3123
+ }
3124
+ };
3125
+ var extractNestedErrorMessage = (value) => {
3126
+ if (value instanceof Error) {
3127
+ return value.message ? `${value.name}: ${value.message}` : value.name;
3128
+ }
3129
+ if (typeof value === "string") {
3130
+ return value;
3131
+ }
3132
+ if (!value || typeof value !== "object") {
3133
+ return void 0;
3134
+ }
3135
+ const record = value;
3136
+ const message = typeof record.message === "string" && record.message ? record.message : typeof record.reason === "string" && record.reason ? record.reason : void 0;
3137
+ if (!message) {
3138
+ return void 0;
3139
+ }
3140
+ const name = typeof record.name === "string" && record.name ? record.name : void 0;
3141
+ return name ? `${name}: ${message}` : message;
3142
+ };
3143
+ var describeWebSocketEvent = (event) => {
3144
+ if (event instanceof Error) {
3145
+ return event.message ? `${event.name}: ${event.message}` : event.name;
3146
+ }
3147
+ if (typeof event === "string") {
3148
+ return event;
3149
+ }
3150
+ if (!event || typeof event !== "object") {
3151
+ return String(event);
3152
+ }
3153
+ const record = event;
3154
+ const parts = [];
3155
+ const topLevelMessage = extractNestedErrorMessage(record);
3156
+ if (topLevelMessage) {
3157
+ parts.push(topLevelMessage);
3158
+ }
3159
+ const nestedErrorMessage = extractNestedErrorMessage(record.error);
3160
+ if (nestedErrorMessage && nestedErrorMessage !== topLevelMessage) {
3161
+ parts.push(`error=${nestedErrorMessage}`);
3162
+ }
3163
+ if (typeof record.type === "string" && record.type) {
3164
+ parts.push(`type=${record.type}`);
3165
+ }
3166
+ if (typeof record.code === "number") {
3167
+ parts.push(`code=${record.code}`);
3168
+ }
3169
+ if (typeof record.reason === "string" && record.reason && record.reason !== topLevelMessage) {
3170
+ parts.push(`reason=${record.reason}`);
3171
+ }
3172
+ if (typeof record.wasClean === "boolean") {
3173
+ parts.push(`wasClean=${record.wasClean}`);
3174
+ }
3175
+ const target = record.target ?? record.currentTarget;
3176
+ if (target && typeof target === "object") {
3177
+ if (typeof target.url === "string" && target.url) {
3178
+ parts.push(`url=${sanitizeWebSocketUrl(target.url)}`);
3179
+ }
3180
+ const readyState = getReadyStateLabel(target.readyState);
3181
+ if (readyState) {
3182
+ parts.push(`readyState=${readyState}`);
3183
+ }
3184
+ }
3185
+ return parts.length > 0 ? parts.join(" | ") : "Unknown websocket event";
3186
+ };
3187
+
3105
3188
  // node_modules/isomorphic-ws/browser.js
3106
3189
  var ws = null;
3107
3190
  if (typeof WebSocket !== "undefined") {
@@ -3139,6 +3222,19 @@ var NamedDisposable = class {
3139
3222
  };
3140
3223
 
3141
3224
  // src/socket/index.ts
3225
+ var ConnectionTimeoutError = class extends Error {
3226
+ constructor(message = "WebSocket connection timeout") {
3227
+ super(message);
3228
+ this.name = "ConnectionTimeoutError";
3229
+ }
3230
+ };
3231
+ var ConnectionFailedError = class extends Error {
3232
+ constructor(message, originalError) {
3233
+ super(message);
3234
+ this.originalError = originalError;
3235
+ this.name = "ConnectionFailedError";
3236
+ }
3237
+ };
3142
3238
  var InvalidMessageError = class extends Error {
3143
3239
  constructor(message, data) {
3144
3240
  super(message);
@@ -3190,6 +3286,7 @@ var Transport = class {
3190
3286
  this.validateConfiguration(options);
3191
3287
  this.url = new URL(url);
3192
3288
  this.PING_INTERVAL = options.pingInterval ?? 3e4;
3289
+ this.CONNECT_WAIT_TIMEOUT = options.connectWaitTimeout ?? 3e4;
3193
3290
  this.connectionStats.connectionStartTime = Date.now();
3194
3291
  const startClosed = options.startClosed !== false;
3195
3292
  this.rws = new reconnecting_websocket_mjs_default(this.url.toString(), [], {
@@ -3219,6 +3316,9 @@ var Transport = class {
3219
3316
  if (options.connectionTimeout !== void 0 && (options.connectionTimeout < 100 || options.connectionTimeout > 3e4)) {
3220
3317
  throw new InvalidConfigurationError("connectionTimeout must be between 100ms and 30000ms");
3221
3318
  }
3319
+ if (options.connectWaitTimeout !== void 0 && (options.connectWaitTimeout < 1e3 || options.connectWaitTimeout > 3e5)) {
3320
+ throw new InvalidConfigurationError("connectWaitTimeout must be between 1000ms and 300000ms");
3321
+ }
3222
3322
  if (options.maxRetries !== void 0 && (options.maxRetries < 0 || options.maxRetries > 100)) {
3223
3323
  throw new InvalidConfigurationError("maxRetries must be between 0 and 100");
3224
3324
  }
@@ -3505,7 +3605,8 @@ var Transport = class {
3505
3605
  reject(new RateLimitError(_ev.reason || "Rate limit exceeded", _ev));
3506
3606
  return;
3507
3607
  }
3508
- reject(this.terminalError || new Error(`Connection lost to the notebook during request: ${_ev.reason || "Unknown reason"}`));
3608
+ const detail = describeWebSocketEvent(_ev);
3609
+ reject(this.terminalError || new ConnectionFailedError(`Connection lost to the notebook during request: ${detail}`, _ev));
3509
3610
  };
3510
3611
  this.rws.addEventListener("close", closeHandler);
3511
3612
  this.rws.addEventListener("error", closeHandler);
@@ -3693,8 +3794,10 @@ var Transport = class {
3693
3794
  });
3694
3795
  this.rws.addEventListener("error", (event) => {
3695
3796
  this.connectionStats.totalErrors++;
3797
+ const detail = describeWebSocketEvent(event);
3696
3798
  this.log("error", "Connection error", {
3697
- error: event,
3799
+ error: detail,
3800
+ rawError: event,
3698
3801
  totalErrors: this.connectionStats.totalErrors
3699
3802
  });
3700
3803
  });
@@ -3950,33 +4053,50 @@ connect_fn = function() {
3950
4053
  __privateMethod(this, _Transport_instances, startPeriodicPing_fn).call(this);
3951
4054
  return;
3952
4055
  }
3953
- if (this.rws.readyState === 3) {
3954
- this.rws.reconnect();
3955
- }
3956
4056
  let timeoutId;
3957
- const openHandler = () => {
4057
+ let errorCount = 0;
4058
+ const cleanup = () => {
3958
4059
  this.rws.removeEventListener("open", openHandler);
3959
4060
  this.rws.removeEventListener("error", errorHandler);
4061
+ this.rws.removeEventListener("close", closeHandler);
3960
4062
  clearTimeout(timeoutId);
4063
+ };
4064
+ const openHandler = () => {
4065
+ cleanup();
3961
4066
  this.connectPromise = null;
3962
4067
  resolve();
3963
4068
  __privateMethod(this, _Transport_instances, startPeriodicPing_fn).call(this);
3964
4069
  };
3965
4070
  const errorHandler = (error) => {
3966
- this.rws.removeEventListener("open", openHandler);
3967
- this.rws.removeEventListener("error", errorHandler);
3968
- clearTimeout(timeoutId);
3969
- this.connectPromise = null;
3970
- reject(new Error(`WebSocket connection failed: ${error}`));
4071
+ errorCount += 1;
4072
+ this.log("warn", "WebSocket emitted an error while connecting; waiting for reconnect/open", {
4073
+ errorCount,
4074
+ error: describeWebSocketEvent(error)
4075
+ });
4076
+ };
4077
+ const closeHandler = (event) => {
4078
+ const detail = describeWebSocketEvent(event);
4079
+ if ("code" in event && (event.code === 1008 || event.code === 4e3)) {
4080
+ cleanup();
4081
+ this.connectPromise = null;
4082
+ reject(new ConnectionFailedError(`WebSocket connection failed: ${detail}`, event));
4083
+ return;
4084
+ }
4085
+ this.log("warn", "WebSocket closed before opening; waiting for reconnect/open", {
4086
+ error: detail
4087
+ });
3971
4088
  };
3972
- timeoutId = setTimeout(() => {
3973
- this.rws.removeEventListener("open", openHandler);
3974
- this.rws.removeEventListener("error", errorHandler);
3975
- this.connectPromise = null;
3976
- reject(new Error("WebSocket connection timeout"));
3977
- }, 1e4);
3978
4089
  this.rws.addEventListener("open", openHandler);
3979
4090
  this.rws.addEventListener("error", errorHandler);
4091
+ this.rws.addEventListener("close", closeHandler);
4092
+ if (this.rws.readyState === 3) {
4093
+ this.rws.reconnect();
4094
+ }
4095
+ timeoutId = setTimeout(() => {
4096
+ cleanup();
4097
+ this.connectPromise = null;
4098
+ reject(new ConnectionTimeoutError(`WebSocket connection timeout after ${this.CONNECT_WAIT_TIMEOUT}ms`));
4099
+ }, this.CONNECT_WAIT_TIMEOUT);
3980
4100
  });
3981
4101
  return this.connectPromise;
3982
4102
  };