@phpsandbox/sdk 0.0.29 → 0.0.32
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 +23 -0
- package/dist/browser/phpsandbox-sdk.esm.js +194 -6
- package/dist/browser/phpsandbox-sdk.esm.js.map +3 -3
- package/dist/browser/phpsandbox-sdk.esm.min.js +2 -2
- package/dist/browser/phpsandbox-sdk.esm.min.js.map +4 -4
- package/dist/browser/phpsandbox-sdk.iife.js +194 -6
- package/dist/browser/phpsandbox-sdk.iife.js.map +3 -3
- package/dist/browser/phpsandbox-sdk.iife.min.js +2 -2
- package/dist/browser/phpsandbox-sdk.iife.min.js.map +4 -4
- package/dist/errors/index.d.ts +4 -0
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +7 -0
- package/dist/errors/index.js.map +1 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +37 -1
- package/dist/index.js.map +1 -1
- package/dist/services.d.ts +85 -0
- package/dist/services.d.ts.map +1 -0
- package/dist/services.js +107 -0
- package/dist/services.js.map +1 -0
- package/dist/socket/index.d.ts +9 -0
- package/dist/socket/index.d.ts.map +1 -1
- package/dist/socket/index.js +46 -5
- package/dist/socket/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -336,6 +336,7 @@ var PHPSandbox = (() => {
|
|
|
336
336
|
NotebookSecretApi: () => NotebookSecretApi,
|
|
337
337
|
NotebookSecrets: () => NotebookSecrets,
|
|
338
338
|
NotebookState: () => NotebookState,
|
|
339
|
+
NotebookUnavailableError: () => NotebookUnavailableError,
|
|
339
340
|
PHPSandbox: () => PHPSandbox,
|
|
340
341
|
PHPSandboxError: () => PHPSandboxError,
|
|
341
342
|
PromiseTimeoutError: () => PromiseTimeoutError,
|
|
@@ -344,6 +345,8 @@ var PHPSandbox = (() => {
|
|
|
344
345
|
Transport: () => Transport,
|
|
345
346
|
createBeacon: () => createBeacon,
|
|
346
347
|
isBeaconSupported: () => isBeaconSupported,
|
|
348
|
+
notebookBuiltinServices: () => notebookBuiltinServices,
|
|
349
|
+
notebookKnownServices: () => notebookKnownServices,
|
|
347
350
|
once: () => once,
|
|
348
351
|
timeout: () => timeout
|
|
349
352
|
});
|
|
@@ -614,6 +617,13 @@ var PHPSandbox = (() => {
|
|
|
614
617
|
return new _SendTimeoutError(error.message, error.time);
|
|
615
618
|
}
|
|
616
619
|
};
|
|
620
|
+
var NotebookUnavailableError = class extends Error {
|
|
621
|
+
constructor(message = "Notebook is no longer available", raw = {}) {
|
|
622
|
+
super(message);
|
|
623
|
+
this.raw = raw;
|
|
624
|
+
this.name = "NotebookUnavailableError";
|
|
625
|
+
}
|
|
626
|
+
};
|
|
617
627
|
|
|
618
628
|
// src/utils/promise.ts
|
|
619
629
|
var timeout = (prom, time) => {
|
|
@@ -1061,6 +1071,108 @@ var PHPSandbox = (() => {
|
|
|
1061
1071
|
}
|
|
1062
1072
|
};
|
|
1063
1073
|
|
|
1074
|
+
// src/services.ts
|
|
1075
|
+
var notebookBuiltinServices = ["redis"];
|
|
1076
|
+
var notebookKnownServices = ["start", "nginx", ...notebookBuiltinServices];
|
|
1077
|
+
var Services = class {
|
|
1078
|
+
constructor(okra) {
|
|
1079
|
+
this.okra = okra;
|
|
1080
|
+
}
|
|
1081
|
+
list() {
|
|
1082
|
+
return this.okra.invoke("service.list");
|
|
1083
|
+
}
|
|
1084
|
+
run(name, command) {
|
|
1085
|
+
return this.okra.invoke("service.run", {
|
|
1086
|
+
name,
|
|
1087
|
+
command
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
1090
|
+
stop(name) {
|
|
1091
|
+
return this.okra.invoke("service.stop", { name });
|
|
1092
|
+
}
|
|
1093
|
+
onLog(id, handler) {
|
|
1094
|
+
return this.okra.listen(`service.log.${id}`, handler);
|
|
1095
|
+
}
|
|
1096
|
+
listen(event, handler) {
|
|
1097
|
+
return this.okra.listen(event, handler);
|
|
1098
|
+
}
|
|
1099
|
+
logs(name, options = {}) {
|
|
1100
|
+
if (options.follow) {
|
|
1101
|
+
return this.followLogs(name, options);
|
|
1102
|
+
}
|
|
1103
|
+
return this.okra.invoke("service.logs", {
|
|
1104
|
+
name,
|
|
1105
|
+
tail: options.tail
|
|
1106
|
+
}).then((response) => {
|
|
1107
|
+
if (!("output" in response)) {
|
|
1108
|
+
throw new Error(`Unexpected service.logs response for ${name}`);
|
|
1109
|
+
}
|
|
1110
|
+
return response.output;
|
|
1111
|
+
});
|
|
1112
|
+
}
|
|
1113
|
+
followLogs(name, options) {
|
|
1114
|
+
const id = options.id || nanoid();
|
|
1115
|
+
const disposables = /* @__PURE__ */ new Set();
|
|
1116
|
+
let controller = null;
|
|
1117
|
+
let closed = false;
|
|
1118
|
+
const dispose = () => {
|
|
1119
|
+
for (const disposable of disposables) {
|
|
1120
|
+
disposable.dispose();
|
|
1121
|
+
}
|
|
1122
|
+
disposables.clear();
|
|
1123
|
+
};
|
|
1124
|
+
const close = () => {
|
|
1125
|
+
if (closed) {
|
|
1126
|
+
return;
|
|
1127
|
+
}
|
|
1128
|
+
closed = true;
|
|
1129
|
+
dispose();
|
|
1130
|
+
if (controller) {
|
|
1131
|
+
try {
|
|
1132
|
+
controller.close();
|
|
1133
|
+
} catch {
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
};
|
|
1137
|
+
const fail = (error) => {
|
|
1138
|
+
if (closed) {
|
|
1139
|
+
return;
|
|
1140
|
+
}
|
|
1141
|
+
closed = true;
|
|
1142
|
+
dispose();
|
|
1143
|
+
if (controller) {
|
|
1144
|
+
controller.error(error);
|
|
1145
|
+
}
|
|
1146
|
+
};
|
|
1147
|
+
const stop = once(() => {
|
|
1148
|
+
close();
|
|
1149
|
+
return this.okra.invoke("service.stop-logs", { id });
|
|
1150
|
+
});
|
|
1151
|
+
const output = new ReadableStream({
|
|
1152
|
+
start: (_controller) => {
|
|
1153
|
+
controller = _controller;
|
|
1154
|
+
disposables.add(
|
|
1155
|
+
this.onLog(id, (data) => {
|
|
1156
|
+
controller?.enqueue(data.output);
|
|
1157
|
+
})
|
|
1158
|
+
);
|
|
1159
|
+
void this.okra.invoke("service.logs", {
|
|
1160
|
+
name,
|
|
1161
|
+
tail: options.tail,
|
|
1162
|
+
follow: true,
|
|
1163
|
+
id
|
|
1164
|
+
}).catch((error) => {
|
|
1165
|
+
fail(error);
|
|
1166
|
+
});
|
|
1167
|
+
},
|
|
1168
|
+
cancel: () => {
|
|
1169
|
+
void stop();
|
|
1170
|
+
}
|
|
1171
|
+
});
|
|
1172
|
+
return { id, output, stop };
|
|
1173
|
+
}
|
|
1174
|
+
};
|
|
1175
|
+
|
|
1064
1176
|
// node_modules/@msgpack/msgpack/dist.esm/utils/utf8.mjs
|
|
1065
1177
|
function utf8Count(str) {
|
|
1066
1178
|
const strLength = str.length;
|
|
@@ -3084,6 +3196,7 @@ var PHPSandbox = (() => {
|
|
|
3084
3196
|
this.closed = false;
|
|
3085
3197
|
this.disposables = new NamedDisposable();
|
|
3086
3198
|
this.connectPromise = null;
|
|
3199
|
+
this.terminalError = null;
|
|
3087
3200
|
this.pingIntervalStarted = false;
|
|
3088
3201
|
// Connection health monitoring
|
|
3089
3202
|
this.connectionStats = {
|
|
@@ -3115,7 +3228,7 @@ var PHPSandbox = (() => {
|
|
|
3115
3228
|
const startClosed = options.startClosed !== false;
|
|
3116
3229
|
this.rws = new reconnecting_websocket_mjs_default(this.url.toString(), [], {
|
|
3117
3230
|
WebSocket: globalThis.WebSocket ?? browser_default,
|
|
3118
|
-
connectionTimeout: options.connectionTimeout
|
|
3231
|
+
connectionTimeout: options.connectionTimeout,
|
|
3119
3232
|
maxReconnectionDelay: 2e3,
|
|
3120
3233
|
minReconnectionDelay: 200,
|
|
3121
3234
|
maxEnqueuedMessages: 0,
|
|
@@ -3158,6 +3271,9 @@ var PHPSandbox = (() => {
|
|
|
3158
3271
|
* Ensure the websocket is open without requiring an application-level roundtrip.
|
|
3159
3272
|
*/
|
|
3160
3273
|
connect() {
|
|
3274
|
+
if (this.terminalError) {
|
|
3275
|
+
return Promise.reject(this.terminalError);
|
|
3276
|
+
}
|
|
3161
3277
|
return __privateMethod(this, _Transport_instances, connect_fn).call(this);
|
|
3162
3278
|
}
|
|
3163
3279
|
id() {
|
|
@@ -3214,7 +3330,12 @@ var PHPSandbox = (() => {
|
|
|
3214
3330
|
return;
|
|
3215
3331
|
}
|
|
3216
3332
|
if (event === "Events.BootError" /* BootError */) {
|
|
3333
|
+
const error = new NotebookUnavailableError(
|
|
3334
|
+
data?.message || "Notebook is no longer available",
|
|
3335
|
+
data || {}
|
|
3336
|
+
);
|
|
3217
3337
|
this.log("error", "Boot error received", { data });
|
|
3338
|
+
this.terminate(error, 4e3, error.message);
|
|
3218
3339
|
return;
|
|
3219
3340
|
}
|
|
3220
3341
|
if (event === "response" /* Response */) {
|
|
@@ -3273,6 +3394,11 @@ var PHPSandbox = (() => {
|
|
|
3273
3394
|
listen(event, listener, _context) {
|
|
3274
3395
|
return this.eventEmitter.listen(event, listener);
|
|
3275
3396
|
}
|
|
3397
|
+
onDidBootError(listener) {
|
|
3398
|
+
this.eventEmitter.listen("transport.boot_error", (event) => {
|
|
3399
|
+
listener(event.error);
|
|
3400
|
+
});
|
|
3401
|
+
}
|
|
3276
3402
|
removeListener(event, listener) {
|
|
3277
3403
|
this.eventEmitter.removeListener(event, listener);
|
|
3278
3404
|
}
|
|
@@ -3299,6 +3425,9 @@ var PHPSandbox = (() => {
|
|
|
3299
3425
|
get isClosed() {
|
|
3300
3426
|
return this.closed;
|
|
3301
3427
|
}
|
|
3428
|
+
getTerminalError() {
|
|
3429
|
+
return this.terminalError;
|
|
3430
|
+
}
|
|
3302
3431
|
get status() {
|
|
3303
3432
|
return {
|
|
3304
3433
|
0: "CONNECTING",
|
|
@@ -3308,6 +3437,9 @@ var PHPSandbox = (() => {
|
|
|
3308
3437
|
}[this.rws.readyState];
|
|
3309
3438
|
}
|
|
3310
3439
|
async call(action, data = {}, options = {}) {
|
|
3440
|
+
if (this.terminalError) {
|
|
3441
|
+
throw this.terminalError;
|
|
3442
|
+
}
|
|
3311
3443
|
if (this.isRateLimited()) {
|
|
3312
3444
|
throw new RateLimitError("Rate limit exceeded - too many requests");
|
|
3313
3445
|
}
|
|
@@ -3324,6 +3456,10 @@ var PHPSandbox = (() => {
|
|
|
3324
3456
|
this.eventEmitter.removeListener(errorEvent);
|
|
3325
3457
|
};
|
|
3326
3458
|
const handler = async (resolve, reject) => {
|
|
3459
|
+
if (this.terminalError) {
|
|
3460
|
+
reject(this.terminalError);
|
|
3461
|
+
return;
|
|
3462
|
+
}
|
|
3327
3463
|
const abortError = new DOMException("Request aborted", "AbortError");
|
|
3328
3464
|
if (options.abortSignal?.aborted) {
|
|
3329
3465
|
reject(abortError);
|
|
@@ -3375,7 +3511,7 @@ var PHPSandbox = (() => {
|
|
|
3375
3511
|
reject(new RateLimitError(_ev.reason || "Rate limit exceeded", _ev));
|
|
3376
3512
|
return;
|
|
3377
3513
|
}
|
|
3378
|
-
reject(new Error(`Connection lost to the notebook during request: ${_ev.reason || "Unknown reason"}`));
|
|
3514
|
+
reject(this.terminalError || new Error(`Connection lost to the notebook during request: ${_ev.reason || "Unknown reason"}`));
|
|
3379
3515
|
};
|
|
3380
3516
|
this.rws.addEventListener("close", closeHandler);
|
|
3381
3517
|
this.rws.addEventListener("error", closeHandler);
|
|
@@ -3411,7 +3547,7 @@ var PHPSandbox = (() => {
|
|
|
3411
3547
|
try {
|
|
3412
3548
|
return await sender();
|
|
3413
3549
|
} catch (e) {
|
|
3414
|
-
if (e instanceof ErrorEvent || e instanceof RateLimitError || e instanceof InvalidConfigurationError || e instanceof InvalidMessageError || e instanceof DOMException) {
|
|
3550
|
+
if (e instanceof ErrorEvent || e instanceof RateLimitError || e instanceof InvalidConfigurationError || e instanceof InvalidMessageError || e instanceof NotebookUnavailableError || e instanceof DOMException) {
|
|
3415
3551
|
this.log("debug", "Non-retryable error, bailing", {
|
|
3416
3552
|
error: e.message,
|
|
3417
3553
|
attempt
|
|
@@ -3463,6 +3599,9 @@ var PHPSandbox = (() => {
|
|
|
3463
3599
|
* This preserves all event listeners and state.
|
|
3464
3600
|
*/
|
|
3465
3601
|
reconnect() {
|
|
3602
|
+
if (this.terminalError) {
|
|
3603
|
+
throw this.terminalError;
|
|
3604
|
+
}
|
|
3466
3605
|
if (this.closed) {
|
|
3467
3606
|
throw new Error("Cannot reconnect a closed transport. The transport has been permanently closed.");
|
|
3468
3607
|
}
|
|
@@ -3477,6 +3616,16 @@ var PHPSandbox = (() => {
|
|
|
3477
3616
|
}
|
|
3478
3617
|
this.close();
|
|
3479
3618
|
}
|
|
3619
|
+
terminate(error, code = 4e3, reason = error.message) {
|
|
3620
|
+
this.terminalError = error;
|
|
3621
|
+
if (error instanceof NotebookUnavailableError) {
|
|
3622
|
+
this.eventEmitter.emit("transport.boot_error", {
|
|
3623
|
+
error,
|
|
3624
|
+
timestamp: Date.now()
|
|
3625
|
+
});
|
|
3626
|
+
}
|
|
3627
|
+
this.close(code, reason);
|
|
3628
|
+
}
|
|
3480
3629
|
close(code, reason) {
|
|
3481
3630
|
if (this.closed) {
|
|
3482
3631
|
return;
|
|
@@ -3484,9 +3633,9 @@ var PHPSandbox = (() => {
|
|
|
3484
3633
|
this.log("info", "Closing transport connection", { code, reason });
|
|
3485
3634
|
this.connectPromise = null;
|
|
3486
3635
|
const queuedCount = this.messageQueue.length;
|
|
3636
|
+
const closeError = this.terminalError || new Error("Connection closed while message was queued");
|
|
3487
3637
|
this.messageQueue.forEach((msg) => {
|
|
3488
|
-
|
|
3489
|
-
msg.reject(new Error("Connection closed while message was queued"));
|
|
3638
|
+
msg.reject(closeError);
|
|
3490
3639
|
});
|
|
3491
3640
|
this.messageQueue = [];
|
|
3492
3641
|
if (queuedCount > 0) {
|
|
@@ -3574,6 +3723,9 @@ var PHPSandbox = (() => {
|
|
|
3574
3723
|
this.log("error", "Connection closed due to policy violation");
|
|
3575
3724
|
this.clearOldQueuedMessages();
|
|
3576
3725
|
return "stop";
|
|
3726
|
+
case 4e3:
|
|
3727
|
+
this.log("info", "Connection closed due to terminal notebook error");
|
|
3728
|
+
return "stop";
|
|
3577
3729
|
default:
|
|
3578
3730
|
this.log("warn", `Unknown close code: ${code}, will reconnect`);
|
|
3579
3731
|
return "reconnect";
|
|
@@ -3789,6 +3941,9 @@ var PHPSandbox = (() => {
|
|
|
3789
3941
|
* by caching the connection promise.
|
|
3790
3942
|
*/
|
|
3791
3943
|
connect_fn = function() {
|
|
3944
|
+
if (this.terminalError) {
|
|
3945
|
+
return Promise.reject(this.terminalError);
|
|
3946
|
+
}
|
|
3792
3947
|
if (this.isConnected) {
|
|
3793
3948
|
return Promise.resolve();
|
|
3794
3949
|
}
|
|
@@ -4835,9 +4990,14 @@ var PHPSandbox = (() => {
|
|
|
4835
4990
|
this.laravel = new Lravel(this);
|
|
4836
4991
|
this.shell = new Shell(this);
|
|
4837
4992
|
this.git = new Git(this);
|
|
4993
|
+
this.services = new Services(this);
|
|
4838
4994
|
this.secrets = new NotebookSecrets(client, this.data.id);
|
|
4839
4995
|
}
|
|
4840
4996
|
async ready() {
|
|
4997
|
+
const terminalError = this.socket.getTerminalError();
|
|
4998
|
+
if (terminalError) {
|
|
4999
|
+
throw terminalError;
|
|
5000
|
+
}
|
|
4841
5001
|
const ready = async () => {
|
|
4842
5002
|
if (this.client.options.startClosed && !this.socket.isConnected) {
|
|
4843
5003
|
await this.socket.connect();
|
|
@@ -4850,7 +5010,9 @@ var PHPSandbox = (() => {
|
|
|
4850
5010
|
return this.client.notebook.fork(this.data.id);
|
|
4851
5011
|
}
|
|
4852
5012
|
delete() {
|
|
4853
|
-
return this.client.notebook.delete(this.data.id)
|
|
5013
|
+
return this.client.notebook.delete(this.data.id).then(() => {
|
|
5014
|
+
this.socket.terminate(new NotebookUnavailableError("Notebook has been deleted.", { id: this.data.id }));
|
|
5015
|
+
});
|
|
4854
5016
|
}
|
|
4855
5017
|
stop() {
|
|
4856
5018
|
return this.container.stop();
|
|
@@ -4874,6 +5036,10 @@ var PHPSandbox = (() => {
|
|
|
4874
5036
|
!this.socket.isClosed && this.socket.disconnect();
|
|
4875
5037
|
}
|
|
4876
5038
|
connected() {
|
|
5039
|
+
const terminalError = this.socket.getTerminalError();
|
|
5040
|
+
if (terminalError) {
|
|
5041
|
+
return Promise.reject(terminalError);
|
|
5042
|
+
}
|
|
4877
5043
|
if (this.socket.isConnected) {
|
|
4878
5044
|
return Promise.resolve(this);
|
|
4879
5045
|
}
|
|
@@ -4881,18 +5047,24 @@ var PHPSandbox = (() => {
|
|
|
4881
5047
|
try {
|
|
4882
5048
|
this.socket.onDidConnect(() => resolve(this));
|
|
4883
5049
|
this.socket.onDidClose(() => reject(new Error("Connection closed")));
|
|
5050
|
+
this.socket.onDidBootError((error) => reject(error));
|
|
4884
5051
|
} catch (e) {
|
|
4885
5052
|
reject(e);
|
|
4886
5053
|
}
|
|
4887
5054
|
});
|
|
4888
5055
|
}
|
|
4889
5056
|
whenConnected() {
|
|
5057
|
+
const terminalError = this.socket.getTerminalError();
|
|
5058
|
+
if (terminalError) {
|
|
5059
|
+
return Promise.reject(terminalError);
|
|
5060
|
+
}
|
|
4890
5061
|
if (this.socket.isConnected) {
|
|
4891
5062
|
return Promise.resolve(this);
|
|
4892
5063
|
}
|
|
4893
5064
|
return new Promise((resolve, reject) => {
|
|
4894
5065
|
try {
|
|
4895
5066
|
this.socket.onDidConnect(() => resolve(this));
|
|
5067
|
+
this.socket.onDidBootError((error) => reject(error));
|
|
4896
5068
|
} catch (e) {
|
|
4897
5069
|
reject(e);
|
|
4898
5070
|
}
|
|
@@ -4909,6 +5081,11 @@ var PHPSandbox = (() => {
|
|
|
4909
5081
|
this.socket.emit("okra.disconnected");
|
|
4910
5082
|
this.initialized = false;
|
|
4911
5083
|
});
|
|
5084
|
+
this.socket.onDidBootError((error) => {
|
|
5085
|
+
this.socket.emit("okra.boot_error", error);
|
|
5086
|
+
this.socket.emit("okra.disconnected");
|
|
5087
|
+
this.initialized = false;
|
|
5088
|
+
});
|
|
4912
5089
|
}
|
|
4913
5090
|
onDidConnect(handler) {
|
|
4914
5091
|
this.socket.removeListener("okra.connected", handler);
|
|
@@ -4921,6 +5098,11 @@ var PHPSandbox = (() => {
|
|
|
4921
5098
|
this.disposables.push(disposable);
|
|
4922
5099
|
return disposable;
|
|
4923
5100
|
}
|
|
5101
|
+
onDidBootError(handler) {
|
|
5102
|
+
const disposable = this.socket.listen("okra.boot_error", handler);
|
|
5103
|
+
this.disposables.push(disposable);
|
|
5104
|
+
return disposable;
|
|
5105
|
+
}
|
|
4924
5106
|
update() {
|
|
4925
5107
|
return this.invoke("notebook.update");
|
|
4926
5108
|
}
|
|
@@ -4946,6 +5128,7 @@ var PHPSandbox = (() => {
|
|
|
4946
5128
|
init_fn = function() {
|
|
4947
5129
|
__privateSet(this, _initPromise, new Promise((resolve, reject) => {
|
|
4948
5130
|
const initializationListener = this.onDidInitialize((result) => {
|
|
5131
|
+
bootErrorListener.dispose();
|
|
4949
5132
|
initializationListener.dispose();
|
|
4950
5133
|
this.initialized = result;
|
|
4951
5134
|
if (result.type === "error") {
|
|
@@ -4954,6 +5137,11 @@ var PHPSandbox = (() => {
|
|
|
4954
5137
|
}
|
|
4955
5138
|
resolve(result);
|
|
4956
5139
|
});
|
|
5140
|
+
const bootErrorListener = this.onDidBootError((error) => {
|
|
5141
|
+
initializationListener.dispose();
|
|
5142
|
+
bootErrorListener.dispose();
|
|
5143
|
+
reject(error);
|
|
5144
|
+
});
|
|
4957
5145
|
}));
|
|
4958
5146
|
return __privateGet(this, _initPromise);
|
|
4959
5147
|
};
|