-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1076c3f
commit b6ee9e0
Showing
7 changed files
with
245 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -123,3 +123,6 @@ dmypy.json | |
|
||
# Yarn cache | ||
.yarn/ | ||
|
||
.jupyterlite.doit.db | ||
_output/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"jupyter-lite-schema-version": 0, | ||
"jupyter-config-data": { | ||
"terminalsAvailable": true | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,69 @@ | ||
// Copyright (c) Jupyter Development Team. | ||
// Distributed under the terms of the Modified BSD License. | ||
|
||
import { | ||
JupyterFrontEnd, | ||
JupyterFrontEndPlugin | ||
} from '@jupyterlab/application'; | ||
JupyterLiteServer, | ||
JupyterLiteServerPlugin, | ||
Router, | ||
} from '@jupyterlite/server'; | ||
import { ITerminalTracker } from '@jupyterlab/terminal'; | ||
|
||
import { ITerminals } from './tokens'; | ||
import { Terminals } from './terminals'; | ||
|
||
|
||
/** | ||
* Initialization data for the jupyterlite-terminal extension. | ||
* The terminals service plugin. | ||
*/ | ||
const plugin: JupyterFrontEndPlugin<void> = { | ||
const terminalsPlugin: JupyterLiteServerPlugin<ITerminals> = { | ||
id: 'jupyterlite-terminal:plugin', | ||
description: 'A terminal for JupyterLite', | ||
autoStart: true, | ||
activate: (app: JupyterFrontEnd) => { | ||
console.log('JupyterLab extension jupyterlite-terminal is activated!'); | ||
requires: [ITerminalTracker], | ||
provides: ITerminals, | ||
activate: async (app: JupyterLiteServer, tracker: ITerminalTracker) => { | ||
console.log('JupyterLab extension jupyterlite-terminal:plugin is activated!'); | ||
|
||
console.log("==> ITerminalTracker", tracker); | ||
|
||
const { serviceManager } = app; | ||
const { contents, serverSettings, terminals } = serviceManager; | ||
console.log("terminals available:", terminals.isAvailable()); | ||
console.log("terminals ready:", terminals.isReady); // Not ready | ||
console.log("terminals active:", terminals.isActive); | ||
|
||
// Not sure this is necessary? | ||
await terminals.ready; | ||
console.log("terminals ready after await:", terminals.isReady); // Ready | ||
|
||
return new Terminals(serverSettings.wsUrl, contents); | ||
} | ||
}; | ||
|
||
export default plugin; | ||
/** | ||
* A plugin providing the routes for the terminals service | ||
*/ | ||
const terminalsRoutesPlugin: JupyterLiteServerPlugin<void> = { | ||
id: 'jupyterlite-terminal:routes-plugin', | ||
autoStart: true, | ||
requires: [ITerminals], | ||
activate: (app: JupyterLiteServer, terminals: ITerminals) => { | ||
console.log('JupyterLab extension jupyterlite-terminal:routes-plugin is activated!', terminals); | ||
|
||
// GET /api/terminals - List the running terminals | ||
app.router.get('/api/terminals', async (req: Router.IRequest) => { | ||
const res = terminals.list(); | ||
// Should return last_activity for each too, | ||
return new Response(JSON.stringify(res)); | ||
}); | ||
|
||
// POST /api/terminals - Start a terminal | ||
app.router.post('/api/terminals', async (req: Router.IRequest) => { | ||
const res = await terminals.startNew(); | ||
// Should return last_activity too. | ||
return new Response(JSON.stringify(res)); | ||
}); | ||
}, | ||
}; | ||
|
||
export default [terminalsPlugin, terminalsRoutesPlugin]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// Copyright (c) Jupyter Development Team. | ||
// Distributed under the terms of the Modified BSD License. | ||
|
||
import { JSONPrimitive } from '@lumino/coreutils'; | ||
|
||
import { Server as WebSocketServer, Client as WebSocketClient } from 'mock-socket'; | ||
|
||
import { ITerminal } from './tokens'; | ||
|
||
export class Terminal implements ITerminal { | ||
/** | ||
* Construct a new Terminal. | ||
*/ | ||
constructor(options: ITerminal.IOptions) { | ||
this._name = options.name; | ||
} | ||
|
||
/** | ||
* Get the name of the terminal. | ||
*/ | ||
get name(): string { | ||
return this._name; | ||
} | ||
|
||
async wsConnect(url: string) { | ||
console.log("==> Terminal.wsConnect", url); | ||
|
||
const server = new WebSocketServer(url, { mock: false }); | ||
|
||
server.on('connection', async (socket: WebSocketClient) => { | ||
console.log("==> server connection", this, socket); | ||
|
||
socket.on('message', async (message: any) => { | ||
const data = JSON.parse(message) as JSONPrimitive[]; | ||
console.log("==> socket message", data); | ||
}); | ||
|
||
socket.on('close', async () => { | ||
console.log("==> socket close"); | ||
}); | ||
|
||
socket.on('error', async () => { | ||
console.log("==> socket error"); | ||
}); | ||
|
||
// Return handshake. | ||
const res = JSON.stringify(['setup']); | ||
console.log("==> Returning handshake via socket", res); | ||
socket.send(res); | ||
}); | ||
} | ||
|
||
private _name: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// Copyright (c) Jupyter Development Team. | ||
// Distributed under the terms of the Modified BSD License. | ||
|
||
import { Contents, TerminalAPI } from '@jupyterlab/services'; | ||
|
||
import { Terminal } from './terminal'; | ||
import { ITerminals } from './tokens'; | ||
|
||
/** | ||
* A class to handle requests to /api/terminals | ||
*/ | ||
export class Terminals implements ITerminals { | ||
/** | ||
* Construct a new Terminals object. | ||
*/ | ||
constructor(wsUrl: string, contentsManager: Contents.IManager) { | ||
this._wsUrl = wsUrl; | ||
this._contentsManager = contentsManager; | ||
console.log("==> Terminals.constructor", this._wsUrl, this._contentsManager); | ||
} | ||
|
||
/** | ||
* List the running terminals. | ||
*/ | ||
async list(): Promise<TerminalAPI.IModel[]> { | ||
const ret = [...this._terminals.values()].map((terminal) => ({ | ||
name: terminal.name, | ||
})); | ||
console.log("==> Terminals.list", ret); | ||
return ret; | ||
} | ||
|
||
/** | ||
* Start a new kernel. | ||
*/ | ||
async startNew(): Promise<TerminalAPI.IModel> { | ||
const name = this._nextAvailableName(); | ||
console.log("==> Terminals.new", name); | ||
const term = new Terminal({ name, contentsManager: this._contentsManager }); | ||
this._terminals.set(name, term); | ||
|
||
const url = `${this._wsUrl}terminals/websocket/${name}`; | ||
await term.wsConnect(url); | ||
|
||
return { name }; | ||
} | ||
|
||
private _nextAvailableName(): string { | ||
for (let i = 1; ; ++i) { | ||
const name = `${i}`; | ||
if (!this._terminals.has(name)) { | ||
return name; | ||
} | ||
} | ||
} | ||
|
||
private _wsUrl: string; | ||
private _contentsManager: Contents.IManager; | ||
private _terminals: Map<string, Terminal> = new Map(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// Copyright (c) Jupyter Development Team. | ||
// Distributed under the terms of the Modified BSD License. | ||
|
||
import { Contents, TerminalAPI } from '@jupyterlab/services'; | ||
|
||
import { Token } from '@lumino/coreutils'; | ||
|
||
/** | ||
* The token for the Terminals service. | ||
*/ | ||
export const ITerminals = new Token<ITerminals>('@jupyterlite/terminal:ITerminals'); | ||
|
||
/** | ||
* An interface for the Terminals service. | ||
*/ | ||
export interface ITerminals { | ||
/** | ||
* List the running terminals. | ||
*/ | ||
list: () => Promise<TerminalAPI.IModel[]>; | ||
|
||
/** | ||
* Start a new kernel. | ||
*/ | ||
startNew: () => Promise<TerminalAPI.IModel>; | ||
} | ||
|
||
/** | ||
* An interface for a server-side terminal running in the browser. | ||
*/ | ||
export interface ITerminal { | ||
/** | ||
* The name of the server-side terminal. | ||
*/ | ||
readonly name: string; | ||
} | ||
|
||
/** | ||
* A namespace for ITerminal statics. | ||
*/ | ||
export namespace ITerminal { | ||
/** | ||
* The instantiation options for an ITerminal. | ||
*/ | ||
export interface IOptions { | ||
/** | ||
* The name of the terminal. | ||
*/ | ||
name: string; | ||
|
||
contentsManager: Contents.IManager; | ||
} | ||
} |