@phpsandbox/sdk 0.1.1 → 0.1.4
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 +59 -22
- package/dist/browser/phpsandbox-sdk.esm.js +562 -265
- package/dist/browser/phpsandbox-sdk.esm.min.js +24 -24
- package/dist/browser/phpsandbox-sdk.iife.js +562 -265
- package/dist/browser/phpsandbox-sdk.iife.min.js +24 -24
- package/dist/composer.d.ts +36 -23
- package/dist/composer.js +61 -11
- package/dist/container.d.ts +2 -6
- package/dist/container.js +0 -28
- package/dist/filesystem.d.ts +74 -18
- package/dist/filesystem.js +219 -62
- package/dist/index.d.ts +18 -9
- package/dist/index.js +21 -8
- package/dist/log.d.ts +11 -5
- package/dist/log.js +10 -7
- package/dist/metrics.d.ts +10 -0
- package/dist/metrics.js +13 -0
- package/dist/ports.d.ts +10 -0
- package/dist/ports.js +13 -0
- package/dist/runtime/rest.js +1 -4
- package/dist/runtime-telemetry.d.ts +15 -0
- package/dist/runtime-telemetry.js +111 -0
- package/dist/schemas/publications.d.ts +10 -10
- package/dist/services.d.ts +2 -9
- package/dist/services.js +3 -10
- package/dist/shell.d.ts +9 -0
- package/dist/shell.js +4 -4
- package/dist/terminal.d.ts +17 -11
- package/dist/terminal.js +27 -44
- package/docs/api-summary.md +28 -23
- package/docs/cdn-usage.md +2 -2
- package/docs/getting-started.md +13 -13
- package/examples/basic.ts +1 -1
- package/examples/git-merge-smoke.ts +1 -4
- package/examples/laravel-load-test.ts +67 -80
- package/examples/notebook-readonly-smoke.ts +30 -33
- package/package.json +1 -1
package/dist/composer.d.ts
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
import { Action, Client,
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import { ComposerCredentials, type Action, type Client, type NotebookInstance } from './index.js';
|
|
2
|
+
import { ProcessResult, type ProcessOutputChunk, type ProcessOutputSource, type ProcessResultData } from './shell.js';
|
|
3
|
+
export interface ComposerEventData {
|
|
4
|
+
'composer.output': {
|
|
5
|
+
id: string;
|
|
6
|
+
output: string;
|
|
7
|
+
source: ProcessOutputSource;
|
|
8
|
+
};
|
|
8
9
|
}
|
|
10
|
+
type ComposerEventPattern = `${keyof ComposerEventData}.${string}`;
|
|
11
|
+
export type ComposerEvents = ComposerEventData & {
|
|
12
|
+
[K in ComposerEventPattern]: ComposerEventData['composer.output'];
|
|
13
|
+
};
|
|
9
14
|
export interface ComposerPackage {
|
|
10
15
|
name: string;
|
|
11
16
|
_installedVersion: string;
|
|
@@ -14,32 +19,40 @@ export interface ComposerPackage {
|
|
|
14
19
|
}
|
|
15
20
|
export interface ComposerActions {
|
|
16
21
|
'composer.invoke': Action<{
|
|
22
|
+
id: string;
|
|
17
23
|
command: ComposerCommand;
|
|
18
24
|
args: Argument;
|
|
19
25
|
options: Options;
|
|
20
|
-
},
|
|
21
|
-
'composer.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}>;
|
|
26
|
+
}, ProcessResultData>;
|
|
27
|
+
'composer.kill': Action<{
|
|
28
|
+
id: string;
|
|
29
|
+
}, boolean>;
|
|
25
30
|
'composer.packages': Action<undefined, ComposerPackage[]>;
|
|
26
31
|
}
|
|
27
|
-
export type ComposerCommand = 'install' | 'update' | 'require' | 'remove' | 'search' | 'show';
|
|
32
|
+
export type ComposerCommand = 'install' | 'update' | 'require' | 'remove' | 'search' | 'show' | 'dump-autoload';
|
|
28
33
|
export type Argument<Name extends string = string, Type extends string | string[] = string | string[]> = Record<Name, Type>;
|
|
29
34
|
export type Options<Name extends string = string, Type extends string | string[] | boolean = string | string[] | boolean> = Record<Name, Type>;
|
|
35
|
+
export declare class ComposerProcess {
|
|
36
|
+
readonly id: string;
|
|
37
|
+
private readonly okra;
|
|
38
|
+
readonly output: ReadableStream<ProcessOutputChunk>;
|
|
39
|
+
readonly stdout: ReadableStream<Uint8Array>;
|
|
40
|
+
readonly stderr: ReadableStream<Uint8Array>;
|
|
41
|
+
private readonly completion;
|
|
42
|
+
constructor(id: string, okra: NotebookInstance, command: ComposerCommand, args: Argument, options: Options);
|
|
43
|
+
wait(): Promise<ProcessResult>;
|
|
44
|
+
kill(): Promise<void>;
|
|
45
|
+
}
|
|
30
46
|
export default class Composer {
|
|
31
47
|
protected okra: NotebookInstance;
|
|
32
48
|
readonly credentials: ComposerCredentials;
|
|
33
49
|
constructor(okra: NotebookInstance, client: Client);
|
|
34
|
-
|
|
35
|
-
dumpAutoload():
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
update(args: Argument<'packages'>, options?: Options): Promise<Result>;
|
|
41
|
-
require(packages: Argument<'packages'>, options?: Options): Promise<Result>;
|
|
42
|
-
remove(args: Argument<'packages'>, options?: Options): Promise<Result>;
|
|
43
|
-
stream(fn: (data: string) => void): Disposable;
|
|
50
|
+
run(command: ComposerCommand, args?: Argument, options?: Options): ComposerProcess;
|
|
51
|
+
dumpAutoload(options?: Options): ComposerProcess;
|
|
52
|
+
install(options?: Options): ComposerProcess;
|
|
53
|
+
update(args: Argument<'packages'>, options?: Options): ComposerProcess;
|
|
54
|
+
require(packages: Argument<'packages'>, options?: Options): ComposerProcess;
|
|
55
|
+
remove(args: Argument<'packages'>, options?: Options): ComposerProcess;
|
|
44
56
|
packages(): Promise<ComposerPackage[]>;
|
|
45
57
|
}
|
|
58
|
+
export {};
|
package/dist/composer.js
CHANGED
|
@@ -1,29 +1,79 @@
|
|
|
1
1
|
import { ComposerCredentials } from './index.js';
|
|
2
|
+
import { ProcessReadable, ProcessResult, } from './shell.js';
|
|
3
|
+
import { nanoid } from 'nanoid';
|
|
4
|
+
export class ComposerProcess {
|
|
5
|
+
constructor(id, okra, command, args, options) {
|
|
6
|
+
this.id = id;
|
|
7
|
+
this.okra = okra;
|
|
8
|
+
const output = new ProcessReadable();
|
|
9
|
+
const stdout = new ProcessReadable();
|
|
10
|
+
const stderr = new ProcessReadable();
|
|
11
|
+
this.output = output.stream;
|
|
12
|
+
this.stdout = stdout.stream;
|
|
13
|
+
this.stderr = stderr.stream;
|
|
14
|
+
const encoder = new TextEncoder();
|
|
15
|
+
let subscription = this.okra.listen(`composer.output.${this.id}`, (event) => {
|
|
16
|
+
const data = encoder.encode(event.output);
|
|
17
|
+
const source = event.source ?? 'output';
|
|
18
|
+
output.enqueue({ source, data });
|
|
19
|
+
if (source === 'stderr') {
|
|
20
|
+
stderr.enqueue(data);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
stdout.enqueue(data);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
const finish = () => {
|
|
27
|
+
subscription?.dispose();
|
|
28
|
+
subscription = null;
|
|
29
|
+
output.close();
|
|
30
|
+
stdout.close();
|
|
31
|
+
stderr.close();
|
|
32
|
+
};
|
|
33
|
+
const fail = (error) => {
|
|
34
|
+
subscription?.dispose();
|
|
35
|
+
subscription = null;
|
|
36
|
+
output.fail(error);
|
|
37
|
+
stdout.fail(error);
|
|
38
|
+
stderr.fail(error);
|
|
39
|
+
};
|
|
40
|
+
this.completion = this.okra.invoke('composer.invoke', { id, command, args, options }).then((result) => {
|
|
41
|
+
finish();
|
|
42
|
+
return new ProcessResult(result.output, result.stdout, result.stderr, result.exitCode);
|
|
43
|
+
}).catch((error) => {
|
|
44
|
+
fail(error);
|
|
45
|
+
throw error;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
wait() {
|
|
49
|
+
return this.completion;
|
|
50
|
+
}
|
|
51
|
+
async kill() {
|
|
52
|
+
await this.okra.invoke('composer.kill', { id: this.id });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
2
55
|
export default class Composer {
|
|
3
56
|
constructor(okra, client) {
|
|
4
57
|
this.okra = okra;
|
|
5
58
|
this.credentials = new ComposerCredentials(client, okra.data.id);
|
|
6
59
|
}
|
|
7
|
-
|
|
8
|
-
return this.okra
|
|
60
|
+
run(command, args = {}, options = {}) {
|
|
61
|
+
return new ComposerProcess(nanoid(), this.okra, command, args, options);
|
|
9
62
|
}
|
|
10
|
-
dumpAutoload() {
|
|
11
|
-
return this.
|
|
63
|
+
dumpAutoload(options = {}) {
|
|
64
|
+
return this.run('dump-autoload', {}, options);
|
|
12
65
|
}
|
|
13
66
|
install(options = {}) {
|
|
14
|
-
return this.
|
|
67
|
+
return this.run('install', {}, options);
|
|
15
68
|
}
|
|
16
69
|
update(args, options = {}) {
|
|
17
|
-
return this.
|
|
70
|
+
return this.run('update', args, options);
|
|
18
71
|
}
|
|
19
72
|
require(packages, options = {}) {
|
|
20
|
-
return this.
|
|
73
|
+
return this.run('require', packages, options);
|
|
21
74
|
}
|
|
22
75
|
remove(args, options = {}) {
|
|
23
|
-
return this.
|
|
24
|
-
}
|
|
25
|
-
stream(fn) {
|
|
26
|
-
return this.okra.listen('composer.log', fn);
|
|
76
|
+
return this.run('remove', args, options);
|
|
27
77
|
}
|
|
28
78
|
packages() {
|
|
29
79
|
return this.okra.invoke('composer.packages');
|
package/dist/container.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Action,
|
|
1
|
+
import { Action, NotebookInstance } from './index.js';
|
|
2
2
|
interface Stat {
|
|
3
3
|
usage: number;
|
|
4
4
|
limit: number;
|
|
@@ -38,6 +38,7 @@ export interface ContainerActions {
|
|
|
38
38
|
state: NotebookState;
|
|
39
39
|
}>;
|
|
40
40
|
'container.opened-ports': Action<{}, PortInfo[]>;
|
|
41
|
+
'container.stats': Action<{}, ContainerStats | null>;
|
|
41
42
|
'container.set-php': Action<{
|
|
42
43
|
version: string;
|
|
43
44
|
}, {
|
|
@@ -57,13 +58,8 @@ export default class Container {
|
|
|
57
58
|
state(): Promise<{
|
|
58
59
|
state: NotebookState;
|
|
59
60
|
}>;
|
|
60
|
-
openedPorts(): Promise<PortInfo[]>;
|
|
61
61
|
setPhp(version: string): Promise<{
|
|
62
62
|
version: string;
|
|
63
63
|
}>;
|
|
64
|
-
enableTelemetry(features: Set<TelemetryFeature>): Promise<void>;
|
|
65
|
-
stopTelemetry(): Promise<void>;
|
|
66
|
-
listen<T extends keyof ContainerEvents>(event: T, handler: (data: ContainerEvents[T]) => void): Disposable;
|
|
67
|
-
onPort(handler: (port: PortInfo, type: 'open' | 'close') => void): Disposable;
|
|
68
64
|
}
|
|
69
65
|
export {};
|
package/dist/container.js
CHANGED
|
@@ -24,35 +24,7 @@ export default class Container {
|
|
|
24
24
|
state() {
|
|
25
25
|
return this.okra.invoke('container.state');
|
|
26
26
|
}
|
|
27
|
-
openedPorts() {
|
|
28
|
-
return this.okra.invoke('container.opened-ports');
|
|
29
|
-
}
|
|
30
27
|
setPhp(version) {
|
|
31
28
|
return this.okra.invoke('container.set-php', { version });
|
|
32
29
|
}
|
|
33
|
-
enableTelemetry(features) {
|
|
34
|
-
return this.okra.invoke('container.stream-telemetry', { features: Array.from(features) });
|
|
35
|
-
}
|
|
36
|
-
stopTelemetry() {
|
|
37
|
-
return this.okra.invoke('container.stop-telemetry');
|
|
38
|
-
}
|
|
39
|
-
listen(event, handler) {
|
|
40
|
-
return this.okra.listen(event, handler);
|
|
41
|
-
}
|
|
42
|
-
onPort(handler) {
|
|
43
|
-
let ports = [];
|
|
44
|
-
return this.listen('container.ports', (newPorts) => {
|
|
45
|
-
for (const port of newPorts) {
|
|
46
|
-
if (!ports.some((p) => p.port === port.port)) {
|
|
47
|
-
handler(port, 'open');
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
for (const port of ports) {
|
|
51
|
-
if (!newPorts.some((p) => p.port === port.port)) {
|
|
52
|
-
handler(port, 'close');
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
ports = newPorts;
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
30
|
}
|
package/dist/filesystem.d.ts
CHANGED
|
@@ -60,6 +60,30 @@ export interface FileDeleteOptions {
|
|
|
60
60
|
postfix: string;
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
|
+
export type FileContents = string | Uint8Array | ReadableStream<Uint8Array> | AsyncIterable<Uint8Array>;
|
|
64
|
+
export interface FileListOptions {
|
|
65
|
+
include?: string[];
|
|
66
|
+
exclude?: string[];
|
|
67
|
+
}
|
|
68
|
+
export interface FileTailOptions {
|
|
69
|
+
lines?: number;
|
|
70
|
+
}
|
|
71
|
+
export interface FileFollowOptions extends FileTailOptions {
|
|
72
|
+
signal?: AbortSignal;
|
|
73
|
+
}
|
|
74
|
+
export interface FileLineRange {
|
|
75
|
+
start: number;
|
|
76
|
+
end: number;
|
|
77
|
+
}
|
|
78
|
+
export interface FileLineRangeResult extends FileLineRange {
|
|
79
|
+
content: string;
|
|
80
|
+
warning?: string;
|
|
81
|
+
}
|
|
82
|
+
export interface FileDownloadOptions {
|
|
83
|
+
onChunk?: (data: Uint8Array) => void;
|
|
84
|
+
exclude?: string[];
|
|
85
|
+
include?: string[];
|
|
86
|
+
}
|
|
63
87
|
export interface SearchOptions {
|
|
64
88
|
/**
|
|
65
89
|
* The maximum number of results to be returned.
|
|
@@ -375,6 +399,36 @@ export interface FilesystemActions {
|
|
|
375
399
|
contents: Uint8Array;
|
|
376
400
|
options: FileWriteOptions;
|
|
377
401
|
}, void>;
|
|
402
|
+
'fs.readStream': Action<{
|
|
403
|
+
id: string;
|
|
404
|
+
path: string;
|
|
405
|
+
}, boolean>;
|
|
406
|
+
'fs.cancelRead': Action<{
|
|
407
|
+
id: string;
|
|
408
|
+
}, boolean>;
|
|
409
|
+
'fs.follow': Action<{
|
|
410
|
+
id: string;
|
|
411
|
+
path: string;
|
|
412
|
+
lines: number;
|
|
413
|
+
}, boolean>;
|
|
414
|
+
'fs.cancelFollow': Action<{
|
|
415
|
+
id: string;
|
|
416
|
+
}, boolean>;
|
|
417
|
+
'fs.writeStream': Action<{
|
|
418
|
+
id: string;
|
|
419
|
+
path: string;
|
|
420
|
+
options: FileWriteOptions;
|
|
421
|
+
}, boolean>;
|
|
422
|
+
'fs.writeChunk': Action<{
|
|
423
|
+
id: string;
|
|
424
|
+
contents: Uint8Array;
|
|
425
|
+
}, boolean>;
|
|
426
|
+
'fs.endWrite': Action<{
|
|
427
|
+
id: string;
|
|
428
|
+
}, boolean>;
|
|
429
|
+
'fs.abortWrite': Action<{
|
|
430
|
+
id: string;
|
|
431
|
+
}, boolean>;
|
|
378
432
|
'fs.stat': Action<{
|
|
379
433
|
path: string;
|
|
380
434
|
}, Stats>;
|
|
@@ -424,6 +478,14 @@ interface FilesystemEventData {
|
|
|
424
478
|
'fs.watch': FileChange;
|
|
425
479
|
'fs.download': Uint8Array;
|
|
426
480
|
'fs.text.search': TextSearchResult | false;
|
|
481
|
+
'fs.read': {
|
|
482
|
+
id: string;
|
|
483
|
+
data: Uint8Array;
|
|
484
|
+
};
|
|
485
|
+
'fs.follow': {
|
|
486
|
+
id: string;
|
|
487
|
+
data: Uint8Array;
|
|
488
|
+
};
|
|
427
489
|
}
|
|
428
490
|
type PrefixKey<K extends keyof FilesystemEventData> = `${K}.${string}`;
|
|
429
491
|
export type FilesystemEvents = FilesystemEventData & {
|
|
@@ -453,30 +515,24 @@ export declare class Filesystem {
|
|
|
453
515
|
private watches;
|
|
454
516
|
constructor(okra: NotebookInstance, registerReconnect?: ((handler: () => void) => Disposable) | null);
|
|
455
517
|
private registerReconnectHandler;
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
518
|
+
write(path: string, contents: FileContents, options?: Partial<FileWriteOptions>): Promise<void>;
|
|
519
|
+
read(path: string): Promise<Uint8Array>;
|
|
520
|
+
readText(path: string): Promise<string>;
|
|
521
|
+
readLines(path: string, range: FileLineRange): Promise<FileLineRangeResult>;
|
|
522
|
+
readStream(path: string): ReadableStream<Uint8Array>;
|
|
523
|
+
follow(path: string, options?: FileFollowOptions): ReadableStream<Uint8Array>;
|
|
459
524
|
find(query: string, options?: Partial<FileSearchOptions>): Promise<FileResult[]>;
|
|
460
525
|
search(query: TextSearchQuery, options?: Partial<TextSearchOptions>, onMatch?: (result: TextSearchResult | false) => boolean | Promise<boolean> | void | Promise<void>): Promise<[boolean, TextSearchMatch[]]>;
|
|
461
|
-
|
|
462
|
-
move(from: string, to: string): Promise<boolean>;
|
|
463
|
-
remove(path: string, type: 'file' | 'directory'): Promise<boolean>;
|
|
464
|
-
readFile(path: string): Promise<Uint8Array>;
|
|
465
|
-
readFile(path: string, lineRange: {
|
|
466
|
-
lineStart: number;
|
|
467
|
-
lineEnd: number;
|
|
468
|
-
}): Promise<ReadFileRangeResult>;
|
|
469
|
-
tail(path: string, lines?: number): Promise<string>;
|
|
470
|
-
writeFile(path: string, contents: Uint8Array, options: FileWriteOptions): Promise<void>;
|
|
526
|
+
tail(path: string, options?: FileTailOptions): Promise<string>;
|
|
471
527
|
stat(path: string): Promise<Stats>;
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
copy(source: string, destination: string, options
|
|
475
|
-
|
|
528
|
+
move(from: string, to: string, options?: Partial<FileOverwriteOptions>): Promise<void>;
|
|
529
|
+
remove(path: string, options?: Partial<FileDeleteOptions>): Promise<void>;
|
|
530
|
+
copy(source: string, destination: string, options?: Partial<FileOverwriteOptions>): Promise<void>;
|
|
531
|
+
list(path: string, options?: FileListOptions): Promise<[string, FileType, number | null][]>;
|
|
476
532
|
createDirectory(path: string): Promise<void>;
|
|
477
533
|
watch(path: string, options: WatchOptions, onDidChange: (e: FileChange) => void): Promise<FilesystemSubscription>;
|
|
478
534
|
exists(path: string): Promise<boolean>;
|
|
479
|
-
download(
|
|
535
|
+
download(options?: FileDownloadOptions): Promise<Blob>;
|
|
480
536
|
tree(path?: string): Promise<string>;
|
|
481
537
|
protected handleError(e: unknown): never;
|
|
482
538
|
}
|