@phpsandbox/sdk 0.0.65 → 0.0.66

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -65,13 +65,16 @@ export class Transport {
65
65
  this.incomingMessageChain = Promise.resolve();
66
66
  // Validate configuration
67
67
  this.validateConfiguration(options);
68
- this.url = new URL(url);
68
+ this.url = typeof url === 'string' ? new URL(url) : null;
69
+ const urlProvider = typeof url === 'string'
70
+ ? this.url.toString()
71
+ : async () => new URL(await url()).toString();
69
72
  // Use configurable ping interval
70
73
  this.PING_INTERVAL = options.pingInterval ?? 30000;
71
74
  this.CONNECT_WAIT_TIMEOUT = options.connectWaitTimeout ?? 30000;
72
75
  // Always start closed by default (lazy initialization)
73
76
  const startClosed = options.startClosed !== false;
74
- this.rws = new ReconnectingWebSocket(this.url.toString(), [], {
77
+ this.rws = new ReconnectingWebSocket(urlProvider, [], {
75
78
  WebSocket: options.webSocket ?? globalThis.WebSocket ?? WebSocket,
76
79
  connectionTimeout: options.connectionTimeout,
77
80
  maxReconnectionDelay: 2000,
@@ -81,7 +84,7 @@ export class Transport {
81
84
  startClosed,
82
85
  });
83
86
  this.log('debug', 'Transport initialized', {
84
- url: this.url.toString(),
87
+ url: this.url === null ? 'dynamic' : transportLogUrl(this.url),
85
88
  options,
86
89
  });
87
90
  this.registerWatchers();
@@ -699,3 +702,9 @@ _Transport_instances = new WeakSet(), _Transport_connect = function _Transport_c
699
702
  };
700
703
  });
701
704
  };
705
+ function transportLogUrl(url) {
706
+ const safeUrl = new URL(url);
707
+ safeUrl.search = '';
708
+ safeUrl.hash = '';
709
+ return safeUrl.toString();
710
+ }
package/dist/types.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type ErrorCode = 500 | 400 | 401 | 403 | 404 | 409 | 422 | 429 | 5000;
1
+ export type ErrorCode = 400 | 401 | 403 | 404 | 405 | 409 | 413 | 422 | 429 | 500 | 503 | 5000;
2
2
  export declare class ErrorEvent extends Error {
3
3
  readonly code: ErrorCode;
4
4
  readonly message: string;
@@ -7,12 +7,18 @@ This is a quick reference for the current SDK surface.
7
7
  ```ts
8
8
  import { PHPSandbox } from '@phpsandbox/sdk';
9
9
 
10
- const client = new PHPSandbox(token, 'https://api.phpsandbox.io/v1', {
10
+ const client = PHPSandbox.realtime(token, 'https://api.phpsandbox.io/v1', {
11
11
  debug: false,
12
12
  startClosed: true,
13
13
  });
14
+
15
+ const restClient = PHPSandbox.rest(token, 'https://api.phpsandbox.io/v1', {
16
+ okraUrlProvider: async (notebookId) => getFreshOkraUrl(notebookId),
17
+ });
14
18
  ```
15
19
 
20
+ Connection lifecycle methods, streaming actions, and event subscriptions require the realtime transport. The REST transport rejects unsupported operations without falling back to a websocket.
21
+
16
22
  ### `NotebookApi`
17
23
 
18
24
  - `create(template, input?, init = true)`
@@ -114,7 +120,7 @@ const client = new PHPSandbox(token, 'https://api.phpsandbox.io/v1', {
114
120
 
115
121
  ### Auth (`notebook.auth`)
116
122
 
117
- - `login(newConnectionData)`
123
+ - `login(okraUrl)` using a fresh ticket-bearing Okra URL
118
124
  - `logout()`
119
125
 
120
126
  ### Log (`notebook.log`)
@@ -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
- - `--auth-payload=...` exercises `notebook.auth.login()` / `logout()`.
107
+ - `--reauthorization-url=wss://...?ticket=...` exercises `notebook.auth.login()` / `logout()` with a fresh ticket-bearing Okra 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 real connection payload
134
+ - `auth`, because it needs a fresh ticket-bearing Okra 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
 
@@ -84,7 +84,7 @@ interface LoadTestOptions {
84
84
  requireInitMessages: string[];
85
85
  expectProvisioned?: boolean;
86
86
  expectProvisioningAction?: NotebookProvisioningAction;
87
- authPayload?: string;
87
+ reauthorizationUrl?: string;
88
88
  json: boolean;
89
89
  jsonFile?: string;
90
90
  insecureTls: boolean;
@@ -947,14 +947,14 @@ async function runScenario(
947
947
  recordSkippedStep(steps, 'lsp.initialize', 'Enable with --include-lsp.');
948
948
  }
949
949
 
950
- if (options.authPayload) {
950
+ if (options.reauthorizationUrl) {
951
951
  await runCheckedStep('auth.login-logout', async () => {
952
- await notebook!.auth.login(options.authPayload!);
952
+ await notebook!.auth.login(options.reauthorizationUrl!);
953
953
  await notebook!.auth.logout();
954
954
  return 'ok';
955
955
  });
956
956
  } else {
957
- recordSkippedStep(steps, 'auth.login-logout', 'Provide --auth-payload to exercise auth.');
957
+ recordSkippedStep(steps, 'auth.login-logout', 'Provide --reauthorization-url to exercise auth.');
958
958
  }
959
959
  }
960
960
  } catch (error) {
@@ -1085,7 +1085,7 @@ function renderConfiguration(options: LoadTestOptions): string {
1085
1085
  ` required init messages: ${options.requireInitMessages.length > 0 ? options.requireInitMessages.join(' -> ') : 'none'}`,
1086
1086
  ` expect provisioned: ${options.expectProvisioned ?? 'not asserted'}`,
1087
1087
  ` expect provisioning action: ${options.expectProvisioningAction ?? 'not asserted'}`,
1088
- ` include auth: ${Boolean(options.authPayload)}`,
1088
+ ` include auth: ${Boolean(options.reauthorizationUrl)}`,
1089
1089
  ` insecure tls: ${options.insecureTls}`,
1090
1090
  ` ca file: ${options.caFile ?? 'none'}`,
1091
1091
  ];
@@ -2291,8 +2291,8 @@ function sanitizeArtifact<T>(payload: T): T {
2291
2291
  if ('token' in cloned.options) {
2292
2292
  cloned.options.token = '<redacted>';
2293
2293
  }
2294
- if ('authPayload' in cloned.options) {
2295
- cloned.options.authPayload = '<redacted>';
2294
+ if ('reauthorizationUrl' in cloned.options) {
2295
+ cloned.options.reauthorizationUrl = '<redacted>';
2296
2296
  }
2297
2297
  }
2298
2298
 
@@ -2425,7 +2425,7 @@ function parseOptions(argv: string[]): LoadTestOptions {
2425
2425
  requireInitMessages: listArg(args, 'require-init-messages'),
2426
2426
  expectProvisioned: booleanArg(args, 'expect-provisioned'),
2427
2427
  expectProvisioningAction: provisioningActionArg(args, 'expect-provisioning-action'),
2428
- authPayload: stringArg(args, 'auth-payload'),
2428
+ reauthorizationUrl: stringArg(args, 'reauthorization-url'),
2429
2429
  json: booleanArg(args, 'json') ?? false,
2430
2430
  jsonFile: stringArg(args, 'json-file'),
2431
2431
  insecureTls,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phpsandbox/sdk",
3
- "version": "0.0.65",
3
+ "version": "0.0.66",
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",