@phpsandbox/sdk 0.0.65 → 0.0.66
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 +10 -5
- package/dist/auth.d.ts +3 -4
- package/dist/auth.js +7 -3
- package/dist/browser/phpsandbox-sdk.esm.js +366 -44
- package/dist/browser/phpsandbox-sdk.esm.min.js +24 -24
- package/dist/browser/phpsandbox-sdk.iife.js +366 -44
- package/dist/browser/phpsandbox-sdk.iife.min.js +24 -24
- package/dist/errors/index.d.ts +3 -0
- package/dist/errors/index.js +6 -0
- package/dist/filesystem.d.ts +2 -2
- package/dist/filesystem.js +7 -4
- package/dist/index.d.ts +10 -0
- package/dist/index.js +108 -34
- package/dist/runtime/rest.d.ts +20 -0
- package/dist/runtime/rest.js +226 -0
- package/dist/socket/index.d.ts +2 -1
- package/dist/socket/index.js +12 -3
- package/dist/types.d.ts +1 -1
- package/docs/api-summary.md +8 -2
- package/examples/README.md +2 -2
- package/examples/laravel-load-test.ts +8 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ import { PHPSandbox } from '@phpsandbox/sdk';
|
|
|
18
18
|
const token = process.env.PHPSANDBOX_TOKEN;
|
|
19
19
|
if (!token) throw new Error('Missing PHPSANDBOX_TOKEN');
|
|
20
20
|
|
|
21
|
-
const client =
|
|
21
|
+
const client = PHPSandbox.realtime(token);
|
|
22
22
|
|
|
23
23
|
// create() initializes the notebook by default
|
|
24
24
|
const notebook = await client.notebook.create('php');
|
|
@@ -53,22 +53,27 @@ Use an API token:
|
|
|
53
53
|
```ts
|
|
54
54
|
import { PHPSandbox } from '@phpsandbox/sdk';
|
|
55
55
|
|
|
56
|
-
const client =
|
|
56
|
+
const client = PHPSandbox.realtime(process.env.PHPSANDBOX_TOKEN!);
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
Explicit realtime and REST clients:
|
|
60
60
|
|
|
61
61
|
```ts
|
|
62
|
-
|
|
62
|
+
PHPSandbox.realtime('token', 'https://api.phpsandbox.io/v1', {
|
|
63
63
|
debug: false,
|
|
64
64
|
startClosed: true,
|
|
65
65
|
});
|
|
66
|
+
|
|
67
|
+
// Use explicit request/response runtime actions without a websocket.
|
|
68
|
+
PHPSandbox.rest('token', 'https://api.phpsandbox.io/v1', {
|
|
69
|
+
okraUrlProvider: async (notebookId) => getFreshOkraUrl(notebookId),
|
|
70
|
+
});
|
|
66
71
|
```
|
|
67
72
|
|
|
68
73
|
## Notebook Lifecycle
|
|
69
74
|
|
|
70
75
|
```ts
|
|
71
|
-
const client =
|
|
76
|
+
const client = PHPSandbox.realtime(process.env.PHPSANDBOX_TOKEN!);
|
|
72
77
|
|
|
73
78
|
const created = await client.notebook.create('laravel');
|
|
74
79
|
const opened = await client.notebook.open('notebook-id');
|
package/dist/auth.d.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { Action, NotebookInstance } from './index.js';
|
|
2
2
|
export interface AuthActions {
|
|
3
3
|
'auth.login': Action<{
|
|
4
|
-
|
|
4
|
+
runtimeTicket: string;
|
|
5
5
|
}, boolean>;
|
|
6
|
-
'auth.logout': Action<null>;
|
|
7
6
|
}
|
|
8
7
|
export default class Auth {
|
|
9
8
|
protected okra: NotebookInstance;
|
|
10
9
|
constructor(okra: NotebookInstance);
|
|
11
|
-
logout():
|
|
12
|
-
login(
|
|
10
|
+
logout(): void;
|
|
11
|
+
login(okraUrl: string): Promise<boolean>;
|
|
13
12
|
}
|
package/dist/auth.js
CHANGED
|
@@ -3,9 +3,13 @@ export default class Auth {
|
|
|
3
3
|
this.okra = okra;
|
|
4
4
|
}
|
|
5
5
|
logout() {
|
|
6
|
-
|
|
6
|
+
this.okra.dispose();
|
|
7
7
|
}
|
|
8
|
-
login(
|
|
9
|
-
|
|
8
|
+
login(okraUrl) {
|
|
9
|
+
const runtimeTicket = new URL(okraUrl).searchParams.get('ticket');
|
|
10
|
+
if (runtimeTicket === null || runtimeTicket === '') {
|
|
11
|
+
throw new TypeError('The notebook connection does not contain a runtime ticket.');
|
|
12
|
+
}
|
|
13
|
+
return this.okra.invoke('auth.login', { runtimeTicket });
|
|
10
14
|
}
|
|
11
15
|
}
|
|
@@ -93,13 +93,16 @@ var FilesystemSubscription = class {
|
|
|
93
93
|
}
|
|
94
94
|
};
|
|
95
95
|
var Filesystem = class {
|
|
96
|
-
constructor(okra) {
|
|
96
|
+
constructor(okra, registerReconnect = (handler) => okra.onDidConnect(handler)) {
|
|
97
97
|
this.okra = okra;
|
|
98
98
|
this.watches = /* @__PURE__ */ new Map();
|
|
99
|
-
this.
|
|
99
|
+
this.registerReconnectHandler(registerReconnect);
|
|
100
100
|
}
|
|
101
|
-
|
|
102
|
-
|
|
101
|
+
registerReconnectHandler(registerReconnect) {
|
|
102
|
+
if (registerReconnect === null) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
registerReconnect(() => {
|
|
103
106
|
for (const { path, options } of this.watches.values()) {
|
|
104
107
|
void this.okra.invoke("fs.watch", { path, options }).catch(() => {
|
|
105
108
|
});
|
|
@@ -306,6 +309,12 @@ var NotebookUnavailableError = class extends Error {
|
|
|
306
309
|
this.name = "NotebookUnavailableError";
|
|
307
310
|
}
|
|
308
311
|
};
|
|
312
|
+
var UnsupportedRuntimeTransportError = class extends Error {
|
|
313
|
+
constructor(message) {
|
|
314
|
+
super(message);
|
|
315
|
+
this.name = "UnsupportedRuntimeTransportError";
|
|
316
|
+
}
|
|
317
|
+
};
|
|
309
318
|
|
|
310
319
|
// src/utils/promise.ts
|
|
311
320
|
var timeout = (prom, time3) => {
|
|
@@ -573,10 +582,14 @@ var Auth = class {
|
|
|
573
582
|
this.okra = okra;
|
|
574
583
|
}
|
|
575
584
|
logout() {
|
|
576
|
-
|
|
585
|
+
this.okra.dispose();
|
|
577
586
|
}
|
|
578
|
-
login(
|
|
579
|
-
|
|
587
|
+
login(okraUrl) {
|
|
588
|
+
const runtimeTicket = new URL(okraUrl).searchParams.get("ticket");
|
|
589
|
+
if (runtimeTicket === null || runtimeTicket === "") {
|
|
590
|
+
throw new TypeError("The notebook connection does not contain a runtime ticket.");
|
|
591
|
+
}
|
|
592
|
+
return this.okra.invoke("auth.login", { runtimeTicket });
|
|
580
593
|
}
|
|
581
594
|
};
|
|
582
595
|
|
|
@@ -3136,11 +3149,12 @@ var Transport = class {
|
|
|
3136
3149
|
this.pingIntervalStarted = false;
|
|
3137
3150
|
this.incomingMessageChain = Promise.resolve();
|
|
3138
3151
|
this.validateConfiguration(options);
|
|
3139
|
-
this.url = new URL(url2);
|
|
3152
|
+
this.url = typeof url2 === "string" ? new URL(url2) : null;
|
|
3153
|
+
const urlProvider = typeof url2 === "string" ? this.url.toString() : async () => new URL(await url2()).toString();
|
|
3140
3154
|
this.PING_INTERVAL = options.pingInterval ?? 3e4;
|
|
3141
3155
|
this.CONNECT_WAIT_TIMEOUT = options.connectWaitTimeout ?? 3e4;
|
|
3142
3156
|
const startClosed = options.startClosed !== false;
|
|
3143
|
-
this.rws = new ReconnectingWebSocket2(
|
|
3157
|
+
this.rws = new ReconnectingWebSocket2(urlProvider, [], {
|
|
3144
3158
|
WebSocket: options.webSocket ?? globalThis.WebSocket ?? browser_default,
|
|
3145
3159
|
connectionTimeout: options.connectionTimeout,
|
|
3146
3160
|
maxReconnectionDelay: 2e3,
|
|
@@ -3150,7 +3164,7 @@ var Transport = class {
|
|
|
3150
3164
|
startClosed
|
|
3151
3165
|
});
|
|
3152
3166
|
this.log("debug", "Transport initialized", {
|
|
3153
|
-
url: this.url.
|
|
3167
|
+
url: this.url === null ? "dynamic" : transportLogUrl(this.url),
|
|
3154
3168
|
options
|
|
3155
3169
|
});
|
|
3156
3170
|
this.registerWatchers();
|
|
@@ -3736,6 +3750,12 @@ startPeriodicPing_fn = function() {
|
|
|
3736
3750
|
};
|
|
3737
3751
|
});
|
|
3738
3752
|
};
|
|
3753
|
+
function transportLogUrl(url2) {
|
|
3754
|
+
const safeUrl = new URL(url2);
|
|
3755
|
+
safeUrl.search = "";
|
|
3756
|
+
safeUrl.hash = "";
|
|
3757
|
+
return safeUrl.toString();
|
|
3758
|
+
}
|
|
3739
3759
|
|
|
3740
3760
|
// node_modules/mitt/dist/mitt.mjs
|
|
3741
3761
|
var mitt_exports = {};
|
|
@@ -19785,6 +19805,231 @@ var ServerInstance = class {
|
|
|
19785
19805
|
}
|
|
19786
19806
|
};
|
|
19787
19807
|
|
|
19808
|
+
// src/runtime/rest.ts
|
|
19809
|
+
var restActionRoutes = {
|
|
19810
|
+
"runtime.ready": { method: "GET", path: "/runtime" },
|
|
19811
|
+
ping: { method: "GET", path: "/runtime/ping" },
|
|
19812
|
+
"config.get": { method: "GET", path: "/runtime/config" },
|
|
19813
|
+
"config.update": { method: "PATCH", path: "/runtime/config" },
|
|
19814
|
+
"config.set-ports": { method: "PUT", path: "/runtime/config/ports" },
|
|
19815
|
+
"container.state": { method: "GET", path: "/runtime/container" },
|
|
19816
|
+
"container.start": { method: "POST", path: "/runtime/container/start" },
|
|
19817
|
+
"container.restart": { method: "POST", path: "/runtime/container/restart" },
|
|
19818
|
+
"container.stop": { method: "POST", path: "/runtime/container/stop" },
|
|
19819
|
+
"container.set-php": { method: "PUT", path: "/runtime/container/php" },
|
|
19820
|
+
"container.opened-ports": { method: "GET", path: "/runtime/container/ports" },
|
|
19821
|
+
"terminal.list": { method: "GET", path: "/runtime/terminals" },
|
|
19822
|
+
"shell.exec": { method: "POST", path: "/runtime/executions" },
|
|
19823
|
+
"fs.info": { method: "POST", path: "/runtime/files/info" },
|
|
19824
|
+
"fs.readFile": { method: "GET", path: "/runtime/files/content" },
|
|
19825
|
+
"fs.writeFile": { method: "PUT", path: "/runtime/files/content" },
|
|
19826
|
+
"fs.write": { method: "PUT", path: "/runtime/files/text" },
|
|
19827
|
+
"fs.mkdir": { method: "POST", path: "/runtime/directories" },
|
|
19828
|
+
"fs.createDirectory": { method: "PUT", path: "/runtime/directories" },
|
|
19829
|
+
"fs.readDirectory": { method: "POST", path: "/runtime/directories/read" },
|
|
19830
|
+
"fs.stat": { method: "POST", path: "/runtime/files/stat" },
|
|
19831
|
+
"fs.move": { method: "POST", path: "/runtime/files/move" },
|
|
19832
|
+
"fs.rename": { method: "POST", path: "/runtime/files/rename" },
|
|
19833
|
+
"fs.copy": { method: "POST", path: "/runtime/files/copy" },
|
|
19834
|
+
"fs.remove": { method: "POST", path: "/runtime/files/remove" },
|
|
19835
|
+
"fs.delete": { method: "DELETE", path: "/runtime/files" },
|
|
19836
|
+
"fs.tail": { method: "POST", path: "/runtime/files/tail" },
|
|
19837
|
+
"fs.find": { method: "POST", path: "/runtime/files/find" },
|
|
19838
|
+
"fs.textSearch": { method: "POST", path: "/runtime/files/search" },
|
|
19839
|
+
"fs.tree": { method: "POST", path: "/runtime/files/tree" },
|
|
19840
|
+
"service.list": { method: "GET", path: "/runtime/services" },
|
|
19841
|
+
"service.run": { method: "POST", path: "/runtime/services/run" },
|
|
19842
|
+
"service.stop": { method: "POST", path: "/runtime/services/stop" },
|
|
19843
|
+
"service.logs": { method: "POST", path: "/runtime/services/logs" },
|
|
19844
|
+
"composer.invoke": { method: "POST", path: "/runtime/composer/executions" },
|
|
19845
|
+
"composer.packages": { method: "GET", path: "/runtime/composer/packages" },
|
|
19846
|
+
"composer.dump-autoload": {
|
|
19847
|
+
method: "POST",
|
|
19848
|
+
path: "/runtime/composer/autoload"
|
|
19849
|
+
},
|
|
19850
|
+
"git.checkpoint": { method: "POST", path: "/runtime/git/checkpoints" },
|
|
19851
|
+
"git.checkout": { method: "POST", path: "/runtime/git/checkouts" },
|
|
19852
|
+
"git.log": { method: "POST", path: "/runtime/git/log" },
|
|
19853
|
+
"git.sync": { method: "POST", path: "/runtime/git/sync" },
|
|
19854
|
+
"git.diff": { method: "POST", path: "/runtime/git/diff" },
|
|
19855
|
+
"git.merge": { method: "POST", path: "/runtime/git/merge" },
|
|
19856
|
+
"git.conflicts": { method: "GET", path: "/runtime/git/conflicts" },
|
|
19857
|
+
"git.resolve": { method: "POST", path: "/runtime/git/conflicts/resolve" },
|
|
19858
|
+
"git.restore": { method: "POST", path: "/runtime/git/restore" },
|
|
19859
|
+
"git.status": { method: "GET", path: "/runtime/git/status" },
|
|
19860
|
+
"git.review": { method: "GET", path: "/runtime/git/review" },
|
|
19861
|
+
"git.stage": { method: "POST", path: "/runtime/git/stage" },
|
|
19862
|
+
"git.unstage": { method: "POST", path: "/runtime/git/unstage" },
|
|
19863
|
+
"git.revert": { method: "POST", path: "/runtime/git/revert" }
|
|
19864
|
+
};
|
|
19865
|
+
var RestRuntimeInvoker = class {
|
|
19866
|
+
constructor(data, fetch, refresh) {
|
|
19867
|
+
this.fetch = fetch;
|
|
19868
|
+
this.refresh = refresh;
|
|
19869
|
+
this.refreshPromise = null;
|
|
19870
|
+
this.notebookId = data.id;
|
|
19871
|
+
this.configure(data.okraUrl);
|
|
19872
|
+
}
|
|
19873
|
+
configure(connectionUrl) {
|
|
19874
|
+
const okraUrl = new URL(connectionUrl);
|
|
19875
|
+
const ticket = okraUrl.searchParams.get("ticket") ?? "";
|
|
19876
|
+
if (ticket === "") {
|
|
19877
|
+
throw new UnsupportedRuntimeTransportError("The notebook connection does not contain a runtime ticket.");
|
|
19878
|
+
}
|
|
19879
|
+
this.ticket = ticket;
|
|
19880
|
+
okraUrl.protocol = okraUrl.protocol === "wss:" ? "https:" : "http:";
|
|
19881
|
+
okraUrl.pathname = `/api/v1/notebooks/${encodeURIComponent(this.notebookId)}`;
|
|
19882
|
+
okraUrl.searchParams.delete("ticket");
|
|
19883
|
+
okraUrl.hash = "";
|
|
19884
|
+
this.actionUrl = okraUrl;
|
|
19885
|
+
}
|
|
19886
|
+
ready() {
|
|
19887
|
+
return this.invokeRaw("runtime.ready", {}, {});
|
|
19888
|
+
}
|
|
19889
|
+
supports(action) {
|
|
19890
|
+
return action in restActionRoutes;
|
|
19891
|
+
}
|
|
19892
|
+
invoke(action, data = {}, options = {}) {
|
|
19893
|
+
return this.invokeRaw(action, data ?? {}, options);
|
|
19894
|
+
}
|
|
19895
|
+
send() {
|
|
19896
|
+
throw new UnsupportedRuntimeTransportError("Fire-and-forget actions require the realtime transport.");
|
|
19897
|
+
}
|
|
19898
|
+
async invokeRaw(action, data, options) {
|
|
19899
|
+
const abort = runtimeAbort(options);
|
|
19900
|
+
try {
|
|
19901
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
19902
|
+
const response = await this.fetch(this.request(action, data, abort.signal));
|
|
19903
|
+
if (response.status === 401 && attempt === 0 && this.refresh !== void 0) {
|
|
19904
|
+
await this.refreshAuthorization();
|
|
19905
|
+
continue;
|
|
19906
|
+
}
|
|
19907
|
+
const payload = await runtimeActionResponse(response);
|
|
19908
|
+
if (!response.ok || payload.error !== void 0) {
|
|
19909
|
+
const error51 = payload.error ?? payload;
|
|
19910
|
+
const message = typeof error51.message === "string" ? error51.message : `Runtime action ${action} failed.`;
|
|
19911
|
+
const code = typeof error51.code === "number" ? error51.code : response.status;
|
|
19912
|
+
throw new ErrorEvent(code, message, error51);
|
|
19913
|
+
}
|
|
19914
|
+
return payload.data;
|
|
19915
|
+
}
|
|
19916
|
+
throw new ErrorEvent(401, `Runtime action ${action} could not be authorized.`, {});
|
|
19917
|
+
} finally {
|
|
19918
|
+
abort.dispose();
|
|
19919
|
+
}
|
|
19920
|
+
}
|
|
19921
|
+
request(action, data, signal) {
|
|
19922
|
+
const route = restActionRoutes[action];
|
|
19923
|
+
if (route === void 0) {
|
|
19924
|
+
throw new UnsupportedRuntimeTransportError(`Runtime action ${action} requires the realtime transport.`);
|
|
19925
|
+
}
|
|
19926
|
+
const url2 = new URL(this.actionUrl);
|
|
19927
|
+
url2.pathname += route.path;
|
|
19928
|
+
const headers = {
|
|
19929
|
+
Accept: "application/json, application/octet-stream",
|
|
19930
|
+
Authorization: `Bearer ${this.ticket}`
|
|
19931
|
+
};
|
|
19932
|
+
const body = runtimeActionRequestBody(action, data, url2, headers);
|
|
19933
|
+
return new Request(url2, {
|
|
19934
|
+
method: route.method,
|
|
19935
|
+
headers,
|
|
19936
|
+
body: route.method === "GET" ? void 0 : body,
|
|
19937
|
+
signal
|
|
19938
|
+
});
|
|
19939
|
+
}
|
|
19940
|
+
async refreshAuthorization() {
|
|
19941
|
+
if (this.refreshPromise === null) {
|
|
19942
|
+
this.refreshPromise = this.refresh().then((okraUrl) => this.configure(okraUrl));
|
|
19943
|
+
}
|
|
19944
|
+
try {
|
|
19945
|
+
await this.refreshPromise;
|
|
19946
|
+
} finally {
|
|
19947
|
+
this.refreshPromise = null;
|
|
19948
|
+
}
|
|
19949
|
+
}
|
|
19950
|
+
};
|
|
19951
|
+
async function runtimeActionResponse(response) {
|
|
19952
|
+
if (response.ok && response.headers.get("content-type")?.toLowerCase().startsWith("application/octet-stream")) {
|
|
19953
|
+
return { data: new Uint8Array(await response.arrayBuffer()) };
|
|
19954
|
+
}
|
|
19955
|
+
const body = await response.text();
|
|
19956
|
+
if (body === "") {
|
|
19957
|
+
return {};
|
|
19958
|
+
}
|
|
19959
|
+
try {
|
|
19960
|
+
return JSON.parse(body);
|
|
19961
|
+
} catch {
|
|
19962
|
+
return { error: { code: response.status, message: body } };
|
|
19963
|
+
}
|
|
19964
|
+
}
|
|
19965
|
+
function runtimeActionRequestBody(action, data, url2, headers) {
|
|
19966
|
+
const payload = runtimeActionRecord(data);
|
|
19967
|
+
if (action === "fs.readFile") {
|
|
19968
|
+
setRequiredRuntimeQuery(url2, "path", payload.path);
|
|
19969
|
+
const lineRange = runtimeActionRecord(payload.lineRange);
|
|
19970
|
+
if (lineRange.lineStart !== void 0 || lineRange.lineEnd !== void 0) {
|
|
19971
|
+
setRequiredRuntimeQuery(url2, "lineStart", lineRange.lineStart);
|
|
19972
|
+
setRequiredRuntimeQuery(url2, "lineEnd", lineRange.lineEnd);
|
|
19973
|
+
}
|
|
19974
|
+
return void 0;
|
|
19975
|
+
}
|
|
19976
|
+
if (action === "fs.writeFile") {
|
|
19977
|
+
setRequiredRuntimeQuery(url2, "path", payload.path);
|
|
19978
|
+
const options = runtimeActionRecord(payload.options);
|
|
19979
|
+
setBooleanRuntimeQuery(url2, "overwrite", options.overwrite);
|
|
19980
|
+
setBooleanRuntimeQuery(url2, "create", options.create);
|
|
19981
|
+
setBooleanRuntimeQuery(url2, "unlock", options.unlock);
|
|
19982
|
+
const atomic = runtimeActionRecord(options.atomic);
|
|
19983
|
+
if (typeof atomic.postfix === "string" && atomic.postfix !== "") {
|
|
19984
|
+
url2.searchParams.set("atomicPostfix", atomic.postfix);
|
|
19985
|
+
}
|
|
19986
|
+
if (!ArrayBuffer.isView(payload.contents)) {
|
|
19987
|
+
throw new TypeError("Runtime file contents must be binary data.");
|
|
19988
|
+
}
|
|
19989
|
+
headers["Content-Type"] = "application/octet-stream";
|
|
19990
|
+
return Uint8Array.from(
|
|
19991
|
+
new Uint8Array(payload.contents.buffer, payload.contents.byteOffset, payload.contents.byteLength)
|
|
19992
|
+
).buffer;
|
|
19993
|
+
}
|
|
19994
|
+
headers["Content-Type"] = "application/json";
|
|
19995
|
+
return JSON.stringify(data);
|
|
19996
|
+
}
|
|
19997
|
+
function runtimeActionRecord(value) {
|
|
19998
|
+
return value !== null && typeof value === "object" ? value : {};
|
|
19999
|
+
}
|
|
20000
|
+
function setRequiredRuntimeQuery(url2, name, value) {
|
|
20001
|
+
if (typeof value !== "string" && typeof value !== "number" || String(value) === "") {
|
|
20002
|
+
throw new TypeError(`Runtime file ${name} is required.`);
|
|
20003
|
+
}
|
|
20004
|
+
url2.searchParams.set(name, String(value));
|
|
20005
|
+
}
|
|
20006
|
+
function setBooleanRuntimeQuery(url2, name, value) {
|
|
20007
|
+
url2.searchParams.set(name, value === true ? "true" : "false");
|
|
20008
|
+
}
|
|
20009
|
+
function runtimeAbort(options) {
|
|
20010
|
+
if (options.timeout === void 0 && options.abortSignal === void 0) {
|
|
20011
|
+
return { signal: new AbortController().signal, dispose: () => void 0 };
|
|
20012
|
+
}
|
|
20013
|
+
const controller = new AbortController();
|
|
20014
|
+
const abortFromCaller = () => controller.abort(options.abortSignal?.reason);
|
|
20015
|
+
options.abortSignal?.addEventListener("abort", abortFromCaller, {
|
|
20016
|
+
once: true
|
|
20017
|
+
});
|
|
20018
|
+
if (options.abortSignal?.aborted) {
|
|
20019
|
+
abortFromCaller();
|
|
20020
|
+
}
|
|
20021
|
+
const timeout2 = options.timeout === void 0 ? void 0 : setTimeout(() => controller.abort(), options.timeout);
|
|
20022
|
+
return {
|
|
20023
|
+
signal: controller.signal,
|
|
20024
|
+
dispose: () => {
|
|
20025
|
+
options.abortSignal?.removeEventListener("abort", abortFromCaller);
|
|
20026
|
+
if (timeout2 !== void 0) {
|
|
20027
|
+
clearTimeout(timeout2);
|
|
20028
|
+
}
|
|
20029
|
+
}
|
|
20030
|
+
};
|
|
20031
|
+
}
|
|
20032
|
+
|
|
19788
20033
|
// src/index.ts
|
|
19789
20034
|
function normalizeNotebookSecretInputs(input) {
|
|
19790
20035
|
if (Array.isArray(input)) {
|
|
@@ -19892,6 +20137,7 @@ function normalizeApiBaseUrl(url2) {
|
|
|
19892
20137
|
}
|
|
19893
20138
|
var Client2 = class {
|
|
19894
20139
|
constructor(token, url2 = "https://api.phpsandbox.io/v1", options = {}) {
|
|
20140
|
+
this.runtimeTransportValue = "realtime";
|
|
19895
20141
|
this.fetch = globalThis.fetch;
|
|
19896
20142
|
this.deployments = new DeploymentApi(this);
|
|
19897
20143
|
this.notebook = new NotebookApi(this);
|
|
@@ -19907,6 +20153,9 @@ var Client2 = class {
|
|
|
19907
20153
|
"Content-Type": "application/json"
|
|
19908
20154
|
};
|
|
19909
20155
|
}
|
|
20156
|
+
get runtimeTransport() {
|
|
20157
|
+
return this.runtimeTransportValue;
|
|
20158
|
+
}
|
|
19910
20159
|
get(path) {
|
|
19911
20160
|
return this.makeRequest("GET", path);
|
|
19912
20161
|
}
|
|
@@ -19970,7 +20219,15 @@ var Client2 = class {
|
|
|
19970
20219
|
return { data: body === "" ? void 0 : JSON.parse(body) };
|
|
19971
20220
|
}
|
|
19972
20221
|
};
|
|
19973
|
-
var PHPSandbox = class extends Client2 {
|
|
20222
|
+
var PHPSandbox = class _PHPSandbox extends Client2 {
|
|
20223
|
+
static realtime(token, url2 = "https://api.phpsandbox.io/v1", options = {}) {
|
|
20224
|
+
return new _PHPSandbox(token, url2, options);
|
|
20225
|
+
}
|
|
20226
|
+
static rest(token, url2 = "https://api.phpsandbox.io/v1", options = {}) {
|
|
20227
|
+
const client = new _PHPSandbox(token, url2, options);
|
|
20228
|
+
client.runtimeTransportValue = "rest";
|
|
20229
|
+
return client;
|
|
20230
|
+
}
|
|
19974
20231
|
};
|
|
19975
20232
|
var NotebookSecretApi = class {
|
|
19976
20233
|
constructor(client) {
|
|
@@ -20076,17 +20333,38 @@ var NotebookInstance2 = class {
|
|
|
20076
20333
|
this.client = client;
|
|
20077
20334
|
__privateAdd(this, _NotebookInstance_instances);
|
|
20078
20335
|
this.initialized = false;
|
|
20079
|
-
__privateAdd(this, _initPromise);
|
|
20336
|
+
__privateAdd(this, _initPromise, null);
|
|
20080
20337
|
this.disposables = [];
|
|
20081
20338
|
this.emitter = EventManager.createInstance();
|
|
20082
|
-
|
|
20083
|
-
|
|
20084
|
-
|
|
20085
|
-
|
|
20086
|
-
|
|
20087
|
-
|
|
20088
|
-
|
|
20089
|
-
|
|
20339
|
+
if (client.runtimeTransport === "rest") {
|
|
20340
|
+
this.socket = null;
|
|
20341
|
+
this.restInvoker = new RestRuntimeInvoker(
|
|
20342
|
+
data,
|
|
20343
|
+
client.options.fetch ?? globalThis.fetch,
|
|
20344
|
+
client.options.okraUrlProvider === void 0 ? void 0 : () => client.options.okraUrlProvider(data.id)
|
|
20345
|
+
);
|
|
20346
|
+
} else {
|
|
20347
|
+
this.restInvoker = null;
|
|
20348
|
+
let initialConnection = true;
|
|
20349
|
+
const connectionUrl = client.options.okraUrlProvider === void 0 ? data.okraUrl : async () => {
|
|
20350
|
+
if (initialConnection) {
|
|
20351
|
+
initialConnection = false;
|
|
20352
|
+
return data.okraUrl;
|
|
20353
|
+
}
|
|
20354
|
+
return client.options.okraUrlProvider(data.id);
|
|
20355
|
+
};
|
|
20356
|
+
this.socket = new Transport(connectionUrl, this.emitter, {
|
|
20357
|
+
debug: client.options.debug,
|
|
20358
|
+
startClosed: client.options.startClosed,
|
|
20359
|
+
webSocket: client.options.webSocket
|
|
20360
|
+
});
|
|
20361
|
+
this.watchConnection();
|
|
20362
|
+
__privateSet(this, _initPromise, __privateMethod(this, _NotebookInstance_instances, init_fn).call(this));
|
|
20363
|
+
}
|
|
20364
|
+
this.file = new Filesystem(
|
|
20365
|
+
this,
|
|
20366
|
+
this.socket === null ? null : (handler) => this.onDidConnect(handler)
|
|
20367
|
+
);
|
|
20090
20368
|
this.terminal = new Terminal(this);
|
|
20091
20369
|
this.auth = new Auth(this);
|
|
20092
20370
|
this.lsp = new Lsp(this);
|
|
@@ -20103,14 +20381,21 @@ var NotebookInstance2 = class {
|
|
|
20103
20381
|
this.preview = new NotebookPreview(client, this.data.id);
|
|
20104
20382
|
this.mail = new NotebookMail(client, this.data.id);
|
|
20105
20383
|
}
|
|
20384
|
+
get runtimeTransport() {
|
|
20385
|
+
return this.client.runtimeTransport;
|
|
20386
|
+
}
|
|
20106
20387
|
async ready() {
|
|
20107
|
-
|
|
20388
|
+
if (this.restInvoker !== null) {
|
|
20389
|
+
return this.restInitialization();
|
|
20390
|
+
}
|
|
20391
|
+
const socket = this.realtimeSocket();
|
|
20392
|
+
const terminalError = socket.getTerminalError();
|
|
20108
20393
|
if (terminalError) {
|
|
20109
20394
|
throw terminalError;
|
|
20110
20395
|
}
|
|
20111
20396
|
const ready = async () => {
|
|
20112
|
-
if (this.client.options.startClosed && !
|
|
20113
|
-
await
|
|
20397
|
+
if (this.client.options.startClosed && !socket.isConnected) {
|
|
20398
|
+
await socket.connect();
|
|
20114
20399
|
}
|
|
20115
20400
|
return __privateGet(this, _initPromise);
|
|
20116
20401
|
};
|
|
@@ -20130,7 +20415,7 @@ var NotebookInstance2 = class {
|
|
|
20130
20415
|
}
|
|
20131
20416
|
delete() {
|
|
20132
20417
|
return this.client.notebook.delete(this.data.id).then(() => {
|
|
20133
|
-
this.socket
|
|
20418
|
+
this.socket?.terminate(new NotebookUnavailableError("Notebook has been deleted.", { id: this.data.id }));
|
|
20134
20419
|
});
|
|
20135
20420
|
}
|
|
20136
20421
|
stop() {
|
|
@@ -20140,10 +20425,19 @@ var NotebookInstance2 = class {
|
|
|
20140
20425
|
return this.container.restart();
|
|
20141
20426
|
}
|
|
20142
20427
|
invoke(action, data = {}, options = {}) {
|
|
20143
|
-
|
|
20428
|
+
if (this.restInvoker !== null) {
|
|
20429
|
+
if (this.restInvoker.supports(String(action))) {
|
|
20430
|
+
void this.restInitialization();
|
|
20431
|
+
}
|
|
20432
|
+
return this.restInvoker.invoke(action, data || {}, options);
|
|
20433
|
+
}
|
|
20434
|
+
return this.realtimeSocket().invoke(action, data || {}, options);
|
|
20144
20435
|
}
|
|
20145
20436
|
send(action, data = {}) {
|
|
20146
|
-
|
|
20437
|
+
if (this.restInvoker !== null) {
|
|
20438
|
+
return this.restInvoker.send();
|
|
20439
|
+
}
|
|
20440
|
+
return this.realtimeSocket().send(action, data || {});
|
|
20147
20441
|
}
|
|
20148
20442
|
ping() {
|
|
20149
20443
|
return this.invoke("ping");
|
|
@@ -20155,7 +20449,9 @@ var NotebookInstance2 = class {
|
|
|
20155
20449
|
}
|
|
20156
20450
|
dispose() {
|
|
20157
20451
|
this.disposables.forEach((d) => d.dispose());
|
|
20158
|
-
|
|
20452
|
+
if (this.socket !== null && !this.socket.isClosed) {
|
|
20453
|
+
this.socket.disconnect();
|
|
20454
|
+
}
|
|
20159
20455
|
}
|
|
20160
20456
|
connected() {
|
|
20161
20457
|
return this.waitForSocketConnection({ rejectOnClose: true });
|
|
@@ -20164,11 +20460,12 @@ var NotebookInstance2 = class {
|
|
|
20164
20460
|
return this.waitForSocketConnection({ rejectOnClose: false });
|
|
20165
20461
|
}
|
|
20166
20462
|
waitForSocketConnection(options) {
|
|
20167
|
-
const
|
|
20463
|
+
const socket = this.realtimeSocket();
|
|
20464
|
+
const terminalError = socket.getTerminalError();
|
|
20168
20465
|
if (terminalError) {
|
|
20169
20466
|
return Promise.reject(terminalError);
|
|
20170
20467
|
}
|
|
20171
|
-
if (
|
|
20468
|
+
if (socket.isConnected) {
|
|
20172
20469
|
return Promise.resolve(this);
|
|
20173
20470
|
}
|
|
20174
20471
|
return new Promise((resolve, reject) => {
|
|
@@ -20189,49 +20486,66 @@ var NotebookInstance2 = class {
|
|
|
20189
20486
|
callback();
|
|
20190
20487
|
};
|
|
20191
20488
|
try {
|
|
20192
|
-
disposables.push(
|
|
20489
|
+
disposables.push(socket.onDidConnect(() => settle(() => resolve(this))));
|
|
20193
20490
|
if (options.rejectOnClose) {
|
|
20194
|
-
disposables.push(
|
|
20491
|
+
disposables.push(socket.onDidClose(() => settle(() => reject(new Error("Connection closed")))));
|
|
20195
20492
|
}
|
|
20196
|
-
disposables.push(
|
|
20493
|
+
disposables.push(socket.onDidBootError((error51) => settle(() => reject(error51))));
|
|
20197
20494
|
} catch (e) {
|
|
20198
20495
|
settle(() => reject(e));
|
|
20199
20496
|
}
|
|
20200
20497
|
});
|
|
20201
20498
|
}
|
|
20202
20499
|
watchConnection() {
|
|
20203
|
-
this.
|
|
20204
|
-
|
|
20500
|
+
const socket = this.realtimeSocket();
|
|
20501
|
+
socket.onDidConnect(() => {
|
|
20502
|
+
socket.emit("okra.connected");
|
|
20205
20503
|
if (this.client.options.telemetry) {
|
|
20206
20504
|
this.container.enableTelemetry(this.client.options.telemetry);
|
|
20207
20505
|
}
|
|
20208
20506
|
});
|
|
20209
|
-
|
|
20210
|
-
|
|
20507
|
+
socket.onDidClose(() => {
|
|
20508
|
+
socket.emit("okra.disconnected");
|
|
20211
20509
|
this.initialized = false;
|
|
20212
20510
|
});
|
|
20213
|
-
|
|
20214
|
-
|
|
20215
|
-
|
|
20511
|
+
socket.onDidBootError((error51) => {
|
|
20512
|
+
socket.emit("okra.boot_error", error51);
|
|
20513
|
+
socket.emit("okra.disconnected");
|
|
20216
20514
|
this.initialized = false;
|
|
20217
20515
|
});
|
|
20218
20516
|
}
|
|
20219
20517
|
onDidConnect(handler) {
|
|
20220
|
-
this.
|
|
20221
|
-
|
|
20518
|
+
const socket = this.realtimeSocket();
|
|
20519
|
+
socket.removeListener("okra.connected", handler);
|
|
20520
|
+
const disposable = socket.listen("okra.connected", handler);
|
|
20222
20521
|
this.disposables.push(disposable);
|
|
20223
20522
|
return disposable;
|
|
20224
20523
|
}
|
|
20225
20524
|
onDidDisconnect(handler) {
|
|
20226
|
-
const disposable = this.
|
|
20525
|
+
const disposable = this.realtimeSocket().listen("okra.disconnected", handler);
|
|
20227
20526
|
this.disposables.push(disposable);
|
|
20228
20527
|
return disposable;
|
|
20229
20528
|
}
|
|
20230
20529
|
onDidBootError(handler) {
|
|
20231
|
-
const disposable = this.
|
|
20530
|
+
const disposable = this.realtimeSocket().listen("okra.boot_error", handler);
|
|
20232
20531
|
this.disposables.push(disposable);
|
|
20233
20532
|
return disposable;
|
|
20234
20533
|
}
|
|
20534
|
+
restInitialization() {
|
|
20535
|
+
if (this.restInvoker === null) {
|
|
20536
|
+
throw new UnsupportedRuntimeTransportError("This operation requires the REST transport.");
|
|
20537
|
+
}
|
|
20538
|
+
if (__privateGet(this, _initPromise) === null) {
|
|
20539
|
+
__privateSet(this, _initPromise, this.restInvoker.ready().then((result) => {
|
|
20540
|
+
this.initialized = result;
|
|
20541
|
+
this.emitter.emit("notebook.initialized", result);
|
|
20542
|
+
return result;
|
|
20543
|
+
}));
|
|
20544
|
+
void __privateGet(this, _initPromise).catch(() => {
|
|
20545
|
+
});
|
|
20546
|
+
}
|
|
20547
|
+
return __privateGet(this, _initPromise);
|
|
20548
|
+
}
|
|
20235
20549
|
update(input) {
|
|
20236
20550
|
return this.client.notebook.update(this.data.id, input);
|
|
20237
20551
|
}
|
|
@@ -20239,8 +20553,9 @@ var NotebookInstance2 = class {
|
|
|
20239
20553
|
return this.listen("notebook.initialized", handler);
|
|
20240
20554
|
}
|
|
20241
20555
|
async reconnect() {
|
|
20556
|
+
const socket = this.realtimeSocket();
|
|
20242
20557
|
const whenConnected = this.whenConnected();
|
|
20243
|
-
|
|
20558
|
+
socket.reconnect();
|
|
20244
20559
|
this.initialized = false;
|
|
20245
20560
|
await whenConnected;
|
|
20246
20561
|
__privateMethod(this, _NotebookInstance_instances, init_fn).call(this);
|
|
@@ -20251,6 +20566,12 @@ var NotebookInstance2 = class {
|
|
|
20251
20566
|
iframe.src = result.data.previewUrl;
|
|
20252
20567
|
return createBeacon(iframe, options);
|
|
20253
20568
|
}
|
|
20569
|
+
realtimeSocket() {
|
|
20570
|
+
if (this.socket === null) {
|
|
20571
|
+
throw new UnsupportedRuntimeTransportError("This operation requires the realtime transport.");
|
|
20572
|
+
}
|
|
20573
|
+
return this.socket;
|
|
20574
|
+
}
|
|
20254
20575
|
};
|
|
20255
20576
|
_initPromise = new WeakMap();
|
|
20256
20577
|
_NotebookInstance_instances = new WeakSet();
|
|
@@ -20431,6 +20752,7 @@ export {
|
|
|
20431
20752
|
ServerApi,
|
|
20432
20753
|
ServerInstance,
|
|
20433
20754
|
Transport,
|
|
20755
|
+
UnsupportedRuntimeTransportError,
|
|
20434
20756
|
createBeacon,
|
|
20435
20757
|
isBeaconSupported,
|
|
20436
20758
|
notebookBuiltinServices,
|