@phpsandbox/sdk 0.0.16 → 0.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,46 +1,6 @@
1
1
  # PHPSandbox SDK
2
2
 
3
- A comprehensive TypeScript SDK for interacting with cloud-based PHP development environments. The PHPSandbox SDK provides programmatic access to containerized PHP environments with full filesystem, terminal, and development tool integration.
4
-
5
- ## Table of Contents
6
-
7
- - [PHPSandbox SDK](#phpsandbox-sdk)
8
- - [Table of Contents](#table-of-contents)
9
- - [Installation](#installation)
10
- - [Quick Start](#quick-start)
11
- - [Authentication](#authentication)
12
- - [Core Concepts](#core-concepts)
13
- - [Client](#client)
14
- - [NotebookInstance](#notebookinstance)
15
- - [Event-Driven Architecture](#event-driven-architecture)
16
- - [API Reference](#api-reference)
17
- - [Client](#client-1)
18
- - [NotebookApi Methods](#notebookapi-methods)
19
- - [NotebookInstance](#notebookinstance-1)
20
- - [Filesystem](#filesystem)
21
- - [File Search Example](#file-search-example)
22
- - [Terminal](#terminal)
23
- - [Terminal Usage Example](#terminal-usage-example)
24
- - [Container](#container)
25
- - [Language Server Protocol (LSP)](#language-server-protocol-lsp)
26
- - [Composer](#composer)
27
- - [Git](#git)
28
- - [Laravel](#laravel)
29
- - [REPL](#repl)
30
- - [Shell](#shell)
31
- - [Auth](#auth)
32
- - [Logging](#logging)
33
- - [Event System](#event-system)
34
- - [Error Handling](#error-handling)
35
- - [Common Error Types](#common-error-types)
36
- - [Examples](#examples)
37
- - [Complete Laravel Application Setup](#complete-laravel-application-setup)
38
- - [File Processing Pipeline](#file-processing-pipeline)
39
- - [Real-time Development Environment](#real-time-development-environment)
40
- - [TypeScript Support](#typescript-support)
41
- - [Generic Types](#generic-types)
42
- - [Support and Contributing](#support-and-contributing)
43
- - [License](#license)
3
+ TypeScript SDK for working with PHPSandbox notebooks: create environments, edit files, run commands, and stream real-time events.
44
4
 
45
5
  ## Installation
46
6
 
@@ -48,691 +8,222 @@ A comprehensive TypeScript SDK for interacting with cloud-based PHP development
48
8
  npm install @phpsandbox/sdk
49
9
  ```
50
10
 
11
+ Node.js `>=18` is required.
12
+
51
13
  ## Quick Start
52
14
 
53
- ```typescript
15
+ ```ts
54
16
  import { PHPSandbox } from '@phpsandbox/sdk';
55
17
 
56
- // Create a client instance
57
- const client = new PHPSandbox('your-api-token');
58
-
59
- // Create and initialize a new notebook
60
- const notebook = await client.notebook.create('laravel');
18
+ const token = process.env.PHPSANDBOX_TOKEN;
19
+ if (!token) throw new Error('Missing PHPSANDBOX_TOKEN');
61
20
 
62
- // Access various services
63
- const files = notebook.file;
64
- const terminal = notebook.terminal;
65
- const container = notebook.container;
21
+ const client = new PHPSandbox(token);
66
22
 
67
- // Write a PHP file
68
- await files.write('index.php', '<?php echo "Hello World!"; ?>');
23
+ // create() initializes the notebook by default
24
+ const notebook = await client.notebook.create('php');
69
25
 
70
- // Execute a command
71
- const process = await terminal.spawn('php', ['index.php']);
72
- process.output
73
- .getReader()
74
- .read()
75
- .then(({ value }) => {
76
- console.log(value); // "Hello World!"
77
- });
78
- ```
79
-
80
- ## Authentication
26
+ await notebook.file.write('index.php', '<?php echo "Hello from PHPSandbox";');
81
27
 
82
- The SDK requires an API token for authentication:
28
+ const process = await notebook.terminal.spawn('php', ['index.php']);
83
29
 
84
- ```typescript
85
- // Using environment variable (recommended)
86
- const client = new PHPSandbox(process.env.PHPSANDBOX_TOKEN);
30
+ const reader = process.output.getReader();
31
+ let output = '';
32
+ try {
33
+ while (true) {
34
+ const { done, value } = await reader.read();
35
+ if (done) break;
36
+ output += value;
37
+ }
38
+ } finally {
39
+ reader.releaseLock();
40
+ }
87
41
 
88
- // Or direct token
89
- const client = new PHPSandbox('your-token-here');
42
+ await process.exit;
43
+ console.log(output.trim());
90
44
 
91
- // Custom API URL (optional)
92
- const client = new PHPSandbox('token', 'https://api.phpsandbox.io/v1');
45
+ // close websocket resources when done
46
+ notebook.dispose();
93
47
  ```
94
48
 
95
- ## Core Concepts
96
-
97
- ### Client
49
+ ## Authentication
98
50
 
99
- The main entry point for the SDK. Handles authentication and provides access to notebook management.
51
+ Use an API token:
100
52
 
101
- ### NotebookInstance
53
+ ```ts
54
+ import { PHPSandbox } from '@phpsandbox/sdk';
102
55
 
103
- Represents a containerized PHP environment with access to all development tools:
56
+ const client = new PHPSandbox(process.env.PHPSANDBOX_TOKEN!);
57
+ ```
104
58
 
105
- - **Filesystem**: File operations, search, and monitoring
106
- - **Terminal**: Interactive terminal and process execution
107
- - **Container**: Environment management and monitoring
108
- - **LSP**: Language server integration for IDE features
109
- - **Development Tools**: Composer, Git, Laravel tooling, REPL
59
+ Optional constructor args:
110
60
 
111
- ### Event-Driven Architecture
61
+ ```ts
62
+ new PHPSandbox('token', 'https://api.phpsandbox.io/v1', {
63
+ debug: false,
64
+ startClosed: true,
65
+ });
66
+ ```
112
67
 
113
- The SDK uses WebSocket connections for real-time communication and events.
68
+ ## Notebook Lifecycle
114
69
 
115
- ## API Reference
70
+ ```ts
71
+ const client = new PHPSandbox(process.env.PHPSANDBOX_TOKEN!);
116
72
 
117
- ### Client
73
+ const created = await client.notebook.create('laravel');
74
+ const opened = await client.notebook.open('notebook-id');
75
+ await opened.ready();
118
76
 
119
- ```typescript
120
- class PHPSandbox {
121
- constructor(token: string, url?: string, options?: PHPSandboxClientOptions);
77
+ const fetched = await client.notebook.get('notebook-id');
78
+ await fetched.ready();
122
79
 
123
- readonly notebook: NotebookApi;
124
- readonly http: AxiosInstance;
125
- }
80
+ const forked = await created.fork();
81
+ await forked.delete();
126
82
  ```
127
83
 
128
- #### NotebookApi Methods
84
+ Notes:
129
85
 
130
- ```typescript
131
- // Create a new notebook from a template
132
- create(template: string, input?: Partial<CreateNotebookInput>, init?: boolean): Promise<NotebookInstance>
86
+ - `create()` and `fork()` initialize automatically.
87
+ - `open()` and `get()` return a notebook instance; call `await notebook.ready()` before using tools.
133
88
 
134
- // Get existing notebook by ID
135
- get(id: string): Promise<NotebookInstance>
89
+ ## Services At A Glance
136
90
 
137
- // Fork an existing notebook
138
- fork(id: string): Promise<NotebookInstance>
91
+ Each `NotebookInstance` exposes service clients:
139
92
 
140
- // Open and initialize a notebook
141
- open(id: string): Promise<NotebookInstance>
93
+ - `notebook.file` (`Filesystem`)
94
+ - `notebook.terminal` (`Terminal`)
95
+ - `notebook.container` (`Container`)
96
+ - `notebook.shell` (`Shell`)
97
+ - `notebook.composer` (`Composer`)
98
+ - `notebook.git` (`Git`)
99
+ - `notebook.lsp` (`Lsp`)
100
+ - `notebook.repl` (`Repl`)
101
+ - `notebook.laravel` (`Laravel`)
102
+ - `notebook.auth` (`Auth`)
103
+ - `notebook.log` (`Log`)
142
104
 
143
- // Create from existing data
144
- openFromData(data: NotebookData): Promise<NotebookInstance>
145
- ```
105
+ ## Common Operations
146
106
 
147
- #### Create Notebook from GitHub Repository
148
-
149
- ```typescript
150
- const notebook = await client.notebook.create(
151
- 'php',
152
- {
153
- title: 'Imported Repo',
154
- import: {
155
- provider: 'github',
156
- repo: 'https://github.com/acme/private-repo.git',
157
- branch: 'main',
158
- auth: {
159
- access_token: process.env.GITHUB_TOKEN!,
160
- },
161
- },
162
- },
163
- false
164
- );
165
- ```
107
+ ### Files
166
108
 
167
- ### NotebookInstance
168
-
169
- The core class providing access to all development environment features.
170
-
171
- ```typescript
172
- class NotebookInstance {
173
- // Core services
174
- readonly file: Filesystem;
175
- readonly terminal: Terminal;
176
- readonly container: Container;
177
- readonly lsp: Lsp;
178
- readonly composer: Composer;
179
- readonly git: Git;
180
- readonly laravel: Laravel;
181
- readonly repl: Repl;
182
- readonly shell: Shell;
183
- readonly auth: Auth;
184
- readonly log: Log;
185
-
186
- // Connection management
187
- ready(): Promise<NotebookInitResult>;
188
- connected(): Promise<NotebookInstance>;
189
- reconnect(): void;
190
- dispose(): void;
191
-
192
- // Event handling
193
- listen<T extends keyof Events>(event: T, handler: (data: Events[T]) => void): Disposable;
194
- onDidConnect(handler: () => void): Disposable;
195
- onDidDisconnect(handler: () => void): Disposable;
196
-
197
- // Direct API calls
198
- invoke<T extends keyof Invokable>(
199
- action: T,
200
- data?: Invokable[T]['args'],
201
- options?: CallOption
202
- ): Promise<Invokable[T]['response']>;
203
- }
204
- ```
205
-
206
- ### Filesystem
207
-
208
- Comprehensive file system operations with advanced search and monitoring capabilities.
209
-
210
- ```typescript
211
- class Filesystem {
212
- // File operations
213
- readFile(path: string, lineRange?: { lineStart: number; lineEnd: number }): Promise<Uint8Array | ReadFileRangeResult>;
214
- writeFile(path: string, contents: Uint8Array, options: FileWriteOptions): Promise<void>;
215
- info(path: string): Promise<FileInfo>;
216
- stat(path: string): Promise<Stats>;
217
- exists(path: string): Promise<boolean>;
218
-
219
- // Directory operations
220
- createDirectory(path: string): Promise<void>;
221
- readDirectory(path: string, include?: string[], exclude?: string[]): Promise<[string, FileType, number | null][]>;
222
-
223
- // File management
224
- copy(source: string, destination: string, options: FileOverwriteOptions): Promise<void>;
225
- move(from: string, to: string): Promise<boolean>;
226
- rename(from: string, to: string, options: FileOverwriteOptions): Promise<void>;
227
- delete(path: string, options: FileDeleteOptions): Promise<void>;
228
-
229
- // Search capabilities
230
- find(query: string, options?: Partial<FileSearchOptions>): Promise<FileResult[]>;
231
- search(
232
- query: TextSearchQuery,
233
- options?: Partial<TextSearchOptions>,
234
- onMatch?: (result: TextSearchResult | false) => void
235
- ): Promise<[boolean, TextSearchMatch[]]>;
236
-
237
- // File monitoring
238
- watch(path: string, options: WatchOptions, onDidChange: (e: FileChange) => void): FilesystemSubscription;
239
-
240
- // Bulk operations
241
- download(chunk?: (data: Uint8Array) => void, exclude?: string[]): Promise<Blob>;
242
- }
243
- ```
109
+ ```ts
110
+ await notebook.file.write('README.md', '# App');
244
111
 
245
- #### File Search Example
112
+ const raw = await notebook.file.readFile('README.md');
113
+ const text = new TextDecoder().decode(raw);
246
114
 
247
- ```typescript
248
- // Find files by name
249
- const phpFiles = await notebook.file.find('*.php', {
250
- includes: ['src/**'],
115
+ const files = await notebook.file.find('*.php', {
116
+ includes: ['app/**'],
251
117
  excludes: ['vendor/**'],
252
- useIgnoreFiles: true,
253
118
  });
254
119
 
255
- // Full-text search with context
256
120
  const [hasMore, matches] = await notebook.file.search(
257
- { pattern: 'function.*authenticate', isRegExp: true },
258
- { maxResults: 50, beforeContext: 2, afterContext: 2 }
121
+ { pattern: 'class\\s+User', isRegExp: true },
122
+ { maxResults: 20, includes: ['app/**'], excludes: ['vendor/**'] }
259
123
  );
260
124
  ```
261
125
 
262
126
  ### Terminal
263
127
 
264
- Interactive terminal with process execution and stream handling.
265
-
266
- ```typescript
267
- class Terminal {
268
- // Terminal management
269
- create(input: TerminalCreateInput): Promise<Task>;
270
- list(): Promise<Task[]>;
271
- resize(id: string, size: [number, number]): Promise<boolean>;
272
- input(id: string, input: string): Promise<void>;
273
-
274
- // Process execution
275
- spawn(command: string, args: string[], opts?: SpawnOptions): Promise<SandboxProcess & Task>;
276
-
277
- // Event handling
278
- onStarted(handler: (task: Task) => void): void;
279
- onOutput(id: string, handler: (data: TerminalEvents['terminal.output']) => void): void;
280
- listen<T extends keyof TerminalEvents>(event: T, handler: (data: TerminalEvents[T]) => void): Disposable;
281
- }
282
- ```
283
-
284
- #### Terminal Usage Example
128
+ ```ts
129
+ const task = await notebook.terminal.spawn('composer', ['--version']);
285
130
 
286
- ```typescript
287
- // Spawn a process with I/O streams
288
- const process = await notebook.terminal.spawn('composer', ['install'], {
289
- cwd: '/app',
290
- env: { COMPOSER_NO_INTERACTION: '1' },
291
- });
292
-
293
- // Handle output stream
294
- const reader = process.output.getReader();
295
- while (true) {
296
- const { done, value } = await reader.read();
297
- if (done) break;
131
+ task.output.getReader().read().then(({ value }) => {
298
132
  console.log(value);
299
- }
300
-
301
- // Wait for completion
302
- const exitCode = await process.exit;
303
- console.log(`Process exited with code: ${exitCode}`);
304
- ```
305
-
306
- ### Container
307
-
308
- Container lifecycle and resource management.
309
-
310
- ```typescript
311
- class Container {
312
- // Container control
313
- start(): Promise<void>;
314
- stop(): Promise<void>;
315
- state(): Promise<{ state: NotebookState }>;
316
-
317
- // Port management
318
- openedPorts(): Promise<PortInfo[]>;
319
- onPort(handler: (port: PortInfo, type: 'open' | 'close') => void): Disposable;
320
-
321
- // Environment configuration
322
- setPhp(version: string): Promise<{ version: string }>;
133
+ });
323
134
 
324
- // Resource monitoring
325
- listen<T extends keyof ContainerEvents>(event: T, handler: (data: ContainerEvents[T]) => void): void;
326
- }
135
+ const exitCode = await task.exit;
136
+ console.log(exitCode);
327
137
  ```
328
138
 
329
- ### Language Server Protocol (LSP)
330
-
331
- IDE-like features through Language Server Protocol integration.
332
-
333
- ```typescript
334
- class Lsp {
335
- // Connection management
336
- connection(id: string): LspConnection;
337
- start(id: string): Promise<void>;
338
- close(id: string): Promise<void>;
339
-
340
- // Communication
341
- message(id: string, message: string): Promise<void>;
342
-
343
- // Event handling
344
- onResponse(id: string, cb: (data: string) => void): void;
345
- onError(id: string, cb: (message: string) => void): void;
346
- onClose(id: string, cb: (code: number, reason: string) => void): void;
347
- }
139
+ ### Shell
348
140
 
349
- class LspConnection {
350
- send(content: string): Promise<void>;
351
- onMessage(cb: (data: string) => void): void;
352
- onError(cb: (message: string) => void): void;
353
- onClose(cb: (code: number, reason: string) => void): void;
354
- start(): Promise<void>;
355
- dispose(): void;
356
- }
141
+ ```ts
142
+ const result = await notebook.shell.exec('php -v');
143
+ result.throw();
144
+ console.log(result.output);
357
145
  ```
358
146
 
359
147
  ### Composer
360
148
 
361
- PHP dependency management integration.
362
-
363
- ```typescript
364
- class Composer {
365
- // Package management
366
- install(packages?: string[]): Promise<void>;
367
- update(packages?: string[]): Promise<void>;
368
- remove(packages: string[]): Promise<void>;
149
+ ```ts
150
+ await notebook.composer.install({ noInteraction: true });
151
+ await notebook.composer.require({ packages: ['monolog/monolog'] });
369
152
 
370
- // Project operations
371
- init(options?: ComposerInitOptions): Promise<void>;
372
- validate(): Promise<void>;
373
-
374
- // Information
375
- show(package?: string): Promise<object>;
376
- outdated(): Promise<object>;
377
-
378
- // Event handling
379
- listen<T extends keyof ComposerEvents>(event: T, handler: (data: ComposerEvents[T]) => void): Disposable;
380
- }
153
+ const installed = await notebook.composer.packages();
154
+ console.log(installed.map((pkg) => pkg.name));
381
155
  ```
382
156
 
383
157
  ### Git
384
158
 
385
- Version control operations and repository management.
386
-
387
- ```typescript
388
- class Git {
389
- // Repository operations
390
- init(): Promise<void>;
391
- clone(url: string, directory?: string): Promise<void>;
392
-
393
- // Branch management
394
- branch(name?: string): Promise<string[] | void>;
395
- checkout(branch: string): Promise<void>;
396
-
397
- // Staging and commits
398
- add(files: string[]): Promise<void>;
399
- commit(message: string): Promise<void>;
400
- push(remote?: string, branch?: string): Promise<void>;
401
- pull(remote?: string, branch?: string): Promise<void>;
402
-
403
- // Information
404
- status(): Promise<GitStatus>;
405
- log(options?: GitLogOptions): Promise<GitCommit[]>;
406
- diff(options?: GitDiffOptions): Promise<string>;
407
-
408
- // Event handling
409
- listen<T extends keyof GitEvents>(event: T, handler: (data: GitEvents[T]) => void): Disposable;
410
- }
411
- ```
412
-
413
- ### Laravel
414
-
415
- Laravel-specific development tools and utilities.
416
-
417
- ```typescript
418
- class Laravel {
419
- // Artisan commands
420
- artisan(command: string, args?: string[]): Promise<void>
421
-
422
- // Code generation
423
- make(type: string, name: string, options?: object): Promise<void>
424
-
425
- // Database operations
426
- migrate(options?: MigrateOptions): Promise<void>
427
- seed(class?: string): Promise<void>
428
-
429
- // Cache management
430
- cache(action: 'clear' | 'config' | 'route' | 'view'): Promise<void>
431
-
432
- // Event handling
433
- listen<T extends keyof LaravelEvents>(event: T, handler: (data: LaravelEvents[T]) => void): Disposable
434
- }
435
- ```
436
-
437
- ### REPL
438
-
439
- Interactive PHP execution environment.
440
-
441
- ```typescript
442
- class Repl {
443
- // Code execution
444
- execute(code: string): Promise<ReplResult>;
159
+ ```ts
160
+ await notebook.git.checkpoint('Jane Doe <jane@example.com>', 'Initial checkpoint');
445
161
 
446
- // Session management
447
- reset(): Promise<void>;
448
-
449
- // Variable inspection
450
- variables(): Promise<object>;
451
-
452
- // Event handling
453
- listen<T extends keyof ReplEvents>(event: T, handler: (data: ReplEvents[T]) => void): Disposable;
454
- }
455
- ```
456
-
457
- ### Shell
458
-
459
- Shell command execution with customizable environments.
460
-
461
- ```typescript
462
- class Shell {
463
- // Command execution
464
- execute(command: string, options?: ShellOptions): Promise<ShellResult>;
465
-
466
- // Environment management
467
- setEnv(variables: Record<string, string>): Promise<void>;
468
- getEnv(): Promise<Record<string, string>>;
469
-
470
- // Working directory
471
- pwd(): Promise<string>;
472
- cd(directory: string): Promise<void>;
473
-
474
- // Event handling
475
- listen<T extends keyof ShellEvents>(event: T, handler: (data: ShellEvents[T]) => void): Disposable;
476
- }
477
- ```
478
-
479
- ### Auth
480
-
481
- Authentication and authorization services.
482
-
483
- ```typescript
484
- class Auth {
485
- // Token management
486
- login(credentials: LoginCredentials): Promise<AuthResult>;
487
- logout(): Promise<void>;
488
- refresh(): Promise<AuthResult>;
489
-
490
- // User information
491
- user(): Promise<User>;
492
-
493
- // Permissions
494
- can(permission: string): Promise<boolean>;
495
- }
496
- ```
497
-
498
- ### Logging
499
-
500
- Application logging and monitoring.
501
-
502
- ```typescript
503
- class Log {
504
- // Log levels
505
- debug(message: string, context?: object): Promise<void>;
506
- info(message: string, context?: object): Promise<void>;
507
- warning(message: string, context?: object): Promise<void>;
508
- error(message: string, context?: object): Promise<void>;
509
-
510
- // Log retrieval
511
- recent(limit?: number): Promise<LogEntry[]>;
512
- search(query: string, options?: LogSearchOptions): Promise<LogEntry[]>;
162
+ await notebook.git.sync(
163
+ 'https://github.com/acme/my-repo.git',
164
+ 'Jane Doe <jane@example.com>',
165
+ 'main',
166
+ process.env.GITHUB_TOKEN,
167
+ 'pull'
168
+ );
513
169
 
514
- // Event handling
515
- listen<T extends keyof LogEvents>(event: T, handler: (data: LogEvents[T]) => void): Disposable;
516
- }
170
+ const history = await notebook.git.log('main');
171
+ console.log(history[0]);
517
172
  ```
518
173
 
519
- ## Event System
520
-
521
- The SDK provides a comprehensive event system for real-time updates:
522
-
523
- ```typescript
524
- // File system events
525
- notebook.file.watch('/app', { recursive: true }, (change) => {
526
- console.log(`File ${change.path} was ${change.type}`);
527
- });
528
-
529
- // Terminal output
530
- notebook.terminal.onOutput('terminal-id', (data) => {
531
- console.log(data.output);
532
- });
174
+ ### Events
533
175
 
534
- // Container stats
535
- notebook.container.listen('container.stats', (stats) => {
536
- console.log(`CPU: ${stats.cpu.usage}/${stats.cpu.limit}`);
176
+ ```ts
177
+ const disposeConnect = notebook.onDidConnect(() => {
178
+ console.log('connected');
537
179
  });
538
180
 
539
- // Connection events
540
- notebook.onDidConnect(() => {
541
- console.log('Connected to notebook');
542
- });
181
+ const disposeFs = notebook.file.watch(
182
+ '/app',
183
+ { recursive: true, excludes: ['vendor/**', 'node_modules/**'] },
184
+ (change) => {
185
+ console.log(change.type, change.path);
186
+ }
187
+ );
543
188
 
544
- notebook.onDidDisconnect(() => {
545
- console.log('Disconnected from notebook');
546
- });
189
+ // later
190
+ disposeConnect.dispose();
191
+ disposeFs.dispose();
547
192
  ```
548
193
 
549
194
  ## Error Handling
550
195
 
551
- The SDK provides structured error handling with specific error types:
552
-
553
- ```typescript
554
- import { FilesystemError, FilesystemErrorType, ErrorEvent } from '@phpsandbox/sdk';
196
+ ```ts
197
+ import { ApiError, FilesystemError, FilesystemErrorType } from '@phpsandbox/sdk';
555
198
 
556
199
  try {
557
- await notebook.file.readFile('/nonexistent.php');
200
+ await notebook.file.readFile('/does-not-exist.php');
558
201
  } catch (error) {
559
202
  if (error instanceof FilesystemError && error.name === FilesystemErrorType.FileNotFound) {
560
- console.log('File not found');
561
- } else if (error instanceof ErrorEvent) {
562
- console.log(`Error ${error.code}: ${error.message}`);
203
+ console.error('Missing file');
204
+ } else if (error instanceof ApiError) {
205
+ console.error(error.status, error.body);
206
+ } else {
207
+ throw error;
563
208
  }
564
209
  }
565
210
  ```
566
211
 
567
- ### Common Error Types
568
-
569
- - `FilesystemError`: File system operation errors
570
- - `RateLimitError`: API rate limiting
571
- - `NotebookInitError`: Notebook initialization failures
572
- - `ErrorEvent`: Base error class with error codes
212
+ ## Browser/CDN Usage
573
213
 
574
- ## Examples
214
+ See `docs/cdn-usage.md` for ESM and script-tag examples.
575
215
 
576
- ### Complete Laravel Application Setup
216
+ ## More Docs
577
217
 
578
- ```typescript
579
- import { PHPSandbox } from '@phpsandbox/sdk';
580
-
581
- async function setupLaravelApp() {
582
- const client = new PHPSandbox(process.env.PHPSANDBOX_TOKEN);
583
- const notebook = await client.notebook.create('laravel');
584
-
585
- // Wait for container to be ready
586
- await notebook.ready();
587
-
588
- // Install additional dependencies
589
- await notebook.composer.install(['laravel/sanctum', 'laravel/horizon']);
590
-
591
- // Create a new controller
592
- await notebook.laravel.make('controller', 'ApiController', { resource: true });
593
-
594
- // Run migrations
595
- await notebook.laravel.migrate();
596
-
597
- // Set up Git repository
598
- await notebook.git.init();
599
- await notebook.git.add(['.']);
600
- await notebook.git.commit('Initial commit');
601
-
602
- // Start development server
603
- const server = await notebook.terminal.spawn('php', ['artisan', 'serve', '--host=0.0.0.0']);
604
-
605
- // Monitor for open ports
606
- notebook.container.onPort((port, type) => {
607
- if (type === 'open' && port.port === 8000) {
608
- console.log(`Laravel server available at: ${port.url}`);
609
- }
610
- });
611
-
612
- return notebook;
613
- }
614
- ```
615
-
616
- ### File Processing Pipeline
617
-
618
- ```typescript
619
- async function processPhpFiles(notebook: NotebookInstance) {
620
- // Find all PHP files
621
- const phpFiles = await notebook.file.find('*.php', {
622
- includes: ['app/**', 'src/**'],
623
- excludes: ['vendor/**', 'node_modules/**'],
624
- });
625
-
626
- // Process each file
627
- for (const file of phpFiles) {
628
- const content = await notebook.file.readFile(file.path);
629
-
630
- // Run PHP CS Fixer
631
- await notebook.terminal.spawn('php-cs-fixer', ['fix', file.path]);
632
-
633
- // Run static analysis
634
- const analysis = await notebook.terminal.spawn('phpstan', ['analyse', file.path]);
635
-
636
- // Wait for completion
637
- await analysis.exit;
638
- }
639
-
640
- console.log(`Processed ${phpFiles.length} PHP files`);
641
- }
642
- ```
643
-
644
- ### Real-time Development Environment
645
-
646
- ```typescript
647
- async function createDevelopmentEnvironment() {
648
- const client = new PHPSandbox(process.env.PHPSANDBOX_TOKEN);
649
- const notebook = await client.notebook.create('php');
650
-
651
- // Set up file watching
652
- notebook.file.watch('/app', { recursive: true }, (change) => {
653
- console.log(`[${new Date().toISOString()}] ${change.path} ${change.type}`);
654
-
655
- // Auto-reload on PHP file changes
656
- if (change.path.endsWith('.php') && change.type === 'UPDATED') {
657
- notebook.repl.execute(`include '${change.path}';`);
658
- }
659
- });
660
-
661
- // Set up LSP for IDE features
662
- const lspConnection = notebook.lsp.connection('php-lsp');
663
- await lspConnection.start();
664
-
665
- lspConnection.onMessage((message) => {
666
- const data = JSON.parse(message);
667
- if (data.method === 'textDocument/publishDiagnostics') {
668
- console.log('Diagnostics:', data.params.diagnostics);
669
- }
670
- });
671
-
672
- // Monitor container resources
673
- notebook.container.listen('container.stats', (stats) => {
674
- if (stats.memory.usage / stats.memory.limit > 0.8) {
675
- console.warn('High memory usage detected');
676
- }
677
- });
678
-
679
- return notebook;
680
- }
681
- ```
682
-
683
- ## TypeScript Support
684
-
685
- The SDK is built with TypeScript and provides comprehensive type definitions:
686
-
687
- ```typescript
688
- import type {
689
- NotebookInstance,
690
- FileInfo,
691
- Stats,
692
- TextSearchQuery,
693
- TerminalCreateInput,
694
- ContainerStats,
695
- Events,
696
- FilesystemEvents,
697
- } from '@phpsandbox/sdk';
698
-
699
- // Type-safe event handling
700
- notebook.listen('fs.watch', (change: Events['fs.watch']) => {
701
- // change is properly typed as FileChange
702
- console.log(change.path, change.type);
703
- });
704
-
705
- // Type-safe API calls
706
- const stats: Stats = await notebook.file.stat('/app/composer.json');
707
- const info: FileInfo = await notebook.file.info('/app/index.php');
708
- ```
709
-
710
- ### Generic Types
711
-
712
- ```typescript
713
- // Custom event handlers
714
- type CustomEventHandler<T extends keyof Events> = (data: Events[T]) => void;
715
-
716
- // Action types
717
- type FileSystemActions = FilesystemActions;
718
- type TerminalActions = TerminalActions;
719
-
720
- // Disposable pattern
721
- const disposable: Disposable = notebook.onDidConnect(() => {
722
- console.log('Connected');
723
- });
724
-
725
- // Clean up when done
726
- disposable.dispose();
727
- ```
218
+ - Getting started walkthrough: `docs/getting-started.md`
219
+ - API overview: `docs/api-summary.md`
220
+ - Examples: `examples/README.md`
728
221
 
729
- ## Support and Contributing
222
+ ## Support
730
223
 
731
- - **Documentation**: [https://docs.phpsandbox.io](https://docs.phpsandbox.io)
732
- - **API Reference**: [https://api.phpsandbox.io/docs](https://api.phpsandbox.io/docs)
733
- - **Issues**: [GitHub Issues](https://github.com/phpsandbox/sdk/issues)
734
- - **Examples**: [GitHub Examples](https://github.com/phpsandbox/examples)
224
+ - Issues: https://github.com/phpsandbox/sdk/issues
225
+ - Product docs: https://docs.phpsandbox.io
735
226
 
736
227
  ## License
737
228
 
738
- MIT License - see LICENSE file for details.
229
+ MIT