@jupyterlite/terminal 0.1.0 → 0.1.1

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,6 +1,7 @@
1
- # jupyterlite_terminal
1
+ # jupyterlite-terminal
2
2
 
3
3
  [![Github Actions Status](https://github.com/jupyterlite/terminal/workflows/Build/badge.svg)](https://github.com/jupyterlite/terminal/actions/workflows/build.yml)
4
+ [![lite-badge](https://jupyterlite.rtfd.io/en/latest/_static/badge.svg)](https://jupyterlite.github.io/terminal/lab/index.html)
4
5
 
5
6
  A terminal for JupyterLite.
6
7
 
package/lib/index.js CHANGED
@@ -13,14 +13,14 @@ const terminalsPlugin = {
13
13
  activate: async (app) => {
14
14
  console.log('JupyterLab extension @jupyterlite/terminal:plugin is activated!');
15
15
  const { serviceManager } = app;
16
- const { contents, serverSettings, terminals } = serviceManager;
16
+ const { serverSettings, terminals } = serviceManager;
17
17
  console.log('terminals available:', terminals.isAvailable());
18
18
  console.log('terminals ready:', terminals.isReady); // Not ready
19
19
  console.log('terminals active:', terminals.isActive);
20
20
  // Not sure this is necessary?
21
21
  await terminals.ready;
22
22
  console.log('terminals ready after await:', terminals.isReady); // Ready
23
- return new Terminals(serverSettings.wsUrl, contents);
23
+ return new Terminals(serverSettings.wsUrl);
24
24
  }
25
25
  };
26
26
  /**
@@ -34,7 +34,7 @@ const terminalsRoutesPlugin = {
34
34
  console.log('JupyterLab extension @jupyterlite/terminal:routes-plugin is activated!', terminals);
35
35
  // GET /api/terminals - List the running terminals
36
36
  app.router.get('/api/terminals', async (req) => {
37
- const res = terminals.list();
37
+ const res = await terminals.list();
38
38
  // Should return last_activity for each too,
39
39
  return new Response(JSON.stringify(res));
40
40
  });
package/lib/terminal.d.ts CHANGED
@@ -1,15 +1,16 @@
1
1
  import { ITerminal } from './tokens';
2
2
  export declare class Terminal implements ITerminal {
3
+ readonly options: ITerminal.IOptions;
3
4
  /**
4
5
  * Construct a new Terminal.
5
6
  */
6
7
  constructor(options: ITerminal.IOptions);
8
+ private _outputCallback;
7
9
  /**
8
10
  * Get the name of the terminal.
9
11
  */
10
12
  get name(): string;
11
13
  wsConnect(url: string): Promise<void>;
12
- private _name;
13
- private _fs;
14
- private _shell?;
14
+ private _socket?;
15
+ private _shell;
15
16
  }
package/lib/terminal.js CHANGED
@@ -1,38 +1,41 @@
1
1
  // Copyright (c) Jupyter Development Team.
2
2
  // Distributed under the terms of the Modified BSD License.
3
- import { JupyterFileSystem, Shell } from '@jupyterlite/cockle';
3
+ import { Shell } from '@jupyterlite/cockle';
4
4
  import { Server as WebSocketServer } from 'mock-socket';
5
5
  export class Terminal {
6
6
  /**
7
7
  * Construct a new Terminal.
8
8
  */
9
9
  constructor(options) {
10
- this._name = options.name;
11
- this._fs = new JupyterFileSystem(options.contentsManager);
12
- console.log('==> new Terminal', this._name, this._fs);
10
+ this.options = options;
11
+ this._shell = new Shell({
12
+ mountpoint: '/drive',
13
+ driveFsBaseUrl: options.baseUrl,
14
+ wasmBaseUrl: options.baseUrl + 'extensions/@jupyterlite/terminal/static/wasm/',
15
+ outputCallback: this._outputCallback.bind(this)
16
+ });
17
+ }
18
+ async _outputCallback(text) {
19
+ if (this._socket) {
20
+ const ret = JSON.stringify(['stdout', text]);
21
+ this._socket.send(ret);
22
+ }
13
23
  }
14
24
  /**
15
25
  * Get the name of the terminal.
16
26
  */
17
27
  get name() {
18
- return this._name;
28
+ return this.options.name;
19
29
  }
20
30
  async wsConnect(url) {
21
31
  console.log('==> Terminal.wsConnect', url);
22
- // const server = new WebSocketServer(url, { mock: false });
23
32
  const server = new WebSocketServer(url);
24
33
  server.on('connection', async (socket) => {
25
34
  console.log('==> server connection', this, socket);
26
- const outputCallback = async (output) => {
27
- console.log('==> recv from shell:', output);
28
- const ret = JSON.stringify(['stdout', output]);
29
- socket.send(ret);
30
- };
31
- this._shell = new Shell(this._fs, outputCallback);
32
- console.log('==> shell', this._shell);
35
+ this._socket = socket;
33
36
  socket.on('message', async (message) => {
34
37
  const data = JSON.parse(message);
35
- console.log('==> socket message', data);
38
+ //console.log('==> socket message', data);
36
39
  const message_type = data[0];
37
40
  const content = data.slice(1);
38
41
  if (message_type === 'stdin') {
@@ -1,4 +1,4 @@
1
- import { Contents, TerminalAPI } from '@jupyterlab/services';
1
+ import { TerminalAPI } from '@jupyterlab/services';
2
2
  import { ITerminals } from './tokens';
3
3
  /**
4
4
  * A class to handle requests to /api/terminals
@@ -7,7 +7,7 @@ export declare class Terminals implements ITerminals {
7
7
  /**
8
8
  * Construct a new Terminals object.
9
9
  */
10
- constructor(wsUrl: string, contentsManager: Contents.IManager);
10
+ constructor(wsUrl: string);
11
11
  /**
12
12
  * List the running terminals.
13
13
  */
@@ -18,6 +18,5 @@ export declare class Terminals implements ITerminals {
18
18
  startNew(): Promise<TerminalAPI.IModel>;
19
19
  private _nextAvailableName;
20
20
  private _wsUrl;
21
- private _contentsManager;
22
21
  private _terminals;
23
22
  }
package/lib/terminals.js CHANGED
@@ -1,5 +1,6 @@
1
1
  // Copyright (c) Jupyter Development Team.
2
2
  // Distributed under the terms of the Modified BSD License.
3
+ import { PageConfig } from '@jupyterlab/coreutils';
3
4
  import { Terminal } from './terminal';
4
5
  /**
5
6
  * A class to handle requests to /api/terminals
@@ -8,11 +9,10 @@ export class Terminals {
8
9
  /**
9
10
  * Construct a new Terminals object.
10
11
  */
11
- constructor(wsUrl, contentsManager) {
12
+ constructor(wsUrl) {
12
13
  this._terminals = new Map();
13
14
  this._wsUrl = wsUrl;
14
- this._contentsManager = contentsManager;
15
- console.log('==> Terminals.constructor', this._wsUrl, this._contentsManager);
15
+ console.log('==> Terminals.constructor', this._wsUrl);
16
16
  }
17
17
  /**
18
18
  * List the running terminals.
@@ -30,7 +30,8 @@ export class Terminals {
30
30
  async startNew() {
31
31
  const name = this._nextAvailableName();
32
32
  console.log('==> Terminals.new', name);
33
- const term = new Terminal({ name, contentsManager: this._contentsManager });
33
+ const baseUrl = PageConfig.getBaseUrl();
34
+ const term = new Terminal({ name, baseUrl });
34
35
  this._terminals.set(name, term);
35
36
  const url = `${this._wsUrl}terminals/websocket/${name}`;
36
37
  await term.wsConnect(url);
package/lib/tokens.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Contents, TerminalAPI } from '@jupyterlab/services';
1
+ import { TerminalAPI } from '@jupyterlab/services';
2
2
  import { Token } from '@lumino/coreutils';
3
3
  /**
4
4
  * The token for the Terminals service.
@@ -38,6 +38,6 @@ export declare namespace ITerminal {
38
38
  * The name of the terminal.
39
39
  */
40
40
  name: string;
41
- contentsManager: Contents.IManager;
41
+ baseUrl: string;
42
42
  }
43
43
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jupyterlite/terminal",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "A terminal for JupyterLite",
5
5
  "keywords": [
6
6
  "jupyter",
@@ -30,12 +30,13 @@
30
30
  "url": "https://github.com/jupyterlite/terminal.git"
31
31
  },
32
32
  "scripts": {
33
- "build": "jlpm build:lib && jlpm build:labextension:dev",
34
- "build:prod": "jlpm clean && jlpm build:lib:prod && jlpm build:labextension",
33
+ "build": "jlpm build:lib && jlpm build:labextension:dev && jlpm build:copywasm",
34
+ "build:prod": "jlpm clean && jlpm build:lib:prod && jlpm build:labextension && jlpm build:copywasm",
35
35
  "build:labextension": "jupyter labextension build .",
36
36
  "build:labextension:dev": "jupyter labextension build --development True .",
37
37
  "build:lib": "tsc --sourceMap",
38
38
  "build:lib:prod": "tsc",
39
+ "build:copywasm": "cp -r node_modules/@jupyterlite/cockle/lib/wasm jupyterlite_terminal/labextension/static/",
39
40
  "clean": "jlpm clean:lib",
40
41
  "clean:lib": "rimraf lib tsconfig.tsbuildinfo",
41
42
  "clean:lintcache": "rimraf .eslintcache .stylelintcache",
@@ -57,17 +58,19 @@
57
58
  "watch:labextension": "jupyter labextension watch ."
58
59
  },
59
60
  "dependencies": {
60
- "@jupyterlab/services": "^7.2.0",
61
- "@jupyterlab/terminal": "^4.2.0",
62
- "@jupyterlab/terminal-extension": "^4.2.0",
63
- "@jupyterlite/cockle": "^0.0.3",
64
- "@jupyterlite/server": "^0.3.0",
65
- "@lumino/coreutils": "^2.1.2",
61
+ "@jupyterlab/coreutils": "^6.2.4",
62
+ "@jupyterlab/services": "^7.2.4",
63
+ "@jupyterlab/terminal": "^4.2.4",
64
+ "@jupyterlab/terminal-extension": "^4.2.4",
65
+ "@jupyterlite/cockle": "^0.0.8",
66
+ "@jupyterlite/contents": "^0.4.0",
67
+ "@jupyterlite/server": "^0.4.0",
68
+ "@lumino/coreutils": "^2.2.0",
66
69
  "mock-socket": "^9.3.1"
67
70
  },
68
71
  "devDependencies": {
69
- "@jupyterlab/builder": "^4.0.0",
70
- "@jupyterlab/testutils": "^4.0.0",
72
+ "@jupyterlab/builder": "^4.2.4",
73
+ "@jupyterlab/testutils": "^4.2.4",
71
74
  "@types/jest": "^29.2.0",
72
75
  "@types/json-schema": "^7.0.11",
73
76
  "@types/react": "^18.0.26",
@@ -90,6 +93,8 @@
90
93
  "stylelint-csstree-validator": "^3.0.0",
91
94
  "stylelint-prettier": "^4.0.0",
92
95
  "typescript": "~5.0.2",
96
+ "webpack": "^5.87.0",
97
+ "webpack-cli": "^5.1.4",
93
98
  "yjs": "^13.5.0"
94
99
  },
95
100
  "sideEffects": [
@@ -102,7 +107,8 @@
102
107
  },
103
108
  "jupyterlab": {
104
109
  "extension": true,
105
- "outputDir": "jupyterlite_terminal/labextension"
110
+ "outputDir": "jupyterlite_terminal/labextension",
111
+ "webpackConfig": "./webpack.extra.config.js"
106
112
  },
107
113
  "jupyterlite": {
108
114
  "liteExtension": true
package/src/index.ts CHANGED
@@ -24,7 +24,7 @@ const terminalsPlugin: JupyterLiteServerPlugin<ITerminals> = {
24
24
  );
25
25
 
26
26
  const { serviceManager } = app;
27
- const { contents, serverSettings, terminals } = serviceManager;
27
+ const { serverSettings, terminals } = serviceManager;
28
28
  console.log('terminals available:', terminals.isAvailable());
29
29
  console.log('terminals ready:', terminals.isReady); // Not ready
30
30
  console.log('terminals active:', terminals.isActive);
@@ -33,7 +33,7 @@ const terminalsPlugin: JupyterLiteServerPlugin<ITerminals> = {
33
33
  await terminals.ready;
34
34
  console.log('terminals ready after await:', terminals.isReady); // Ready
35
35
 
36
- return new Terminals(serverSettings.wsUrl, contents);
36
+ return new Terminals(serverSettings.wsUrl);
37
37
  }
38
38
  };
39
39
 
@@ -52,7 +52,7 @@ const terminalsRoutesPlugin: JupyterLiteServerPlugin<void> = {
52
52
 
53
53
  // GET /api/terminals - List the running terminals
54
54
  app.router.get('/api/terminals', async (req: Router.IRequest) => {
55
- const res = terminals.list();
55
+ const res = await terminals.list();
56
56
  // Should return last_activity for each too,
57
57
  return new Response(JSON.stringify(res));
58
58
  });
package/src/terminal.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  // Copyright (c) Jupyter Development Team.
2
2
  // Distributed under the terms of the Modified BSD License.
3
3
 
4
- import { JupyterFileSystem, Shell, IFileSystem } from '@jupyterlite/cockle';
5
-
4
+ import { Shell } from '@jupyterlite/cockle';
6
5
  import { JSONPrimitive } from '@lumino/coreutils';
7
6
 
8
7
  import {
@@ -16,49 +15,51 @@ export class Terminal implements ITerminal {
16
15
  /**
17
16
  * Construct a new Terminal.
18
17
  */
19
- constructor(options: ITerminal.IOptions) {
20
- this._name = options.name;
21
- this._fs = new JupyterFileSystem(options.contentsManager);
22
- console.log('==> new Terminal', this._name, this._fs);
18
+ constructor(readonly options: ITerminal.IOptions) {
19
+ this._shell = new Shell({
20
+ mountpoint: '/drive',
21
+ driveFsBaseUrl: options.baseUrl,
22
+ wasmBaseUrl:
23
+ options.baseUrl + 'extensions/@jupyterlite/terminal/static/wasm/',
24
+ outputCallback: this._outputCallback.bind(this)
25
+ });
26
+ }
27
+
28
+ private async _outputCallback(text: string): Promise<void> {
29
+ if (this._socket) {
30
+ const ret = JSON.stringify(['stdout', text]);
31
+ this._socket.send(ret);
32
+ }
23
33
  }
24
34
 
25
35
  /**
26
36
  * Get the name of the terminal.
27
37
  */
28
38
  get name(): string {
29
- return this._name;
39
+ return this.options.name;
30
40
  }
31
41
 
32
42
  async wsConnect(url: string) {
33
43
  console.log('==> Terminal.wsConnect', url);
34
44
 
35
- // const server = new WebSocketServer(url, { mock: false });
36
45
  const server = new WebSocketServer(url);
37
46
 
38
47
  server.on('connection', async (socket: WebSocketClient) => {
39
48
  console.log('==> server connection', this, socket);
40
-
41
- const outputCallback = async (output: string) => {
42
- console.log('==> recv from shell:', output);
43
- const ret = JSON.stringify(['stdout', output]);
44
- socket.send(ret);
45
- };
46
-
47
- this._shell = new Shell(this._fs, outputCallback);
48
- console.log('==> shell', this._shell);
49
+ this._socket = socket;
49
50
 
50
51
  socket.on('message', async (message: any) => {
51
52
  const data = JSON.parse(message) as JSONPrimitive[];
52
- console.log('==> socket message', data);
53
+ //console.log('==> socket message', data);
53
54
  const message_type = data[0];
54
55
  const content = data.slice(1);
55
56
 
56
57
  if (message_type === 'stdin') {
57
- await this._shell!.input(content[0] as string);
58
+ await this._shell.input(content[0] as string);
58
59
  } else if (message_type === 'set_size') {
59
60
  const rows = content[0] as number;
60
61
  const columns = content[1] as number;
61
- await this._shell!.setSize(rows, columns);
62
+ await this._shell.setSize(rows, columns);
62
63
  }
63
64
  });
64
65
 
@@ -75,11 +76,10 @@ export class Terminal implements ITerminal {
75
76
  console.log('==> Returning handshake via socket', res);
76
77
  socket.send(res);
77
78
 
78
- await this._shell!.start();
79
+ await this._shell.start();
79
80
  });
80
81
  }
81
82
 
82
- private _name: string;
83
- private _fs: IFileSystem;
84
- private _shell?: Shell;
83
+ private _socket?: WebSocketClient;
84
+ private _shell: Shell;
85
85
  }
package/src/terminals.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  // Copyright (c) Jupyter Development Team.
2
2
  // Distributed under the terms of the Modified BSD License.
3
3
 
4
- import { Contents, TerminalAPI } from '@jupyterlab/services';
4
+ import { PageConfig } from '@jupyterlab/coreutils';
5
+ import { TerminalAPI } from '@jupyterlab/services';
5
6
 
6
7
  import { Terminal } from './terminal';
7
8
  import { ITerminals } from './tokens';
@@ -13,14 +14,9 @@ export class Terminals implements ITerminals {
13
14
  /**
14
15
  * Construct a new Terminals object.
15
16
  */
16
- constructor(wsUrl: string, contentsManager: Contents.IManager) {
17
+ constructor(wsUrl: string) {
17
18
  this._wsUrl = wsUrl;
18
- this._contentsManager = contentsManager;
19
- console.log(
20
- '==> Terminals.constructor',
21
- this._wsUrl,
22
- this._contentsManager
23
- );
19
+ console.log('==> Terminals.constructor', this._wsUrl);
24
20
  }
25
21
 
26
22
  /**
@@ -40,7 +36,8 @@ export class Terminals implements ITerminals {
40
36
  async startNew(): Promise<TerminalAPI.IModel> {
41
37
  const name = this._nextAvailableName();
42
38
  console.log('==> Terminals.new', name);
43
- const term = new Terminal({ name, contentsManager: this._contentsManager });
39
+ const baseUrl = PageConfig.getBaseUrl();
40
+ const term = new Terminal({ name, baseUrl });
44
41
  this._terminals.set(name, term);
45
42
 
46
43
  const url = `${this._wsUrl}terminals/websocket/${name}`;
@@ -59,6 +56,5 @@ export class Terminals implements ITerminals {
59
56
  }
60
57
 
61
58
  private _wsUrl: string;
62
- private _contentsManager: Contents.IManager;
63
59
  private _terminals: Map<string, Terminal> = new Map();
64
60
  }
package/src/tokens.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  // Copyright (c) Jupyter Development Team.
2
2
  // Distributed under the terms of the Modified BSD License.
3
3
 
4
- import { Contents, TerminalAPI } from '@jupyterlab/services';
4
+ import { TerminalAPI } from '@jupyterlab/services';
5
5
 
6
6
  import { Token } from '@lumino/coreutils';
7
7
 
@@ -50,6 +50,6 @@ export namespace ITerminal {
50
50
  */
51
51
  name: string;
52
52
 
53
- contentsManager: Contents.IManager;
53
+ baseUrl: string;
54
54
  }
55
55
  }