@jupyterlite/terminal 0.1.6 → 0.2.0
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 +13 -15
- package/lib/client.d.ts +28 -0
- package/lib/client.js +118 -0
- package/lib/index.d.ts +3 -3
- package/lib/index.js +54 -48
- package/lib/shell.d.ts +2 -0
- package/lib/tokens.d.ts +10 -44
- package/lib/tokens.js +1 -6
- package/lib/worker.js +24 -22
- package/package.json +11 -13
- package/src/client.ts +157 -0
- package/src/index.ts +79 -63
- package/src/shell.ts +4 -0
- package/src/tokens.ts +15 -53
- package/src/worker.ts +26 -38
- package/lib/manager.d.ts +0 -32
- package/lib/manager.js +0 -67
- package/lib/terminal.d.ts +0 -24
- package/lib/terminal.js +0 -101
- package/src/manager.ts +0 -82
- package/src/terminal.ts +0 -131
package/lib/terminal.js
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Jupyter Development Team.
|
|
2
|
-
// Distributed under the terms of the Modified BSD License.
|
|
3
|
-
import { Signal } from '@lumino/signaling';
|
|
4
|
-
import { Server as WebSocketServer } from 'mock-socket';
|
|
5
|
-
import { Shell } from './shell';
|
|
6
|
-
export class Terminal {
|
|
7
|
-
/**
|
|
8
|
-
* Construct a new Terminal.
|
|
9
|
-
*/
|
|
10
|
-
constructor(options) {
|
|
11
|
-
this.options = options;
|
|
12
|
-
this._disposed = new Signal(this);
|
|
13
|
-
this._isDisposed = false;
|
|
14
|
-
this._running = false;
|
|
15
|
-
this._shell = new Shell({
|
|
16
|
-
mountpoint: '/drive',
|
|
17
|
-
driveFsBaseUrl: options.baseUrl,
|
|
18
|
-
wasmBaseUrl: options.baseUrl + 'extensions/@jupyterlite/terminal/static/wasm/',
|
|
19
|
-
outputCallback: this._outputCallback.bind(this)
|
|
20
|
-
});
|
|
21
|
-
this._shell.disposed.connect(() => this.dispose());
|
|
22
|
-
}
|
|
23
|
-
_outputCallback(text) {
|
|
24
|
-
if (this._socket) {
|
|
25
|
-
const ret = JSON.stringify(['stdout', text]);
|
|
26
|
-
this._socket.send(ret);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
dispose() {
|
|
30
|
-
if (this._isDisposed) {
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
console.log('Terminal.dispose');
|
|
34
|
-
this._isDisposed = true;
|
|
35
|
-
if (this._socket !== undefined) {
|
|
36
|
-
// Disconnect from frontend.
|
|
37
|
-
this._socket.send(JSON.stringify(['disconnect']));
|
|
38
|
-
this._socket.close();
|
|
39
|
-
this._socket = undefined;
|
|
40
|
-
}
|
|
41
|
-
if (this._server !== undefined) {
|
|
42
|
-
this._server.close();
|
|
43
|
-
this._server = undefined;
|
|
44
|
-
}
|
|
45
|
-
this._shell.dispose();
|
|
46
|
-
this._disposed.emit();
|
|
47
|
-
}
|
|
48
|
-
get disposed() {
|
|
49
|
-
return this._disposed;
|
|
50
|
-
}
|
|
51
|
-
get isDisposed() {
|
|
52
|
-
return this._isDisposed;
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Get the name of the terminal.
|
|
56
|
-
*/
|
|
57
|
-
get name() {
|
|
58
|
-
return this.options.name;
|
|
59
|
-
}
|
|
60
|
-
async wsConnect(url) {
|
|
61
|
-
console.log('Terminal wsConnect', url);
|
|
62
|
-
this._server = new WebSocketServer(url);
|
|
63
|
-
this._server.on('connection', async (socket) => {
|
|
64
|
-
console.log('Terminal server connection');
|
|
65
|
-
if (this._socket !== undefined) {
|
|
66
|
-
this._socket.send(JSON.stringify(['disconnect']));
|
|
67
|
-
this._socket.close();
|
|
68
|
-
this._socket = undefined;
|
|
69
|
-
}
|
|
70
|
-
this._socket = socket;
|
|
71
|
-
socket.on('message', async (message) => {
|
|
72
|
-
const data = JSON.parse(message);
|
|
73
|
-
//console.log('==> socket message', data);
|
|
74
|
-
const message_type = data[0];
|
|
75
|
-
const content = data.slice(1);
|
|
76
|
-
if (message_type === 'stdin') {
|
|
77
|
-
await this._shell.input(content[0]);
|
|
78
|
-
}
|
|
79
|
-
else if (message_type === 'set_size') {
|
|
80
|
-
const rows = content[0];
|
|
81
|
-
const columns = content[1];
|
|
82
|
-
await this._shell.setSize(rows, columns);
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
socket.on('close', () => {
|
|
86
|
-
console.log('Terminal socket close');
|
|
87
|
-
});
|
|
88
|
-
socket.on('error', () => {
|
|
89
|
-
console.log('Terminal socket error');
|
|
90
|
-
});
|
|
91
|
-
// Return handshake.
|
|
92
|
-
const res = JSON.stringify(['setup']);
|
|
93
|
-
console.log('Terminal returning handshake via socket');
|
|
94
|
-
socket.send(res);
|
|
95
|
-
if (!this._running) {
|
|
96
|
-
this._running = true;
|
|
97
|
-
await this._shell.start();
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
}
|
package/src/manager.ts
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Jupyter Development Team.
|
|
2
|
-
// Distributed under the terms of the Modified BSD License.
|
|
3
|
-
|
|
4
|
-
import { PageConfig } from '@jupyterlab/coreutils';
|
|
5
|
-
import { TerminalAPI } from '@jupyterlab/services';
|
|
6
|
-
|
|
7
|
-
import { Terminal } from './terminal';
|
|
8
|
-
import { ITerminalManager } from './tokens';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* A class to handle requests to /api/terminals.
|
|
12
|
-
* Although this looks similar to a JupyterLab TerminalManager, it is really a class that
|
|
13
|
-
* implements the terminal REST API.
|
|
14
|
-
*/
|
|
15
|
-
export class TerminalManager implements ITerminalManager {
|
|
16
|
-
/**
|
|
17
|
-
* Construct a new TerminalManager object.
|
|
18
|
-
*/
|
|
19
|
-
constructor(wsUrl: string) {
|
|
20
|
-
this._wsUrl = wsUrl;
|
|
21
|
-
console.log('==> TerminalManager.constructor', this._wsUrl);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Return whether the named terminal exists.
|
|
26
|
-
*/
|
|
27
|
-
has(name: string): boolean {
|
|
28
|
-
return this._terminals.has(name);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* List the running terminals.
|
|
33
|
-
*/
|
|
34
|
-
async listRunning(): Promise<TerminalAPI.IModel[]> {
|
|
35
|
-
const ret = [...this._terminals.values()].map(terminal => ({
|
|
36
|
-
name: terminal.name
|
|
37
|
-
}));
|
|
38
|
-
return ret;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Shutdown a terminal by name.
|
|
43
|
-
*/
|
|
44
|
-
async shutdownTerminal(name: string): Promise<void> {
|
|
45
|
-
const terminal = this._terminals.get(name);
|
|
46
|
-
if (terminal !== undefined) {
|
|
47
|
-
console.log('==> TerminalManager.shutdownTerminal', name);
|
|
48
|
-
this._terminals.delete(name);
|
|
49
|
-
terminal.dispose();
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Start a new kernel.
|
|
55
|
-
*/
|
|
56
|
-
async startNew(): Promise<TerminalAPI.IModel> {
|
|
57
|
-
const name = this._nextAvailableName();
|
|
58
|
-
console.log('==> TerminalManager.startNew', name);
|
|
59
|
-
const baseUrl = PageConfig.getBaseUrl();
|
|
60
|
-
const terminal = new Terminal({ name, baseUrl });
|
|
61
|
-
this._terminals.set(name, terminal);
|
|
62
|
-
|
|
63
|
-
terminal.disposed.connect(() => this.shutdownTerminal(name));
|
|
64
|
-
|
|
65
|
-
const url = `${this._wsUrl}terminals/websocket/${name}`;
|
|
66
|
-
await terminal.wsConnect(url);
|
|
67
|
-
|
|
68
|
-
return { name };
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
private _nextAvailableName(): string {
|
|
72
|
-
for (let i = 1; ; ++i) {
|
|
73
|
-
const name = `${i}`;
|
|
74
|
-
if (!this._terminals.has(name)) {
|
|
75
|
-
return name;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
private _wsUrl: string;
|
|
81
|
-
private _terminals: Map<string, Terminal> = new Map();
|
|
82
|
-
}
|
package/src/terminal.ts
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Jupyter Development Team.
|
|
2
|
-
// Distributed under the terms of the Modified BSD License.
|
|
3
|
-
|
|
4
|
-
import { IShell } from '@jupyterlite/cockle';
|
|
5
|
-
import { JSONPrimitive } from '@lumino/coreutils';
|
|
6
|
-
import { ISignal, Signal } from '@lumino/signaling';
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
Server as WebSocketServer,
|
|
10
|
-
Client as WebSocketClient
|
|
11
|
-
} from 'mock-socket';
|
|
12
|
-
|
|
13
|
-
import { Shell } from './shell';
|
|
14
|
-
import { ITerminal } from './tokens';
|
|
15
|
-
|
|
16
|
-
export class Terminal implements ITerminal {
|
|
17
|
-
/**
|
|
18
|
-
* Construct a new Terminal.
|
|
19
|
-
*/
|
|
20
|
-
constructor(readonly options: ITerminal.IOptions) {
|
|
21
|
-
this._shell = new Shell({
|
|
22
|
-
mountpoint: '/drive',
|
|
23
|
-
driveFsBaseUrl: options.baseUrl,
|
|
24
|
-
wasmBaseUrl:
|
|
25
|
-
options.baseUrl + 'extensions/@jupyterlite/terminal/static/wasm/',
|
|
26
|
-
outputCallback: this._outputCallback.bind(this)
|
|
27
|
-
});
|
|
28
|
-
this._shell.disposed.connect(() => this.dispose());
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
private _outputCallback(text: string): void {
|
|
32
|
-
if (this._socket) {
|
|
33
|
-
const ret = JSON.stringify(['stdout', text]);
|
|
34
|
-
this._socket.send(ret);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
dispose(): void {
|
|
39
|
-
if (this._isDisposed) {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
console.log('Terminal.dispose');
|
|
44
|
-
this._isDisposed = true;
|
|
45
|
-
|
|
46
|
-
if (this._socket !== undefined) {
|
|
47
|
-
// Disconnect from frontend.
|
|
48
|
-
this._socket.send(JSON.stringify(['disconnect']));
|
|
49
|
-
this._socket.close();
|
|
50
|
-
this._socket = undefined;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (this._server !== undefined) {
|
|
54
|
-
this._server.close();
|
|
55
|
-
this._server = undefined;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
this._shell.dispose();
|
|
59
|
-
this._disposed.emit();
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
get disposed(): ISignal<this, void> {
|
|
63
|
-
return this._disposed;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
get isDisposed(): boolean {
|
|
67
|
-
return this._isDisposed;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Get the name of the terminal.
|
|
72
|
-
*/
|
|
73
|
-
get name(): string {
|
|
74
|
-
return this.options.name;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
async wsConnect(url: string) {
|
|
78
|
-
console.log('Terminal wsConnect', url);
|
|
79
|
-
this._server = new WebSocketServer(url);
|
|
80
|
-
|
|
81
|
-
this._server.on('connection', async (socket: WebSocketClient) => {
|
|
82
|
-
console.log('Terminal server connection');
|
|
83
|
-
if (this._socket !== undefined) {
|
|
84
|
-
this._socket.send(JSON.stringify(['disconnect']));
|
|
85
|
-
this._socket.close();
|
|
86
|
-
this._socket = undefined;
|
|
87
|
-
}
|
|
88
|
-
this._socket = socket;
|
|
89
|
-
|
|
90
|
-
socket.on('message', async (message: any) => {
|
|
91
|
-
const data = JSON.parse(message) as JSONPrimitive[];
|
|
92
|
-
//console.log('==> socket message', data);
|
|
93
|
-
const message_type = data[0];
|
|
94
|
-
const content = data.slice(1);
|
|
95
|
-
|
|
96
|
-
if (message_type === 'stdin') {
|
|
97
|
-
await this._shell.input(content[0] as string);
|
|
98
|
-
} else if (message_type === 'set_size') {
|
|
99
|
-
const rows = content[0] as number;
|
|
100
|
-
const columns = content[1] as number;
|
|
101
|
-
await this._shell.setSize(rows, columns);
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
socket.on('close', () => {
|
|
106
|
-
console.log('Terminal socket close');
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
socket.on('error', () => {
|
|
110
|
-
console.log('Terminal socket error');
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
// Return handshake.
|
|
114
|
-
const res = JSON.stringify(['setup']);
|
|
115
|
-
console.log('Terminal returning handshake via socket');
|
|
116
|
-
socket.send(res);
|
|
117
|
-
|
|
118
|
-
if (!this._running) {
|
|
119
|
-
this._running = true;
|
|
120
|
-
await this._shell.start();
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
private _disposed = new Signal<this, void>(this);
|
|
126
|
-
private _isDisposed = false;
|
|
127
|
-
private _server?: WebSocketServer;
|
|
128
|
-
private _socket?: WebSocketClient;
|
|
129
|
-
private _shell: IShell;
|
|
130
|
-
private _running = false;
|
|
131
|
-
}
|