@phpsandbox/sdk 0.0.66 → 0.0.67

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.
@@ -153,6 +153,8 @@ export interface DeploymentData<TProvider extends DeploymentTargetProvider = Dep
153
153
  strategy: string;
154
154
  targetProvider: TProvider;
155
155
  options: DeploymentOptionsForProvider<TProvider>;
156
+ eventStreamUrl?: string | null;
157
+ /** @deprecated Use eventStreamUrl instead. */
156
158
  okraUrl: string | null;
157
159
  originUrl: string | null;
158
160
  currentRelease?: DeploymentReleaseData | null;
@@ -124,8 +124,9 @@ export class DeploymentRun {
124
124
  if (this.started) {
125
125
  return this;
126
126
  }
127
- if (!this.initial.data.okraUrl) {
128
- throw new Error(`Deployment ${this.initial.data.id} has no okraUrl for SSE streaming`);
127
+ const eventStreamUrl = this.initial.data.eventStreamUrl ?? this.initial.data.okraUrl;
128
+ if (!eventStreamUrl) {
129
+ throw new Error(`Deployment ${this.initial.data.id} has no eventStreamUrl for SSE streaming`);
129
130
  }
130
131
  this.started = true;
131
132
  this.resultPromise = new Promise((resolve, reject) => {
@@ -133,7 +134,7 @@ export class DeploymentRun {
133
134
  this.rejectResult = reject;
134
135
  });
135
136
  this.resultPromise.catch(() => undefined);
136
- void this.consumeStream(this.initial.data.okraUrl);
137
+ void this.consumeStream(eventStreamUrl);
137
138
  return this;
138
139
  }
139
140
  subscribe() {
@@ -152,9 +153,9 @@ export class DeploymentRun {
152
153
  }
153
154
  return queue;
154
155
  }
155
- async consumeStream(okraUrl) {
156
+ async consumeStream(eventStreamUrl) {
156
157
  try {
157
- const stream = await this.client.sse(okraUrl);
158
+ const stream = await this.client.sse(eventStreamUrl);
158
159
  for await (const event of readDeployStreamEvents(stream)) {
159
160
  this.publish(event);
160
161
  if (event.type === 'result') {
package/dist/index.d.ts CHANGED
@@ -307,6 +307,8 @@ export interface PHPSandboxClientOptions {
307
307
  telemetry?: Set<TelemetryFeature>;
308
308
  fetch?: typeof globalThis.fetch;
309
309
  webSocket?: unknown;
310
+ runtimeUrlProvider?: (notebookId: string) => Promise<string>;
311
+ /** @deprecated Use runtimeUrlProvider instead. */
310
312
  okraUrlProvider?: (notebookId: string) => Promise<string>;
311
313
  }
312
314
  export type RuntimeTransport = 'realtime' | 'rest';
@@ -377,6 +379,8 @@ export declare class NotebookMailApi {
377
379
  }
378
380
  export interface NotebookData {
379
381
  id: string;
382
+ runtimeUrl?: string;
383
+ /** @deprecated Use runtimeUrl instead. */
380
384
  okraUrl: string;
381
385
  gitUrl: string;
382
386
  type?: string;
package/dist/index.js CHANGED
@@ -347,24 +347,26 @@ export class NotebookInstance {
347
347
  this.initialized = false;
348
348
  _NotebookInstance_initPromise.set(this, null);
349
349
  this.disposables = [];
350
+ const runtimeUrl = data.runtimeUrl ?? data.okraUrl;
351
+ const runtimeUrlProvider = client.options.runtimeUrlProvider ?? client.options.okraUrlProvider;
350
352
  this.emitter = EventManager.createInstance();
351
353
  if (client.runtimeTransport === 'rest') {
352
354
  this.socket = null;
353
- this.restInvoker = new RestRuntimeInvoker(data, client.options.fetch ?? globalThis.fetch, client.options.okraUrlProvider === undefined
355
+ this.restInvoker = new RestRuntimeInvoker(data, client.options.fetch ?? globalThis.fetch, runtimeUrlProvider === undefined
354
356
  ? undefined
355
- : () => client.options.okraUrlProvider(data.id));
357
+ : () => runtimeUrlProvider(data.id));
356
358
  }
357
359
  else {
358
360
  this.restInvoker = null;
359
361
  let initialConnection = true;
360
- const connectionUrl = client.options.okraUrlProvider === undefined
361
- ? data.okraUrl
362
+ const connectionUrl = runtimeUrlProvider === undefined
363
+ ? runtimeUrl
362
364
  : async () => {
363
365
  if (initialConnection) {
364
366
  initialConnection = false;
365
- return data.okraUrl;
367
+ return runtimeUrl;
366
368
  }
367
- return client.options.okraUrlProvider(data.id);
369
+ return runtimeUrlProvider(data.id);
368
370
  };
369
371
  this.socket = new Transport(connectionUrl, this.emitter, {
370
372
  debug: client.options.debug,
@@ -62,20 +62,20 @@ export class RestRuntimeInvoker {
62
62
  this.refresh = refresh;
63
63
  this.refreshPromise = null;
64
64
  this.notebookId = data.id;
65
- this.configure(data.okraUrl);
65
+ this.configure(data.runtimeUrl ?? data.okraUrl);
66
66
  }
67
- configure(connectionUrl) {
68
- const okraUrl = new URL(connectionUrl);
69
- const ticket = okraUrl.searchParams.get('ticket') ?? '';
67
+ configure(runtimeUrl) {
68
+ const actionUrl = new URL(runtimeUrl);
69
+ const ticket = actionUrl.searchParams.get('ticket') ?? '';
70
70
  if (ticket === '') {
71
71
  throw new UnsupportedRuntimeTransportError('The notebook connection does not contain a runtime ticket.');
72
72
  }
73
73
  this.ticket = ticket;
74
- okraUrl.protocol = okraUrl.protocol === 'wss:' ? 'https:' : 'http:';
75
- okraUrl.pathname = `/api/v1/notebooks/${encodeURIComponent(this.notebookId)}`;
76
- okraUrl.searchParams.delete('ticket');
77
- okraUrl.hash = '';
78
- this.actionUrl = okraUrl;
74
+ actionUrl.protocol = actionUrl.protocol === 'wss:' ? 'https:' : 'http:';
75
+ actionUrl.pathname = `/api/v1/notebooks/${encodeURIComponent(this.notebookId)}`;
76
+ actionUrl.searchParams.delete('ticket');
77
+ actionUrl.hash = '';
78
+ this.actionUrl = actionUrl;
79
79
  }
80
80
  ready() {
81
81
  return this.invokeRaw('runtime.ready', {}, {});
@@ -134,7 +134,7 @@ export class RestRuntimeInvoker {
134
134
  }
135
135
  async refreshAuthorization() {
136
136
  if (this.refreshPromise === null) {
137
- this.refreshPromise = this.refresh().then((okraUrl) => this.configure(okraUrl));
137
+ this.refreshPromise = this.refresh().then((runtimeUrl) => this.configure(runtimeUrl));
138
138
  }
139
139
  try {
140
140
  await this.refreshPromise;
@@ -13,7 +13,7 @@ const client = PHPSandbox.realtime(token, 'https://api.phpsandbox.io/v1', {
13
13
  });
14
14
 
15
15
  const restClient = PHPSandbox.rest(token, 'https://api.phpsandbox.io/v1', {
16
- okraUrlProvider: async (notebookId) => getFreshOkraUrl(notebookId),
16
+ runtimeUrlProvider: async (notebookId) => getFreshRuntimeUrl(notebookId),
17
17
  });
18
18
  ```
19
19
 
@@ -116,11 +116,11 @@ Connection lifecycle methods, streaming actions, and event subscriptions require
116
116
 
117
117
  ### Laravel (`notebook.laravel`)
118
118
 
119
- - Wrapper exists in the SDK, but the current okra websocket action set does not expose Laravel maintenance actions.
119
+ - Wrapper exists in the SDK, but the current runtime action set does not expose Laravel maintenance actions.
120
120
 
121
121
  ### Auth (`notebook.auth`)
122
122
 
123
- - `login(okraUrl)` using a fresh ticket-bearing Okra URL
123
+ - `login(runtimeUrl)` using a fresh ticket-bearing runtime URL
124
124
  - `logout()`
125
125
 
126
126
  ### Log (`notebook.log`)
@@ -96,7 +96,7 @@ Useful flags:
96
96
 
97
97
  - `--no-cleanup` keeps every notebook after the run.
98
98
  - `--keep-failed` keeps failed notebooks for inspection. By default, failures are deleted too.
99
- - `--okra-origin=ws://127.0.0.1:9511` preserves the SDK-issued websocket path/auth but routes okra traffic to another host.
99
+ - `--runtime-origin=ws://127.0.0.1:9511` preserves the SDK-issued websocket path/auth but routes runtime traffic to another host.
100
100
  - `--include-container-restart` adds a mutable `container.start()` restart check on the fresh notebook.
101
101
  - `--include-download` adds `file.download()` to the baseline.
102
102
  - `--include-preview` fetches the initialized preview URL in init mode, or the route written by the scenario in full mode.
@@ -104,7 +104,7 @@ Useful flags:
104
104
  - `--require-init-messages="Preparing...|Setting up...|Opening..."` asserts frontend-visible init messages were received in order.
105
105
  - `--expect-provisioned=true` asserts the `notebook.ready()` initialization result reports provisioning work.
106
106
  - `--expect-provisioning-action=template` asserts the initialization result action.
107
- - `--reauthorization-url=wss://...?ticket=...` exercises `notebook.auth.login()` / `logout()` with a fresh ticket-bearing Okra URL.
107
+ - `--reauthorization-url=wss://...?ticket=...` exercises `notebook.auth.login()` / `logout()` with a fresh ticket-bearing runtime URL.
108
108
  - `--mode=init` limits the scenario to notebook create, ready, and delete so you can isolate init capacity.
109
109
  - `--init-only` is shorthand for `--mode=init`.
110
110
  - `--stop-on-failure-level` stops after the first level that has at least one failing scenario.
@@ -131,7 +131,7 @@ Default baseline coverage:
131
131
  Intentionally excluded by default:
132
132
 
133
133
  - `beacon`, because it needs a browser iframe runtime
134
- - `auth`, because it needs a fresh ticket-bearing Okra URL
134
+ - `auth`, because it needs a fresh ticket-bearing runtime URL
135
135
  - `laravel.maintenance.*`, because it is not part of the current okra websocket action set
136
136
  - `lsp`, because it is useful but more brittle than the rest of the headless baseline
137
137
 
@@ -153,12 +153,12 @@ PHPSANDBOX_TOKEN=your-token npx tsx examples/notebook-readonly-smoke.ts \
153
153
  --notebook-id=gypjc
154
154
  ```
155
155
 
156
- To preserve the SDK-issued notebook auth/path but route the websocket to a different okra host:
156
+ To preserve the SDK-issued notebook auth/path but route the websocket to a different runtime host:
157
157
 
158
158
  ```bash
159
159
  PHPSANDBOX_TOKEN=your-token npx tsx examples/notebook-readonly-smoke.ts \
160
160
  --notebook-id=gypjc \
161
- --okra-origin=ws://127.0.0.1:9501
161
+ --runtime-origin=ws://127.0.0.1:9501
162
162
  ```
163
163
 
164
164
  Default smoke coverage:
@@ -59,8 +59,8 @@ interface LoadTestOptions {
59
59
  token: string;
60
60
  local: boolean;
61
61
  apiUrl: string;
62
- okraOrigin?: string;
63
- okraUrl?: string;
62
+ runtimeOrigin?: string;
63
+ runtimeUrl?: string;
64
64
  template: string;
65
65
  mode: LoadTestMode;
66
66
  stopOnFailureLevel: boolean;
@@ -478,7 +478,7 @@ async function runScenario(
478
478
 
479
479
  const data = {
480
480
  ...created.data,
481
- okraUrl: resolveOkraUrl(created.data.okraUrl, options),
481
+ runtimeUrl: resolveRuntimeUrl(created.data.runtimeUrl ?? created.data.okraUrl, options),
482
482
  };
483
483
  created.dispose();
484
484
 
@@ -1071,8 +1071,8 @@ function renderConfiguration(options: LoadTestOptions): string {
1071
1071
  ` mode: ${options.mode}`,
1072
1072
  ` stop on failing level: ${options.stopOnFailureLevel}`,
1073
1073
  ` api url: ${options.apiUrl}`,
1074
- options.okraOrigin ? ` okra origin override: ${options.okraOrigin}` : undefined,
1075
- options.okraUrl ? ` okra url override: ${redactUrl(options.okraUrl)}` : undefined,
1074
+ options.runtimeOrigin ? ` runtime origin override: ${options.runtimeOrigin}` : undefined,
1075
+ options.runtimeUrl ? ` runtime url override: ${redactUrl(options.runtimeUrl)}` : undefined,
1076
1076
  ` levels: ${options.levels.join(', ')}`,
1077
1077
  ` waves per level: ${options.waves}`,
1078
1078
  ` visibility: ${options.visibility}`,
@@ -2400,8 +2400,8 @@ function parseOptions(argv: string[]): LoadTestOptions {
2400
2400
  token,
2401
2401
  local,
2402
2402
  apiUrl,
2403
- okraOrigin: stringArg(args, 'okra-origin'),
2404
- okraUrl: stringArg(args, 'okra-url'),
2403
+ runtimeOrigin: stringArg(args, 'runtime-origin'),
2404
+ runtimeUrl: stringArg(args, 'runtime-url'),
2405
2405
  template: stringArg(args, 'template') ?? 'laravel',
2406
2406
  mode: resolveMode(args),
2407
2407
  stopOnFailureLevel: booleanArg(args, 'stop-on-failure-level') ?? false,
@@ -2433,17 +2433,17 @@ function parseOptions(argv: string[]): LoadTestOptions {
2433
2433
  };
2434
2434
  }
2435
2435
 
2436
- function resolveOkraUrl(original: string, options: LoadTestOptions): string {
2437
- if (options.okraUrl) {
2438
- return options.okraUrl;
2436
+ function resolveRuntimeUrl(original: string, options: LoadTestOptions): string {
2437
+ if (options.runtimeUrl) {
2438
+ return options.runtimeUrl;
2439
2439
  }
2440
2440
 
2441
- if (!options.okraOrigin) {
2441
+ if (!options.runtimeOrigin) {
2442
2442
  return original;
2443
2443
  }
2444
2444
 
2445
2445
  const source = new URL(original);
2446
- const target = new URL(options.okraOrigin);
2446
+ const target = new URL(options.runtimeOrigin);
2447
2447
  source.protocol = target.protocol;
2448
2448
  source.host = target.host;
2449
2449
  return source.toString();
@@ -24,8 +24,8 @@ interface SmokeOptions {
24
24
  local: boolean;
25
25
  apiUrl: string;
26
26
  notebookId: string;
27
- okraUrl?: string;
28
- okraOrigin?: string;
27
+ runtimeUrl?: string;
28
+ runtimeOrigin?: string;
29
29
  includeExec: boolean;
30
30
  includeDownload: boolean;
31
31
  includePreview: boolean;
@@ -67,8 +67,8 @@ interface SmokeArtifact {
67
67
  apiUrl: string;
68
68
  local: boolean;
69
69
  notebookId: string;
70
- okraUrl?: string;
71
- okraOrigin?: string;
70
+ runtimeUrl?: string;
71
+ runtimeOrigin?: string;
72
72
  includeExec: boolean;
73
73
  includeDownload: boolean;
74
74
  includePreview: boolean;
@@ -77,7 +77,7 @@ interface SmokeArtifact {
77
77
  id: string;
78
78
  title?: string;
79
79
  type?: string;
80
- okraUrl: string;
80
+ runtimeUrl: string;
81
81
  };
82
82
  initTrace: InitTraceArtifact;
83
83
  steps: StepArtifact[];
@@ -103,13 +103,13 @@ async function main(): Promise<void> {
103
103
  const result = await client.get<NotebookData>(`/notebook/${options.notebookId}`);
104
104
  return {
105
105
  data: result.data,
106
- detail: `id=${result.data.id} type=${result.data.type ?? ''} title=${result.data.title ?? ''} okraUrl=${redactUrl(result.data.okraUrl)}`,
106
+ detail: `id=${result.data.id} type=${result.data.type ?? ''} title=${result.data.title ?? ''} runtimeUrl=${redactUrl(result.data.runtimeUrl ?? result.data.okraUrl)}`,
107
107
  };
108
108
  });
109
109
 
110
110
  notebookData = {
111
111
  ...response.data,
112
- okraUrl: resolveOkraUrl(response.data.okraUrl, options),
112
+ runtimeUrl: resolveRuntimeUrl(response.data.runtimeUrl ?? response.data.okraUrl, options),
113
113
  };
114
114
 
115
115
  notebook = new NotebookInstance(notebookData, client);
@@ -289,8 +289,8 @@ async function main(): Promise<void> {
289
289
  apiUrl: options.apiUrl,
290
290
  local: options.local,
291
291
  notebookId: options.notebookId,
292
- okraUrl: options.okraUrl ? redactUrl(options.okraUrl) : undefined,
293
- okraOrigin: options.okraOrigin,
292
+ runtimeUrl: options.runtimeUrl ? redactUrl(options.runtimeUrl) : undefined,
293
+ runtimeOrigin: options.runtimeOrigin,
294
294
  includeExec: options.includeExec,
295
295
  includeDownload: options.includeDownload,
296
296
  includePreview: options.includePreview,
@@ -300,7 +300,7 @@ async function main(): Promise<void> {
300
300
  id: notebookData.id,
301
301
  title: notebookData.title,
302
302
  type: notebookData.type,
303
- okraUrl: redactUrl(notebookData.okraUrl),
303
+ runtimeUrl: redactUrl(notebookData.runtimeUrl ?? notebookData.okraUrl),
304
304
  }
305
305
  : undefined,
306
306
  initTrace,
@@ -471,17 +471,17 @@ async function readStreamToString(stream: ReadableStream<string>, timeoutMs: num
471
471
  }
472
472
  }
473
473
 
474
- function resolveOkraUrl(original: string, options: SmokeOptions): string {
475
- if (options.okraUrl) {
476
- return options.okraUrl;
474
+ function resolveRuntimeUrl(original: string, options: SmokeOptions): string {
475
+ if (options.runtimeUrl) {
476
+ return options.runtimeUrl;
477
477
  }
478
478
 
479
- if (!options.okraOrigin) {
479
+ if (!options.runtimeOrigin) {
480
480
  return original;
481
481
  }
482
482
 
483
483
  const source = new URL(original);
484
- const target = new URL(options.okraOrigin);
484
+ const target = new URL(options.runtimeOrigin);
485
485
  source.protocol = target.protocol;
486
486
  source.host = target.host;
487
487
  return source.toString();
@@ -508,8 +508,8 @@ function parseOptions(argv: string[]): SmokeOptions {
508
508
  process.env.PHPSANDBOX_API_URL ??
509
509
  ((booleanArg(args, 'local') ?? false) ? DEFAULT_LOCAL_API_URL : DEFAULT_API_URL),
510
510
  notebookId: stringArg(args, 'notebook-id') ?? 'gypjc',
511
- okraUrl: stringArg(args, 'okra-url'),
512
- okraOrigin: stringArg(args, 'okra-origin'),
511
+ runtimeUrl: stringArg(args, 'runtime-url'),
512
+ runtimeOrigin: stringArg(args, 'runtime-origin'),
513
513
  includeExec: booleanArg(args, 'include-exec') ?? false,
514
514
  includeDownload: booleanArg(args, 'include-download') ?? false,
515
515
  includePreview: booleanArg(args, 'include-preview') ?? false,
@@ -786,7 +786,7 @@ function printSummary(artifact: SmokeArtifact): void {
786
786
  console.log('\n=== Notebook readonly smoke summary ===');
787
787
  console.log(`Status: ${artifact.status}`);
788
788
  console.log(`Notebook: ${artifact.options.notebookId}`);
789
- console.log(`Okra URL: ${artifact.notebook?.okraUrl ?? 'unresolved'}`);
789
+ console.log(`Runtime URL: ${artifact.notebook?.runtimeUrl ?? 'unresolved'}`);
790
790
  console.log(`Duration: ${formatDuration(artifact.durationMs)}`);
791
791
  console.log(`Steps: passed=${passed} failed=${failed} skipped=${skipped}`);
792
792
 
@@ -806,8 +806,8 @@ Options:
806
806
  --local Use ${DEFAULT_LOCAL_API_URL} and default to insecure TLS.
807
807
  --insecure-tls Disable TLS verification for local HTTPS/WSS.
808
808
  --ca-file=<path> Trust a custom CA for local HTTPS/WSS.
809
- --okra-url=<url> Replace notebook okraUrl with a full WebSocket URL.
810
- --okra-origin=<origin> Replace only the okraUrl origin, preserving path/query auth.
809
+ --runtime-url=<url> Replace the notebook runtimeUrl with a full WebSocket URL.
810
+ --runtime-origin=<origin> Replace only the runtimeUrl origin, preserving path/query auth.
811
811
  --include-exec Also run shell, terminal, and REPL read-safe execution checks.
812
812
  --include-download Also run a read-only file.download() check for a known file.
813
813
  --include-preview Fetch the initialized preview URL.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phpsandbox/sdk",
3
- "version": "0.0.66",
3
+ "version": "0.0.67",
4
4
  "description": "A comprehensive TypeScript SDK for interacting with cloud-based PHP development environments",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",