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