@phpsandbox/sdk 0.0.68 → 0.1.2

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.
Files changed (56) hide show
  1. package/README.md +66 -32
  2. package/dist/auth.d.ts +0 -1
  3. package/dist/auth.js +0 -3
  4. package/dist/beacon/index.d.ts +2 -0
  5. package/dist/beacon/index.js +5 -0
  6. package/dist/browser/phpsandbox-sdk.esm.js +842 -1320
  7. package/dist/browser/phpsandbox-sdk.esm.min.js +24 -24
  8. package/dist/browser/phpsandbox-sdk.iife.js +842 -1320
  9. package/dist/browser/phpsandbox-sdk.iife.min.js +23 -23
  10. package/dist/composer.d.ts +36 -23
  11. package/dist/composer.js +61 -11
  12. package/dist/container.d.ts +2 -6
  13. package/dist/container.js +0 -28
  14. package/dist/filesystem.d.ts +58 -17
  15. package/dist/filesystem.js +169 -51
  16. package/dist/index.d.ts +30 -26
  17. package/dist/index.js +37 -32
  18. package/dist/log.d.ts +11 -5
  19. package/dist/log.js +10 -7
  20. package/dist/metrics.d.ts +10 -0
  21. package/dist/metrics.js +13 -0
  22. package/dist/ports.d.ts +10 -0
  23. package/dist/ports.js +13 -0
  24. package/dist/publications.d.ts +222 -0
  25. package/dist/{deployments.js → publications.js} +64 -69
  26. package/dist/repl.d.ts +0 -2
  27. package/dist/repl.js +0 -3
  28. package/dist/runtime/rest.js +1 -4
  29. package/dist/runtime-telemetry.d.ts +15 -0
  30. package/dist/runtime-telemetry.js +111 -0
  31. package/dist/schemas/{deployments.d.ts → publications.d.ts} +76 -76
  32. package/dist/schemas/publications.js +133 -0
  33. package/dist/services.d.ts +2 -9
  34. package/dist/services.js +3 -10
  35. package/dist/shell.d.ts +52 -22
  36. package/dist/shell.js +103 -75
  37. package/dist/terminal.d.ts +18 -14
  38. package/dist/terminal.js +29 -49
  39. package/docs/api-summary.md +37 -29
  40. package/docs/cdn-usage.md +4 -4
  41. package/docs/getting-started.md +17 -17
  42. package/examples/README.md +8 -9
  43. package/examples/basic.ts +2 -2
  44. package/examples/git-merge-smoke.ts +3 -6
  45. package/examples/laravel-load-test.ts +80 -98
  46. package/examples/notebook-readonly-smoke.ts +38 -41
  47. package/examples/publication-provider-label.ts +11 -0
  48. package/examples/{deploy-cloudflare-container.ts → publish-cloudflare-container.ts} +11 -11
  49. package/examples/{deploy-laravel-cloud.ts → publish-laravel-cloud.ts} +11 -11
  50. package/examples/{deploy-ssh-agent.ts → publish-ssh-agent.ts} +15 -16
  51. package/package.json +7 -2
  52. package/dist/deployments.d.ts +0 -251
  53. package/dist/laravel.d.ts +0 -22
  54. package/dist/laravel.js +0 -11
  55. package/dist/schemas/deployments.js +0 -133
  56. package/examples/deployment-provider-label.ts +0 -11
@@ -29,44 +29,9 @@ var PHPSandbox = (() => {
29
29
  var index_exports = {};
30
30
  __export(index_exports, {
31
31
  ApiError: () => ApiError,
32
- Beacon: () => Beacon,
33
- BeaconConnectionError: () => BeaconConnectionError,
34
- BeaconError: () => BeaconError,
35
- BeaconTimeoutError: () => BeaconTimeoutError,
36
- Client: () => Client2,
32
+ Client: () => Client,
37
33
  CommandError: () => CommandError,
38
34
  ComposerCredentials: () => ComposerCredentials,
39
- DeployStreamErrorSchema: () => DeployStreamErrorSchema,
40
- DeployStreamEventSchema: () => DeployStreamEventSchema,
41
- DeployStreamLogEventSchema: () => DeployStreamLogEventSchema,
42
- DeployStreamLogSchema: () => DeployStreamLogSchema,
43
- DeployStreamLogStreamSchema: () => DeployStreamLogStreamSchema,
44
- DeployStreamPhaseEventSchema: () => DeployStreamPhaseEventSchema,
45
- DeployStreamPhaseSchema: () => DeployStreamPhaseSchema,
46
- DeployStreamResultEventSchema: () => DeployStreamResultEventSchema,
47
- DeployStreamResultSchema: () => DeployStreamResultSchema,
48
- DeployStreamSseDoneEventSchema: () => DeployStreamSseDoneEventSchema,
49
- DeployStreamSseErrorEventSchema: () => DeployStreamSseErrorEventSchema,
50
- DeployStreamSseEventNameSchema: () => DeployStreamSseEventNameSchema,
51
- DeployStreamSseEventSchema: () => DeployStreamSseEventSchema,
52
- DeployStreamSseLogEventSchema: () => DeployStreamSseLogEventSchema,
53
- DeployStreamSsePhaseEventSchema: () => DeployStreamSsePhaseEventSchema,
54
- DeployStreamSseResultEventSchema: () => DeployStreamSseResultEventSchema,
55
- DeploymentApi: () => DeploymentApi,
56
- DeploymentBuildStatusSchema: () => DeploymentBuildStatusSchema,
57
- DeploymentDomainDnsRecordTypeSchema: () => DeploymentDomainDnsRecordTypeSchema,
58
- DeploymentEventDataSchema: () => DeploymentEventDataSchema,
59
- DeploymentInstance: () => DeploymentInstance,
60
- DeploymentJurisdictionSchema: () => DeploymentJurisdictionSchema,
61
- DeploymentLogChunkDataSchema: () => DeploymentLogChunkDataSchema,
62
- DeploymentLogStreamSchema: () => DeploymentLogStreamSchema,
63
- DeploymentProtectionModeSchema: () => DeploymentProtectionModeSchema,
64
- DeploymentRegionSchema: () => DeploymentRegionSchema,
65
- DeploymentReleaseStatusSchema: () => DeploymentReleaseStatusSchema,
66
- DeploymentRun: () => DeploymentRun,
67
- DeploymentSizeSchema: () => DeploymentSizeSchema,
68
- DeploymentStatusSchema: () => DeploymentStatusSchema,
69
- DeploymentTargetProviderSchema: () => DeploymentTargetProviderSchema,
70
35
  ErrorEvent: () => ErrorEvent,
71
36
  FileChangeFilter: () => FileChangeFilter,
72
37
  FileChangeType: () => FileChangeType,
@@ -75,35 +40,67 @@ var PHPSandbox = (() => {
75
40
  FilesystemError: () => FilesystemError,
76
41
  FilesystemErrorType: () => FilesystemErrorType,
77
42
  LspConnection: () => LspConnection,
78
- Navigator: () => Navigator,
79
43
  NotebookApi: () => NotebookApi,
80
44
  NotebookComposerCredentialApi: () => NotebookComposerCredentialApi,
81
- NotebookDeploymentApi: () => NotebookDeploymentApi,
82
45
  NotebookInitError: () => NotebookInitError,
83
- NotebookInstance: () => NotebookInstance2,
46
+ NotebookInstance: () => NotebookInstance,
84
47
  NotebookMail: () => NotebookMail,
85
48
  NotebookMailApi: () => NotebookMailApi,
86
49
  NotebookPreview: () => NotebookPreview,
87
50
  NotebookPreviewApi: () => NotebookPreviewApi,
51
+ NotebookPublicationApi: () => NotebookPublicationApi,
88
52
  NotebookSecretApi: () => NotebookSecretApi,
89
53
  NotebookSecrets: () => NotebookSecrets,
90
54
  NotebookState: () => NotebookState,
91
55
  NotebookUnavailableError: () => NotebookUnavailableError,
92
56
  PHPSandbox: () => PHPSandbox,
93
57
  PHPSandboxError: () => PHPSandboxError,
58
+ ProcessReadable: () => ProcessReadable,
59
+ ProcessResult: () => ProcessResult,
94
60
  PromiseTimeoutError: () => PromiseTimeoutError,
61
+ PublicationApi: () => PublicationApi,
62
+ PublicationBuildStatusSchema: () => PublicationBuildStatusSchema,
63
+ PublicationDomainDnsRecordTypeSchema: () => PublicationDomainDnsRecordTypeSchema,
64
+ PublicationEventDataSchema: () => PublicationEventDataSchema,
65
+ PublicationInstance: () => PublicationInstance,
66
+ PublicationJurisdictionSchema: () => PublicationJurisdictionSchema,
67
+ PublicationLogChunkDataSchema: () => PublicationLogChunkDataSchema,
68
+ PublicationLogStreamSchema: () => PublicationLogStreamSchema,
69
+ PublicationProtectionModeSchema: () => PublicationProtectionModeSchema,
70
+ PublicationProviderNameSchema: () => PublicationProviderNameSchema,
71
+ PublicationRegionSchema: () => PublicationRegionSchema,
72
+ PublicationReleaseStatusSchema: () => PublicationReleaseStatusSchema,
73
+ PublicationRun: () => PublicationRun,
74
+ PublicationSizeSchema: () => PublicationSizeSchema,
75
+ PublicationStatusSchema: () => PublicationStatusSchema,
76
+ PublishStreamErrorSchema: () => PublishStreamErrorSchema,
77
+ PublishStreamEventSchema: () => PublishStreamEventSchema,
78
+ PublishStreamLogEventSchema: () => PublishStreamLogEventSchema,
79
+ PublishStreamLogSchema: () => PublishStreamLogSchema,
80
+ PublishStreamLogStreamSchema: () => PublishStreamLogStreamSchema,
81
+ PublishStreamPhaseEventSchema: () => PublishStreamPhaseEventSchema,
82
+ PublishStreamPhaseSchema: () => PublishStreamPhaseSchema,
83
+ PublishStreamResultEventSchema: () => PublishStreamResultEventSchema,
84
+ PublishStreamResultSchema: () => PublishStreamResultSchema,
85
+ PublishStreamSseDoneEventSchema: () => PublishStreamSseDoneEventSchema,
86
+ PublishStreamSseErrorEventSchema: () => PublishStreamSseErrorEventSchema,
87
+ PublishStreamSseEventNameSchema: () => PublishStreamSseEventNameSchema,
88
+ PublishStreamSseEventSchema: () => PublishStreamSseEventSchema,
89
+ PublishStreamSseLogEventSchema: () => PublishStreamSseLogEventSchema,
90
+ PublishStreamSsePhaseEventSchema: () => PublishStreamSsePhaseEventSchema,
91
+ PublishStreamSseResultEventSchema: () => PublishStreamSseResultEventSchema,
95
92
  RateLimitError: () => RateLimitError,
93
+ RuntimeTelemetry: () => RuntimeTelemetry,
96
94
  SendTimeoutError: () => SendTimeoutError,
97
95
  ServerApi: () => ServerApi,
98
96
  ServerInstance: () => ServerInstance,
99
- Transport: () => Transport,
97
+ ShellProcess: () => ShellProcess,
100
98
  UnsupportedRuntimeTransportError: () => UnsupportedRuntimeTransportError,
101
- createBeacon: () => createBeacon,
102
- isBeaconSupported: () => isBeaconSupported,
103
99
  notebookBuiltinServices: () => notebookBuiltinServices,
104
100
  notebookKnownServices: () => notebookKnownServices,
105
101
  once: () => once,
106
- timeout: () => timeout
102
+ timeout: () => timeout,
103
+ watchRuntimeTelemetry: () => watchRuntimeTelemetry
107
104
  });
108
105
 
109
106
  // src/types.ts
@@ -203,11 +200,122 @@ var PHPSandbox = (() => {
203
200
  }
204
201
  });
205
202
  }
206
- info(path) {
207
- return this.okra.invoke("fs.info", { path });
203
+ async write(path, contents, options = {}) {
204
+ const resolvedOptions = {
205
+ overwrite: true,
206
+ create: true,
207
+ unlock: false,
208
+ atomic: false,
209
+ ...options
210
+ };
211
+ const source = typeof contents === "string" ? new TextEncoder().encode(contents) : contents;
212
+ if (this.okra.runtimeTransport === "rest") {
213
+ const bytes = source instanceof Uint8Array ? source : await collectBytes(source);
214
+ await this.okra.invoke("fs.writeFile", {
215
+ path,
216
+ contents: bytes,
217
+ options: resolvedOptions
218
+ }).catch((error51) => this.handleError(error51));
219
+ return;
220
+ }
221
+ const id = nanoid();
222
+ const completion = this.okra.invoke("fs.writeStream", { id, path, options: resolvedOptions });
223
+ void completion.catch(() => {
224
+ });
225
+ try {
226
+ for await (const chunk of toAsyncIterable(source)) {
227
+ const written = await this.okra.invoke("fs.writeChunk", { id, contents: chunk });
228
+ if (!written) {
229
+ throw new Error(`File write stream ${id} is not available`);
230
+ }
231
+ }
232
+ const ended = await this.okra.invoke("fs.endWrite", { id });
233
+ if (!ended) {
234
+ throw new Error(`File write stream ${id} could not be completed`);
235
+ }
236
+ await completion;
237
+ } catch (error51) {
238
+ await this.okra.invoke("fs.abortWrite", { id }).catch(() => false);
239
+ await completion.catch(() => false);
240
+ throw error51;
241
+ }
242
+ }
243
+ async read(path) {
244
+ try {
245
+ const content = await this.okra.invoke("fs.readFile", { path });
246
+ return content instanceof Uint8Array ? content : new TextEncoder().encode(content);
247
+ } catch (error51) {
248
+ this.handleError(error51);
249
+ }
250
+ }
251
+ async readText(path) {
252
+ return new TextDecoder().decode(await this.read(path));
253
+ }
254
+ async readLines(path, range) {
255
+ try {
256
+ const result = await this.okra.invoke("fs.readFile", {
257
+ path,
258
+ lineRange: {
259
+ lineStart: range.start,
260
+ lineEnd: range.end
261
+ }
262
+ });
263
+ if (typeof result === "string" || result instanceof Uint8Array) {
264
+ throw new Error(`Unexpected ranged file response for ${path}`);
265
+ }
266
+ return {
267
+ start: result.lineStart,
268
+ end: result.lineEnd,
269
+ content: result.content,
270
+ ...result.error === null ? {} : { warning: result.error }
271
+ };
272
+ } catch (error51) {
273
+ this.handleError(error51);
274
+ }
208
275
  }
209
- write(path, contents) {
210
- return this.okra.invoke("fs.write", { path, contents });
276
+ readStream(path) {
277
+ if (this.okra.runtimeTransport === "rest") {
278
+ return new ReadableStream({
279
+ start: async (controller) => {
280
+ try {
281
+ controller.enqueue(await this.read(path));
282
+ controller.close();
283
+ } catch (error51) {
284
+ controller.error(error51);
285
+ }
286
+ }
287
+ });
288
+ }
289
+ const id = nanoid();
290
+ let disposable = null;
291
+ let closed = false;
292
+ return new ReadableStream({
293
+ start: (controller) => {
294
+ disposable = this.okra.listen(`fs.read.${id}`, (event) => {
295
+ controller.enqueue(event.data);
296
+ });
297
+ void this.okra.invoke("fs.readStream", { id, path }).then(() => {
298
+ if (!closed) {
299
+ closed = true;
300
+ disposable?.dispose();
301
+ controller.close();
302
+ }
303
+ }).catch((error51) => {
304
+ if (!closed) {
305
+ closed = true;
306
+ disposable?.dispose();
307
+ controller.error(error51);
308
+ }
309
+ });
310
+ },
311
+ cancel: async () => {
312
+ if (!closed) {
313
+ closed = true;
314
+ disposable?.dispose();
315
+ await this.okra.invoke("fs.cancelRead", { id }).catch(() => false);
316
+ }
317
+ }
318
+ });
211
319
  }
212
320
  find(query, options = {
213
321
  useIgnoreFiles: false,
@@ -286,53 +394,38 @@ var PHPSandbox = (() => {
286
394
  const disposable = this.okra.listen(`fs.text.search.${sid}`, localOnMatch);
287
395
  return this.okra.invoke("fs.textSearch", { query, options: { ...defaultOptions, ...options } }).finally(() => disposable.dispose());
288
396
  }
289
- mkdir(path) {
290
- return this.okra.invoke("fs.mkdir", { path });
291
- }
292
- move(from, to) {
293
- return this.okra.invoke("fs.move", { from, to });
294
- }
295
- remove(path, type) {
296
- return this.okra.invoke("fs.remove", { path, type });
297
- }
298
- async readFile(path, lineRange) {
299
- try {
300
- const content = await this.okra.invoke("fs.readFile", { path, lineRange });
301
- if (content instanceof Uint8Array) {
302
- return content;
303
- }
304
- if (typeof content === "string") {
305
- return new TextEncoder().encode(content);
306
- }
307
- return content;
308
- } catch (e) {
309
- this.handleError(e);
310
- }
311
- }
312
- tail(path, lines = 10) {
313
- return this.okra.invoke("fs.tail", { path, lines }).catch((e) => this.handleError(e));
314
- }
315
- writeFile(path, contents, options) {
316
- return this.okra.invoke("fs.writeFile", {
317
- path,
318
- contents,
319
- options
320
- }).catch((e) => this.handleError(e));
397
+ tail(path, options = {}) {
398
+ return this.okra.invoke("fs.tail", { path, lines: options.lines ?? 10 }).catch((e) => this.handleError(e));
321
399
  }
322
400
  stat(path) {
323
401
  return this.okra.invoke("fs.stat", { path }).catch((e) => this.handleError(e));
324
402
  }
325
- rename(from, to, options) {
326
- return this.okra.invoke("fs.rename", { from, to, options }).catch((e) => this.handleError(e));
403
+ move(from, to, options = {}) {
404
+ return this.okra.invoke("fs.rename", {
405
+ from,
406
+ to,
407
+ options: { overwrite: false, ...options }
408
+ }).catch((e) => this.handleError(e));
327
409
  }
328
- delete(path, options) {
329
- return this.okra.invoke("fs.delete", { path, options }).catch((e) => this.handleError(e));
410
+ remove(path, options = {}) {
411
+ return this.okra.invoke("fs.delete", {
412
+ path,
413
+ options: { recursive: false, useTrash: false, atomic: false, ...options }
414
+ }).catch((e) => this.handleError(e));
330
415
  }
331
- copy(source, destination, options) {
332
- return this.okra.invoke("fs.copy", { source, destination, options }).catch((e) => this.handleError(e));
416
+ copy(source, destination, options = {}) {
417
+ return this.okra.invoke("fs.copy", {
418
+ source,
419
+ destination,
420
+ options: { overwrite: false, ...options }
421
+ }).catch((e) => this.handleError(e));
333
422
  }
334
- readDirectory(path, include = [], exclude = []) {
335
- return this.okra.invoke("fs.readDirectory", { path, include, exclude }).catch((e) => this.handleError(e));
423
+ list(path, options = {}) {
424
+ return this.okra.invoke("fs.readDirectory", {
425
+ path,
426
+ include: options.include ?? [],
427
+ exclude: options.exclude ?? []
428
+ }).catch((e) => this.handleError(e));
336
429
  }
337
430
  createDirectory(path) {
338
431
  return this.okra.invoke("fs.createDirectory", { path }).catch((e) => this.handleError(e));
@@ -361,17 +454,17 @@ var PHPSandbox = (() => {
361
454
  exists(path) {
362
455
  return this.stat(path).then(() => true).catch(() => false);
363
456
  }
364
- async download(chunk, exclude, include) {
457
+ async download(options = {}) {
365
458
  const id = nanoid();
366
- const stream = !!chunk;
459
+ const stream = !!options.onChunk;
367
460
  const chunks = [];
368
461
  const disposable = this.okra.listen(
369
462
  `fs.download.${id}`,
370
- stream ? chunk : (data) => {
463
+ stream ? options.onChunk : (data) => {
371
464
  chunks.push(data);
372
465
  }
373
466
  );
374
- return this.okra.invoke("fs.download", { id, exclude, include }).then(() => new Blob(chunks, { type: "application/octet-stream" })).finally(() => disposable.dispose());
467
+ return this.okra.invoke("fs.download", { id, exclude: options.exclude, include: options.include }).then(() => new Blob(chunks, { type: "application/octet-stream" })).finally(() => disposable.dispose());
375
468
  }
376
469
  tree(path = "/") {
377
470
  return this.okra.invoke("fs.tree", { path });
@@ -383,6 +476,28 @@ var PHPSandbox = (() => {
383
476
  throw e;
384
477
  }
385
478
  };
479
+ async function* toAsyncIterable(contents) {
480
+ if (contents instanceof Uint8Array) {
481
+ yield contents;
482
+ return;
483
+ }
484
+ yield* contents;
485
+ }
486
+ async function collectBytes(stream) {
487
+ const chunks = [];
488
+ let length = 0;
489
+ for await (const chunk of stream) {
490
+ chunks.push(chunk);
491
+ length += chunk.byteLength;
492
+ }
493
+ const output = new Uint8Array(length);
494
+ let offset = 0;
495
+ for (const chunk of chunks) {
496
+ output.set(chunk, offset);
497
+ offset += chunk.byteLength;
498
+ }
499
+ return output;
500
+ }
386
501
 
387
502
  // src/errors/index.ts
388
503
  var PromiseTimeoutError = class extends Error {
@@ -428,33 +543,35 @@ var PHPSandbox = (() => {
428
543
  // src/terminal.ts
429
544
  var TERMINAL_INPUT_FLUSH_DELAY_MS = 8;
430
545
  var terminalInputFlushPattern = /[\x00-\x1f\x7f]/;
431
- var Terminal = class {
546
+ var Terminals = class {
432
547
  constructor(okra) {
433
548
  this.okra = okra;
434
549
  }
435
550
  list() {
436
551
  return this.okra.invoke("terminal.list");
437
552
  }
438
- start() {
439
- return this.okra.invoke("terminal.start");
440
- }
441
- create(input) {
442
- return this.okra.invoke("terminal.create", input);
443
- }
444
- onStarted(handler) {
445
- return this.okra.listen("terminal.started", handler);
446
- }
447
- resize(id, size) {
448
- return this.okra.invoke("terminal.resize", { id, width: size[0], height: size[1] });
449
- }
450
- onOutput(id, handler) {
451
- return this.okra.listen(`terminal.output.${id}`, handler);
452
- }
453
- input(id, input) {
454
- return Promise.resolve(this.okra.send("terminal.input", { id, input }));
455
- }
456
- listen(event, handler) {
457
- return this.okra.listen(event, handler);
553
+ async create(options = {}) {
554
+ const id = options.id ?? nanoid();
555
+ const handle = this.processHandle(id, options.abortSignal);
556
+ const command = typeof options.command === "string" && options.args?.length ? [options.command, ...options.args] : options.command;
557
+ const { abortSignal, args: _args, ...input } = options;
558
+ try {
559
+ const task = await this.okra.invoke(
560
+ "terminal.create",
561
+ {
562
+ ...input,
563
+ id,
564
+ kind: options.kind ?? "bash",
565
+ size: options.size ?? [80, 24],
566
+ command
567
+ },
568
+ { abortSignal }
569
+ );
570
+ return { ...handle.process, ...task };
571
+ } catch (error51) {
572
+ handle.dispose();
573
+ throw error51;
574
+ }
458
575
  }
459
576
  async attach(id, opts) {
460
577
  const handle = this.processHandle(id, opts?.abortSignal);
@@ -480,31 +597,6 @@ var PHPSandbox = (() => {
480
597
  throw error51;
481
598
  }
482
599
  }
483
- async spawn(command, args, opts) {
484
- const id = opts?.id || nanoid();
485
- const handle = this.processHandle(id, opts?.abortSignal);
486
- const { abortSignal, ...otherOpts } = opts ?? {};
487
- try {
488
- const result = await this.okra.invoke(
489
- "terminal.spawn",
490
- {
491
- command: [command, ...args],
492
- opts: {
493
- id,
494
- ...otherOpts
495
- }
496
- },
497
- { abortSignal }
498
- );
499
- return {
500
- ...handle.process,
501
- ...result
502
- };
503
- } catch (error51) {
504
- handle.dispose();
505
- throw error51;
506
- }
507
- }
508
600
  processHandle(id, abortSignal) {
509
601
  const disposables = /* @__PURE__ */ new Set();
510
602
  let abortHandler;
@@ -530,7 +622,7 @@ var PHPSandbox = (() => {
530
622
  }
531
623
  const input2 = pendingInput;
532
624
  pendingInput = "";
533
- void this.input(id, input2);
625
+ void this.okra.send("terminal.input", { id, input: input2 });
534
626
  };
535
627
  const scheduleInputFlush = () => {
536
628
  if (inputFlushTimer) {
@@ -538,7 +630,8 @@ var PHPSandbox = (() => {
538
630
  }
539
631
  inputFlushTimer = setTimeout(flushInput, TERMINAL_INPUT_FLUSH_DELAY_MS);
540
632
  };
541
- const queueInput = (chunk) => {
633
+ const queueInput = (value) => {
634
+ const chunk = typeof value === "string" ? value : new TextDecoder().decode(value);
542
635
  pendingInput += chunk;
543
636
  if (terminalInputFlushPattern.test(chunk)) {
544
637
  flushInput();
@@ -560,7 +653,7 @@ var PHPSandbox = (() => {
560
653
  start: (_controller) => {
561
654
  controller = _controller;
562
655
  disposables.add(
563
- this.listen(`terminal.output.${id}`, (data) => {
656
+ this.okra.listen(`terminal.output.${id}`, (data) => {
564
657
  controller?.enqueue(data.output);
565
658
  })
566
659
  );
@@ -570,9 +663,9 @@ var PHPSandbox = (() => {
570
663
  disposeInput();
571
664
  }
572
665
  });
573
- const exit = new Promise((resolve) => {
666
+ const completion = new Promise((resolve) => {
574
667
  disposables.add(
575
- this.listen(`terminal.close.${id}`, (data) => {
668
+ this.okra.listen(`terminal.close.${id}`, (data) => {
576
669
  if (controller) {
577
670
  try {
578
671
  controller.close();
@@ -599,7 +692,7 @@ var PHPSandbox = (() => {
599
692
  }
600
693
  return {
601
694
  process: {
602
- exit,
695
+ wait: () => completion,
603
696
  input,
604
697
  output,
605
698
  kill,
@@ -637,37 +730,9 @@ var PHPSandbox = (() => {
637
730
  state() {
638
731
  return this.okra.invoke("container.state");
639
732
  }
640
- openedPorts() {
641
- return this.okra.invoke("container.opened-ports");
642
- }
643
733
  setPhp(version2) {
644
734
  return this.okra.invoke("container.set-php", { version: version2 });
645
735
  }
646
- enableTelemetry(features) {
647
- return this.okra.invoke("container.stream-telemetry", { features: Array.from(features) });
648
- }
649
- stopTelemetry() {
650
- return this.okra.invoke("container.stop-telemetry");
651
- }
652
- listen(event, handler) {
653
- return this.okra.listen(event, handler);
654
- }
655
- onPort(handler) {
656
- let ports = [];
657
- return this.listen("container.ports", (newPorts) => {
658
- for (const port of newPorts) {
659
- if (!ports.some((p) => p.port === port.port)) {
660
- handler(port, "open");
661
- }
662
- }
663
- for (const port of ports) {
664
- if (!newPorts.some((p) => p.port === port.port)) {
665
- handler(port, "close");
666
- }
667
- }
668
- ports = newPorts;
669
- });
670
- }
671
736
  };
672
737
 
673
738
  // src/auth.ts
@@ -675,9 +740,6 @@ var PHPSandbox = (() => {
675
740
  constructor(okra) {
676
741
  this.okra = okra;
677
742
  }
678
- logout() {
679
- this.okra.dispose();
680
- }
681
743
  login(runtimeUrl) {
682
744
  const runtimeTicket = new URL(runtimeUrl).searchParams.get("ticket");
683
745
  if (runtimeTicket === null || runtimeTicket === "") {
@@ -757,61 +819,376 @@ var PHPSandbox = (() => {
757
819
  }
758
820
  };
759
821
 
822
+ // src/shell.ts
823
+ function resolveRunInput(command, argsOrOpts = [], opts) {
824
+ const args = Array.isArray(argsOrOpts) ? argsOrOpts : [];
825
+ const resolvedOpts = Array.isArray(argsOrOpts) ? opts : argsOrOpts;
826
+ return {
827
+ command: Array.isArray(command) ? command : args.length > 0 ? [command, ...args] : command,
828
+ opts: { tty: false, ...resolvedOpts }
829
+ };
830
+ }
831
+ var CommandError = class extends Error {
832
+ constructor(result) {
833
+ super(result.output);
834
+ this.result = result;
835
+ }
836
+ };
837
+ var ProcessResult = class {
838
+ constructor(output, stdout, stderr, exitCode) {
839
+ this.output = output;
840
+ this.stdout = stdout;
841
+ this.stderr = stderr;
842
+ this.exitCode = exitCode;
843
+ }
844
+ throw() {
845
+ if (this.exitCode !== 0) {
846
+ throw new CommandError(this);
847
+ }
848
+ return this;
849
+ }
850
+ };
851
+ var ProcessReadable = class {
852
+ constructor() {
853
+ this.controller = null;
854
+ this.closed = false;
855
+ this.stream = new ReadableStream({
856
+ start: (controller) => {
857
+ this.controller = controller;
858
+ },
859
+ cancel: () => {
860
+ this.closed = true;
861
+ this.controller = null;
862
+ }
863
+ });
864
+ }
865
+ enqueue(value) {
866
+ if (!this.closed) {
867
+ this.controller?.enqueue(value);
868
+ }
869
+ }
870
+ close() {
871
+ if (this.closed) {
872
+ return;
873
+ }
874
+ this.closed = true;
875
+ this.controller?.close();
876
+ this.controller = null;
877
+ }
878
+ fail(error51) {
879
+ if (this.closed) {
880
+ return;
881
+ }
882
+ this.closed = true;
883
+ this.controller?.error(error51);
884
+ this.controller = null;
885
+ }
886
+ };
887
+ var ShellProcess = class {
888
+ constructor(id, okra, command, opts) {
889
+ this.id = id;
890
+ this.okra = okra;
891
+ const output = new ProcessReadable();
892
+ const stdout = new ProcessReadable();
893
+ const stderr = new ProcessReadable();
894
+ this.output = output.stream;
895
+ this.stdout = stdout.stream;
896
+ this.stderr = stderr.stream;
897
+ this.stdin = new WritableStream({
898
+ write: async (chunk) => {
899
+ const input = typeof chunk === "string" ? chunk : new TextDecoder().decode(chunk);
900
+ const written = await this.okra.invoke("shell.input", { id: this.id, input });
901
+ if (!written) {
902
+ throw new Error(`Process ${this.id} is not accepting input`);
903
+ }
904
+ }
905
+ });
906
+ const encoder = new TextEncoder();
907
+ let subscription = this.okra.listen(`shell.output.${this.id}`, (event) => {
908
+ const data = encoder.encode(event.output);
909
+ const source = event.source ?? "output";
910
+ output.enqueue({ source, data });
911
+ if (source === "stderr") {
912
+ stderr.enqueue(data);
913
+ } else {
914
+ stdout.enqueue(data);
915
+ }
916
+ });
917
+ const finish = () => {
918
+ subscription?.dispose();
919
+ subscription = null;
920
+ output.close();
921
+ stdout.close();
922
+ stderr.close();
923
+ };
924
+ const fail = (error51) => {
925
+ subscription?.dispose();
926
+ subscription = null;
927
+ output.fail(error51);
928
+ stdout.fail(error51);
929
+ stderr.fail(error51);
930
+ };
931
+ const { abortSignal, ...payloadOpts } = opts;
932
+ this.completion = this.okra.invoke(
933
+ "shell.exec",
934
+ { command, opts: { ...payloadOpts, id: this.id } },
935
+ { abortSignal }
936
+ ).then((result) => {
937
+ finish();
938
+ return new ProcessResult(result.output, result.stdout, result.stderr, result.exitCode);
939
+ }).catch((error51) => {
940
+ fail(error51);
941
+ throw error51;
942
+ });
943
+ }
944
+ wait() {
945
+ return this.completion;
946
+ }
947
+ async kill() {
948
+ await this.okra.invoke("shell.kill", { id: this.id });
949
+ }
950
+ };
951
+ var Shell = class {
952
+ constructor(okra) {
953
+ this.okra = okra;
954
+ }
955
+ run(command, argsOrOpts = [], opts) {
956
+ const input = resolveRunInput(command, argsOrOpts, opts);
957
+ const id = input.opts?.id ?? nanoid();
958
+ return new ShellProcess(id, this.okra, input.command, { ...input.opts, id });
959
+ }
960
+ };
961
+
760
962
  // src/composer.ts
963
+ var ComposerProcess = class {
964
+ constructor(id, okra, command, args, options) {
965
+ this.id = id;
966
+ this.okra = okra;
967
+ const output = new ProcessReadable();
968
+ const stdout = new ProcessReadable();
969
+ const stderr = new ProcessReadable();
970
+ this.output = output.stream;
971
+ this.stdout = stdout.stream;
972
+ this.stderr = stderr.stream;
973
+ const encoder = new TextEncoder();
974
+ let subscription = this.okra.listen(`composer.output.${this.id}`, (event) => {
975
+ const data = encoder.encode(event.output);
976
+ const source = event.source ?? "output";
977
+ output.enqueue({ source, data });
978
+ if (source === "stderr") {
979
+ stderr.enqueue(data);
980
+ } else {
981
+ stdout.enqueue(data);
982
+ }
983
+ });
984
+ const finish = () => {
985
+ subscription?.dispose();
986
+ subscription = null;
987
+ output.close();
988
+ stdout.close();
989
+ stderr.close();
990
+ };
991
+ const fail = (error51) => {
992
+ subscription?.dispose();
993
+ subscription = null;
994
+ output.fail(error51);
995
+ stdout.fail(error51);
996
+ stderr.fail(error51);
997
+ };
998
+ this.completion = this.okra.invoke("composer.invoke", { id, command, args, options }).then((result) => {
999
+ finish();
1000
+ return new ProcessResult(result.output, result.stdout, result.stderr, result.exitCode);
1001
+ }).catch((error51) => {
1002
+ fail(error51);
1003
+ throw error51;
1004
+ });
1005
+ }
1006
+ wait() {
1007
+ return this.completion;
1008
+ }
1009
+ async kill() {
1010
+ await this.okra.invoke("composer.kill", { id: this.id });
1011
+ }
1012
+ };
761
1013
  var Composer = class {
762
1014
  constructor(okra, client) {
763
1015
  this.okra = okra;
764
1016
  this.credentials = new ComposerCredentials(client, okra.data.id);
765
1017
  }
766
- invoke(command, args = {}, options = {}) {
767
- return this.okra.invoke("composer.invoke", { command, args, options });
1018
+ run(command, args = {}, options = {}) {
1019
+ return new ComposerProcess(nanoid(), this.okra, command, args, options);
768
1020
  }
769
- dumpAutoload() {
770
- return this.okra.invoke("composer.dump-autoload");
1021
+ dumpAutoload(options = {}) {
1022
+ return this.run("dump-autoload", {}, options);
771
1023
  }
772
1024
  install(options = {}) {
773
- return this.invoke("install", {}, options);
1025
+ return this.run("install", {}, options);
774
1026
  }
775
1027
  update(args, options = {}) {
776
- return this.invoke("update", args, options);
1028
+ return this.run("update", args, options);
777
1029
  }
778
1030
  require(packages, options = {}) {
779
- return this.invoke("require", packages, options);
1031
+ return this.run("require", packages, options);
780
1032
  }
781
1033
  remove(args, options = {}) {
782
- return this.invoke("remove", args, options);
783
- }
784
- stream(fn) {
785
- return this.okra.listen("composer.log", fn);
1034
+ return this.run("remove", args, options);
786
1035
  }
787
1036
  packages() {
788
1037
  return this.okra.invoke("composer.packages");
789
1038
  }
790
1039
  };
791
1040
 
792
- // src/log.ts
793
- var Log = class {
1041
+ // src/runtime-telemetry.ts
1042
+ var RuntimeTelemetry = class {
794
1043
  constructor(okra) {
795
1044
  this.okra = okra;
1045
+ this.references = /* @__PURE__ */ new Map();
1046
+ this.synchronization = Promise.resolve();
1047
+ if (okra.runtimeTransport === "realtime") {
1048
+ okra.onDidConnect(() => {
1049
+ if (this.references.size > 0) {
1050
+ void this.synchronize();
1051
+ }
1052
+ });
1053
+ }
796
1054
  }
797
- stream(fn) {
798
- return this.okra.listen("notebook.log", fn);
1055
+ async acquire(feature) {
1056
+ this.references.set(feature, (this.references.get(feature) ?? 0) + 1);
1057
+ try {
1058
+ await this.synchronize();
1059
+ } catch (error51) {
1060
+ this.removeReference(feature);
1061
+ throw error51;
1062
+ }
1063
+ let released = false;
1064
+ return async () => {
1065
+ if (released) {
1066
+ return;
1067
+ }
1068
+ released = true;
1069
+ this.removeReference(feature);
1070
+ await this.synchronize();
1071
+ };
799
1072
  }
800
- listen(event, handler) {
801
- return this.okra.listen(event, handler);
1073
+ removeReference(feature) {
1074
+ const references = this.references.get(feature) ?? 0;
1075
+ if (references <= 1) {
1076
+ this.references.delete(feature);
1077
+ } else {
1078
+ this.references.set(feature, references - 1);
1079
+ }
1080
+ }
1081
+ synchronize() {
1082
+ this.synchronization = this.synchronization.catch(() => {
1083
+ }).then(async () => {
1084
+ const features = Array.from(this.references.keys());
1085
+ if (features.length === 0) {
1086
+ await this.okra.invoke("container.stop-telemetry");
1087
+ } else {
1088
+ await this.okra.invoke("container.stream-telemetry", { features });
1089
+ }
1090
+ });
1091
+ return this.synchronization;
1092
+ }
1093
+ };
1094
+ function watchRuntimeTelemetry(okra, telemetry, feature, event, transform2, options = {}) {
1095
+ let subscription = null;
1096
+ let release = null;
1097
+ let closed = false;
1098
+ let abort = null;
1099
+ const stop = async () => {
1100
+ if (closed) {
1101
+ return;
1102
+ }
1103
+ closed = true;
1104
+ subscription?.dispose();
1105
+ subscription = null;
1106
+ if (abort && options.signal) {
1107
+ options.signal.removeEventListener("abort", abort);
1108
+ }
1109
+ abort = null;
1110
+ await release?.();
1111
+ release = null;
1112
+ };
1113
+ return new ReadableStream({
1114
+ start(controller) {
1115
+ subscription = okra.listen(event, (data) => {
1116
+ if (!closed) {
1117
+ controller.enqueue(transform2(data));
1118
+ }
1119
+ });
1120
+ if (options.signal) {
1121
+ abort = () => {
1122
+ void stop().finally(() => controller.error(options.signal?.reason ?? new Error("Aborted")));
1123
+ };
1124
+ if (options.signal.aborted) {
1125
+ abort();
1126
+ return;
1127
+ }
1128
+ options.signal.addEventListener("abort", abort, { once: true });
1129
+ }
1130
+ void telemetry.acquire(feature).then(async (releaseTelemetry) => {
1131
+ if (closed) {
1132
+ await releaseTelemetry();
1133
+ return;
1134
+ }
1135
+ release = releaseTelemetry;
1136
+ }).catch((error51) => {
1137
+ if (!closed) {
1138
+ closed = true;
1139
+ subscription?.dispose();
1140
+ if (abort && options.signal) {
1141
+ options.signal.removeEventListener("abort", abort);
1142
+ }
1143
+ abort = null;
1144
+ controller.error(error51);
1145
+ }
1146
+ });
1147
+ },
1148
+ cancel: stop
1149
+ });
1150
+ }
1151
+
1152
+ // src/log.ts
1153
+ var Logs = class {
1154
+ constructor(okra, telemetry) {
1155
+ this.okra = okra;
1156
+ this.telemetry = telemetry;
1157
+ }
1158
+ follow(options = {}) {
1159
+ return watchRuntimeTelemetry(this.okra, this.telemetry, "logs", "notebook.log", (message) => ({
1160
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1161
+ source: "runtime",
1162
+ message
1163
+ }), options);
802
1164
  }
803
1165
  };
804
1166
 
805
- // src/laravel.ts
806
- var Laravel = class {
807
- constructor(okra) {
1167
+ // src/metrics.ts
1168
+ var Metrics = class {
1169
+ constructor(okra, telemetry) {
808
1170
  this.okra = okra;
1171
+ this.telemetry = telemetry;
809
1172
  }
810
- maintenanceInfo() {
811
- return this.okra.invoke("laravel.maintenance.info", {});
1173
+ current() {
1174
+ return this.okra.invoke("container.stats");
1175
+ }
1176
+ watch(options = {}) {
1177
+ return watchRuntimeTelemetry(this.okra, this.telemetry, "stats", "container.stats", (stats) => stats, options);
1178
+ }
1179
+ };
1180
+
1181
+ // src/ports.ts
1182
+ var Ports = class {
1183
+ constructor(okra, telemetry) {
1184
+ this.okra = okra;
1185
+ this.telemetry = telemetry;
1186
+ }
1187
+ list() {
1188
+ return this.okra.invoke("container.opened-ports");
812
1189
  }
813
- toggleMaintenance(down) {
814
- return this.okra.invoke("laravel.maintenance.toggle", down);
1190
+ watch(options = {}) {
1191
+ return watchRuntimeTelemetry(this.okra, this.telemetry, "ports", "container.ports", (ports) => ports, options);
815
1192
  }
816
1193
  };
817
1194
 
@@ -829,9 +1206,6 @@ var PHPSandbox = (() => {
829
1206
  stop() {
830
1207
  return this.okra.invoke("repl.stop");
831
1208
  }
832
- start() {
833
- return this.okra.invoke("repl.start");
834
- }
835
1209
  resize(cols, rows) {
836
1210
  return this.okra.invoke("repl.resize", { cols, rows });
837
1211
  }
@@ -843,117 +1217,6 @@ var PHPSandbox = (() => {
843
1217
  }
844
1218
  };
845
1219
 
846
- // src/shell.ts
847
- function resolveExecInput(command, argsOrOpts = [], opts) {
848
- const args = Array.isArray(argsOrOpts) ? argsOrOpts : [];
849
- const resolvedOpts = Array.isArray(argsOrOpts) ? opts : argsOrOpts;
850
- return {
851
- command: Array.isArray(command) ? command : args.length > 0 ? [command, ...args] : command,
852
- opts: resolvedOpts
853
- };
854
- }
855
- var CommandError = class extends Error {
856
- constructor(output, exitCode) {
857
- super(output);
858
- this.output = output;
859
- this.exitCode = exitCode;
860
- }
861
- };
862
- var Result = class {
863
- constructor(output, exitCode) {
864
- this.output = output;
865
- this.exitCode = exitCode;
866
- }
867
- throw() {
868
- if (this.exitCode !== 0) {
869
- throw new CommandError(this.output, this.exitCode);
870
- }
871
- return this;
872
- }
873
- };
874
- var Shell = class {
875
- constructor(okra) {
876
- this.okra = okra;
877
- }
878
- onOutput(id, handler) {
879
- return this.okra.listen(`shell.output.${id}`, handler);
880
- }
881
- listen(event, handler) {
882
- return this.okra.listen(event, handler);
883
- }
884
- async exec(command, argsOrOpts = [], opts) {
885
- const input = resolveExecInput(command, argsOrOpts, opts);
886
- const { abortSignal, ...payloadOpts } = input.opts ?? {};
887
- const result = await this.okra.invoke(
888
- "shell.exec",
889
- {
890
- command: input.command,
891
- opts: Object.keys(payloadOpts).length > 0 ? payloadOpts : void 0
892
- },
893
- { abortSignal }
894
- );
895
- return new Result(result.output, result.exitCode);
896
- }
897
- execStream(command, argsOrOpts = [], opts) {
898
- const input = resolveExecInput(command, argsOrOpts, opts);
899
- const id = input.opts?.id || nanoid();
900
- const disposables = /* @__PURE__ */ new Set();
901
- let controller = null;
902
- let closed = false;
903
- const dispose = () => {
904
- for (const disposable of disposables) {
905
- disposable.dispose();
906
- }
907
- disposables.clear();
908
- };
909
- const close = () => {
910
- if (closed) {
911
- return;
912
- }
913
- closed = true;
914
- dispose();
915
- if (controller) {
916
- try {
917
- controller.close();
918
- } catch {
919
- }
920
- }
921
- };
922
- const fail = (error51) => {
923
- if (closed) {
924
- return;
925
- }
926
- closed = true;
927
- dispose();
928
- if (controller) {
929
- controller.error(error51);
930
- }
931
- };
932
- const output = new ReadableStream({
933
- start: (_controller) => {
934
- controller = _controller;
935
- disposables.add(
936
- this.listen(`shell.output.${id}`, (data) => {
937
- controller?.enqueue(data.output);
938
- })
939
- );
940
- },
941
- cancel: () => {
942
- closed = true;
943
- dispose();
944
- }
945
- });
946
- const result = this.exec(input.command, { ...input.opts, id }).then((response) => {
947
- close();
948
- return response;
949
- }).catch((error51) => {
950
- fail(error51);
951
- throw error51;
952
- });
953
- return { output, result };
954
- }
955
- };
956
-
957
1220
  // src/services.ts
958
1221
  var notebookBuiltinServices = ["redis"];
959
1222
  var notebookKnownServices = ["start", "nginx", ...notebookBuiltinServices];
@@ -973,12 +1236,6 @@ var PHPSandbox = (() => {
973
1236
  stop(name) {
974
1237
  return this.okra.invoke("service.stop", { name });
975
1238
  }
976
- onLog(id, handler) {
977
- return this.okra.listen(`service.log.${id}`, handler);
978
- }
979
- listen(event, handler) {
980
- return this.okra.listen(event, handler);
981
- }
982
1239
  logs(name, options = {}) {
983
1240
  if (options.follow) {
984
1241
  return this.followLogs(name, options);
@@ -1031,11 +1288,11 @@ var PHPSandbox = (() => {
1031
1288
  close();
1032
1289
  return this.okra.invoke("service.stop-logs", { id });
1033
1290
  });
1034
- const output = new ReadableStream({
1291
+ return new ReadableStream({
1035
1292
  start: (_controller) => {
1036
1293
  controller = _controller;
1037
1294
  disposables.add(
1038
- this.onLog(id, (data) => {
1295
+ this.okra.listen(`service.log.${id}`, (data) => {
1039
1296
  controller?.enqueue(data.output);
1040
1297
  })
1041
1298
  );
@@ -1049,10 +1306,9 @@ var PHPSandbox = (() => {
1049
1306
  });
1050
1307
  },
1051
1308
  cancel: () => {
1052
- void stop();
1309
+ return stop().then(() => void 0);
1053
1310
  }
1054
1311
  });
1055
- return { id, output, stop };
1056
1312
  }
1057
1313
  };
1058
1314
 
@@ -3874,878 +4130,152 @@ var PHPSandbox = (() => {
3874
4130
  }
3875
4131
 
3876
4132
  // src/events/index.ts
3877
- var createMitt = mitt_default ?? mitt_exports;
3878
- function mittWithOnce(all) {
3879
- const inst = createMitt(all);
3880
- inst.once = (type, fn) => {
3881
- const onceHandler = (event) => {
3882
- inst.off(type, onceHandler);
3883
- fn(event);
3884
- };
3885
- inst.on(type, onceHandler);
3886
- return {
3887
- dispose: () => {
3888
- inst.off(type, onceHandler);
3889
- }
3890
- };
3891
- };
3892
- return inst;
3893
- }
3894
- var EventManager = class _EventManager {
3895
- constructor() {
3896
- this.emitter = mittWithOnce();
3897
- }
3898
- listen(event, callback) {
3899
- const dispose = () => {
3900
- this.removeListener(event, callback);
3901
- };
3902
- this.emitter.on(event, callback);
3903
- return { dispose };
3904
- }
3905
- emit(event, ...data) {
3906
- this.emitter.emit(event, data.length > 1 ? data : data[0]);
3907
- }
3908
- once(event, callback) {
3909
- return this.emitter.once(event, callback);
3910
- }
3911
- static make() {
3912
- return new _EventManager();
3913
- }
3914
- static refresh() {
3915
- return new _EventManager();
3916
- }
3917
- removeListener(event, callbackSignature) {
3918
- this.emitter.off(event, callbackSignature);
3919
- }
3920
- static createInstance() {
3921
- return new _EventManager();
3922
- }
3923
- inspect() {
3924
- return this.emitter.all;
3925
- }
3926
- };
3927
-
3928
- // src/git.ts
3929
- var Git = class {
3930
- constructor(okra, client) {
3931
- this.okra = okra;
3932
- this.client = client;
3933
- }
3934
- checkpoint(author, message, branch = "main", allowEmpty = false) {
3935
- return this.okra.invoke("git.checkpoint", { author, message, branch, allowEmpty });
3936
- }
3937
- checkout(branch, create = true) {
3938
- return this.okra.invoke("git.checkout", { branch, create });
3939
- }
3940
- async sync(input) {
3941
- const response = await this.client.post(
3942
- `/notebook/${this.okra.data.id}/git/sync-targets`,
3943
- this.omitUndefined({ ...input })
3944
- );
3945
- return response.data;
3946
- }
3947
- async syncTargets() {
3948
- const response = await this.client.get(`/notebook/${this.okra.data.id}/git/sync-targets`);
3949
- return response.data;
3950
- }
3951
- log(ref = "main") {
3952
- return this.okra.invoke("git.log", { ref });
3953
- }
3954
- diff(input) {
3955
- return this.okra.invoke("git.diff", this.normalizeRemoteInput(input));
3956
- }
3957
- merge(input) {
3958
- return this.okra.invoke("git.merge", this.normalizeRemoteInput(input));
3959
- }
3960
- conflicts() {
3961
- return this.okra.invoke("git.conflicts", {});
3962
- }
3963
- abortMerge() {
3964
- return this.okra.invoke("git.resolve", { action: "abort" });
3965
- }
3966
- continueMerge(author, message) {
3967
- return this.okra.invoke("git.resolve", { action: "continue", author, message });
3968
- }
3969
- review() {
3970
- return this.okra.invoke("git.review", {});
3971
- }
3972
- stage(input = { all: true }) {
3973
- return this.okra.invoke("git.stage", input);
3974
- }
3975
- unstage(input = { all: true }) {
3976
- return this.okra.invoke("git.unstage", input);
3977
- }
3978
- revert(input) {
3979
- return this.okra.invoke("git.revert", input);
3980
- }
3981
- credentials() {
3982
- return this.okra.gitCredentials();
3983
- }
3984
- restore(ref) {
3985
- return this.okra.invoke("git.restore", { ref });
3986
- }
3987
- status() {
3988
- return this.okra.invoke("git.status", {});
3989
- }
3990
- normalizeRemoteInput(input) {
3991
- if (input.notebookId === void 0) {
3992
- return input;
3993
- }
3994
- const notebookId = input.notebookId.trim();
3995
- if (!notebookId) {
3996
- throw new Error("'notebookId' cannot be empty.");
3997
- }
3998
- if (input.url?.trim()) {
3999
- throw new Error("Pass either 'url' or 'notebookId', not both.");
4000
- }
4001
- if (input.target?.trim()) {
4002
- throw new Error("Pass either 'target' or 'notebookId', not both.");
4003
- }
4004
- const { notebookId: _notebookId, ...payload } = input;
4005
- return {
4006
- ...payload,
4007
- url: this.gitUrlForNotebook(notebookId)
4008
- };
4009
- }
4010
- gitUrlForNotebook(notebookId) {
4011
- const url2 = new URL(this.okra.data.gitUrl);
4012
- url2.username = "";
4013
- url2.password = "";
4014
- url2.pathname = `/${encodeURIComponent(notebookId)}.git`;
4015
- url2.search = "";
4016
- url2.hash = "";
4017
- return url2.toString();
4018
- }
4019
- omitUndefined(input) {
4020
- return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0));
4021
- }
4022
- };
4023
-
4024
- // src/beacon/navigator.ts
4025
- var Navigator = class {
4026
- constructor(onEvent, onceEvent, beacon) {
4027
- this.onEvent = onEvent;
4028
- this.onceEvent = onceEvent;
4029
- this.beacon = beacon;
4030
- this.urlHistory = [];
4031
- this.currentIndex = 0;
4032
- this._canGoBack = false;
4033
- this._canGoForward = false;
4034
- this.beacon = beacon;
4035
- this.setupUrlChangeListener();
4036
- this.urlHistory.push(beacon.iframe.src);
4037
- this.updateNavigationState();
4038
- }
4039
- /**
4040
- * Navigate to a URL using internal history management
4041
- */
4042
- visit(url2) {
4043
- if (!this.beacon) {
4044
- throw new Error("Beacon reference not set");
4045
- }
4046
- this.beacon.navigate(url2);
4047
- if (this.currentIndex < this.urlHistory.length - 1) {
4048
- this.urlHistory = this.urlHistory.slice(0, this.currentIndex + 1);
4049
- }
4050
- this.urlHistory.push(url2);
4051
- this.currentIndex = this.urlHistory.length - 1;
4052
- this.updateNavigationState();
4053
- this.emitHistoryChange(url2, "push");
4054
- }
4055
- /**
4056
- * Set up listener for URL change events from the beacon
4057
- */
4058
- setupUrlChangeListener() {
4059
- this.beacon.on("urlChange", (payload) => {
4060
- this.addToHistory(payload.newUrl);
4061
- });
4062
- }
4063
- /**
4064
- * Add URL to internal history
4065
- */
4066
- addToHistory(url2) {
4067
- if (this.currentIndex < this.urlHistory.length - 1) {
4068
- this.urlHistory = this.urlHistory.slice(0, this.currentIndex + 1);
4069
- }
4070
- this.urlHistory.push(url2);
4071
- this.currentIndex = this.urlHistory.length - 1;
4072
- this.updateNavigationState();
4073
- }
4074
- /**
4075
- * Update internal navigation state and emit changes
4076
- */
4077
- updateNavigationState() {
4078
- const previousCanGoBack = this._canGoBack;
4079
- const previousCanGoForward = this._canGoForward;
4080
- this._canGoBack = this.currentIndex > 0;
4081
- this._canGoForward = this.currentIndex < this.urlHistory.length - 1;
4082
- if (previousCanGoBack !== this._canGoBack || previousCanGoForward !== this._canGoForward) {
4083
- this.emitNavigationStateChange();
4084
- }
4085
- }
4086
- /**
4087
- * Emit navigation state change event
4088
- */
4089
- emitNavigationStateChange() {
4090
- if (this.beacon && this.beacon.emit) {
4091
- this.beacon.emit("navigationStateChange", {
4092
- canGoBack: this._canGoBack,
4093
- canGoForward: this._canGoForward,
4094
- currentIndex: this.currentIndex,
4095
- historyLength: this.urlHistory.length,
4096
- timestamp: Date.now()
4097
- });
4098
- }
4099
- }
4100
- get canGoBack() {
4101
- return this._canGoBack;
4102
- }
4103
- get canGoForward() {
4104
- return this._canGoForward;
4105
- }
4106
- async goBack() {
4107
- if (!this.canGoBack) {
4108
- return { success: false, error: "Cannot go back - no previous history" };
4109
- }
4110
- this.currentIndex--;
4111
- this.updateNavigationState();
4112
- const url2 = this.urlHistory[this.currentIndex];
4113
- if (!this.beacon) {
4114
- return { success: false, error: "Beacon reference not set" };
4115
- }
4116
- this.beacon.navigate(url2);
4117
- this.emitHistoryChange(url2, "back");
4118
- return { success: true, url: url2 };
4119
- }
4120
- /**
4121
- * Navigate forward in internal history
4122
- */
4123
- async goForward() {
4124
- if (!this.canGoForward) {
4125
- return { success: false, error: "Cannot go forward - no forward history" };
4126
- }
4127
- this.currentIndex++;
4128
- this.updateNavigationState();
4129
- const url2 = this.urlHistory[this.currentIndex];
4130
- if (!this.beacon) {
4131
- return { success: false, error: "Beacon reference not set" };
4132
- }
4133
- this.beacon.navigate(url2);
4134
- this.emitHistoryChange(url2, "forward");
4135
- return { success: true, url: url2 };
4136
- }
4137
- /**
4138
- * Reload the current page
4139
- */
4140
- async reload() {
4141
- if (this.currentIndex >= 0 && this.currentIndex < this.urlHistory.length) {
4142
- const currentUrl = this.urlHistory[this.currentIndex];
4143
- if (!this.beacon) {
4144
- throw new Error("Beacon reference not set");
4145
- }
4146
- this.beacon.navigate(currentUrl);
4147
- this.emitHistoryChange(currentUrl, "reload");
4148
- }
4149
- }
4150
- /**
4151
- * Get current URL from internal history
4152
- */
4153
- getCurrentUrl() {
4154
- if (this.currentIndex >= 0 && this.currentIndex < this.urlHistory.length) {
4155
- return new URL(this.urlHistory[this.currentIndex]);
4156
- }
4157
- return new URL("about:blank");
4158
- }
4159
- /**
4160
- * Get the complete history array
4161
- */
4162
- getHistory() {
4163
- return [...this.urlHistory];
4164
- }
4165
- /**
4166
- * Get current history index
4167
- */
4168
- getCurrentIndex() {
4169
- return this.currentIndex;
4170
- }
4171
- /**
4172
- * Check if can go back synchronously
4173
- */
4174
- canGoBackSync() {
4175
- return this.currentIndex > 0;
4176
- }
4177
- /**
4178
- * Check if can go forward synchronously
4179
- */
4180
- canGoForwardSync() {
4181
- return this.currentIndex < this.urlHistory.length - 1;
4182
- }
4183
- /**
4184
- * Emit history change event
4185
- */
4186
- emitHistoryChange(url2, direction) {
4187
- if (this.beacon && this.beacon.emit) {
4188
- this.beacon.emit("historyChange", {
4189
- url: url2,
4190
- state: null,
4191
- direction,
4192
- timestamp: Date.now()
4193
- });
4194
- }
4195
- }
4196
- /**
4197
- * Push a new state to internal history (legacy method for compatibility)
4198
- */
4199
- async pushState(url2) {
4200
- this.visit(url2);
4201
- }
4202
- /**
4203
- * Replace current state in internal history (legacy method for compatibility)
4204
- */
4205
- async replaceState(url2) {
4206
- if (this.currentIndex >= 0 && this.currentIndex < this.urlHistory.length) {
4207
- this.urlHistory[this.currentIndex] = url2;
4208
- if (!this.beacon) {
4209
- throw new Error("Beacon reference not set");
4210
- }
4211
- this.beacon.navigate(url2);
4212
- this.emitHistoryChange(url2, "replace");
4213
- } else {
4214
- this.visit(url2);
4215
- }
4216
- }
4217
- /**
4218
- * Get the current history length
4219
- */
4220
- async getHistoryLength() {
4221
- return this.urlHistory.length;
4222
- }
4223
- /**
4224
- * Get the current history state (always null since we don't store state)
4225
- */
4226
- async getHistoryState() {
4227
- return null;
4228
- }
4229
- /**
4230
- * Get comprehensive history information
4231
- */
4232
- async getHistoryInfo() {
4233
- return {
4234
- length: this.urlHistory.length,
4235
- state: null,
4236
- url: this.urlHistory[this.currentIndex] || "",
4237
- canGoBack: this.canGoBack,
4238
- canGoForward: this.canGoForward
4239
- };
4240
- }
4241
- /**
4242
- * Listen for navigator events
4243
- */
4244
- on(event, handler) {
4245
- return this.onEvent(event, handler);
4246
- }
4247
- /**
4248
- * Listen for navigator events (once)
4249
- */
4250
- once(event, handler) {
4251
- this.onceEvent(event, handler);
4252
- }
4253
- };
4254
-
4255
- // src/beacon/index.ts
4256
- function ensureBrowserEnvironment() {
4257
- if (typeof window === "undefined") {
4258
- throw new Error("Beacon SDK can only be used in a browser environment");
4259
- }
4260
- }
4261
- var BeaconError = class extends Error {
4262
- constructor(message, code) {
4263
- super(message);
4264
- this.code = code;
4265
- this.name = "BeaconError";
4266
- }
4267
- };
4268
- var BeaconTimeoutError = class extends BeaconError {
4269
- constructor(operation, timeoutMs) {
4270
- super(`Beacon operation '${operation}' timed out after ${timeoutMs}ms`);
4271
- this.code = "TIMEOUT";
4272
- }
4273
- };
4274
- var BeaconConnectionError = class extends BeaconError {
4275
- constructor(message) {
4276
- super(`Beacon connection error: ${message}`);
4277
- this.code = "CONNECTION_ERROR";
4278
- }
4279
- };
4280
- var Beacon = class {
4281
- constructor(iframe, options = {}) {
4282
- this.messageHandlers = /* @__PURE__ */ new Map();
4283
- this.isBeaconReady = false;
4284
- this.readyPromise = null;
4285
- this.isStarted = false;
4286
- this.disposables = [];
4287
- // MessagePort communication
4288
- this.messageChannel = null;
4289
- this.port = null;
4290
- this.channelEstablished = false;
4291
- ensureBrowserEnvironment();
4292
- this.iframe = iframe;
4293
- const defaultRetryOptions = {
4294
- retries: 3,
4295
- minTimeout: 1e3,
4296
- maxTimeout: 5e3,
4297
- factor: 2,
4298
- randomize: true
4299
- };
4300
- this.options = {
4301
- timeout: 1e4,
4302
- targetOrigin: "*",
4303
- debug: false,
4304
- retry: {
4305
- ...defaultRetryOptions,
4306
- ...options.retry
4307
- },
4308
- ...options
4309
- };
4310
- this.eventEmitter = EventManager.make();
4311
- this.setupMessageChannel();
4312
- this.navigator = new Navigator(
4313
- this.eventEmitter.listen.bind(this.eventEmitter),
4314
- this.eventEmitter.once.bind(this.eventEmitter),
4315
- this
4316
- );
4317
- }
4318
- /**
4319
- * Setup communication channel using MessagePort
4320
- */
4321
- setupMessageChannel() {
4322
- const readyHandler = (event) => {
4323
- try {
4324
- if (event.source !== this.iframe.contentWindow) {
4325
- return;
4326
- }
4327
- const message = event.data;
4328
- if (!message || typeof message !== "object" || !message.type) {
4329
- return;
4330
- }
4331
- if (message.type === "beacon:ready-for-channel") {
4332
- this.establishChannel().catch((error51) => {
4333
- if (this.options.debug) {
4334
- console.error("[Beacon SDK] Channel establishment failed:", error51);
4335
- }
4336
- });
4337
- }
4338
- if (message.type === "beacon:channel-established") {
4339
- this.channelEstablished = true;
4340
- this.isBeaconReady = true;
4341
- this.emit("ready", message.payload);
4342
- if (this.options.debug) {
4343
- console.log("[Beacon SDK] Channel established and beacon ready");
4344
- }
4345
- }
4346
- } catch (error51) {
4347
- if (this.options.debug) {
4348
- console.error("[Beacon SDK] Message parsing error:", error51);
4349
- }
4350
- }
4351
- };
4352
- window.addEventListener("message", readyHandler);
4353
- this.disposables.push({
4354
- dispose: () => window.removeEventListener("message", readyHandler)
4355
- });
4356
- }
4357
- /**
4358
- * Establish MessagePort communication channel
4359
- */
4360
- async establishChannel() {
4361
- if (!this.iframe.contentWindow) {
4362
- throw new BeaconConnectionError("Iframe contentWindow not available");
4363
- }
4364
- this.messageChannel = new MessageChannel();
4365
- this.port = this.messageChannel.port1;
4366
- this.port.onmessage = (event) => {
4367
- this.handleBeaconMessage(event.data);
4133
+ var createMitt = mitt_default ?? mitt_exports;
4134
+ function mittWithOnce(all) {
4135
+ const inst = createMitt(all);
4136
+ inst.once = (type, fn) => {
4137
+ const onceHandler = (event) => {
4138
+ inst.off(type, onceHandler);
4139
+ fn(event);
4368
4140
  };
4369
- this.port.onmessageerror = (event) => {
4370
- if (this.options.debug) {
4371
- console.error("[Beacon SDK] Port message error:", event);
4141
+ inst.on(type, onceHandler);
4142
+ return {
4143
+ dispose: () => {
4144
+ inst.off(type, onceHandler);
4372
4145
  }
4373
4146
  };
4374
- this.port.start();
4375
- const establishMessage = {
4376
- type: "beacon:establish-channel",
4377
- timestamp: Date.now(),
4378
- id: this.generateId()
4379
- };
4380
- this.iframe.contentWindow.postMessage(
4381
- establishMessage,
4382
- "*",
4383
- // Safe for channel establishment
4384
- [this.messageChannel.port2]
4385
- // Transfer the port
4386
- );
4387
- if (this.options.debug) {
4388
- console.log("[Beacon SDK] Channel establishment message sent");
4389
- }
4390
- return new Promise((resolve, reject) => {
4391
- const timeoutId = setTimeout(() => {
4392
- reject(new BeaconConnectionError("Channel establishment timeout"));
4393
- }, this.options.timeout);
4394
- const checkReady = () => {
4395
- if (this.channelEstablished && this.isBeaconReady) {
4396
- clearTimeout(timeoutId);
4397
- resolve();
4398
- } else {
4399
- setTimeout(checkReady, 100);
4400
- }
4401
- };
4402
- checkReady();
4403
- });
4147
+ };
4148
+ return inst;
4149
+ }
4150
+ var EventManager = class _EventManager {
4151
+ constructor() {
4152
+ this.emitter = mittWithOnce();
4404
4153
  }
4405
- /**
4406
- * Handle incoming beacon messages
4407
- */
4408
- handleBeaconMessage(message) {
4409
- if (this.options.debug) {
4410
- console.log("[Beacon SDK] Received message:", message.type, message.payload);
4411
- }
4412
- const eventType = message.type.replace("beacon:", "");
4413
- this.emit(eventType, message.payload);
4414
- const handlers = this.messageHandlers.get(message.type);
4415
- if (handlers) {
4416
- handlers.forEach((handler) => {
4417
- try {
4418
- handler(message.payload);
4419
- } catch (error51) {
4420
- if (this.options.debug) {
4421
- console.error("[Beacon SDK] Message handler error:", error51);
4422
- }
4423
- }
4424
- });
4425
- }
4154
+ listen(event, callback) {
4155
+ const dispose = () => {
4156
+ this.removeListener(event, callback);
4157
+ };
4158
+ this.emitter.on(event, callback);
4159
+ return { dispose };
4426
4160
  }
4427
- /**
4428
- * Wait for beacon to be ready - simplified approach
4429
- */
4430
- waitForBeaconReady() {
4431
- return retry(
4432
- async () => {
4433
- return new Promise((resolve, reject) => {
4434
- if (this.isBeaconReady && this.channelEstablished) {
4435
- resolve();
4436
- return;
4437
- }
4438
- const timeoutMs = this.options.timeout;
4439
- const timeoutId = setTimeout(() => {
4440
- reject(new BeaconTimeoutError("beacon ready", timeoutMs));
4441
- }, timeoutMs);
4442
- const unsubscribe = this.on("ready", () => {
4443
- clearTimeout(timeoutId);
4444
- unsubscribe.dispose();
4445
- resolve();
4446
- });
4447
- });
4448
- },
4449
- {
4450
- retries: this.options.retry?.retries ?? 3,
4451
- minTimeout: this.options.retry?.minTimeout ?? 1e3,
4452
- maxTimeout: this.options.retry?.maxTimeout ?? 5e3,
4453
- factor: this.options.retry?.factor ?? 2,
4454
- randomize: this.options.retry?.randomize ?? true,
4455
- onRetry: (error51, attempt) => {
4456
- if (this.options.debug) {
4457
- const errorMessage = error51 instanceof Error ? error51.message : String(error51);
4458
- console.warn(`[Beacon SDK] Beacon ready retry attempt ${attempt}:`, errorMessage);
4459
- }
4460
- this.isBeaconReady = false;
4461
- this.channelEstablished = false;
4462
- }
4463
- }
4464
- );
4161
+ emit(event, ...data) {
4162
+ this.emitter.emit(event, data.length > 1 ? data : data[0]);
4465
4163
  }
4466
- /**
4467
- * Send a message to the beacon via MessagePort
4468
- */
4469
- sendMessage(type, payload = {}) {
4470
- if (!this.port) {
4471
- throw new BeaconConnectionError("MessagePort not available - channel not established");
4472
- }
4473
- const message = {
4474
- type: `beacon:${type}`,
4475
- payload,
4476
- timestamp: Date.now(),
4477
- source: "parent",
4478
- id: this.generateId()
4479
- };
4480
- try {
4481
- this.port.postMessage(message);
4482
- if (this.options.debug) {
4483
- console.log("[Beacon SDK] Sent message via port:", message.type, message.payload);
4484
- }
4485
- } catch (error51) {
4486
- throw new BeaconConnectionError(
4487
- `Failed to send message via port: ${error51 instanceof Error ? error51.message : String(error51)}`
4488
- );
4489
- }
4164
+ once(event, callback) {
4165
+ return this.emitter.once(event, callback);
4490
4166
  }
4491
- /**
4492
- * Send a message and wait for a specific response with retry logic
4493
- */
4494
- async sendAndWaitFor(sendType, responseType, payload = {}, timeoutMs) {
4495
- await this.ready();
4496
- return retry(
4497
- async (bail) => {
4498
- return new Promise((resolve, reject) => {
4499
- const actualTimeout = timeoutMs || this.options.timeout;
4500
- const timeoutId = setTimeout(() => {
4501
- unsubscribe.dispose();
4502
- const error51 = new BeaconTimeoutError(sendType, actualTimeout);
4503
- reject(error51);
4504
- }, actualTimeout);
4505
- const unsubscribe = this.eventEmitter.listen(responseType, (data) => {
4506
- clearTimeout(timeoutId);
4507
- unsubscribe.dispose();
4508
- resolve(data);
4509
- });
4510
- try {
4511
- this.sendMessage(sendType, payload);
4512
- } catch (error51) {
4513
- clearTimeout(timeoutId);
4514
- unsubscribe.dispose();
4515
- if (error51 instanceof BeaconConnectionError) {
4516
- reject(error51);
4517
- } else {
4518
- bail(error51);
4519
- }
4520
- }
4521
- });
4522
- },
4523
- {
4524
- retries: this.options.retry?.retries ?? 3,
4525
- minTimeout: this.options.retry?.minTimeout ?? 1e3,
4526
- maxTimeout: this.options.retry?.maxTimeout ?? 5e3,
4527
- factor: this.options.retry?.factor ?? 2,
4528
- randomize: this.options.retry?.randomize ?? true,
4529
- onRetry: (error51, attempt) => {
4530
- if (this.options.debug) {
4531
- const errorMessage = error51 instanceof Error ? error51.message : String(error51);
4532
- console.warn(`[Beacon SDK] Retry attempt ${attempt} for ${sendType}:`, errorMessage);
4533
- }
4534
- }
4535
- }
4536
- );
4167
+ static make() {
4168
+ return new _EventManager();
4537
4169
  }
4538
- /**
4539
- * Generate a unique ID for messages
4540
- */
4541
- generateId() {
4542
- return `sdk_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
4170
+ static refresh() {
4171
+ return new _EventManager();
4543
4172
  }
4544
- /**
4545
- * Event emitter methods (both private and public for navigator access)
4546
- */
4547
- emit(event, payload) {
4548
- this.eventEmitter.emit(event, payload);
4173
+ removeListener(event, callbackSignature) {
4174
+ this.emitter.off(event, callbackSignature);
4549
4175
  }
4550
- /**
4551
- * Start the beacon initialization process
4552
- */
4553
- start() {
4554
- if (this.isStarted) {
4555
- return this.readyPromise || Promise.resolve();
4556
- }
4557
- this.isStarted = true;
4558
- this.readyPromise = this.waitForBeaconReady();
4559
- return this.readyPromise;
4176
+ static createInstance() {
4177
+ return new _EventManager();
4560
4178
  }
4561
- /**
4562
- * Wait for the beacon to be ready
4563
- */
4564
- async ready() {
4565
- if (!this.isStarted) {
4566
- throw new BeaconError("Beacon has not been started. Call start() first.");
4567
- }
4568
- if (!this.readyPromise) {
4569
- throw new BeaconError("Beacon ready promise is not available");
4570
- }
4571
- return timeout(this.readyPromise, this.options.timeout);
4179
+ inspect() {
4180
+ return this.emitter.all;
4572
4181
  }
4573
- /**
4574
- * Check if beacon is ready
4575
- */
4576
- get isReady() {
4577
- return this.isBeaconReady;
4182
+ };
4183
+
4184
+ // src/git.ts
4185
+ var Git = class {
4186
+ constructor(okra, client) {
4187
+ this.okra = okra;
4188
+ this.client = client;
4578
4189
  }
4579
- /**
4580
- * Listen for beacon events
4581
- */
4582
- on(event, handler) {
4583
- return this.eventEmitter.listen(event, handler);
4190
+ checkpoint(author, message, branch = "main", allowEmpty = false) {
4191
+ return this.okra.invoke("git.checkpoint", { author, message, branch, allowEmpty });
4584
4192
  }
4585
- /**
4586
- * Listen for beacon events (one-time)
4587
- */
4588
- once(event, handler) {
4589
- return this.eventEmitter.once(event, handler);
4193
+ checkout(branch, create = true) {
4194
+ return this.okra.invoke("git.checkout", { branch, create });
4590
4195
  }
4591
- /**
4592
- * Ping the beacon to check if it's responsive
4593
- */
4594
- async ping() {
4595
- try {
4596
- await this.sendAndWaitFor("ping", "pong", { timestamp: Date.now() });
4597
- return true;
4598
- } catch (error51) {
4599
- if (this.options.debug) {
4600
- console.warn("[Beacon SDK] Ping failed:", error51);
4601
- }
4602
- return false;
4603
- }
4196
+ async sync(input) {
4197
+ const response = await this.client.post(
4198
+ `/notebook/${this.okra.data.id}/git/sync-targets`,
4199
+ this.omitUndefined({ ...input })
4200
+ );
4201
+ return response.data;
4604
4202
  }
4605
- /**
4606
- * Get debug information from the beacon
4607
- */
4608
- async getDebugInfo() {
4609
- return this.sendAndWaitFor("getDebugInfo", "debugInfo");
4203
+ async syncTargets() {
4204
+ const response = await this.client.get(`/notebook/${this.okra.data.id}/git/sync-targets`);
4205
+ return response.data;
4610
4206
  }
4611
- /**
4612
- * Get console events from the beacon
4613
- */
4614
- async getConsoleEvents() {
4615
- return this.sendAndWaitFor("getConsoleEvents", "consoleEvents");
4207
+ log(ref = "main") {
4208
+ return this.okra.invoke("git.log", { ref });
4616
4209
  }
4617
- /**
4618
- * Get error events from the beacon
4619
- */
4620
- async getErrorEvents() {
4621
- return this.sendAndWaitFor("getErrorEvents", "errorEvents");
4210
+ diff(input) {
4211
+ return this.okra.invoke("git.diff", this.normalizeRemoteInput(input));
4622
4212
  }
4623
- /**
4624
- * Clear console events in the beacon
4625
- */
4626
- async clearConsole() {
4627
- await this.ready();
4628
- this.sendMessage("clearConsole");
4213
+ merge(input) {
4214
+ return this.okra.invoke("git.merge", this.normalizeRemoteInput(input));
4629
4215
  }
4630
- /**
4631
- * Clear error events in the beacon
4632
- */
4633
- async clearErrors() {
4634
- await this.ready();
4635
- this.sendMessage("clearErrors");
4216
+ conflicts() {
4217
+ return this.okra.invoke("git.conflicts", {});
4636
4218
  }
4637
- /**
4638
- * Execute code in the beacon context
4639
- */
4640
- async executeCode(code) {
4641
- return this.sendAndWaitFor("executeCode", "codeExecutionResult", { code });
4219
+ abortMerge() {
4220
+ return this.okra.invoke("git.resolve", { action: "abort" });
4642
4221
  }
4643
- /**
4644
- * Inspect an element in the beacon context
4645
- */
4646
- async inspectElement(selector) {
4647
- return this.sendAndWaitFor("inspectElement", "elementInspectionResult", { selector });
4222
+ continueMerge(author, message) {
4223
+ return this.okra.invoke("git.resolve", { action: "continue", author, message });
4648
4224
  }
4649
- /**
4650
- * Fetch a URL in the beacon context
4651
- */
4652
- async fetch(request) {
4653
- return this.sendAndWaitFor("fetch", "fetchResult", request);
4225
+ review() {
4226
+ return this.okra.invoke("git.review", {});
4654
4227
  }
4655
- /**
4656
- * Capture the current beacon document, optionally clipped to a viewport or document rectangle.
4657
- */
4658
- async captureScreenshot(request = {}) {
4659
- const mediaTimeoutMs = request.mediaTimeoutMs ?? request.timeout ?? 3e4;
4660
- const timeoutMs = request.transportTimeoutMs ?? mediaTimeoutMs + 5e3;
4661
- return this.sendAndWaitFor("captureScreenshot", "screenshotResult", request, timeoutMs);
4228
+ stage(input = { all: true }) {
4229
+ return this.okra.invoke("git.stage", input);
4662
4230
  }
4663
- /**
4664
- * Debug a page (navigate and capture debug information). It loads
4665
- * the page fresh in the IFRAME so that we can capture the latest state.
4666
- */
4667
- async debug(request, waitSeconds) {
4668
- const targetUrl = new URL(request.path, this.iframe.src || window.location.origin).href;
4669
- if (this.iframe.src !== targetUrl) {
4670
- this.navigator.visit(targetUrl);
4671
- await this.ready();
4672
- }
4673
- waitSeconds && await this.wait(waitSeconds);
4674
- const timeoutMs = (request.options?.timeout || 3e4) + 5e3;
4675
- return this.sendAndWaitFor("debug", "debugResult", request, timeoutMs);
4231
+ unstage(input = { all: true }) {
4232
+ return this.okra.invoke("git.unstage", input);
4676
4233
  }
4677
- async wait(forSeconds) {
4678
- return new Promise((resolve) => setTimeout(resolve, forSeconds * 1e3));
4234
+ revert(input) {
4235
+ return this.okra.invoke("git.revert", input);
4679
4236
  }
4680
- /**
4681
- * Navigate the iframe to a new URL
4682
- */
4683
- navigate(url2) {
4684
- if (!this.iframe) {
4685
- throw new BeaconConnectionError("Iframe not available");
4686
- }
4687
- try {
4688
- const targetUrl = new URL(url2, this.iframe.src || window.location.origin);
4689
- this.iframe.src = targetUrl.href;
4690
- this.isBeaconReady = false;
4691
- this.channelEstablished = false;
4692
- if (this.port) {
4693
- this.port.close();
4694
- this.port = null;
4695
- }
4696
- if (this.messageChannel) {
4697
- this.messageChannel = null;
4698
- }
4699
- if (this.isStarted) {
4700
- this.readyPromise = this.waitForBeaconReady();
4701
- }
4702
- } catch (error51) {
4703
- throw new BeaconConnectionError(`Invalid URL: ${url2}`);
4704
- }
4237
+ credentials() {
4238
+ return this.okra.gitCredentials();
4705
4239
  }
4706
- /**
4707
- * Get current iframe URL
4708
- */
4709
- get url() {
4710
- return this.iframe.src;
4240
+ restore(ref) {
4241
+ return this.okra.invoke("git.restore", { ref });
4711
4242
  }
4712
- /**
4713
- * Get the iframe element
4714
- */
4715
- get element() {
4716
- return this.iframe;
4243
+ status() {
4244
+ return this.okra.invoke("git.status", {});
4717
4245
  }
4718
- /**
4719
- * Dispose of all resources
4720
- */
4721
- dispose() {
4722
- if (this.port) {
4723
- this.port.close();
4724
- this.port = null;
4246
+ normalizeRemoteInput(input) {
4247
+ if (input.notebookId === void 0) {
4248
+ return input;
4249
+ }
4250
+ const notebookId = input.notebookId.trim();
4251
+ if (!notebookId) {
4252
+ throw new Error("'notebookId' cannot be empty.");
4725
4253
  }
4726
- if (this.messageChannel) {
4727
- this.messageChannel = null;
4254
+ if (input.url?.trim()) {
4255
+ throw new Error("Pass either 'url' or 'notebookId', not both.");
4728
4256
  }
4729
- this.disposables.forEach((disposable) => disposable.dispose());
4730
- this.disposables = [];
4731
- this.messageHandlers.clear();
4732
- this.isBeaconReady = false;
4733
- this.channelEstablished = false;
4734
- this.isStarted = false;
4735
- this.readyPromise = null;
4257
+ if (input.target?.trim()) {
4258
+ throw new Error("Pass either 'target' or 'notebookId', not both.");
4259
+ }
4260
+ const { notebookId: _notebookId, ...payload } = input;
4261
+ return {
4262
+ ...payload,
4263
+ url: this.gitUrlForNotebook(notebookId)
4264
+ };
4736
4265
  }
4737
- };
4738
- function createBeacon(iframe, options) {
4739
- return new Beacon(iframe, options);
4740
- }
4741
- function isBeaconSupported() {
4742
- try {
4743
- ensureBrowserEnvironment();
4744
- return true;
4745
- } catch {
4746
- return false;
4266
+ gitUrlForNotebook(notebookId) {
4267
+ const url2 = new URL(this.okra.data.gitUrl);
4268
+ url2.username = "";
4269
+ url2.password = "";
4270
+ url2.pathname = `/${encodeURIComponent(notebookId)}.git`;
4271
+ url2.search = "";
4272
+ url2.hash = "";
4273
+ return url2.toString();
4747
4274
  }
4748
- }
4275
+ omitUndefined(input) {
4276
+ return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0));
4277
+ }
4278
+ };
4749
4279
 
4750
4280
  // node_modules/zod/v4/classic/external.js
4751
4281
  var external_exports = {};
@@ -19261,13 +18791,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19261
18791
  // node_modules/zod/v4/classic/external.js
19262
18792
  config(en_default());
19263
18793
 
19264
- // src/schemas/deployments.ts
19265
- var DeploymentTargetProviderSchema = external_exports.enum([
19266
- "okraCloudflareContainer",
19267
- "okraSshAgent",
19268
- "okraLaravelCloud"
18794
+ // src/schemas/publications.ts
18795
+ var PublicationProviderNameSchema = external_exports.enum([
18796
+ "cloudflare-containers",
18797
+ "ssh-server",
18798
+ "laravel-cloud"
19269
18799
  ]);
19270
- var DeploymentStatusSchema = external_exports.enum([
18800
+ var PublicationStatusSchema = external_exports.enum([
19271
18801
  "pending",
19272
18802
  "queued",
19273
18803
  "building",
@@ -19279,7 +18809,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19279
18809
  "deleted",
19280
18810
  "delete_failed"
19281
18811
  ]);
19282
- var DeploymentBuildStatusSchema = external_exports.enum([
18812
+ var PublicationBuildStatusSchema = external_exports.enum([
19283
18813
  "pending",
19284
18814
  "queued",
19285
18815
  "running",
@@ -19287,8 +18817,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19287
18817
  "failed",
19288
18818
  "cancelled"
19289
18819
  ]);
19290
- var DeploymentReleaseStatusSchema = external_exports.enum(["created", "ready", "deleted"]);
19291
- var DeploymentSizeSchema = external_exports.enum([
18820
+ var PublicationReleaseStatusSchema = external_exports.enum(["created", "ready", "deleted"]);
18821
+ var PublicationSizeSchema = external_exports.enum([
19292
18822
  "nano",
19293
18823
  "small",
19294
18824
  "medium",
@@ -19298,7 +18828,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19298
18828
  "standard-1",
19299
18829
  "standard-2"
19300
18830
  ]);
19301
- var DeploymentRegionSchema = external_exports.enum([
18831
+ var PublicationRegionSchema = external_exports.enum([
19302
18832
  "ENAM",
19303
18833
  "WNAM",
19304
18834
  "EEUR",
@@ -19309,103 +18839,103 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19309
18839
  "OC",
19310
18840
  "AFR"
19311
18841
  ]);
19312
- var DeploymentJurisdictionSchema = external_exports.enum(["eu", "fedramp"]);
19313
- var DeploymentDomainDnsRecordTypeSchema = external_exports.enum(["CNAME", "ALIAS", "ANAME"]);
19314
- var DeploymentProtectionModeSchema = external_exports.enum(["none", "password"]);
19315
- var DeploymentLogStreamSchema = external_exports.enum(["build", "runtime"]);
19316
- var DeployStreamLogStreamSchema = external_exports.enum(["build", "deploy", "runtime"]);
19317
- var DeploymentEventDataSchema = external_exports.object({
18842
+ var PublicationJurisdictionSchema = external_exports.enum(["eu", "fedramp"]);
18843
+ var PublicationDomainDnsRecordTypeSchema = external_exports.enum(["CNAME", "ALIAS", "ANAME"]);
18844
+ var PublicationProtectionModeSchema = external_exports.enum(["none", "password"]);
18845
+ var PublicationLogStreamSchema = external_exports.enum(["build", "runtime"]);
18846
+ var PublishStreamLogStreamSchema = external_exports.enum(["build", "publish", "runtime"]);
18847
+ var PublicationEventDataSchema = external_exports.object({
19318
18848
  id: external_exports.union([external_exports.number(), external_exports.string()]).optional(),
19319
18849
  sequence: external_exports.number(),
19320
18850
  type: external_exports.string(),
19321
18851
  payload: external_exports.record(external_exports.string(), external_exports.unknown()),
19322
18852
  createdAt: external_exports.string().nullable()
19323
18853
  }).passthrough();
19324
- var DeploymentLogChunkDataSchema = external_exports.object({
18854
+ var PublicationLogChunkDataSchema = external_exports.object({
19325
18855
  sequence: external_exports.number(),
19326
- stream: DeploymentLogStreamSchema,
18856
+ stream: PublicationLogStreamSchema,
19327
18857
  content: external_exports.string(),
19328
18858
  createdAt: external_exports.string().nullable()
19329
18859
  }).passthrough();
19330
- var DeployStreamPhaseSchema = external_exports.object({
18860
+ var PublishStreamPhaseSchema = external_exports.object({
19331
18861
  name: external_exports.string(),
19332
18862
  status: external_exports.enum(["running", "completed", "failed"]).optional(),
19333
18863
  data: external_exports.record(external_exports.string(), external_exports.unknown()).optional()
19334
18864
  }).strict();
19335
- var DeployStreamLogSchema = external_exports.object({
19336
- stream: DeployStreamLogStreamSchema,
18865
+ var PublishStreamLogSchema = external_exports.object({
18866
+ stream: PublishStreamLogStreamSchema,
19337
18867
  content: external_exports.string()
19338
18868
  }).strict();
19339
- var DeployStreamResultSchema = external_exports.object({
18869
+ var PublishStreamResultSchema = external_exports.object({
19340
18870
  success: external_exports.boolean(),
19341
- deploymentId: external_exports.string(),
18871
+ publicationId: external_exports.string(),
19342
18872
  buildId: external_exports.string(),
19343
18873
  releaseId: external_exports.string(),
19344
- status: DeploymentStatusSchema
18874
+ status: PublicationStatusSchema
19345
18875
  }).strict();
19346
- var DeployStreamPhaseEventSchema = DeployStreamPhaseSchema.extend({
18876
+ var PublishStreamPhaseEventSchema = PublishStreamPhaseSchema.extend({
19347
18877
  type: external_exports.literal("phase")
19348
18878
  }).strict();
19349
- var DeployStreamLogEventSchema = DeployStreamLogSchema.extend({
18879
+ var PublishStreamLogEventSchema = PublishStreamLogSchema.extend({
19350
18880
  type: external_exports.literal("log")
19351
18881
  }).strict();
19352
- var DeployStreamResultEventSchema = DeployStreamResultSchema.extend({
18882
+ var PublishStreamResultEventSchema = PublishStreamResultSchema.extend({
19353
18883
  type: external_exports.literal("result")
19354
18884
  }).strict();
19355
- var DeployStreamEventSchema = external_exports.discriminatedUnion("type", [
19356
- DeployStreamPhaseEventSchema,
19357
- DeployStreamLogEventSchema,
19358
- DeployStreamResultEventSchema
18885
+ var PublishStreamEventSchema = external_exports.discriminatedUnion("type", [
18886
+ PublishStreamPhaseEventSchema,
18887
+ PublishStreamLogEventSchema,
18888
+ PublishStreamResultEventSchema
19359
18889
  ]);
19360
- var DeployStreamErrorSchema = external_exports.object({
18890
+ var PublishStreamErrorSchema = external_exports.object({
19361
18891
  message: external_exports.string().optional()
19362
18892
  }).passthrough();
19363
- var DeployStreamSseEventNameSchema = external_exports.enum(["phase", "log", "done", "result", "error"]);
19364
- var DeployStreamSsePhaseEventSchema = external_exports.object({
18893
+ var PublishStreamSseEventNameSchema = external_exports.enum(["phase", "log", "done", "result", "error"]);
18894
+ var PublishStreamSsePhaseEventSchema = external_exports.object({
19365
18895
  event: external_exports.literal("phase"),
19366
- data: DeployStreamPhaseSchema
18896
+ data: PublishStreamPhaseSchema
19367
18897
  }).strict();
19368
- var DeployStreamSseLogEventSchema = external_exports.object({
18898
+ var PublishStreamSseLogEventSchema = external_exports.object({
19369
18899
  event: external_exports.literal("log"),
19370
- data: DeployStreamLogSchema
18900
+ data: PublishStreamLogSchema
19371
18901
  }).strict();
19372
- var DeployStreamSseDoneEventSchema = external_exports.object({
18902
+ var PublishStreamSseDoneEventSchema = external_exports.object({
19373
18903
  event: external_exports.literal("done"),
19374
- data: DeployStreamResultSchema
18904
+ data: PublishStreamResultSchema
19375
18905
  }).strict();
19376
- var DeployStreamSseResultEventSchema = external_exports.object({
18906
+ var PublishStreamSseResultEventSchema = external_exports.object({
19377
18907
  event: external_exports.literal("result"),
19378
- data: DeployStreamResultSchema
18908
+ data: PublishStreamResultSchema
19379
18909
  }).strict();
19380
- var DeployStreamSseErrorEventSchema = external_exports.object({
18910
+ var PublishStreamSseErrorEventSchema = external_exports.object({
19381
18911
  event: external_exports.literal("error"),
19382
- data: DeployStreamErrorSchema
18912
+ data: PublishStreamErrorSchema
19383
18913
  }).strict();
19384
- var DeployStreamSseEventSchema = external_exports.discriminatedUnion("event", [
19385
- DeployStreamSsePhaseEventSchema,
19386
- DeployStreamSseLogEventSchema,
19387
- DeployStreamSseDoneEventSchema,
19388
- DeployStreamSseResultEventSchema,
19389
- DeployStreamSseErrorEventSchema
18914
+ var PublishStreamSseEventSchema = external_exports.discriminatedUnion("event", [
18915
+ PublishStreamSsePhaseEventSchema,
18916
+ PublishStreamSseLogEventSchema,
18917
+ PublishStreamSseDoneEventSchema,
18918
+ PublishStreamSseResultEventSchema,
18919
+ PublishStreamSseErrorEventSchema
19390
18920
  ]).transform((event) => {
19391
18921
  if (event.event === "error") {
19392
- throw new Error(event.data.message ?? "Deploy failed");
18922
+ throw new Error(event.data.message ?? "Publish failed");
19393
18923
  }
19394
18924
  const type = event.event === "done" ? "result" : event.event;
19395
- return DeployStreamEventSchema.parse({ type, ...event.data });
18925
+ return PublishStreamEventSchema.parse({ type, ...event.data });
19396
18926
  });
19397
18927
 
19398
- // src/deployments.ts
19399
- var NotebookDeploymentApi = class {
18928
+ // src/publications.ts
18929
+ var NotebookPublicationApi = class {
19400
18930
  constructor(client) {
19401
18931
  this.client = client;
19402
18932
  }
19403
18933
  async current(notebookId) {
19404
18934
  try {
19405
18935
  const response = await this.client.get(
19406
- `/notebook/${notebookId}/deployment`
18936
+ `/notebook/${notebookId}/publication`
19407
18937
  );
19408
- return new DeploymentInstance(response.data, this.client, notebookId);
18938
+ return new PublicationInstance(response.data, this.client, notebookId);
19409
18939
  } catch (error51) {
19410
18940
  if (error51 instanceof ApiError && error51.status === 404) {
19411
18941
  return null;
@@ -19415,89 +18945,82 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19415
18945
  }
19416
18946
  async publish(notebookId, input) {
19417
18947
  const response = await this.client.post(
19418
- `/notebook/${notebookId}/deployment/publish`,
18948
+ `/notebook/${notebookId}/publication`,
19419
18949
  input
19420
18950
  );
19421
- const run = new DeploymentRun(new DeploymentInstance(response.data, this.client, notebookId), this.client);
18951
+ const run = new PublicationRun(new PublicationInstance(response.data, this.client, notebookId), this.client);
19422
18952
  run.start();
19423
18953
  return run;
19424
18954
  }
19425
- async slugAvailability(id, slug) {
19426
- const query = new URLSearchParams({ slug }).toString();
19427
- const response = await this.client.get(
19428
- `/notebook/${id}/deployment/slug-availability?${query}`
19429
- );
19430
- return response.data;
19431
- }
19432
18955
  };
19433
- var DeploymentApi = class {
18956
+ var PublicationApi = class {
19434
18957
  constructor(client) {
19435
18958
  this.client = client;
19436
18959
  }
19437
18960
  async get(id) {
19438
- const response = await this.client.get(`/deployments/${id}`);
19439
- return new DeploymentInstance(response.data, this.client);
18961
+ const response = await this.client.get(`/publications/${id}`);
18962
+ return new PublicationInstance(response.data, this.client);
19440
18963
  }
19441
- async delete(id) {
19442
- await this.client.delete(`/deployments/${id}`);
18964
+ async destroy(id) {
18965
+ await this.client.delete(`/publications/${id}`);
19443
18966
  }
19444
18967
  async setProtection(id, input) {
19445
- const response = await this.client.put(`/deployments/${id}/protection`, input);
19446
- return new DeploymentInstance(response.data, this.client);
18968
+ const response = await this.client.put(`/publications/${id}/protection`, input);
18969
+ return new PublicationInstance(response.data, this.client);
19447
18970
  }
19448
18971
  async protection(id) {
19449
- const response = await this.client.get(`/deployments/${id}/protection`);
18972
+ const response = await this.client.get(`/publications/${id}/protection`);
19450
18973
  return response.data;
19451
18974
  }
19452
18975
  async createProtectionSession(id) {
19453
- const response = await this.client.post(`/deployments/${id}/protection/session`);
18976
+ const response = await this.client.post(`/publications/${id}/protection/session`);
19454
18977
  return response.data;
19455
18978
  }
19456
18979
  async disableProtection(id) {
19457
- const response = await this.client.delete(`/deployments/${id}/protection`);
19458
- return new DeploymentInstance(response.data, this.client);
18980
+ const response = await this.client.delete(`/publications/${id}/protection`);
18981
+ return new PublicationInstance(response.data, this.client);
19459
18982
  }
19460
18983
  async setFeedback(id, input) {
19461
- const response = await this.client.put(`/deployments/${id}/feedback`, input);
19462
- return new DeploymentInstance(response.data, this.client);
18984
+ const response = await this.client.put(`/publications/${id}/feedback`, input);
18985
+ return new PublicationInstance(response.data, this.client);
19463
18986
  }
19464
18987
  async listDomains(id) {
19465
18988
  const response = await this.client.get(
19466
- `/deployments/${id}/domains`
18989
+ `/publications/${id}/domains`
19467
18990
  );
19468
- return unwrapDeploymentDomainCollection(response.data);
18991
+ return unwrapPublicationDomainCollection(response.data);
19469
18992
  }
19470
18993
  async createDomain(id, input) {
19471
- const response = await this.client.post(`/deployments/${id}/domains`, input);
18994
+ const response = await this.client.post(`/publications/${id}/domains`, input);
19472
18995
  return response.data;
19473
18996
  }
19474
18997
  async refreshDomain(id, domainId) {
19475
- const response = await this.client.post(`/deployments/${id}/domains/${domainId}/refresh`);
18998
+ const response = await this.client.post(`/publications/${id}/domains/${domainId}/refresh`);
19476
18999
  return response.data;
19477
19000
  }
19478
19001
  async deleteDomain(id, domainId) {
19479
- await this.client.delete(`/deployments/${id}/domains/${domainId}`);
19002
+ await this.client.delete(`/publications/${id}/domains/${domainId}`);
19480
19003
  }
19481
19004
  async events(id) {
19482
19005
  return parseNdjsonStream(
19483
- await this.client.stream(`/deployments/${id}/events/stream`),
19484
- DeploymentEventDataSchema
19006
+ await this.client.stream(`/publications/${id}/events/stream`),
19007
+ PublicationEventDataSchema
19485
19008
  );
19486
19009
  }
19487
19010
  async buildLogs(id, buildId) {
19488
19011
  return parseNdjsonStream(
19489
- await this.client.stream(`/deployments/${id}/builds/${buildId}/logs/stream`),
19490
- DeploymentLogChunkDataSchema
19012
+ await this.client.stream(`/publications/${id}/builds/${buildId}/logs/stream`),
19013
+ PublicationLogChunkDataSchema
19491
19014
  );
19492
19015
  }
19493
19016
  async logs(id) {
19494
19017
  return parseNdjsonStream(
19495
- await this.client.stream(`/deployments/${id}/logs/stream`),
19496
- DeploymentLogChunkDataSchema
19018
+ await this.client.stream(`/publications/${id}/logs/stream`),
19019
+ PublicationLogChunkDataSchema
19497
19020
  );
19498
19021
  }
19499
19022
  };
19500
- var DeploymentRun = class {
19023
+ var PublicationRun = class {
19501
19024
  constructor(initial, client) {
19502
19025
  this.initial = initial;
19503
19026
  this.client = client;
@@ -19527,7 +19050,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19527
19050
  this.start();
19528
19051
  return this.resultPromise;
19529
19052
  }
19530
- async deployment() {
19053
+ async publication() {
19531
19054
  await this.result();
19532
19055
  return this.initial.refresh();
19533
19056
  }
@@ -19537,7 +19060,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19537
19060
  }
19538
19061
  const eventStreamUrl = this.initial.data.eventStreamUrl;
19539
19062
  if (!eventStreamUrl) {
19540
- throw new Error(`Deployment ${this.initial.data.id} has no eventStreamUrl for SSE streaming`);
19063
+ throw new Error(`Publication ${this.initial.data.id} has no eventStreamUrl for SSE streaming`);
19541
19064
  }
19542
19065
  this.started = true;
19543
19066
  this.resultPromise = new Promise((resolve, reject) => {
@@ -19549,7 +19072,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19549
19072
  return this;
19550
19073
  }
19551
19074
  subscribe() {
19552
- const queue = new AsyncDeployEventQueue();
19075
+ const queue = new AsyncPublishEventQueue();
19553
19076
  for (const event of this.bufferedEvents) {
19554
19077
  queue.push(event);
19555
19078
  }
@@ -19565,7 +19088,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19565
19088
  async consumeStream(eventStreamUrl) {
19566
19089
  try {
19567
19090
  const stream = await this.client.sse(eventStreamUrl);
19568
- for await (const event of readDeployStreamEvents(stream)) {
19091
+ for await (const event of readPublishStreamEvents(stream)) {
19569
19092
  this.publish(event);
19570
19093
  if (event.type === "result") {
19571
19094
  const { type: _, ...result } = event;
@@ -19574,7 +19097,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19574
19097
  }
19575
19098
  }
19576
19099
  if (!this.finalResult) {
19577
- throw new Error("Deploy stream ended without result");
19100
+ throw new Error("Publish stream ended without result");
19578
19101
  }
19579
19102
  this.closeSubscribers();
19580
19103
  } catch (err) {
@@ -19604,33 +19127,33 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19604
19127
  this.subscribers.clear();
19605
19128
  }
19606
19129
  };
19607
- var DeploymentInstance = class _DeploymentInstance {
19130
+ var PublicationInstance = class _PublicationInstance {
19608
19131
  constructor(data, client, notebookId) {
19609
19132
  this.data = data;
19610
19133
  this.client = client;
19611
19134
  this.notebookId = notebookId;
19612
19135
  }
19613
19136
  async refresh() {
19614
- const response = await this.client.get(`/deployments/${this.data.id}`);
19615
- return new _DeploymentInstance(response.data, this.client, this.notebookId);
19137
+ const response = await this.client.get(`/publications/${this.data.id}`);
19138
+ return new _PublicationInstance(response.data, this.client, this.notebookId);
19616
19139
  }
19617
19140
  publish() {
19618
19141
  if (!this.notebookId) {
19619
- return Promise.reject(new Error("Deployment publish requires a notebook-scoped deployment instance."));
19142
+ return Promise.reject(new Error("Publishing requires a notebook-scoped publication instance."));
19620
19143
  }
19621
- return this.client.notebook.deployment.publish(this.notebookId);
19144
+ return this.client.notebook.publication.publish(this.notebookId);
19622
19145
  }
19623
- delete() {
19624
- return this.client.deployments.delete(this.data.id);
19146
+ destroy() {
19147
+ return this.client.publications.destroy(this.data.id);
19625
19148
  }
19626
19149
  async wait(options = {}) {
19627
19150
  const intervalMs = options.intervalMs ?? 1e3;
19628
19151
  const timeoutMs = options.timeoutMs ?? 3e5;
19629
19152
  const startedAt = Date.now();
19630
19153
  let current = this;
19631
- while (!deploymentStatusIsTerminal(current.data.status)) {
19154
+ while (!publicationStatusIsTerminal(current.data.status)) {
19632
19155
  if (Date.now() - startedAt > timeoutMs) {
19633
- throw new Error(`Timed out waiting for deployment ${this.data.id}`);
19156
+ throw new Error(`Timed out waiting for publication ${this.data.id}`);
19634
19157
  }
19635
19158
  await delay(intervalMs);
19636
19159
  current = await current.refresh();
@@ -19638,58 +19161,58 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19638
19161
  return current;
19639
19162
  }
19640
19163
  events() {
19641
- return this.client.deployments.events(this.data.id);
19164
+ return this.client.publications.events(this.data.id);
19642
19165
  }
19643
19166
  buildLogs(buildId = this.data.latestBuild?.id ?? "") {
19644
19167
  if (buildId === "") {
19645
- return Promise.reject(new Error("Deployment has no latest build id"));
19168
+ return Promise.reject(new Error("Publication has no latest build id"));
19646
19169
  }
19647
- return this.client.deployments.buildLogs(this.data.id, buildId);
19170
+ return this.client.publications.buildLogs(this.data.id, buildId);
19648
19171
  }
19649
19172
  logs() {
19650
- return this.client.deployments.logs(this.data.id);
19173
+ return this.client.publications.logs(this.data.id);
19651
19174
  }
19652
19175
  setProtection(input) {
19653
- return this.client.deployments.setProtection(this.data.id, input);
19176
+ return this.client.publications.setProtection(this.data.id, input);
19654
19177
  }
19655
19178
  protection() {
19656
- return this.client.deployments.protection(this.data.id);
19179
+ return this.client.publications.protection(this.data.id);
19657
19180
  }
19658
19181
  createProtectionSession() {
19659
- return this.client.deployments.createProtectionSession(this.data.id);
19182
+ return this.client.publications.createProtectionSession(this.data.id);
19660
19183
  }
19661
19184
  disableProtection() {
19662
- return this.client.deployments.disableProtection(this.data.id);
19185
+ return this.client.publications.disableProtection(this.data.id);
19663
19186
  }
19664
19187
  setFeedback(input) {
19665
- return this.client.deployments.setFeedback(this.data.id, input);
19188
+ return this.client.publications.setFeedback(this.data.id, input);
19666
19189
  }
19667
19190
  domains() {
19668
- return this.client.deployments.listDomains(this.data.id);
19191
+ return this.client.publications.listDomains(this.data.id);
19669
19192
  }
19670
19193
  addDomain(input) {
19671
- return this.client.deployments.createDomain(this.data.id, input);
19194
+ return this.client.publications.createDomain(this.data.id, input);
19672
19195
  }
19673
19196
  refreshDomain(domainId) {
19674
- return this.client.deployments.refreshDomain(this.data.id, domainId);
19197
+ return this.client.publications.refreshDomain(this.data.id, domainId);
19675
19198
  }
19676
19199
  deleteDomain(domainId) {
19677
- return this.client.deployments.deleteDomain(this.data.id, domainId);
19200
+ return this.client.publications.deleteDomain(this.data.id, domainId);
19678
19201
  }
19679
19202
  };
19680
- function deploymentStatusIsTerminal(status) {
19203
+ function publicationStatusIsTerminal(status) {
19681
19204
  return ["healthy", "failed", "stopped", "deleted", "delete_failed"].includes(status);
19682
19205
  }
19683
19206
  function delay(ms) {
19684
19207
  return new Promise((resolve) => setTimeout(resolve, ms));
19685
19208
  }
19686
- function unwrapDeploymentDomainCollection(input) {
19209
+ function unwrapPublicationDomainCollection(input) {
19687
19210
  if (Array.isArray(input)) {
19688
19211
  return input;
19689
19212
  }
19690
19213
  return Array.isArray(input.data) ? input.data : [];
19691
19214
  }
19692
- var AsyncDeployEventQueue = class {
19215
+ var AsyncPublishEventQueue = class {
19693
19216
  constructor() {
19694
19217
  this.values = [];
19695
19218
  this.pending = [];
@@ -19751,7 +19274,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19751
19274
  });
19752
19275
  }
19753
19276
  };
19754
- async function* readDeployStreamEvents(stream) {
19277
+ async function* readPublishStreamEvents(stream) {
19755
19278
  const reader = parseSSEStream(stream).getReader();
19756
19279
  try {
19757
19280
  while (true) {
@@ -19759,7 +19282,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19759
19282
  if (done) {
19760
19283
  return;
19761
19284
  }
19762
- const event = parseDeployStreamEvent(value);
19285
+ const event = parsePublishStreamEvent(value);
19763
19286
  if (event) {
19764
19287
  yield event;
19765
19288
  }
@@ -19768,11 +19291,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19768
19291
  reader.releaseLock();
19769
19292
  }
19770
19293
  }
19771
- function parseDeployStreamEvent(event) {
19772
- if (!DeployStreamSseEventNameSchema.safeParse(event.event).success) {
19294
+ function parsePublishStreamEvent(event) {
19295
+ if (!PublishStreamSseEventNameSchema.safeParse(event.event).success) {
19773
19296
  return null;
19774
19297
  }
19775
- return DeployStreamSseEventSchema.parse(event);
19298
+ return PublishStreamSseEventSchema.parse(event);
19776
19299
  }
19777
19300
  function parseSSEStream(input) {
19778
19301
  const decoder = new TextDecoder();
@@ -19913,6 +19436,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19913
19436
  "container.stop": { method: "POST", path: "/runtime/container/stop" },
19914
19437
  "container.set-php": { method: "PUT", path: "/runtime/container/php" },
19915
19438
  "container.opened-ports": { method: "GET", path: "/runtime/container/ports" },
19439
+ "container.stats": { method: "GET", path: "/runtime/container/stats" },
19916
19440
  "terminal.list": { method: "GET", path: "/runtime/terminals" },
19917
19441
  "shell.exec": { method: "POST", path: "/runtime/executions" },
19918
19442
  "fs.info": { method: "POST", path: "/runtime/files/info" },
@@ -19938,10 +19462,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19938
19462
  "service.logs": { method: "POST", path: "/runtime/services/logs" },
19939
19463
  "composer.invoke": { method: "POST", path: "/runtime/composer/executions" },
19940
19464
  "composer.packages": { method: "GET", path: "/runtime/composer/packages" },
19941
- "composer.dump-autoload": {
19942
- method: "POST",
19943
- path: "/runtime/composer/autoload"
19944
- },
19945
19465
  "git.checkpoint": { method: "POST", path: "/runtime/git/checkpoints" },
19946
19466
  "git.checkout": { method: "POST", path: "/runtime/git/checkouts" },
19947
19467
  "git.log": { method: "POST", path: "/runtime/git/log" },
@@ -20181,11 +19701,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20181
19701
  this.composerCredentials = new NotebookComposerCredentialApi(client);
20182
19702
  this.preview = new NotebookPreviewApi(client);
20183
19703
  this.mail = new NotebookMailApi(client);
20184
- this.deployment = new NotebookDeploymentApi(client);
19704
+ this.publication = new NotebookPublicationApi(client);
20185
19705
  }
20186
19706
  async create(template, input = {}, init = true) {
20187
19707
  const response = await this.client.post("/notebook", { template, ...input });
20188
- const instance = new NotebookInstance2(response.data, this.client);
19708
+ const instance = new NotebookInstance(response.data, this.client);
20189
19709
  if (!init) {
20190
19710
  return instance;
20191
19711
  }
@@ -20193,29 +19713,25 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20193
19713
  }
20194
19714
  async get(id) {
20195
19715
  const response = await this.client.get(`/notebook/${id}`);
20196
- return new NotebookInstance2(response.data, this.client);
19716
+ return new NotebookInstance(response.data, this.client);
20197
19717
  }
20198
19718
  async update(id, input = {}) {
20199
19719
  const response = await this.client.put(`/notebook/${id}`, input);
20200
- return new NotebookInstance2(response.data, this.client);
19720
+ return new NotebookInstance(response.data, this.client);
20201
19721
  }
20202
- async delete(id) {
19722
+ async destroy(id) {
20203
19723
  await this.client.delete(`/notebook/${id}`);
20204
19724
  }
20205
19725
  async fork(id, input = {}) {
20206
19726
  const response = await this.client.post(`/notebook/${id}/fork`, input);
20207
- return new NotebookInstance2(response.data, this.client);
19727
+ return new NotebookInstance(response.data, this.client);
20208
19728
  }
20209
19729
  async gitCredentials(id) {
20210
19730
  const response = await this.client.post(`/notebook/${id}/git/credentials`);
20211
19731
  return response.data;
20212
19732
  }
20213
- async open(id) {
20214
- const response = await this.client.get(`/notebook/${id}`);
20215
- return new NotebookInstance2(response.data, this.client);
20216
- }
20217
19733
  openFromData(data) {
20218
- return this.init(new NotebookInstance2(data, this.client));
19734
+ return this.init(new NotebookInstance(data, this.client));
20219
19735
  }
20220
19736
  async init(instance) {
20221
19737
  await instance.ready();
@@ -20230,11 +19746,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20230
19746
  baseUrl.hash = "";
20231
19747
  return baseUrl.toString();
20232
19748
  }
20233
- var Client2 = class {
19749
+ var Client = class {
20234
19750
  constructor(token, url2 = "https://api.phpsandbox.io/v1", options = {}) {
20235
19751
  this.runtimeTransportValue = "realtime";
20236
19752
  this.fetch = globalThis.fetch;
20237
- this.deployments = new DeploymentApi(this);
19753
+ this.publications = new PublicationApi(this);
20238
19754
  this.notebook = new NotebookApi(this);
20239
19755
  this.servers = new ServerApi(this);
20240
19756
  this.options = Object.assign({ startClosed: true }, options);
@@ -20314,7 +19830,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20314
19830
  return { data: body === "" ? void 0 : JSON.parse(body) };
20315
19831
  }
20316
19832
  };
20317
- var PHPSandbox = class _PHPSandbox extends Client2 {
19833
+ var PHPSandbox = class _PHPSandbox extends Client {
20318
19834
  static realtime(token, url2 = "https://api.phpsandbox.io/v1", options = {}) {
20319
19835
  return new _PHPSandbox(token, url2, options);
20320
19836
  }
@@ -20422,7 +19938,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20422
19938
  }
20423
19939
  };
20424
19940
  var _initPromise, _NotebookInstance_instances, init_fn;
20425
- var NotebookInstance2 = class {
19941
+ var NotebookInstance = class {
20426
19942
  constructor(data, client) {
20427
19943
  this.data = data;
20428
19944
  this.client = client;
@@ -20457,18 +19973,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20457
19973
  this.watchConnection();
20458
19974
  __privateSet(this, _initPromise, __privateMethod(this, _NotebookInstance_instances, init_fn).call(this));
20459
19975
  }
20460
- this.file = new Filesystem(
19976
+ this.files = new Filesystem(
20461
19977
  this,
20462
19978
  this.socket === null ? null : (handler) => this.onDidConnect(handler)
20463
19979
  );
20464
- this.terminal = new Terminal(this);
19980
+ this.terminals = new Terminals(this);
20465
19981
  this.auth = new Auth(this);
20466
19982
  this.lsp = new Lsp(this);
20467
19983
  this.composer = new Composer(this, client);
20468
- this.log = new Log(this);
19984
+ const telemetry = new RuntimeTelemetry(this);
19985
+ this.logs = new Logs(this, telemetry);
19986
+ this.metrics = new Metrics(this, telemetry);
19987
+ this.ports = new Ports(this, telemetry);
20469
19988
  this.repl = new Repl(this);
20470
19989
  this.container = new Container(this);
20471
- this.laravel = new Laravel(this);
20472
19990
  this.shell = new Shell(this);
20473
19991
  this.git = new Git(this, client);
20474
19992
  this.services = new Services(this);
@@ -20500,17 +20018,29 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20500
20018
  fork(input = {}) {
20501
20019
  return this.client.notebook.fork(this.data.id, input);
20502
20020
  }
20503
- deployment() {
20504
- return this.client.notebook.deployment.current(this.data.id);
20021
+ publication() {
20022
+ return this.client.notebook.publication.current(this.data.id);
20505
20023
  }
20506
20024
  publish(input) {
20507
- return this.client.notebook.deployment.publish(this.data.id, input);
20025
+ return this.client.notebook.publication.publish(this.data.id, input);
20026
+ }
20027
+ run(command, argsOrOpts = [], opts) {
20028
+ if (Array.isArray(argsOrOpts)) {
20029
+ return this.shell.run(command, argsOrOpts, opts);
20030
+ }
20031
+ return this.shell.run(command, argsOrOpts);
20032
+ }
20033
+ exec(command, argsOrOpts = [], opts) {
20034
+ if (Array.isArray(argsOrOpts)) {
20035
+ return this.run(command, argsOrOpts, opts).wait();
20036
+ }
20037
+ return this.run(command, argsOrOpts).wait();
20508
20038
  }
20509
20039
  gitCredentials() {
20510
20040
  return this.client.notebook.gitCredentials(this.data.id);
20511
20041
  }
20512
- delete() {
20513
- return this.client.notebook.delete(this.data.id).then(() => {
20042
+ destroy() {
20043
+ return this.client.notebook.destroy(this.data.id).then(() => {
20514
20044
  this.socket?.terminate(new NotebookUnavailableError("Notebook has been deleted.", { id: this.data.id }));
20515
20045
  });
20516
20046
  }
@@ -20596,9 +20126,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20596
20126
  const socket = this.realtimeSocket();
20597
20127
  socket.onDidConnect(() => {
20598
20128
  socket.emit("okra.connected");
20599
- if (this.client.options.telemetry) {
20600
- this.container.enableTelemetry(this.client.options.telemetry);
20601
- }
20602
20129
  });
20603
20130
  socket.onDidClose(() => {
20604
20131
  socket.emit("okra.disconnected");
@@ -20657,11 +20184,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20657
20184
  __privateMethod(this, _NotebookInstance_instances, init_fn).call(this);
20658
20185
  return this.ready().then(() => this);
20659
20186
  }
20660
- async beacon(iframe, options) {
20661
- const result = await this.ready();
20662
- iframe.src = result.data.previewUrl;
20663
- return createBeacon(iframe, options);
20664
- }
20665
20187
  realtimeSocket() {
20666
20188
  if (this.socket === null) {
20667
20189
  throw new UnsupportedRuntimeTransportError("This operation requires the realtime transport.");