@phpsandbox/sdk 0.0.64 → 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 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 = new PHPSandbox(token);
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 = new PHPSandbox(process.env.PHPSANDBOX_TOKEN!);
56
+ const client = PHPSandbox.realtime(process.env.PHPSANDBOX_TOKEN!);
57
57
  ```
58
58
 
59
- Optional constructor args:
59
+ Explicit realtime and REST clients:
60
60
 
61
61
  ```ts
62
- new PHPSandbox('token', 'https://api.phpsandbox.io/v1', {
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 = new PHPSandbox(process.env.PHPSANDBOX_TOKEN!);
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');
@@ -246,6 +251,7 @@ if (preview.status === 'ready') {
246
251
  ```
247
252
 
248
253
  Use `notebookId` when diffing or merging from another PHPSandbox notebook. Use `url` for external Git remotes. `notebookId`, `url`, and `target` are mutually exclusive.
254
+ Set `patch: false` when only the structured file list, stat, and divergence counts are needed. Patch generation defaults to enabled for backward compatibility.
249
255
 
250
256
  Fork diff requires the base and fork to share Git history. If they do not, `diff()` returns `status: 'unrelated'`.
251
257
 
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
- newConnectionData: string;
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(): Promise<void>;
12
- login(newConnectionData: string): Promise<boolean>;
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
- return this.okra.invoke('auth.logout');
6
+ this.okra.dispose();
7
7
  }
8
- login(newConnectionData) {
9
- return this.okra.invoke('auth.login', { newConnectionData });
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.watchOkraConnection();
99
+ this.registerReconnectHandler(registerReconnect);
100
100
  }
101
- watchOkraConnection() {
102
- this.okra.onDidConnect(() => {
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
- return this.okra.invoke("auth.logout");
585
+ this.okra.dispose();
577
586
  }
578
- login(newConnectionData) {
579
- return this.okra.invoke("auth.login", { newConnectionData });
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(this.url.toString(), [], {
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.toString(),
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
- this.socket = new Transport(data.okraUrl, this.emitter, {
20083
- debug: client.options.debug,
20084
- startClosed: client.options.startClosed,
20085
- webSocket: client.options.webSocket
20086
- });
20087
- this.watchConnection();
20088
- __privateSet(this, _initPromise, __privateMethod(this, _NotebookInstance_instances, init_fn).call(this));
20089
- this.file = new Filesystem(this);
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
- const terminalError = this.socket.getTerminalError();
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 && !this.socket.isConnected) {
20113
- await this.socket.connect();
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.terminate(new NotebookUnavailableError("Notebook has been deleted.", { id: this.data.id }));
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
- return this.socket.invoke(action, data || {}, options);
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
- return this.socket.send(action, data || {});
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
- !this.socket.isClosed && this.socket.disconnect();
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 terminalError = this.socket.getTerminalError();
20463
+ const socket = this.realtimeSocket();
20464
+ const terminalError = socket.getTerminalError();
20168
20465
  if (terminalError) {
20169
20466
  return Promise.reject(terminalError);
20170
20467
  }
20171
- if (this.socket.isConnected) {
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(this.socket.onDidConnect(() => settle(() => resolve(this))));
20489
+ disposables.push(socket.onDidConnect(() => settle(() => resolve(this))));
20193
20490
  if (options.rejectOnClose) {
20194
- disposables.push(this.socket.onDidClose(() => settle(() => reject(new Error("Connection closed")))));
20491
+ disposables.push(socket.onDidClose(() => settle(() => reject(new Error("Connection closed")))));
20195
20492
  }
20196
- disposables.push(this.socket.onDidBootError((error51) => settle(() => reject(error51))));
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.socket.onDidConnect(() => {
20204
- this.socket.emit("okra.connected");
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
- this.socket.onDidClose(() => {
20210
- this.socket.emit("okra.disconnected");
20507
+ socket.onDidClose(() => {
20508
+ socket.emit("okra.disconnected");
20211
20509
  this.initialized = false;
20212
20510
  });
20213
- this.socket.onDidBootError((error51) => {
20214
- this.socket.emit("okra.boot_error", error51);
20215
- this.socket.emit("okra.disconnected");
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.socket.removeListener("okra.connected", handler);
20221
- const disposable = this.socket.listen("okra.connected", handler);
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.socket.listen("okra.disconnected", handler);
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.socket.listen("okra.boot_error", handler);
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
- this.socket.reconnect();
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,