jupyterpack 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/LICENSE +29 -0
- package/README.md +79 -0
- package/lib/document/iframePanel.d.ts +7 -0
- package/lib/document/iframePanel.js +20 -0
- package/lib/document/jupyterpackDocWidget.d.ts +9 -0
- package/lib/document/jupyterpackDocWidget.js +16 -0
- package/lib/document/plugin.d.ts +2 -0
- package/lib/document/plugin.js +31 -0
- package/lib/document/widgetFactory.d.ts +23 -0
- package/lib/document/widgetFactory.js +60 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +3 -0
- package/lib/pythonWidget/connectionManager.d.ts +18 -0
- package/lib/pythonWidget/connectionManager.js +27 -0
- package/lib/pythonWidget/kernelExecutor.d.ts +27 -0
- package/lib/pythonWidget/kernelExecutor.js +104 -0
- package/lib/pythonWidget/pythonWidget.d.ts +13 -0
- package/lib/pythonWidget/pythonWidget.js +22 -0
- package/lib/pythonWidget/pythonWidgetModel.d.ts +29 -0
- package/lib/pythonWidget/pythonWidgetModel.js +75 -0
- package/lib/sandpackWidget/sandpackFilesModel.d.ts +27 -0
- package/lib/sandpackWidget/sandpackFilesModel.js +114 -0
- package/lib/sandpackWidget/sandpackPanel.d.ts +16 -0
- package/lib/sandpackWidget/sandpackPanel.js +52 -0
- package/lib/swConnection/comm_manager.d.ts +6 -0
- package/lib/swConnection/comm_manager.js +46 -0
- package/lib/swConnection/connection_manager.d.ts +18 -0
- package/lib/swConnection/connection_manager.js +27 -0
- package/lib/swConnection/index.d.ts +3 -0
- package/lib/swConnection/index.js +68 -0
- package/lib/swConnection/sw.d.ts +1 -0
- package/lib/swConnection/sw.js +49 -0
- package/lib/token.d.ts +3 -0
- package/lib/token.js +2 -0
- package/lib/tools.d.ts +2 -0
- package/lib/tools.js +17 -0
- package/lib/type.d.ts +38 -0
- package/lib/type.js +9 -0
- package/package.json +199 -0
- package/src/document/iframePanel.ts +25 -0
- package/src/document/jupyterpackDocWidget.ts +19 -0
- package/src/document/plugin.ts +44 -0
- package/src/document/widgetFactory.ts +79 -0
- package/src/index.ts +4 -0
- package/src/pythonWidget/connectionManager.ts +43 -0
- package/src/pythonWidget/kernelExecutor.ts +140 -0
- package/src/pythonWidget/pythonWidget.ts +34 -0
- package/src/pythonWidget/pythonWidgetModel.ts +107 -0
- package/src/sandpackWidget/sandpackFilesModel.ts +141 -0
- package/src/sandpackWidget/sandpackPanel.ts +82 -0
- package/src/swConnection/comm_manager.ts +53 -0
- package/src/swConnection/connection_manager.ts +43 -0
- package/src/swConnection/index.ts +93 -0
- package/src/swConnection/sw.ts +57 -0
- package/src/token.ts +6 -0
- package/src/tools.ts +18 -0
- package/src/type.ts +44 -0
- package/style/base.css +51 -0
- package/style/index.css +1 -0
- package/style/index.js +1 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { Signal } from '@lumino/signaling';
|
|
2
|
+
import { removePrefix } from '../tools';
|
|
3
|
+
export class SandpackFilesModel {
|
|
4
|
+
constructor(options) {
|
|
5
|
+
this._fileChanged = new Signal(this);
|
|
6
|
+
this._contentManager = options.contentsManager;
|
|
7
|
+
this._path = options.path;
|
|
8
|
+
this._contentManager.fileChanged.connect(this._onFileChanged, this);
|
|
9
|
+
}
|
|
10
|
+
async getAllFiles() {
|
|
11
|
+
if (!this._allFiles) {
|
|
12
|
+
const files = await this._contentManager.get(this._path, {
|
|
13
|
+
content: true
|
|
14
|
+
});
|
|
15
|
+
this._allFiles = await this.flattenDirectory(files);
|
|
16
|
+
}
|
|
17
|
+
return this._allFiles;
|
|
18
|
+
}
|
|
19
|
+
get fileChanged() {
|
|
20
|
+
return this._fileChanged;
|
|
21
|
+
}
|
|
22
|
+
async flattenDirectory(dirContent) {
|
|
23
|
+
const flatDict = {};
|
|
24
|
+
const content = dirContent.content;
|
|
25
|
+
for (const item of content) {
|
|
26
|
+
if (item.type === 'file') {
|
|
27
|
+
const pathWithoutRoot = this._removeRoot(item.path);
|
|
28
|
+
let itemContent = item;
|
|
29
|
+
if (!itemContent.content) {
|
|
30
|
+
itemContent = await this._getContent(item.path);
|
|
31
|
+
}
|
|
32
|
+
if (itemContent.mimetype === 'application/json' &&
|
|
33
|
+
typeof itemContent.content !== 'string') {
|
|
34
|
+
flatDict[pathWithoutRoot] = {
|
|
35
|
+
code: JSON.stringify(itemContent.content)
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
flatDict[pathWithoutRoot] = { code: itemContent.content };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
else if (item.type === 'directory') {
|
|
43
|
+
// If it's a directory, recursively flatten its content
|
|
44
|
+
const nestedContent = await this._getContent(item.path);
|
|
45
|
+
const nestedDict = await this.flattenDirectory(nestedContent);
|
|
46
|
+
Object.assign(flatDict, nestedDict);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return flatDict;
|
|
50
|
+
}
|
|
51
|
+
async _onFileChanged(sender, args) {
|
|
52
|
+
var _a, _b, _c, _d, _e;
|
|
53
|
+
switch (args.type) {
|
|
54
|
+
case 'save': {
|
|
55
|
+
if ((_a = args.newValue) === null || _a === void 0 ? void 0 : _a.path) {
|
|
56
|
+
const newContent = await this._getContent(args.newValue.path);
|
|
57
|
+
const pathWithoutRoot = this._removeRoot(args.newValue.path);
|
|
58
|
+
if (this._allFiles) {
|
|
59
|
+
this._allFiles[pathWithoutRoot] = {
|
|
60
|
+
code: newContent.content
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
case 'delete': {
|
|
67
|
+
if ((_b = args.oldValue) === null || _b === void 0 ? void 0 : _b.path) {
|
|
68
|
+
const pathWithoutRoot = this._removeRoot(args.oldValue.path);
|
|
69
|
+
if (this._allFiles) {
|
|
70
|
+
delete this._allFiles[pathWithoutRoot];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
case 'rename': {
|
|
76
|
+
if (((_c = args.oldValue) === null || _c === void 0 ? void 0 : _c.path) && ((_d = args.newValue) === null || _d === void 0 ? void 0 : _d.path)) {
|
|
77
|
+
const oldPathWithoutRoot = this._removeRoot(args.oldValue.path);
|
|
78
|
+
const newPathWithoutRoot = this._removeRoot(args.newValue.path);
|
|
79
|
+
if (this._allFiles) {
|
|
80
|
+
this._allFiles[newPathWithoutRoot] =
|
|
81
|
+
this._allFiles[oldPathWithoutRoot];
|
|
82
|
+
delete this._allFiles[newPathWithoutRoot];
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
case 'new': {
|
|
88
|
+
if ((_e = args.newValue) === null || _e === void 0 ? void 0 : _e.path) {
|
|
89
|
+
const newContent = await this._getContent(args.newValue.path);
|
|
90
|
+
const pathWithoutRoot = this._removeRoot(args.newValue.path);
|
|
91
|
+
if (this._allFiles) {
|
|
92
|
+
this._allFiles[pathWithoutRoot] = {
|
|
93
|
+
code: newContent.content
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
default:
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
if (this._allFiles) {
|
|
103
|
+
this._fileChanged.emit({
|
|
104
|
+
allFiles: this._allFiles
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
_removeRoot(path) {
|
|
109
|
+
return removePrefix(path, this._path);
|
|
110
|
+
}
|
|
111
|
+
_getContent(path) {
|
|
112
|
+
return this._contentManager.get(path, { content: true });
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SandpackClient } from '@codesandbox/sandpack-client';
|
|
2
|
+
import { DocumentRegistry } from '@jupyterlab/docregistry';
|
|
3
|
+
import { Contents } from '@jupyterlab/services';
|
|
4
|
+
import { IFramePanel } from '../document/iframePanel';
|
|
5
|
+
import { SandpackFilesModel } from './sandpackFilesModel';
|
|
6
|
+
export declare class SandpackPanel extends IFramePanel {
|
|
7
|
+
constructor(options: {
|
|
8
|
+
context: DocumentRegistry.IContext<DocumentRegistry.IModel>;
|
|
9
|
+
contentsManager: Contents.IManager;
|
|
10
|
+
});
|
|
11
|
+
init(localPath: string): Promise<void>;
|
|
12
|
+
connectSignals(filesModel: SandpackFilesModel, sandpackClient: SandpackClient): Promise<void>;
|
|
13
|
+
private _onFileChanged;
|
|
14
|
+
private _spClient?;
|
|
15
|
+
private _contentsManager;
|
|
16
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { loadSandpackClient } from '@codesandbox/sandpack-client';
|
|
2
|
+
import { IFramePanel } from '../document/iframePanel';
|
|
3
|
+
import { SandpackFilesModel } from './sandpackFilesModel';
|
|
4
|
+
export class SandpackPanel extends IFramePanel {
|
|
5
|
+
constructor(options) {
|
|
6
|
+
super();
|
|
7
|
+
this._contentsManager = options.contentsManager;
|
|
8
|
+
options.context.ready.then(async () => {
|
|
9
|
+
await this.init(options.context.localPath);
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
async init(localPath) {
|
|
13
|
+
const currentDir = localPath.split('/').slice(0, -1).join('/');
|
|
14
|
+
const filesModel = new SandpackFilesModel({
|
|
15
|
+
contentsManager: this._contentsManager,
|
|
16
|
+
path: currentDir
|
|
17
|
+
});
|
|
18
|
+
const allFiles = await filesModel.getAllFiles();
|
|
19
|
+
const options = {
|
|
20
|
+
showLoadingScreen: true,
|
|
21
|
+
showOpenInCodeSandbox: false
|
|
22
|
+
};
|
|
23
|
+
this._spClient = await loadSandpackClient(this._iframe, {
|
|
24
|
+
files: allFiles
|
|
25
|
+
}, options);
|
|
26
|
+
await this.connectSignals(filesModel, this._spClient);
|
|
27
|
+
}
|
|
28
|
+
async connectSignals(filesModel, sandpackClient) {
|
|
29
|
+
filesModel.fileChanged.connect(this._onFileChanged, this);
|
|
30
|
+
sandpackClient.listen(msg => {
|
|
31
|
+
switch (msg.type) {
|
|
32
|
+
case 'start': {
|
|
33
|
+
this.toggleSpinner(true);
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
case 'success': {
|
|
37
|
+
this.toggleSpinner(false);
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
default:
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
_onFileChanged(sender, { allFiles }) {
|
|
46
|
+
if (this._spClient) {
|
|
47
|
+
this._spClient.updateSandbox({
|
|
48
|
+
files: allFiles
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { wrap, transfer } from 'comlink';
|
|
2
|
+
export class CommManager {
|
|
3
|
+
constructor() {
|
|
4
|
+
this._commIds = new Map();
|
|
5
|
+
}
|
|
6
|
+
registerComm(instanceId, port) {
|
|
7
|
+
const comm = wrap(port);
|
|
8
|
+
this._commIds.set(instanceId, comm);
|
|
9
|
+
}
|
|
10
|
+
async generateResponse(request) {
|
|
11
|
+
const url = new URL(request.url);
|
|
12
|
+
const urlPath = url.pathname;
|
|
13
|
+
const method = request.method;
|
|
14
|
+
const requestHeaders = {};
|
|
15
|
+
for (const pair of request.headers.entries()) {
|
|
16
|
+
if (!pair[0].startsWith('sec-ch-ua')) {
|
|
17
|
+
requestHeaders[pair[0]] = pair[1];
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const params = url.searchParams.toString();
|
|
21
|
+
const pathAfterExtensionName = urlPath.split('/jupyterpack/static')[1];
|
|
22
|
+
const pathList = pathAfterExtensionName.split('/').filter(Boolean);
|
|
23
|
+
const instanceId = pathList[0];
|
|
24
|
+
const kernelClientId = pathList[2];
|
|
25
|
+
const comm = this._commIds.get(instanceId);
|
|
26
|
+
if (!comm) {
|
|
27
|
+
throw new Error('Missing comm');
|
|
28
|
+
}
|
|
29
|
+
const requestBody = request.body ? await request.arrayBuffer() : undefined;
|
|
30
|
+
const data = await comm.generateResponse({
|
|
31
|
+
kernelClientId,
|
|
32
|
+
urlPath,
|
|
33
|
+
method,
|
|
34
|
+
headers: requestHeaders,
|
|
35
|
+
requestBody: requestBody
|
|
36
|
+
? transfer(requestBody, [requestBody])
|
|
37
|
+
: undefined,
|
|
38
|
+
params
|
|
39
|
+
});
|
|
40
|
+
if (data) {
|
|
41
|
+
const { headers, content, status_code } = data;
|
|
42
|
+
return new Response(content, { status: status_code, headers });
|
|
43
|
+
}
|
|
44
|
+
return await fetch(url, { method });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { PageConfig, URLExt } from '@jupyterlab/coreutils';
|
|
2
|
+
import { UUID } from '@lumino/coreutils';
|
|
3
|
+
import { expose } from 'comlink';
|
|
4
|
+
import { IConnectionManagerToken } from '../token';
|
|
5
|
+
import { MessageAction } from '../type';
|
|
6
|
+
import { ConnectionManager } from './connection_manager';
|
|
7
|
+
const fullLabextensionsUrl = PageConfig.getOption('fullLabextensionsUrl');
|
|
8
|
+
const SCOPE = `${fullLabextensionsUrl}/jupyterpack/static`;
|
|
9
|
+
async function initServiceWorker() {
|
|
10
|
+
if (!('serviceWorker' in navigator)) {
|
|
11
|
+
console.error('Cannot start extension without service worker');
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const fullWorkerUrl = `${SCOPE}/service-worker.js`;
|
|
15
|
+
try {
|
|
16
|
+
const reg = await navigator.serviceWorker.register(fullWorkerUrl);
|
|
17
|
+
if (!reg) {
|
|
18
|
+
console.error('Missing service worker registration');
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
await reg.update();
|
|
22
|
+
if (reg.installing) {
|
|
23
|
+
const sw = reg.installing || reg.waiting;
|
|
24
|
+
sw.onstatechange = () => {
|
|
25
|
+
if (sw.state === 'installed') {
|
|
26
|
+
window.location.reload();
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
if (reg.active) {
|
|
31
|
+
return reg.active;
|
|
32
|
+
}
|
|
33
|
+
console.log('Service worker newly registered', await navigator.serviceWorker.getRegistration(fullWorkerUrl));
|
|
34
|
+
return reg.active;
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
console.error('Failed to register service worker', e);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function createPingFrame() {
|
|
42
|
+
const iframe = document.createElement('iframe');
|
|
43
|
+
iframe.style.display = 'none';
|
|
44
|
+
iframe.src = URLExt.join(SCOPE, '__jupyterpack__', 'ping.html');
|
|
45
|
+
document.body.appendChild(iframe);
|
|
46
|
+
}
|
|
47
|
+
export const swPlugin = {
|
|
48
|
+
id: 'jupyterpack:service-worker-plugin',
|
|
49
|
+
description: 'jupyterpack service worker plugin',
|
|
50
|
+
autoStart: true,
|
|
51
|
+
provides: IConnectionManagerToken,
|
|
52
|
+
activate: async (app) => {
|
|
53
|
+
console.log('Activating jupyterpack service worker');
|
|
54
|
+
const serviceWorker = await initServiceWorker();
|
|
55
|
+
if (!serviceWorker) {
|
|
56
|
+
throw new Error('Failed to register the Service Worker, please make sure to use a browser that supports this feature.');
|
|
57
|
+
}
|
|
58
|
+
const instanceId = UUID.uuid4();
|
|
59
|
+
const { port1: mainToServiceWorker, port2: serviceWorkerToMain } = new MessageChannel();
|
|
60
|
+
const connectionManager = new ConnectionManager(instanceId);
|
|
61
|
+
expose(connectionManager, mainToServiceWorker);
|
|
62
|
+
serviceWorker.postMessage({ type: MessageAction.INIT, data: { instanceId } }, [serviceWorkerToMain]);
|
|
63
|
+
setTimeout(() => {
|
|
64
|
+
createPingFrame();
|
|
65
|
+
}, 10000);
|
|
66
|
+
return connectionManager;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// import { expose } from 'comlink';
|
|
2
|
+
import { MessageAction } from '../type';
|
|
3
|
+
import { CommManager } from './comm_manager';
|
|
4
|
+
const COMM_MANAGER = new CommManager();
|
|
5
|
+
/**
|
|
6
|
+
* Install event listeners
|
|
7
|
+
*/
|
|
8
|
+
self.addEventListener('install', onInstall);
|
|
9
|
+
self.addEventListener('activate', onActivate);
|
|
10
|
+
self.addEventListener('fetch', onFetch);
|
|
11
|
+
self.addEventListener('message', onMessage);
|
|
12
|
+
/**
|
|
13
|
+
* Handle installation
|
|
14
|
+
*/
|
|
15
|
+
async function onInstall(event) {
|
|
16
|
+
await self.skipWaiting();
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Handle activation.
|
|
20
|
+
*/
|
|
21
|
+
async function onActivate(event) {
|
|
22
|
+
event.waitUntil(self.clients.claim());
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Handle fetching a single resource.
|
|
26
|
+
*/
|
|
27
|
+
async function onFetch(event) {
|
|
28
|
+
const url = event.request.url;
|
|
29
|
+
if (url.endsWith('__jupyterpack__/ping')) {
|
|
30
|
+
return event.respondWith(new Response('pong'));
|
|
31
|
+
}
|
|
32
|
+
if (url.endsWith('__jupyterpack__/ping.html')) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
event.respondWith(COMM_MANAGER.generateResponse(event.request));
|
|
36
|
+
}
|
|
37
|
+
function onMessage(msg) {
|
|
38
|
+
const { type, data } = msg.data;
|
|
39
|
+
switch (type) {
|
|
40
|
+
case MessageAction.INIT: {
|
|
41
|
+
const { instanceId } = data;
|
|
42
|
+
const serviceWorkerToMain = msg.ports[0];
|
|
43
|
+
COMM_MANAGER.registerComm(instanceId, serviceWorkerToMain);
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
default:
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
}
|
package/lib/token.d.ts
ADDED
package/lib/token.js
ADDED
package/lib/tools.d.ts
ADDED
package/lib/tools.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export function removePrefix(path, prefix) {
|
|
2
|
+
if (path.startsWith(prefix)) {
|
|
3
|
+
return path.slice(prefix.length);
|
|
4
|
+
}
|
|
5
|
+
// If the prefix doesn't match, return the original path
|
|
6
|
+
return path;
|
|
7
|
+
}
|
|
8
|
+
export function arrayBufferToBase64(buffer) {
|
|
9
|
+
let binary = '';
|
|
10
|
+
const bytes = new Uint8Array(buffer);
|
|
11
|
+
const chunkSize = 32768; // process in chunks for large buffers
|
|
12
|
+
for (let i = 0; i < bytes.length; i += chunkSize) {
|
|
13
|
+
const chunk = bytes.subarray(i, i + chunkSize);
|
|
14
|
+
binary += String.fromCharCode(...chunk);
|
|
15
|
+
}
|
|
16
|
+
return btoa(binary);
|
|
17
|
+
}
|
package/lib/type.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { KernelMessage } from '@jupyterlab/services';
|
|
2
|
+
import { IDisposable } from '@lumino/disposable';
|
|
3
|
+
export interface IDict<T = any> {
|
|
4
|
+
[key: string]: T;
|
|
5
|
+
}
|
|
6
|
+
export declare enum JupyterPackFramework {
|
|
7
|
+
REACT = "react",
|
|
8
|
+
DASH = "dash"
|
|
9
|
+
}
|
|
10
|
+
export interface IJupyterPackFileFormat {
|
|
11
|
+
entry: string;
|
|
12
|
+
framework: JupyterPackFramework;
|
|
13
|
+
name?: string;
|
|
14
|
+
metadata?: IDict;
|
|
15
|
+
}
|
|
16
|
+
export declare enum MessageAction {
|
|
17
|
+
INIT = "INIT"
|
|
18
|
+
}
|
|
19
|
+
export interface IKernelExecutorParams {
|
|
20
|
+
method: string;
|
|
21
|
+
urlPath: string;
|
|
22
|
+
headers: IDict;
|
|
23
|
+
params?: string;
|
|
24
|
+
requestBody?: ArrayBuffer;
|
|
25
|
+
}
|
|
26
|
+
export interface IKernelExecutor extends IDisposable {
|
|
27
|
+
getResponse(options: IKernelExecutorParams): Promise<IDict>;
|
|
28
|
+
executeCode(code: KernelMessage.IExecuteRequestMsg['content']): Promise<string>;
|
|
29
|
+
}
|
|
30
|
+
export interface IConnectionManager {
|
|
31
|
+
registerConnection(kernelExecutor: IKernelExecutor): Promise<{
|
|
32
|
+
instanceId: string;
|
|
33
|
+
kernelClientId: string;
|
|
34
|
+
}>;
|
|
35
|
+
generateResponse(option: {
|
|
36
|
+
kernelClientId: string;
|
|
37
|
+
} & IKernelExecutorParams): Promise<IDict | null>;
|
|
38
|
+
}
|
package/lib/type.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export var JupyterPackFramework;
|
|
2
|
+
(function (JupyterPackFramework) {
|
|
3
|
+
JupyterPackFramework["REACT"] = "react";
|
|
4
|
+
JupyterPackFramework["DASH"] = "dash";
|
|
5
|
+
})(JupyterPackFramework || (JupyterPackFramework = {}));
|
|
6
|
+
export var MessageAction;
|
|
7
|
+
(function (MessageAction) {
|
|
8
|
+
MessageAction["INIT"] = "INIT";
|
|
9
|
+
})(MessageAction || (MessageAction = {}));
|