UNPKG

thebe-lite

Version:

Thebe extension library for WASM kernels via JupyterLite

128 lines (111 loc) 4.08 kB
import type { ServiceManager } from '@jupyterlab/services'; import type { LiteServerConfig } from './types'; import { PageConfig } from '@jupyterlab/coreutils'; import { JupyterLiteServer } from '@jupyterlite/server'; const serverExtensions = [import('@jupyterlite/server-extension')]; async function createModule(scope: string, module: string) { try { const factory = await (window as any)._JUPYTERLAB[scope].get(module); return factory(); } catch (e) { console.warn(`Failed to create module: package: ${scope}; module: ${module}`); throw e; } } /** * Iterate over active plugins in an extension. */ function* activePlugins(extension: any) { // Handle commonjs or es2015 modules let exports; if (Object.prototype.hasOwnProperty.call(extension, '__esModule')) { exports = extension.default; } else { // CommonJS exports. exports = extension; } const plugins = Array.isArray(exports) ? exports : [exports]; for (const plugin of plugins) { yield plugin; } } export async function startJupyterLiteServer(config?: LiteServerConfig): Promise<ServiceManager> { /** * This is sufficent to initialise the global object? */ PageConfig.getOption(''); /** * Do not rely on a configuration being on the document body, accept configuration via arguments * and set options on the page config directly */ const defaultLiteConfig = { litePluginSettings: { '@jupyterlite/pyodide-kernel-extension:kernel': { pipliteUrls: ['https://unpkg.com/@jupyterlite/pyodide-kernel@0.4.7/pypi/all.json'], pipliteWheelUrl: 'https://unpkg.com/@jupyterlite/pyodide-kernel@0.4.7/pypi/piplite-0.4.7-py3-none-any.whl', }, }, enableMemoryStorage: true, settingsStorageDrivers: ['memoryStorageDriver'], }; PageConfig.setOption( 'litePluginSettings', JSON.stringify({ ...defaultLiteConfig.litePluginSettings, ...config?.litePluginSettings }), ); PageConfig.setOption( 'enableMemoryStorage', JSON.stringify(config?.enableMemoryStorage ?? defaultLiteConfig.enableMemoryStorage), ); PageConfig.setOption( 'settingsStorageDrivers', JSON.stringify(config?.settingsStorageDrivers ?? defaultLiteConfig.settingsStorageDrivers), ); /** * Seems like there are 4 different extensions we may want to handle * * liteExtension - essential, as these are how kernels are added * federatedExtension - general jupyterlab extensions * federatedMimeExtension - render extensions? e.g. @jupyterlab/javascript-extension, @jupyterlab/json-extension * federatedStyles - ? * * TODO we're not suppporting all of these yet */ const litePluginsToRegister: JupyterLiteServer.IPluginModule[] = []; // Add the base serverlite extensions const baseServerExtensions = await Promise.all(serverExtensions); baseServerExtensions.forEach((p) => { for (const plugin of activePlugins(p)) { litePluginsToRegister.push(plugin); } }); // TODO get federated extensions in from config argument? const extensions: any[] = []; const liteExtensionPromises: any[] = [import('@jupyterlite/pyodide-kernel-extension')]; extensions.forEach((data) => { if (data.liteExtension) { liteExtensionPromises.push(createModule(data.name, data.extension)); return; } }); // Add the serverlite federated extensions. const federatedLiteExtensions = await Promise.allSettled(liteExtensionPromises); federatedLiteExtensions.forEach((p) => { if (p.status === 'fulfilled') { for (const plugin of activePlugins(p.value)) { litePluginsToRegister.push(plugin); } } else { console.error(p.reason); } }); // create the in-browser JupyterLite Server const jupyterLiteServer = new JupyterLiteServer({} as any); jupyterLiteServer.registerPluginModules(litePluginsToRegister); // start the server await jupyterLiteServer.start(); const { serviceManager } = jupyterLiteServer; await serviceManager.ready; // TODO return serviceManager as unknown as ServiceManager; }