Files
pyscript/pyscriptjs/src/components/pyconfig.ts
Madhur Tandon 006d161a32 cleanup leftovers such as mode and pyodideReadyPromise (#649)
* remove usage of mode

* clean up pyodideReadyPromise
2022-08-02 20:44:41 +05:30

186 lines
4.7 KiB
TypeScript

import * as jsyaml from 'js-yaml';
import { BaseEvalElement } from './base';
import {
initializers,
loadedEnvironments,
postInitializers,
pyodideLoaded,
scriptsQueue,
globalLoader,
appConfig,
Initializer,
} from '../stores';
import { loadInterpreter } from '../interpreter';
import type { PyLoader } from './pyloader';
import type { PyScript } from './pyscript';
import type { PyodideInterface } from '../pyodide';
const DEFAULT_RUNTIME = {
src: 'https://cdn.jsdelivr.net/pyodide/v0.20.0/full/pyodide.js',
name: 'pyodide-default',
lang: 'python',
};
export type Runtime = {
src: string;
name?: string;
lang?: string;
};
export type AppConfig = {
autoclose_loader: boolean;
name?: string;
version?: string;
runtimes?: Array<Runtime>;
};
let appConfig_: AppConfig = {
autoclose_loader: true,
};
appConfig.subscribe((value: AppConfig) => {
if (value) {
appConfig_ = value;
}
console.log('config set!');
});
let initializers_: Initializer[];
initializers.subscribe((value: Initializer[]) => {
initializers_ = value;
console.log('initializers set');
});
let postInitializers_: Initializer[];
postInitializers.subscribe((value: Initializer[]) => {
postInitializers_ = value;
console.log('post initializers set');
});
let scriptsQueue_: PyScript[];
scriptsQueue.subscribe((value: PyScript[]) => {
scriptsQueue_ = value;
console.log('post initializers set');
});
let loader: PyLoader | undefined;
globalLoader.subscribe(value => {
loader = value;
});
export class PyodideRuntime extends Object {
src: string;
constructor(url: string) {
super();
this.src = url;
}
async initialize() {
loader?.log('Loading runtime...');
const pyodide: PyodideInterface = await loadInterpreter(this.src);
const newEnv = {
id: 'a',
runtime: pyodide,
state: 'loading',
};
pyodideLoaded.set(pyodide);
// Inject the loader into the runtime namespace
// eslint-disable-next-line
pyodide.globals.set('pyscript_loader', loader);
loader?.log('Runtime created...');
loadedEnvironments.update(environments => ({
...environments,
[newEnv['id']]: newEnv,
}));
// now we call all initializers before we actually executed all page scripts
loader?.log('Initializing components...');
for (const initializer of initializers_) {
await initializer();
}
loader?.log('Initializing scripts...');
for (const script of scriptsQueue_) {
await script.evaluate();
}
scriptsQueue.set([]);
// now we call all post initializers AFTER we actually executed all page scripts
loader?.log('Running post initializers...');
if (appConfig_ && appConfig_.autoclose_loader) {
loader?.close();
console.log('------ loader closed ------');
}
for (const initializer of postInitializers_) {
await initializer();
}
}
}
export class PyConfig extends BaseEvalElement {
shadow: ShadowRoot;
wrapper: HTMLElement;
theme: string;
widths: Array<string>;
label: string;
mount_name: string;
details: HTMLElement;
operation: HTMLElement;
code: string;
values: AppConfig;
constructor() {
super();
}
connectedCallback() {
this.code = this.innerHTML;
this.innerHTML = '';
const loadedValues = jsyaml.load(this.code);
if (loadedValues === undefined) {
this.values = {
autoclose_loader: true,
};
} else {
// eslint-disable-next-line
// @ts-ignore
this.values = loadedValues;
}
if (this.values.runtimes === undefined) {
this.values.runtimes = [DEFAULT_RUNTIME];
}
appConfig.set(this.values);
console.log('config set', this.values);
this.loadRuntimes();
}
log(msg: string) {
const newLog = document.createElement('p');
newLog.innerText = msg;
this.details.appendChild(newLog);
}
close() {
this.remove();
}
loadRuntimes() {
console.log('Initializing runtimes...');
for (const runtime of this.values.runtimes) {
const script = document.createElement('script'); // create a script DOM node
const runtimeSpec = new PyodideRuntime(runtime.src);
script.src = runtime.src; // set its src to the provided URL
script.addEventListener('load', () => {
void runtimeSpec.initialize();
});
document.head.appendChild(script);
}
}
}