jupyterpack 0.2.1 → 0.4.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 +2 -0
- package/lib/document/commands.d.ts +8 -0
- package/lib/document/commands.js +76 -0
- package/lib/document/iframePanel.d.ts +4 -1
- package/lib/document/plugin.d.ts +2 -1
- package/lib/document/plugin.js +22 -4
- package/lib/document/toolbar.d.ts +9 -0
- package/lib/document/toolbar.js +20 -0
- package/lib/document/widgetFactory.d.ts +2 -1
- package/lib/document/widgetFactory.js +15 -6
- package/lib/index.d.ts +1 -1
- package/lib/pythonServer/dash/dashServer.d.ts +22 -0
- package/lib/pythonServer/dash/dashServer.js +47 -0
- package/lib/pythonServer/index.d.ts +5 -0
- package/lib/pythonServer/index.js +9 -0
- package/lib/pythonServer/kernelExecutor.d.ts +71 -0
- package/lib/pythonServer/kernelExecutor.js +140 -0
- package/lib/pythonServer/streamlit/streamlitServer.d.ts +14 -0
- package/lib/pythonServer/streamlit/streamlitServer.js +51 -0
- package/lib/pythonServer/tornado/tornadoServer.d.ts +34 -0
- package/lib/pythonServer/tornado/tornadoServer.js +68 -0
- package/lib/pythonWidget/comm.d.ts +11 -0
- package/lib/pythonWidget/comm.js +52 -0
- package/lib/pythonWidget/pythonWidget.d.ts +6 -0
- package/lib/pythonWidget/pythonWidget.js +28 -3
- package/lib/pythonWidget/pythonWidgetModel.d.ts +27 -6
- package/lib/pythonWidget/pythonWidgetModel.js +101 -15
- package/lib/sandpackWidget/sandpackFilesModel.d.ts +6 -2
- package/lib/sandpackWidget/sandpackFilesModel.js +13 -2
- package/lib/sandpackWidget/sandpackPanel.d.ts +10 -1
- package/lib/sandpackWidget/sandpackPanel.js +38 -3
- package/lib/swConnection/index.js +2 -2
- package/lib/{pythonWidget/connectionManager.d.ts → swConnection/mainConnectionManager.d.ts} +10 -0
- package/lib/swConnection/mainConnectionManager.js +93 -0
- package/lib/swConnection/sw.js +1 -1
- package/lib/swConnection/swCommManager.d.ts +11 -0
- package/lib/swConnection/{comm_manager.js → swCommManager.js} +5 -0
- package/lib/token.d.ts +2 -1
- package/lib/token.js +1 -0
- package/lib/tools.d.ts +9 -0
- package/lib/tools.js +75 -0
- package/lib/type.d.ts +64 -3
- package/lib/type.js +2 -0
- package/lib/websocket/websocket.d.ts +0 -0
- package/lib/websocket/websocket.js +152 -0
- package/package.json +8 -5
- package/src/document/commands.ts +91 -0
- package/src/document/iframePanel.ts +4 -1
- package/src/document/plugin.ts +28 -7
- package/src/document/toolbar.ts +39 -0
- package/src/document/widgetFactory.ts +17 -6
- package/src/global.d.ts +9 -0
- package/src/pythonServer/dash/dashServer.ts +66 -0
- package/src/pythonServer/index.ts +18 -0
- package/src/pythonServer/kernelExecutor.ts +243 -0
- package/src/pythonServer/streamlit/streamlitServer.ts +67 -0
- package/src/pythonServer/tornado/tornadoServer.ts +97 -0
- package/src/pythonWidget/comm.ts +65 -0
- package/src/pythonWidget/pythonWidget.ts +38 -3
- package/src/pythonWidget/pythonWidgetModel.ts +155 -34
- package/src/sandpackWidget/sandpackFilesModel.ts +17 -3
- package/src/sandpackWidget/sandpackPanel.ts +45 -4
- package/src/swConnection/index.ts +5 -2
- package/src/swConnection/mainConnectionManager.ts +121 -0
- package/src/swConnection/sw.ts +1 -1
- package/src/swConnection/{comm_manager.ts → swCommManager.ts} +6 -0
- package/src/token.ts +5 -1
- package/src/tools.ts +91 -0
- package/src/type.ts +76 -4
- package/src/websocket/websocket.ts +216 -0
- package/style/base.css +7 -0
- package/style/icons/autoreload.svg +16 -0
- package/style/icons/box.svg +12 -0
- package/style/icons/externallink.svg +10 -0
- package/lib/pythonWidget/connectionManager.js +0 -27
- package/lib/pythonWidget/kernelExecutor.d.ts +0 -27
- package/lib/pythonWidget/kernelExecutor.js +0 -104
- package/lib/swConnection/comm_manager.d.ts +0 -6
- package/lib/swConnection/connection_manager.d.ts +0 -18
- package/lib/swConnection/connection_manager.js +0 -27
- package/src/pythonWidget/connectionManager.ts +0 -43
- package/src/pythonWidget/kernelExecutor.ts +0 -140
- package/src/swConnection/connection_manager.ts +0 -43
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { IConnectionManager, IDict } from '../type';
|
|
2
2
|
import { wrap, transfer } from 'comlink';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Manages communication between different components using Comlink's MessagePort-based communication.
|
|
6
|
+
* This class handles registration of communication channels and processing of requests.
|
|
7
|
+
* It's running on the service worker thread
|
|
8
|
+
*/
|
|
3
9
|
export class CommManager {
|
|
4
10
|
constructor() {}
|
|
5
11
|
registerComm(instanceId: string, port: MessagePort): void {
|
package/src/token.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { Token } from '@lumino/coreutils';
|
|
2
|
-
import { IConnectionManager } from './type';
|
|
2
|
+
import { IConnectionManager, IJupyterpackDocTracker } from './type';
|
|
3
3
|
|
|
4
4
|
export const IConnectionManagerToken = new Token<IConnectionManager>(
|
|
5
5
|
'jupyterpack:connection-manager'
|
|
6
6
|
);
|
|
7
|
+
|
|
8
|
+
export const IJupyterpackDocTrackerToken = new Token<IJupyterpackDocTracker>(
|
|
9
|
+
'jupyterpack:dock-tracker'
|
|
10
|
+
);
|
package/src/tools.ts
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
import logoStr from '../style/icons/box.svg';
|
|
2
|
+
import autoReloadStr from '../style/icons/autoreload.svg';
|
|
3
|
+
import linkStr from '../style/icons/externallink.svg';
|
|
4
|
+
import { LabIcon } from '@jupyterlab/ui-components';
|
|
5
|
+
|
|
6
|
+
export const IS_LITE = !!document.getElementById('jupyter-lite-main');
|
|
7
|
+
|
|
8
|
+
export const logoIcon = new LabIcon({
|
|
9
|
+
name: 'jupyterpack:logo',
|
|
10
|
+
svgstr: logoStr
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export const autoReloadIcon = new LabIcon({
|
|
14
|
+
name: 'jupyterpack:autoReload',
|
|
15
|
+
svgstr: autoReloadStr
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export const linkIcon = new LabIcon({
|
|
19
|
+
name: 'jupyterpack:externalLink',
|
|
20
|
+
svgstr: linkStr
|
|
21
|
+
});
|
|
22
|
+
|
|
1
23
|
export function removePrefix(path: string, prefix: string): string {
|
|
2
24
|
if (path.startsWith(prefix)) {
|
|
3
25
|
return path.slice(prefix.length);
|
|
@@ -16,3 +38,72 @@ export function arrayBufferToBase64(buffer: ArrayBuffer) {
|
|
|
16
38
|
}
|
|
17
39
|
return btoa(binary);
|
|
18
40
|
}
|
|
41
|
+
|
|
42
|
+
export function base64ToArrayBuffer(base64: string): Uint8Array {
|
|
43
|
+
const binaryString = atob(base64);
|
|
44
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
45
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
46
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
47
|
+
}
|
|
48
|
+
return bytes;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function base64ToString(base64: string): string {
|
|
52
|
+
const bytes = base64ToArrayBuffer(base64);
|
|
53
|
+
return new TextDecoder('utf-8').decode(bytes);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function stringOrNone(content?: string) {
|
|
57
|
+
return content ? `"${content}"` : 'None';
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function isBinaryContentType(contentType?: string) {
|
|
61
|
+
if (!contentType) {
|
|
62
|
+
// no Content-Type → assume binary for safety
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
contentType = contentType.toLowerCase().trim();
|
|
67
|
+
|
|
68
|
+
const textTypes = [
|
|
69
|
+
'text/',
|
|
70
|
+
'application/json',
|
|
71
|
+
'application/javascript',
|
|
72
|
+
'application/xml',
|
|
73
|
+
'application/xhtml+xml',
|
|
74
|
+
'application/x-www-form-urlencoded',
|
|
75
|
+
'application/sql',
|
|
76
|
+
'application/graphql',
|
|
77
|
+
'application/yaml'
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
const binaryIndicators = [
|
|
81
|
+
'image/',
|
|
82
|
+
'audio/',
|
|
83
|
+
'video/',
|
|
84
|
+
'font/',
|
|
85
|
+
'application/octet-stream',
|
|
86
|
+
'application/pdf',
|
|
87
|
+
'application/zip',
|
|
88
|
+
'application/x-protobuf',
|
|
89
|
+
'application/vnd'
|
|
90
|
+
];
|
|
91
|
+
|
|
92
|
+
// Starts with text/ or one of the textual types
|
|
93
|
+
if (textTypes.some(t => contentType.startsWith(t))) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Starts with binary-indicating prefix
|
|
98
|
+
if (binaryIndicators.some(t => contentType.startsWith(t))) {
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// If charset is specified → text
|
|
103
|
+
if (contentType.includes('charset=')) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Default: assume binary
|
|
108
|
+
return true;
|
|
109
|
+
}
|
package/src/type.ts
CHANGED
|
@@ -1,19 +1,41 @@
|
|
|
1
|
+
import { DocumentWidget } from '@jupyterlab/docregistry';
|
|
1
2
|
import { KernelMessage } from '@jupyterlab/services';
|
|
2
3
|
import { IDisposable } from '@lumino/disposable';
|
|
4
|
+
import { IWidgetTracker } from '@jupyterlab/apputils';
|
|
5
|
+
import { ISignal } from '@lumino/signaling';
|
|
3
6
|
|
|
4
7
|
export interface IDict<T = any> {
|
|
5
8
|
[key: string]: T;
|
|
6
9
|
}
|
|
7
10
|
|
|
11
|
+
export interface IBroadcastMessage {
|
|
12
|
+
action:
|
|
13
|
+
| 'message'
|
|
14
|
+
| 'open'
|
|
15
|
+
| 'close'
|
|
16
|
+
| 'error'
|
|
17
|
+
| 'send'
|
|
18
|
+
| 'connected'
|
|
19
|
+
| 'backend_message';
|
|
20
|
+
dest: string;
|
|
21
|
+
wsUrl: string;
|
|
22
|
+
payload?: any;
|
|
23
|
+
}
|
|
24
|
+
|
|
8
25
|
export enum JupyterPackFramework {
|
|
9
26
|
REACT = 'react',
|
|
10
|
-
DASH = 'dash'
|
|
27
|
+
DASH = 'dash',
|
|
28
|
+
STREAMLIT = 'streamlit',
|
|
29
|
+
TORNADO = 'tornado'
|
|
11
30
|
}
|
|
12
31
|
export interface IJupyterPackFileFormat {
|
|
13
32
|
entry: string;
|
|
14
33
|
framework: JupyterPackFramework;
|
|
15
34
|
name?: string;
|
|
16
|
-
metadata?:
|
|
35
|
+
metadata?: {
|
|
36
|
+
autoreload?: boolean;
|
|
37
|
+
};
|
|
38
|
+
rootUrl?: string;
|
|
17
39
|
}
|
|
18
40
|
|
|
19
41
|
export enum MessageAction {
|
|
@@ -29,9 +51,40 @@ export interface IKernelExecutorParams {
|
|
|
29
51
|
}
|
|
30
52
|
export interface IKernelExecutor extends IDisposable {
|
|
31
53
|
getResponse(options: IKernelExecutorParams): Promise<IDict>;
|
|
54
|
+
openWebsocket(options: {
|
|
55
|
+
instanceId: string;
|
|
56
|
+
kernelId: string;
|
|
57
|
+
wsUrl: string;
|
|
58
|
+
protocol?: string;
|
|
59
|
+
}): Promise<void>;
|
|
60
|
+
sendWebsocketMessage(options: {
|
|
61
|
+
instanceId: string;
|
|
62
|
+
kernelId: string;
|
|
63
|
+
wsUrl: string;
|
|
64
|
+
message: string;
|
|
65
|
+
}): Promise<void>;
|
|
32
66
|
executeCode(
|
|
33
|
-
code: KernelMessage.IExecuteRequestMsg['content']
|
|
34
|
-
|
|
67
|
+
code: KernelMessage.IExecuteRequestMsg['content'],
|
|
68
|
+
waitForResult?: boolean
|
|
69
|
+
): Promise<string | null>;
|
|
70
|
+
init(options: {
|
|
71
|
+
entryPath?: string;
|
|
72
|
+
initCode?: string;
|
|
73
|
+
instanceId: string;
|
|
74
|
+
kernelClientId: string;
|
|
75
|
+
}): Promise<void>;
|
|
76
|
+
disposePythonServer(): Promise<void>;
|
|
77
|
+
reloadPythonServer(options: {
|
|
78
|
+
entryPath?: string;
|
|
79
|
+
initCode?: string;
|
|
80
|
+
}): Promise<void>;
|
|
81
|
+
getResponseFunctionFactory(options: {
|
|
82
|
+
urlPath: string;
|
|
83
|
+
method: string;
|
|
84
|
+
headers: IDict;
|
|
85
|
+
params?: string;
|
|
86
|
+
content?: string;
|
|
87
|
+
}): string;
|
|
35
88
|
}
|
|
36
89
|
|
|
37
90
|
export interface IConnectionManager {
|
|
@@ -42,3 +95,22 @@ export interface IConnectionManager {
|
|
|
42
95
|
option: { kernelClientId: string } & IKernelExecutorParams
|
|
43
96
|
): Promise<IDict | null>;
|
|
44
97
|
}
|
|
98
|
+
|
|
99
|
+
export type IJupyterpackDocTracker = IWidgetTracker<DocumentWidget>;
|
|
100
|
+
|
|
101
|
+
export interface IPythonWidgetModel extends IDisposable {
|
|
102
|
+
connectionManager: IConnectionManager;
|
|
103
|
+
serverReloaded: ISignal<IPythonWidgetModel, void>;
|
|
104
|
+
kernelStatusChanged: ISignal<IPythonWidgetModel, 'started' | 'stopped'>;
|
|
105
|
+
reload(): Promise<void>;
|
|
106
|
+
initialize(): Promise<
|
|
107
|
+
| {
|
|
108
|
+
success: true;
|
|
109
|
+
instanceId: string;
|
|
110
|
+
kernelClientId: string;
|
|
111
|
+
rootUrl: string;
|
|
112
|
+
framework: JupyterPackFramework;
|
|
113
|
+
}
|
|
114
|
+
| { success: false; error: string }
|
|
115
|
+
>;
|
|
116
|
+
}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
(() => {
|
|
2
|
+
const urlPath = new URL(window.location.href).pathname;
|
|
3
|
+
const pathAfterExtensionName: string | undefined = urlPath.split(
|
|
4
|
+
'/jupyterpack/static'
|
|
5
|
+
)[1];
|
|
6
|
+
const pathList = pathAfterExtensionName?.split('/').filter(Boolean);
|
|
7
|
+
const instanceId = pathList?.[0];
|
|
8
|
+
const kernelClientId = pathList?.[2];
|
|
9
|
+
if (!instanceId || !kernelClientId) {
|
|
10
|
+
throw new Error('Missing instance Id or kernelClient Id');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface IBroadcastMessage {
|
|
14
|
+
action:
|
|
15
|
+
| 'message'
|
|
16
|
+
| 'open'
|
|
17
|
+
| 'close'
|
|
18
|
+
| 'error'
|
|
19
|
+
| 'send'
|
|
20
|
+
| 'connected'
|
|
21
|
+
| 'backend_message';
|
|
22
|
+
dest: string;
|
|
23
|
+
wsUrl: string;
|
|
24
|
+
payload?: any;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const sendTypedMessage = (msg: Omit<IBroadcastMessage, 'dest'>) => {
|
|
28
|
+
bcWsChannel.postMessage({ ...msg, dest: kernelClientId });
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
function base64ToBinary(base64: string, dataType: BinaryType) {
|
|
32
|
+
const binary = atob(base64); // decode base64
|
|
33
|
+
const len = binary.length;
|
|
34
|
+
const bytes = new Uint8Array(len);
|
|
35
|
+
for (let i = 0; i < len; i++) {
|
|
36
|
+
bytes[i] = binary.charCodeAt(i);
|
|
37
|
+
}
|
|
38
|
+
if (dataType === 'arraybuffer') {
|
|
39
|
+
return bytes.buffer;
|
|
40
|
+
} else if (dataType === 'blob') {
|
|
41
|
+
return new Blob([bytes], { type: 'application/octet-stream' });
|
|
42
|
+
} else {
|
|
43
|
+
throw new Error("Unsupported type: use 'arraybuffer' or 'blob'");
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const decodeServerMessage = (
|
|
48
|
+
payload: {
|
|
49
|
+
data: string;
|
|
50
|
+
isBinary: boolean;
|
|
51
|
+
},
|
|
52
|
+
binaryType: BinaryType
|
|
53
|
+
) => {
|
|
54
|
+
const { data, isBinary } = payload;
|
|
55
|
+
if (isBinary) {
|
|
56
|
+
// Decode base64 string to array buffer or blob
|
|
57
|
+
|
|
58
|
+
return base64ToBinary(data, binaryType);
|
|
59
|
+
}
|
|
60
|
+
return data;
|
|
61
|
+
};
|
|
62
|
+
const bcWsChannel = new BroadcastChannel(`/jupyterpack/ws/${instanceId}`);
|
|
63
|
+
|
|
64
|
+
class BroadcastChannelWebSocket implements WebSocket {
|
|
65
|
+
constructor(url: string | URL, protocols?: string | string[]) {
|
|
66
|
+
const urlObj = new URL(url);
|
|
67
|
+
this.url = urlObj.pathname + urlObj.search + urlObj.hash;
|
|
68
|
+
|
|
69
|
+
if (protocols) {
|
|
70
|
+
this.protocol = Array.isArray(protocols)
|
|
71
|
+
? protocols.join(',')
|
|
72
|
+
: protocols;
|
|
73
|
+
} else {
|
|
74
|
+
this.protocol = '';
|
|
75
|
+
}
|
|
76
|
+
this.binaryType = 'blob';
|
|
77
|
+
this.bufferedAmount = 0;
|
|
78
|
+
this.extensions = '';
|
|
79
|
+
|
|
80
|
+
this.readyState = this.CONNECTING;
|
|
81
|
+
this._open();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
onclose: ((this: WebSocket, ev?: CloseEvent) => any) | null = () => {
|
|
85
|
+
// no-op
|
|
86
|
+
};
|
|
87
|
+
onerror: ((this: WebSocket, ev: Event) => any) | null = () => {
|
|
88
|
+
// no-op
|
|
89
|
+
};
|
|
90
|
+
onmessage:
|
|
91
|
+
| ((this: WebSocket, ev: MessageEvent | { data: any }) => any)
|
|
92
|
+
| null = () => {
|
|
93
|
+
// no-op
|
|
94
|
+
};
|
|
95
|
+
onopen: ((this: WebSocket, ev: Event | { data: any }) => any) | null =
|
|
96
|
+
() => {
|
|
97
|
+
// no-op
|
|
98
|
+
};
|
|
99
|
+
close(code?: unknown, reason?: unknown): void {
|
|
100
|
+
if (this.readyState === this.CLOSED) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (this.onclose) {
|
|
105
|
+
this.onclose();
|
|
106
|
+
}
|
|
107
|
+
while (this._eventHandlers['close'].length) {
|
|
108
|
+
const cb = this._eventHandlers['close'].pop();
|
|
109
|
+
cb();
|
|
110
|
+
}
|
|
111
|
+
this._eventHandlers['close'] = [];
|
|
112
|
+
bcWsChannel.removeEventListener('message', this._bcMessageHandler);
|
|
113
|
+
|
|
114
|
+
this.readyState = this.CLOSED;
|
|
115
|
+
}
|
|
116
|
+
send(data: unknown): void {
|
|
117
|
+
sendTypedMessage({
|
|
118
|
+
action: 'send',
|
|
119
|
+
payload: data,
|
|
120
|
+
wsUrl: this.url
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
addEventListener(
|
|
125
|
+
type: 'message' | 'open' | 'close' | 'error',
|
|
126
|
+
listener: unknown,
|
|
127
|
+
options?: unknown
|
|
128
|
+
): void {
|
|
129
|
+
this._eventHandlers[type].push(listener);
|
|
130
|
+
}
|
|
131
|
+
removeEventListener(
|
|
132
|
+
type: 'message' | 'open' | 'close' | 'error',
|
|
133
|
+
listener: unknown,
|
|
134
|
+
options?: unknown
|
|
135
|
+
): void {
|
|
136
|
+
this._eventHandlers[type] = this._eventHandlers[type].filter(
|
|
137
|
+
handler => handler !== listener
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
dispatchEvent(event: unknown): boolean {
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
readyState: number;
|
|
145
|
+
url: string;
|
|
146
|
+
protocol: string;
|
|
147
|
+
binaryType: BinaryType;
|
|
148
|
+
bufferedAmount: number;
|
|
149
|
+
extensions: string;
|
|
150
|
+
|
|
151
|
+
readonly CONNECTING = 0;
|
|
152
|
+
readonly OPEN = 1;
|
|
153
|
+
readonly CLOSING = 2;
|
|
154
|
+
readonly CLOSED = 3;
|
|
155
|
+
|
|
156
|
+
private _eventHandlers: {
|
|
157
|
+
message: any[];
|
|
158
|
+
open: any[];
|
|
159
|
+
close: any[];
|
|
160
|
+
error: any[];
|
|
161
|
+
} = { message: [], open: [], close: [], error: [] };
|
|
162
|
+
|
|
163
|
+
private _bcMessageHandler = async (event: MessageEvent) => {
|
|
164
|
+
const rawData = event.data;
|
|
165
|
+
let data: IBroadcastMessage;
|
|
166
|
+
if (typeof rawData === 'string') {
|
|
167
|
+
data = JSON.parse(rawData);
|
|
168
|
+
} else {
|
|
169
|
+
data = rawData;
|
|
170
|
+
}
|
|
171
|
+
const { action, dest, wsUrl, payload } = data;
|
|
172
|
+
if (dest !== kernelClientId || wsUrl !== this.url) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
switch (action) {
|
|
176
|
+
case 'connected': {
|
|
177
|
+
this.readyState = this.OPEN;
|
|
178
|
+
|
|
179
|
+
if (this.onopen) {
|
|
180
|
+
this.onopen(event);
|
|
181
|
+
}
|
|
182
|
+
this._eventHandlers.open.forEach(handler =>
|
|
183
|
+
handler({ data: payload })
|
|
184
|
+
);
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
case 'backend_message': {
|
|
189
|
+
const decoded = decodeServerMessage(payload, this.binaryType);
|
|
190
|
+
if (this.onmessage) {
|
|
191
|
+
this.onmessage({ data: decoded });
|
|
192
|
+
}
|
|
193
|
+
this._eventHandlers.message.forEach(handler =>
|
|
194
|
+
handler({ data: decoded })
|
|
195
|
+
);
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
default:
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
private _open = () => {
|
|
203
|
+
sendTypedMessage({
|
|
204
|
+
action: 'open',
|
|
205
|
+
payload: {
|
|
206
|
+
protocol: this.protocol
|
|
207
|
+
},
|
|
208
|
+
wsUrl: this.url
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
bcWsChannel.addEventListener('message', this._bcMessageHandler);
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
window.WebSocket = BroadcastChannelWebSocket as any;
|
|
216
|
+
})();
|
package/style/base.css
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
|
|
3
|
+
<svg height="800px" width="800px" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
|
|
4
|
+
<g>
|
|
5
|
+
<path d="M403.925,108.102c-27.595-27.595-62.899-47.558-102.459-56.29L304.182,0L201.946,53.867l-27.306,14.454
|
|
6
|
+
l-5.066,2.654l8.076,4.331l38.16,20.542l81.029,43.602l2.277-42.859c28.265,7.546,53.438,22.53,73.623,42.638
|
|
7
|
+
c29.94,29.939,48.358,71.119,48.358,116.776c0,23.407-4.843,45.58-13.575,65.687l40.37,17.532
|
|
8
|
+
c11.076-25.463,17.242-53.637,17.242-83.219C465.212,198.306,441.727,145.904,403.925,108.102z"
|
|
9
|
+
fill="var(--jp-inverse-layout-color3)" />
|
|
10
|
+
<path d="M296.256,416.151l-81.101-43.612l-2.272,42.869c-28.26-7.555-53.51-22.53-73.618-42.636
|
|
11
|
+
c-29.945-29.95-48.364-71.12-48.364-116.767c0-23.427,4.844-45.522,13.576-65.697l-40.37-17.531
|
|
12
|
+
c-11.076,25.53-17.242,53.723-17.242,83.228c0,57.679,23.407,110.157,61.21,147.893c27.595,27.594,62.899,47.548,102.453,56.202
|
|
13
|
+
l-2.716,51.9l102.169-53.878l27.455-14.454l4.988-2.643l-7.999-4.332L296.256,416.151z"
|
|
14
|
+
fill="var(--jp-inverse-layout-color3)" />
|
|
15
|
+
</g>
|
|
16
|
+
</svg>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
3
|
+
<path
|
|
4
|
+
d="M17.5777 4.43152L15.5777 3.38197C13.8221 2.46066 12.9443 2 12 2C11.0557 2 10.1779 2.46066 8.42229 3.38197L6.42229 4.43152C4.64855 5.36234 3.6059 5.9095 2.95969 6.64132L12 11.1615L21.0403 6.64132C20.3941 5.9095 19.3515 5.36234 17.5777 4.43152Z"
|
|
5
|
+
fill="var(--jp-inverse-layout-color3)" />
|
|
6
|
+
<path
|
|
7
|
+
d="M21.7484 7.96435L12.75 12.4635V21.904C13.4679 21.7252 14.2848 21.2965 15.5777 20.618L17.5777 19.5685C19.7294 18.4393 20.8052 17.8748 21.4026 16.8603C22 15.8458 22 14.5833 22 12.0585V11.9415C22 10.0489 22 8.86558 21.7484 7.96435Z"
|
|
8
|
+
fill="var(--jp-inverse-layout-color3)" />
|
|
9
|
+
<path
|
|
10
|
+
d="M11.25 21.904V12.4635L2.25164 7.96434C2 8.86557 2 10.0489 2 11.9415V12.0585C2 14.5833 2 15.8458 2.5974 16.8603C3.19479 17.8748 4.27063 18.4393 6.42229 19.5685L8.42229 20.618C9.71524 21.2965 10.5321 21.7252 11.25 21.904Z"
|
|
11
|
+
fill="var(--jp-inverse-layout-color3)" />
|
|
12
|
+
</svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
5
|
+
<g>
|
|
6
|
+
<path id="Vector"
|
|
7
|
+
d="M10.0002 5H8.2002C7.08009 5 6.51962 5 6.0918 5.21799C5.71547 5.40973 5.40973 5.71547 5.21799 6.0918C5 6.51962 5 7.08009 5 8.2002V15.8002C5 16.9203 5 17.4801 5.21799 17.9079C5.40973 18.2842 5.71547 18.5905 6.0918 18.7822C6.5192 19 7.07899 19 8.19691 19H15.8031C16.921 19 17.48 19 17.9074 18.7822C18.2837 18.5905 18.5905 18.2839 18.7822 17.9076C19 17.4802 19 16.921 19 15.8031V14M20 9V4M20 4H15M20 4L13 11"
|
|
8
|
+
stroke="var(--jp-inverse-layout-color3)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
|
9
|
+
</g>
|
|
10
|
+
</svg>
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { UUID } from '@lumino/coreutils';
|
|
2
|
-
export class ConnectionManager {
|
|
3
|
-
constructor(instanceId) {
|
|
4
|
-
this.instanceId = instanceId;
|
|
5
|
-
this._kernelExecutors = new Map();
|
|
6
|
-
}
|
|
7
|
-
async registerConnection(kernelExecutor) {
|
|
8
|
-
const uuid = UUID.uuid4();
|
|
9
|
-
this._kernelExecutors.set(uuid, kernelExecutor);
|
|
10
|
-
return { instanceId: this.instanceId, kernelClientId: uuid };
|
|
11
|
-
}
|
|
12
|
-
async generateResponse(options) {
|
|
13
|
-
const { urlPath, kernelClientId, method, params, requestBody, headers } = options;
|
|
14
|
-
const executor = this._kernelExecutors.get(kernelClientId);
|
|
15
|
-
if (!executor) {
|
|
16
|
-
return null;
|
|
17
|
-
}
|
|
18
|
-
const response = await executor.getResponse({
|
|
19
|
-
urlPath,
|
|
20
|
-
method,
|
|
21
|
-
params,
|
|
22
|
-
headers,
|
|
23
|
-
requestBody
|
|
24
|
-
});
|
|
25
|
-
return response;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { KernelMessage, Session } from '@jupyterlab/services';
|
|
2
|
-
import { IDict, IKernelExecutor } from '../type';
|
|
3
|
-
export declare class KernelExecutor implements IKernelExecutor {
|
|
4
|
-
constructor(options: KernelExecutor.IOptions);
|
|
5
|
-
get isDisposed(): boolean;
|
|
6
|
-
init(options: {
|
|
7
|
-
initCode?: string;
|
|
8
|
-
instanceId: string;
|
|
9
|
-
kernelClientId: string;
|
|
10
|
-
}): Promise<void>;
|
|
11
|
-
getResponse(options: {
|
|
12
|
-
method: string;
|
|
13
|
-
urlPath: string;
|
|
14
|
-
headers: IDict;
|
|
15
|
-
requestBody?: ArrayBuffer;
|
|
16
|
-
params?: string;
|
|
17
|
-
}): Promise<IDict>;
|
|
18
|
-
executeCode(code: KernelMessage.IExecuteRequestMsg['content']): Promise<string>;
|
|
19
|
-
dispose(): void;
|
|
20
|
-
private _isDisposed;
|
|
21
|
-
private _sessionConnection;
|
|
22
|
-
}
|
|
23
|
-
export declare namespace KernelExecutor {
|
|
24
|
-
interface IOptions {
|
|
25
|
-
sessionConnection: Session.ISessionConnection;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { PageConfig, URLExt } from '@jupyterlab/coreutils';
|
|
2
|
-
import { arrayBufferToBase64 } from '../tools';
|
|
3
|
-
export class KernelExecutor {
|
|
4
|
-
constructor(options) {
|
|
5
|
-
this._isDisposed = false;
|
|
6
|
-
this._sessionConnection = options.sessionConnection;
|
|
7
|
-
}
|
|
8
|
-
get isDisposed() {
|
|
9
|
-
return this._isDisposed;
|
|
10
|
-
}
|
|
11
|
-
async init(options) {
|
|
12
|
-
const { initCode, instanceId, kernelClientId } = options;
|
|
13
|
-
const labBaseUrl = PageConfig.getOption('baseUrl');
|
|
14
|
-
const baseURL = URLExt.join(labBaseUrl, 'extensions/jupyterpack/static', instanceId, 'dash', kernelClientId, '/');
|
|
15
|
-
const osCode = `
|
|
16
|
-
import os
|
|
17
|
-
os.environ['DASH_URL_BASE_PATHNAME'] = '${baseURL}'
|
|
18
|
-
`;
|
|
19
|
-
await this.executeCode({ code: osCode });
|
|
20
|
-
if (initCode) {
|
|
21
|
-
await this.executeCode({ code: initCode });
|
|
22
|
-
}
|
|
23
|
-
const serverCode = `
|
|
24
|
-
import httpx, json, base64
|
|
25
|
-
__monstra_transport = httpx.WSGITransport(app=app.server)
|
|
26
|
-
def __monstra_get_response(method, url, headers, content=None, params=None):
|
|
27
|
-
decoded_content = None
|
|
28
|
-
if content is not None:
|
|
29
|
-
content = base64.b64decode(content)
|
|
30
|
-
decoded_content = content.decode()
|
|
31
|
-
with httpx.Client(transport=__monstra_transport, base_url="http://testserver") as client:
|
|
32
|
-
r = client.request(method, url, headers=headers, content=content, params=params)
|
|
33
|
-
response = {
|
|
34
|
-
"headers": dict(r.headers),
|
|
35
|
-
"content": r.text,
|
|
36
|
-
"status_code": r.status_code,
|
|
37
|
-
"original_request": {"method": method, "url": url, "content": decoded_content, "params": params, "headers": headers},
|
|
38
|
-
}
|
|
39
|
-
json_str = json.dumps(response)
|
|
40
|
-
b64_str = base64.b64encode(json_str.encode("utf-8")).decode("utf-8")
|
|
41
|
-
return b64_str
|
|
42
|
-
`;
|
|
43
|
-
await this.executeCode({ code: serverCode });
|
|
44
|
-
}
|
|
45
|
-
async getResponse(options) {
|
|
46
|
-
const { method, urlPath, requestBody, params, headers } = options;
|
|
47
|
-
const content = requestBody ? arrayBufferToBase64(requestBody) : undefined;
|
|
48
|
-
const code = `__monstra_get_response("${method}", "${urlPath}", headers=${JSON.stringify(headers)} , content=${content ? `"${content}"` : 'None'}, params=${params ? `"${params}"` : 'None'})`;
|
|
49
|
-
const raw = await this.executeCode({ code });
|
|
50
|
-
const jsonStr = atob(raw.slice(1, -1));
|
|
51
|
-
const obj = JSON.parse(jsonStr);
|
|
52
|
-
return obj;
|
|
53
|
-
}
|
|
54
|
-
async executeCode(code) {
|
|
55
|
-
var _a;
|
|
56
|
-
const kernel = (_a = this._sessionConnection) === null || _a === void 0 ? void 0 : _a.kernel;
|
|
57
|
-
if (!kernel) {
|
|
58
|
-
throw new Error('Session has no kernel.');
|
|
59
|
-
}
|
|
60
|
-
return new Promise((resolve, reject) => {
|
|
61
|
-
const future = kernel.requestExecute(code, false, undefined);
|
|
62
|
-
const parentMsgid = future.msg.header.msg_id;
|
|
63
|
-
let executeResult = '';
|
|
64
|
-
future.onIOPub = (msg) => {
|
|
65
|
-
const msgType = msg.header.msg_type;
|
|
66
|
-
switch (msgType) {
|
|
67
|
-
case 'execute_result': {
|
|
68
|
-
const content = msg.content
|
|
69
|
-
.data['text/plain'];
|
|
70
|
-
executeResult += content;
|
|
71
|
-
break;
|
|
72
|
-
}
|
|
73
|
-
case 'status': {
|
|
74
|
-
if (msg.content.execution_state ===
|
|
75
|
-
'idle' &&
|
|
76
|
-
msg.parent_header.msg_id === parentMsgid) {
|
|
77
|
-
resolve(executeResult);
|
|
78
|
-
}
|
|
79
|
-
break;
|
|
80
|
-
}
|
|
81
|
-
case 'stream': {
|
|
82
|
-
const content = msg.content.text;
|
|
83
|
-
executeResult += content;
|
|
84
|
-
break;
|
|
85
|
-
}
|
|
86
|
-
case 'error': {
|
|
87
|
-
console.error('Kernel operation failed', msg.content);
|
|
88
|
-
reject(msg.content);
|
|
89
|
-
break;
|
|
90
|
-
}
|
|
91
|
-
default:
|
|
92
|
-
break;
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
dispose() {
|
|
98
|
-
if (this._isDisposed) {
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
this._isDisposed = true;
|
|
102
|
-
this._sessionConnection.dispose();
|
|
103
|
-
}
|
|
104
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { IConnectionManager, IDict, IKernelExecutor } from '../type';
|
|
2
|
-
export declare class ConnectionManager implements IConnectionManager {
|
|
3
|
-
instanceId: string;
|
|
4
|
-
constructor(instanceId: string);
|
|
5
|
-
registerConnection(kernelExecutor: IKernelExecutor): Promise<{
|
|
6
|
-
instanceId: string;
|
|
7
|
-
kernelClientId: string;
|
|
8
|
-
}>;
|
|
9
|
-
generateResponse(options: {
|
|
10
|
-
kernelClientId: string;
|
|
11
|
-
urlPath: string;
|
|
12
|
-
method: string;
|
|
13
|
-
headers: IDict;
|
|
14
|
-
requestBody?: ArrayBuffer;
|
|
15
|
-
params?: string;
|
|
16
|
-
}): Promise<IDict | null>;
|
|
17
|
-
private _kernelExecutors;
|
|
18
|
-
}
|