@phpsandbox/sdk 0.1.13 → 0.1.15

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 (40) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +7 -18
  3. package/dist/browser/phpsandbox-sdk.esm.js +25 -14
  4. package/dist/browser/phpsandbox-sdk.esm.min.js +9 -9
  5. package/dist/browser/phpsandbox-sdk.iife.js +25 -14
  6. package/dist/browser/phpsandbox-sdk.iife.min.js +9 -9
  7. package/dist/errors/index.d.ts +7 -1
  8. package/dist/errors/index.js +2 -1
  9. package/dist/index.d.ts +27 -6
  10. package/dist/index.js +16 -12
  11. package/dist/{integrations.d.ts → integrations/account.d.ts} +1 -1
  12. package/dist/integrations/index.d.ts +2 -0
  13. package/dist/integrations/index.js +2 -0
  14. package/dist/{sandbox-integrations.d.ts → integrations/sandbox.d.ts} +2 -2
  15. package/dist/{sandbox-integrations.js → integrations/sandbox.js} +1 -1
  16. package/dist/log.d.ts +1 -1
  17. package/dist/log.js +1 -1
  18. package/dist/metrics.d.ts +1 -1
  19. package/dist/metrics.js +1 -1
  20. package/dist/ports.d.ts +1 -1
  21. package/dist/ports.js +1 -1
  22. package/dist/runtime.d.ts +1 -1
  23. package/dist/runtime.js +1 -1
  24. package/package.json +5 -9
  25. package/docs/api-summary.md +0 -181
  26. package/docs/cdn-usage.md +0 -68
  27. package/docs/getting-started.md +0 -169
  28. package/examples/README.md +0 -203
  29. package/examples/basic.ts +0 -15
  30. package/examples/get.ts +0 -22
  31. package/examples/git-merge-smoke.ts +0 -395
  32. package/examples/laravel-load-test.ts +0 -2800
  33. package/examples/notebook-readonly-smoke.ts +0 -806
  34. package/examples/publication-provider-label.ts +0 -11
  35. package/examples/publish-cloudflare-container.ts +0 -65
  36. package/examples/publish-laravel-cloud.ts +0 -123
  37. package/examples/publish-ssh-agent.ts +0 -211
  38. /package/dist/{integrations.js → integrations/account.js} +0 -0
  39. /package/dist/{runtime-telemetry.d.ts → telemetry.d.ts} +0 -0
  40. /package/dist/{runtime-telemetry.js → telemetry.js} +0 -0
@@ -29,9 +29,15 @@ export declare class RemoteError<TCode extends RemoteErrorCode = RemoteErrorCode
29
29
  };
30
30
  is<TExpectedCode extends RemoteErrorCode>(code: TExpectedCode): this is this & RemoteError<TExpectedCode>;
31
31
  }
32
+ export interface HttpResponseDiagnostics {
33
+ readonly status: number;
34
+ readonly statusText: string;
35
+ readonly body: string;
36
+ }
32
37
  export declare class TransportError<TCode extends TransportErrorCode = TransportErrorCode> extends PHPSandboxError {
33
38
  readonly code: TCode;
34
- constructor(message: string, code: TCode, cause?: unknown);
39
+ readonly response?: HttpResponseDiagnostics;
40
+ constructor(message: string, code: TCode, cause?: unknown, response?: HttpResponseDiagnostics);
35
41
  static is(error: unknown): error is TransportError;
36
42
  static is<TCode extends TransportErrorCode>(error: unknown, code: TCode): error is TransportError<TCode>;
37
43
  is<TExpectedCode extends TransportErrorCode>(code: TExpectedCode): this is this & TransportError<TExpectedCode>;
@@ -56,9 +56,10 @@ export class RemoteError extends PHPSandboxError {
56
56
  }
57
57
  }
58
58
  export class TransportError extends PHPSandboxError {
59
- constructor(message, code, cause) {
59
+ constructor(message, code, cause, response) {
60
60
  super(message, cause);
61
61
  this.code = code;
62
+ this.response = response;
62
63
  }
63
64
  static is(error, code) {
64
65
  return error instanceof TransportError && (code === undefined || error.code === code);
package/dist/index.d.ts CHANGED
@@ -15,15 +15,14 @@ import { RemoteError } from './errors/index.js';
15
15
  import { PublicationApi, PublicationInstance, PublicationRun, type PublishInput } from './publications.js';
16
16
  import { ServerApi } from './servers.js';
17
17
  import { Feedback } from './feedback.js';
18
- import { IntegrationApi } from './integrations.js';
19
- import { SandboxIntegrationApi } from './sandbox-integrations.js';
18
+ import { IntegrationApi, SandboxIntegrationApi } from './integrations/index.js';
20
19
  export type { Disposable } from './types.js';
21
20
  export { LspConnection } from './lsp.js';
22
21
  export { FileChangeFilter, FileChangeType, FileType, } from './filesystem.js';
23
22
  export type { FileChange, FileContents, FileDeleteOptions, FileDownloadOptions, FileFollowOptions, FileLineRange, FileLineRangeResult, FileListOptions, FileOverwriteOptions, FileResult, FileSearchOptions, FileTailOptions, FileWriteOptions, Filesystem, Stats, TextSearchMatch, TextSearchOptions, TextSearchQuery, TextSearchResult, WatchOptions, } from './filesystem.js';
24
23
  export type { PortInfo } from './runtime.js';
25
24
  export type { RuntimeLogEntry } from './log.js';
26
- export type { RuntimeWatchOptions } from './runtime-telemetry.js';
25
+ export type { RuntimeWatchOptions } from './telemetry.js';
27
26
  export type { RuntimeResourceUsage, RuntimeStats } from './runtime.js';
28
27
  export type { ProcessOutputChunk, ProcessOutputSource, ProcessResult, ShellProcess } from './shell.js';
29
28
  export type { SandboxProcess, SpawnOptions, Task, TerminalOptions } from './terminal.js';
@@ -32,12 +31,11 @@ export { notebookBuiltinServices, notebookKnownServices } from './services.js';
32
31
  export type { NotebookBuiltinServiceName, NotebookKnownServiceName, NotebookServiceCommand, NotebookServiceKind, NotebookServiceName, NotebookServiceSource, NotebookServiceState, NotebookServiceStatus, ServiceLogOptions, ServiceLogStreamOptions, } from './services.js';
33
32
  export type { ConfigPortMapping, ProjectConfig } from './config.js';
34
33
  export { PHPSandboxError, RemoteError, TransportError, } from './errors/index.js';
35
- export type { RemoteErrorCode, RemoteErrorSource, TransportErrorCode, ValidationErrorDetails, } from './errors/index.js';
34
+ export type { HttpResponseDiagnostics, RemoteErrorCode, RemoteErrorSource, TransportErrorCode, ValidationErrorDetails, } from './errors/index.js';
36
35
  export type { BuiltInPublicationProviderName, CloudflareContainersProviderOptions, LaravelCloudProviderData, LaravelCloudProviderInput, LaravelCloudRegion, PublicationBuildData, PublicationBuildStatus, PublicationData, PublicationEventData, PublicationInstance, PublicationJurisdiction, PublicationLogChunkData, PublicationLogStream, PublicationPlacement, PublicationProtectionData, PublicationProtectionInput, PublicationProtectionMode, PublicationProtectionSessionData, PublicationProvider, PublicationProviderData, PublicationProviderInput, PublicationProviderInputs, PublicationProviderName, PublicationRegion, PublicationReleaseData, PublicationReleaseStatus, PublicationRun, PublicationSize, PublicationStatus, PublishInput, PublishStreamEvent, PublishStreamLog, PublishStreamPhase, PublishStreamResult, PublishStreamSseEvent, SshServerProviderOptions, UpdatePublicationProtectionInput, } from './publications.js';
37
36
  export type { CreateServerInput, ServerData, ServerInstance, ServerListOptions, ServerSshOptions } from './servers.js';
38
37
  export type { ConfigureFeedbackInput, FeedbackData, FeedbackListOptions, FeedbackSource, FeedbackStatus, FeedbackType, FeedbackWidgetConfig, FeedbackWidgetTarget, SubmitFeedbackInput, UpdateFeedbackInput, } from './feedback.js';
39
- export type { Integration, IntegrationAuthorization, IntegrationAuthorizationType, IntegrationData, IntegrationProvider, IntegrationReference, LinkIntegrationInput, UpdateIntegrationInput, } from './integrations.js';
40
- export type { AttachSandboxIntegrationInput, SandboxIntegration, SandboxIntegrationData, SandboxIntegrationEffect, SandboxIntegrationReference, UpdateSandboxIntegrationInput, } from './sandbox-integrations.js';
38
+ export type { Integration, IntegrationAuthorization, IntegrationAuthorizationType, IntegrationData, IntegrationProvider, IntegrationReference, LinkIntegrationInput, UpdateIntegrationInput, AttachSandboxIntegrationInput, SandboxIntegration, SandboxIntegrationData, SandboxIntegrationEffect, SandboxIntegrationReference, UpdateSandboxIntegrationInput, } from './integrations/index.js';
41
39
  interface Result<TType extends 'success' | 'error' | 'running', TData extends object> {
42
40
  type: TType;
43
41
  message: string;
@@ -108,8 +106,24 @@ export interface CreateNotebookImportInput {
108
106
  provider: 'github';
109
107
  repo: string;
110
108
  branch?: string;
109
+ ref?: string;
111
110
  auth: CreateNotebookImportAuthInput;
112
111
  }
112
+ export type InspectNotebookImportInput = CreateNotebookImportInput;
113
+ export interface NotebookImportRequiredSecret {
114
+ name: string;
115
+ description: string | null;
116
+ }
117
+ export interface NotebookImportInspectionData {
118
+ supported: boolean;
119
+ repository: string;
120
+ branch: string;
121
+ ref: string;
122
+ framework: 'laravel' | 'adonisjs' | 'custom' | null;
123
+ template: string | null;
124
+ reason: string | null;
125
+ requiredSecrets: NotebookImportRequiredSecret[];
126
+ }
113
127
  export interface NotebookLifecycleInput {
114
128
  persistent?: true;
115
129
  }
@@ -118,6 +132,7 @@ export interface CreateNotebookInput extends NotebookLifecycleInput {
118
132
  visibility: 'public' | 'private' | 'unlisted';
119
133
  import?: CreateNotebookImportInput;
120
134
  composerCredentials?: ComposerCredentialInput[];
135
+ secrets?: UpsertNotebookSecretItemInput[];
121
136
  }
122
137
  export type ForkNotebookInput = NotebookLifecycleInput;
123
138
  export interface NotebookPolicyData {
@@ -196,11 +211,14 @@ export interface NotebookPreviewDataEnabled {
196
211
  export type NotebookPreviewData = NotebookPreviewDataDisabled | NotebookPreviewDataEnabled;
197
212
  export type NotebookPreviewDataWithUrl = NotebookPreviewDataDisabled | (NotebookPreviewDataEnabled & {
198
213
  url: string;
214
+ accessUrl: string;
199
215
  });
200
216
  export interface SetNotebookPreviewInput {
201
217
  password: string;
202
218
  }
203
219
  export interface NotebookPreviewSessionData {
220
+ /** Open this URL to establish preview access. */
221
+ accessUrl: string;
204
222
  previewSessionId: string;
205
223
  token: string;
206
224
  expiresAt: string;
@@ -215,6 +233,8 @@ export interface CreateNotebookPreviewHandoffInput {
215
233
  url: string;
216
234
  }
217
235
  export interface NotebookPreviewHandoffData {
236
+ /** Open this URL to establish preview access. */
237
+ accessUrl: string;
218
238
  handoffId: string;
219
239
  previewSessionId: string;
220
240
  token: string;
@@ -254,6 +274,7 @@ export interface NotebookMailListOptions {
254
274
  declare class NotebookApi {
255
275
  private readonly client;
256
276
  constructor(client: Client);
277
+ inspectImport(input: InspectNotebookImportInput): Promise<NotebookImportInspectionData>;
257
278
  create(template: string, input?: Partial<CreateNotebookInput>): Promise<NotebookInstance>;
258
279
  get(id: string): Promise<NotebookInstance>;
259
280
  open(data: NotebookData): NotebookInstance;
package/dist/index.js CHANGED
@@ -28,8 +28,7 @@ import { PublicationApi, PublicationInstance, PublicationRun, } from './publicat
28
28
  import { ServerApi } from './servers.js';
29
29
  import { RestRuntimeInvoker } from './runtime/rest.js';
30
30
  import { Feedback } from './feedback.js';
31
- import { IntegrationApi } from './integrations.js';
32
- import { SandboxIntegrationApi } from './sandbox-integrations.js';
31
+ import { IntegrationApi, SandboxIntegrationApi } from './integrations/index.js';
33
32
  import { authenticatedRequest } from './http.js';
34
33
  export { LspConnection } from './lsp.js';
35
34
  export { FileChangeFilter, FileChangeType, FileType, } from './filesystem.js';
@@ -48,6 +47,10 @@ class NotebookApi {
48
47
  constructor(client) {
49
48
  this.client = client;
50
49
  }
50
+ async inspectImport(input) {
51
+ const response = await this.client.post('/notebook/imports/inspect', input);
52
+ return response.data;
53
+ }
51
54
  async create(template, input = {}) {
52
55
  const response = await this.client.post('/notebook', { template, ...input });
53
56
  return new NotebookInstance(response.data, this.client);
@@ -111,7 +114,7 @@ class ClientImplementation {
111
114
  headers: this.headers,
112
115
  }));
113
116
  if (!response.ok) {
114
- throw remoteError('core', errorPayload(await responsePayload(response)), response);
117
+ throw await responseError(response);
115
118
  }
116
119
  if (!response.body) {
117
120
  throw new TransportError('PHPSandbox API response body is not readable.', 'InvalidResponse', response);
@@ -127,7 +130,7 @@ class ClientImplementation {
127
130
  },
128
131
  }));
129
132
  if (!response.ok) {
130
- throw remoteError('core', errorPayload(await responsePayload(response)), response);
133
+ throw await responseError(response);
131
134
  }
132
135
  if (!response.body) {
133
136
  throw new TransportError('PHPSandbox API SSE response body is not readable.', 'InvalidResponse', response);
@@ -141,7 +144,7 @@ class ClientImplementation {
141
144
  headers: this.headers,
142
145
  }));
143
146
  if (!response.ok) {
144
- throw remoteError('core', errorPayload(await responsePayload(response)), response);
147
+ throw await responseError(response);
145
148
  }
146
149
  if (response.status === 204) {
147
150
  return { data: undefined };
@@ -176,16 +179,17 @@ class ClientImplementation {
176
179
  }
177
180
  }
178
181
  }
179
- async function responsePayload(response) {
182
+ async function responseError(response) {
180
183
  const body = await response.text();
181
- if (body === '') {
182
- return undefined;
183
- }
184
184
  try {
185
- return JSON.parse(body);
185
+ return remoteError('core', errorPayload(body === '' ? undefined : JSON.parse(body)), response);
186
186
  }
187
- catch (error) {
188
- throw new TransportError('PHPSandbox API returned an invalid JSON response.', 'InvalidResponse', error);
187
+ catch {
188
+ return new TransportError(`PHPSandbox API returned an invalid error response (HTTP ${response.status}).`, 'InvalidResponse', response, {
189
+ status: response.status,
190
+ statusText: response.statusText,
191
+ body,
192
+ });
189
193
  }
190
194
  }
191
195
  function errorPayload(payload) {
@@ -1,4 +1,4 @@
1
- import type { Client } from './index.js';
1
+ import type { Client } from '../index.js';
2
2
  export type IntegrationProvider = 'cloudflare' | 'github' | 'laravel-cloud';
3
3
  export type IntegrationAuthorizationType = 'token';
4
4
  export interface IntegrationAuthorization {
@@ -0,0 +1,2 @@
1
+ export * from './account.js';
2
+ export * from './sandbox.js';
@@ -0,0 +1,2 @@
1
+ export * from './account.js';
2
+ export * from './sandbox.js';
@@ -1,5 +1,5 @@
1
- import type { Client } from './index.js';
2
- import { Integration, type IntegrationData, type IntegrationReference } from './integrations.js';
1
+ import type { Client } from '../index.js';
2
+ import { Integration, type IntegrationData, type IntegrationReference } from './account.js';
3
3
  export type SandboxIntegrationEffect = 'network';
4
4
  export interface AttachSandboxIntegrationInput {
5
5
  integration: IntegrationReference;
@@ -1,4 +1,4 @@
1
- import { Integration, integrationId, } from './integrations.js';
1
+ import { Integration, integrationId, } from './account.js';
2
2
  export class SandboxIntegrationApi {
3
3
  constructor(notebookId, client) {
4
4
  this.notebookId = notebookId;
package/dist/log.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { NotebookInstance } from './index.js';
2
- import { RuntimeTelemetry, type RuntimeWatchOptions } from './runtime-telemetry.js';
2
+ import { RuntimeTelemetry, type RuntimeWatchOptions } from './telemetry.js';
3
3
  export interface LogEvents {
4
4
  'notebook.log': string;
5
5
  }
package/dist/log.js CHANGED
@@ -1,4 +1,4 @@
1
- import { watchRuntimeTelemetry } from './runtime-telemetry.js';
1
+ import { watchRuntimeTelemetry } from './telemetry.js';
2
2
  export default class Logs {
3
3
  constructor(okra, telemetry) {
4
4
  this.okra = okra;
package/dist/metrics.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { NotebookInstance } from './index.js';
2
2
  import type { RuntimeStats } from './runtime.js';
3
- import { RuntimeTelemetry, type RuntimeWatchOptions } from './runtime-telemetry.js';
3
+ import { RuntimeTelemetry, type RuntimeWatchOptions } from './telemetry.js';
4
4
  export default class Metrics {
5
5
  private readonly okra;
6
6
  private readonly telemetry;
package/dist/metrics.js CHANGED
@@ -1,4 +1,4 @@
1
- import { watchRuntimeTelemetry } from './runtime-telemetry.js';
1
+ import { watchRuntimeTelemetry } from './telemetry.js';
2
2
  export default class Metrics {
3
3
  constructor(okra, telemetry) {
4
4
  this.okra = okra;
package/dist/ports.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { NotebookInstance } from './index.js';
2
2
  import type { PortInfo } from './runtime.js';
3
- import { RuntimeTelemetry, type RuntimeWatchOptions } from './runtime-telemetry.js';
3
+ import { RuntimeTelemetry, type RuntimeWatchOptions } from './telemetry.js';
4
4
  export default class Ports {
5
5
  private readonly okra;
6
6
  private readonly telemetry;
package/dist/ports.js CHANGED
@@ -1,4 +1,4 @@
1
- import { watchRuntimeTelemetry } from './runtime-telemetry.js';
1
+ import { watchRuntimeTelemetry } from './telemetry.js';
2
2
  export default class Ports {
3
3
  constructor(okra, telemetry) {
4
4
  this.okra = okra;
package/dist/runtime.d.ts CHANGED
@@ -2,7 +2,7 @@ import type { Action, NotebookInstance } from './index.js';
2
2
  import Logs, { type RuntimeLogEntry } from './log.js';
3
3
  import Metrics from './metrics.js';
4
4
  import Ports from './ports.js';
5
- import { type RuntimeTelemetryFeature, type RuntimeWatchOptions } from './runtime-telemetry.js';
5
+ import { type RuntimeTelemetryFeature, type RuntimeWatchOptions } from './telemetry.js';
6
6
  export interface PortInfo {
7
7
  subdomain: string;
8
8
  url: string;
package/dist/runtime.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import Logs from './log.js';
2
2
  import Metrics from './metrics.js';
3
3
  import Ports from './ports.js';
4
- import { RuntimeTelemetry, } from './runtime-telemetry.js';
4
+ import { RuntimeTelemetry, } from './telemetry.js';
5
5
  export class RuntimeMetrics {
6
6
  constructor(metrics) {
7
7
  this.metrics = metrics;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@phpsandbox/sdk",
3
- "version": "0.1.13",
4
- "description": "A comprehensive TypeScript SDK for interacting with cloud-based PHP development environments",
3
+ "version": "0.1.15",
4
+ "description": "The TypeScript SDK for PHPSandbox cloud development environments",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -20,8 +20,6 @@
20
20
  },
21
21
  "files": [
22
22
  "dist",
23
- "docs",
24
- "examples",
25
23
  "README.md",
26
24
  "LICENSE"
27
25
  ],
@@ -42,10 +40,8 @@
42
40
  "smoke:feedback-widget": "npm run build:tsc && vitest run --reporter=verbose --config tests/smoke/vitest.config.ts tests/smoke/integrations/feedback-widget.smoke.ts",
43
41
  "smoke:reaper": "npm run build:tsc && vitest run --reporter=verbose --config tests/smoke/vitest.config.ts tests/smoke/maintenance/resources.reaper.smoke.ts",
44
42
  "smoke:typecheck": "npm run build:tsc && tsc --project tests/smoke/tsconfig.json --noEmit",
45
- "check:examples": "tsc --noEmit --module NodeNext --moduleResolution NodeNext --target ES2020 --types node --skipLibCheck --allowSyntheticDefaultImports --esModuleInterop examples/basic.ts examples/publish-cloudflare-container.ts examples/publish-laravel-cloud.ts examples/publish-ssh-agent.ts examples/get.ts examples/git-merge-smoke.ts examples/laravel-load-test.ts examples/notebook-readonly-smoke.ts",
46
- "prepublishOnly": "npm test && npm run check:examples && npm run check:docs && npm run clean && npm run build",
47
- "bumpAndPublish": "npm version patch && npm publish --access public",
48
- "check:docs": "npm run build:tsc && node tools/check-documentation.mjs"
43
+ "prepublishOnly": "npm test && npm run clean && npm run build",
44
+ "bumpAndPublish": "npm version patch && npm publish --access public"
49
45
  },
50
46
  "keywords": [
51
47
  "php",
@@ -86,6 +82,6 @@
86
82
  "esbuild": "^0.27.1",
87
83
  "playwright": "^1.62.1",
88
84
  "typescript": "^5.7.2",
89
- "vitest": "^4.1.8"
85
+ "vitest": "^4.1.11"
90
86
  }
91
87
  }
@@ -1,181 +0,0 @@
1
- # PHPSandbox SDK API Summary
2
-
3
- This is a quick reference for the current SDK surface.
4
-
5
- ## Top-Level Client
6
-
7
- ```ts
8
- import { PHPSandbox } from '@phpsandbox/sdk';
9
-
10
- const client = PHPSandbox.realtime(token, 'https://api.phpsandbox.io/v1', {
11
- debug: false,
12
- });
13
-
14
- const restClient = PHPSandbox.rest(token, 'https://api.phpsandbox.io/v1', {
15
- runtimeUrlProvider: async (notebookId) => getFreshRuntimeUrl(notebookId),
16
- });
17
- ```
18
-
19
- Connection lifecycle methods, streaming actions, and event subscriptions require the realtime transport. The REST transport rejects unsupported operations without falling back to a websocket.
20
-
21
- ### `NotebookApi`
22
-
23
- - `create(template, input?)`
24
- - `get(id)`
25
- - `open(data)`
26
-
27
- ## `NotebookInstance`
28
-
29
- - Lifecycle: `ready()`, `connected()`, `reconnect()`, `dispose()`
30
- - Notebook actions: `fork(input?)`, `destroy()`, `stop()`, `restart()`
31
- - Processes: `exec(command, args?, options?)`, or `run(command, args?, options?)` returning native `stdin`, `stdout`, `stderr`, ordered `output`, `wait()`, and `kill()`
32
- - Events: `listen(event, handler)`, `onDidConnect(handler)`, `onDidDisconnect(handler)`, `onDidInitialize(handler)`
33
- - Raw call: `invoke(action, data?, options?)`
34
-
35
- ## Services
36
-
37
- ### Filesystem (`notebook.files`)
38
-
39
- - File data: `read()`, `readText()`, `readStream()`, `write()`, `tail()`, `stat()`, `exists()`
40
- - File management: `move()`, `copy()`, `remove()`
41
- - Directory: `createDirectory()`, `list()`, `tree()`
42
- - Search: `find()`, `search()`
43
- - Streaming/monitoring: `readStream()`, `watch()`, `download()`
44
- - `tail()` is an eager last-lines snapshot; it does not follow future appends.
45
-
46
- ### Terminal (`notebook.terminals`)
47
-
48
- - `list()` returns terminal metadata
49
- - `create(options?)` returns a terminal handle
50
- - `attach(id, options?)` returns a terminal handle
51
- - Handles expose `input`, `output`, `wait()`, `resize()`, and `kill()`
52
-
53
- ### Notebook lifecycle
54
-
55
- - `notebook.stop()`, `notebook.restart()`
56
-
57
- ### Runtime (`notebook.runtime`)
58
-
59
- - Runtime configuration: `setPhpVersion(version)`
60
-
61
- ### Runtime observability
62
-
63
- - `notebook.runtime.logs.follow({ signal? })` returns `ReadableStream<RuntimeLogEntry>`
64
- - `notebook.runtime.ports.list()` returns the current preview ports
65
- - `notebook.runtime.ports.resolve(port)` returns preview routing information even when the port is not open
66
- - `notebook.runtime.ports.watch({ signal? })` returns `ReadableStream<PortInfo[]>`
67
- - `notebook.runtime.metrics.current()` returns the current CPU, memory, and disk sample
68
- - `notebook.runtime.metrics.watch({ signal? })` returns `ReadableStream<RuntimeStats>`
69
-
70
- ### Processes
71
-
72
- - `notebook.run(command, args?, options?)` returns a streaming process handle
73
- - `notebook.exec(command, args?, options?)` returns a buffered `ProcessResult` for one-shot commands
74
- - Process handles expose `output`, `stdout`, `stderr`, `stdin`, `wait()`, and `kill()`
75
-
76
- ### Services (`notebook.services`)
77
-
78
- - Constants: `notebookBuiltinServices`, `notebookKnownServices`
79
- - `list()`
80
- - `run(name, command?)`
81
- - `stop(name)`
82
- - `logs(name, { tail? })`
83
- - `logs(name, { follow: true, tail?, id? })` returning `ReadableStream<string>`; cancel the stream to stop following
84
-
85
- ### Composer (`notebook.composer`)
86
-
87
- - `run(command, args?, options?)`
88
- - `packages()`
89
- - Command handles expose `output`, `stdout`, `stderr`, `wait()`, and `kill()`
90
-
91
- ### Git (`notebook.git`)
92
-
93
- - `checkpoint(author, message, branch = 'main')`
94
- - `targets.create({ provider, repository, author, branch?, setDefault? })`
95
- - `targets.list()`, `targets.get(target)`, and `target.sync({ direction?, author? })`
96
- - `diff({ notebookId?, url?, token?, ref?, base?, target?, patch? })`
97
- - `merge({ notebookId?, url?, token?, ref?, target?, expectedBaseRef?, author?, message? })`
98
- - `conflicts()`
99
- - `abortMerge()`
100
- - `continueMerge(author, message?)`
101
- - `review()`
102
- - `stage({ path?, paths?, all? })`
103
- - `unstage({ path?, paths?, all? })`
104
- - `revert({ path?, paths?, all?, staged? })`
105
- - `log(ref = 'main')`
106
- - `restore(ref)`
107
-
108
- ### Sandbox integrations (`notebook.integrations`)
109
-
110
- - `attach({ integration, effects? })`
111
- - A sandbox has one attached integration per provider. `binding.update({ integration })` replaces that provider selection.
112
- - Provider-backed operations resolve the attached integration when they run; persistent sandbox behavior remains controlled by explicit effects.
113
- - `list()`
114
- - `get(binding)`
115
- - Binding resources expose `update({ effects })` and `detach()`
116
- - The currently supported sandbox effect is GitHub `network`; effects are explicit and provider-specific.
117
-
118
- ### Mail (`notebook.mail`)
119
-
120
- - `status()` returning non-sensitive mail configuration state
121
- - `enable()` enabling SMTP env injection for the notebook
122
- - `disable()` disabling SMTP env injection and revoking the active SMTP token
123
- - `list({ page? })` returning paginated notebook mail
124
- - `get(hash)`
125
- - `delete(hash)`
126
-
127
- ### Feedback (`sandbox.feedback`)
128
-
129
- - `configure({ widget })`, where `widget` is `null` or contains `targets`, optional `label`, and optional `types`
130
- - `submit({ type, message, author?, context?, metadata? })`
131
- - `list({ type?, status?, source?, page? })`
132
- - `get(id)`
133
- - `update(id, { status })`
134
-
135
- Feedback ingestion is always available through the authenticated API. Configuration controls only the optional widget and can target `preview`, `publication`, or both.
136
-
137
- ### LSP (`notebook.lsp`)
138
-
139
- - Messaging: `start(id)`, `close(id)`, `message(id, payload)`
140
- - Events: `onResponse()`, `onError()`, `onClose()`, `onClientDisconnect()`
141
- - Connection wrapper: `connection(id)`
142
-
143
- ### REPL (`notebook.repl`)
144
-
145
- - `stop()`, `eval(code, args?, replOpts?)`, `write(input)`, `resize(cols, rows)`
146
- - Events: `listen()`, `onOutput()`
147
-
148
- ### Auth (`notebook.auth`)
149
-
150
- - `login(runtimeUrl)` using a fresh ticket-bearing runtime URL
151
-
152
- ## Publications
153
-
154
- - `notebook.publish({ slug, provider, protection?, metadata? })`
155
- - `notebook.publication()` returns the current publication or `null`
156
- - `client.publications.get(id)` returns a publication reference.
157
- - Publication references expose `refresh()`, `destroy()`, `events()`, `logs()`, `buildLogs()`, and protection operations.
158
- - A publish run exposes `events()` as an `AsyncIterable`, `result()` with the final status and URL, and `publication()` when refreshed deployment state is needed.
159
- - Built-in provider names are `cloudflare-containers`, `ssh-server`, and `laravel-cloud`. Provider maps support TypeScript declaration merging.
160
- - Cloudflare Containers input uses `{ name: 'cloudflare-containers', accountId, size?, sleepAfter?, placement?, instances? }` and resolves the sandbox's attached Cloudflare integration when each operation runs.
161
- - Laravel Cloud input uses `{ name: 'laravel-cloud', region }` and resolves the sandbox's attached Laravel Cloud integration when each operation runs.
162
-
163
- ## Account integrations
164
-
165
- - `client.integrations.link({ provider, label?, authorization })`
166
- - `client.integrations.list()` and `get(integration)`
167
- - Resource instances expose `update(input)` and `unlink()`.
168
- - Built-in providers are `cloudflare`, `github`, and `laravel-cloud`; current public authorization uses opaque caller-managed tokens.
169
-
170
- ## Common Errors
171
-
172
- - `RemoteError` when Core or the notebook runtime returns a structured failure
173
- - `RemoteError.is(error, code)` for exact conditions such as `FileNotFound` and `RateLimited`
174
- - `RemoteError.isValidation(error)` for typed validation details
175
- - `TransportError` when no valid remote response is received
176
-
177
- ## Notes for Consumers
178
-
179
- - Runtime actions wait for readiness before their handlers run.
180
- - Call `ready()` explicitly when you need provisioning metadata or initialization errors before another action.
181
- - Always call `notebook.dispose()` when finished.
package/docs/cdn-usage.md DELETED
@@ -1,68 +0,0 @@
1
- # Browser/CDN usage
2
-
3
- The SDK includes ESM and script-tag browser bundles. Browser support is a packaging capability, not permission to expose an account API key.
4
-
5
- ## Choose a trust boundary
6
-
7
- For public applications, keep the SDK on your backend. Authenticate your application users and authorize the sandbox and operation before making SDK calls. Do not expose a generic proxy for arbitrary management or runtime operations.
8
-
9
- There is no public SDK API for minting short-lived account keys. Never embed a `psb_` API key in a page, frontend environment variable, local storage, or CDN example.
10
-
11
- A trusted workspace can receive a notebook-specific runtime URL from its backend. That URL contains a bearer ticket and grants access to the sandbox runtime. Only give it to a user you trust to access that sandbox; it is not a preview link. Use preview sessions or handoffs for application review.
12
-
13
- ## Trusted workspace example (ESM)
14
-
15
- The `/api/sandbox-session` endpoint below belongs to **your application** and must be implemented on your backend. It must authenticate the user, authorize access to the selected notebook, retrieve fresh notebook data using your server-side API key, and return `id`, `gitUrl`, and `runtimeUrl` with `Cache-Control: no-store`. Never return the account API key. Do not accept arbitrary notebook IDs without authorization.
16
-
17
- ```html
18
- <script type="module">
19
- import { PHPSandbox } from 'https://cdn.jsdelivr.net/npm/@phpsandbox/sdk@0.1.9/dist/browser/phpsandbox-sdk.esm.min.js';
20
-
21
- async function getSession() {
22
- const response = await fetch('/api/sandbox-session', {
23
- credentials: 'same-origin',
24
- cache: 'no-store',
25
- });
26
- if (!response.ok) throw new Error(`Sandbox session failed: ${response.status}`);
27
- return response.json();
28
- }
29
-
30
- // No account token in this client. Management calls stay on your backend.
31
- const client = PHPSandbox.realtime('', undefined, {
32
- runtimeUrlProvider: async () => (await getSession()).runtimeUrl,
33
- });
34
- const notebook = client.notebook.open(await getSession());
35
-
36
- const result = await notebook.exec('php', ['-v']);
37
- if (result.exitCode !== 0) throw new Error(result.stderr || result.output);
38
- document.querySelector('#output').textContent = result.stdout;
39
- notebook.dispose();
40
- </script>
41
- <pre id="output"></pre>
42
- ```
43
-
44
- `open()` creates a runtime handle without requesting notebook data from Core. Do not call `client.notebook.create()`, `get()`, or other management methods with this tokenless client. Refresh the same authorized notebook's ticket through your backend when reconnecting. Never log session responses or runtime URLs.
45
-
46
- ## Script tag (IIFE)
47
-
48
- ```html
49
- <script src="https://unpkg.com/@phpsandbox/sdk@0.1.9/dist/browser/phpsandbox-sdk.iife.min.js"></script>
50
- <script>
51
- // The IIFE namespace contains the exported PHPSandbox class.
52
- const client = PHPSandbox.PHPSandbox.realtime('');
53
- // Use the same authorized backend session and open flow shown above.
54
- </script>
55
- ```
56
-
57
- ## Version pinning
58
-
59
- These URLs pin `0.1.9`. Use the version you have tested when upgrading; avoid unversioned or `latest` URLs. Both CDNs serve the same package files:
60
-
61
- - `dist/browser/phpsandbox-sdk.esm.js`
62
- - `dist/browser/phpsandbox-sdk.esm.min.js`
63
- - `dist/browser/phpsandbox-sdk.iife.js`
64
- - `dist/browser/phpsandbox-sdk.iife.min.js`
65
-
66
- ## Browser requirements
67
-
68
- Use a modern browser with `fetch`, `WebSocket`, `ReadableStream`, `WritableStream`, `TextEncoder`, `TextDecoder`, and `AbortController`. ES2020 syntax support alone does not supply these web APIs. Your application's CSP must permit the CDN script and the authorized runtime connection.