|
1 | 1 | import './styles/pyscript_base.css';
|
2 | 2 |
|
| 3 | +import { loadConfigFromElement } from './pyconfig'; |
| 4 | +import type { AppConfig } from './pyconfig'; |
| 5 | +import type { Runtime } from './runtime'; |
3 | 6 | import { PyScript } from './components/pyscript';
|
4 | 7 | import { PyEnv } from './components/pyenv';
|
5 | 8 | import { PyLoader } from './components/pyloader';
|
6 |
| -import { PyConfig } from './components/pyconfig'; |
| 9 | +import { PyodideRuntime } from './pyodide'; |
7 | 10 | import { getLogger } from './logger';
|
8 |
| -import { globalLoader } from './stores'; |
| 11 | +import { globalLoader, runtimeLoaded, addInitializer } from './stores'; |
| 12 | +import { handleFetchError, globalExport } from './utils' |
9 | 13 |
|
10 | 14 | const logger = getLogger('pyscript/main');
|
11 | 15 |
|
12 |
| -/* eslint-disable @typescript-eslint/no-unused-vars */ |
13 |
| -const xPyScript = customElements.define('py-script', PyScript); |
14 |
| -const xPyLoader = customElements.define('py-loader', PyLoader); |
15 |
| -const xPyConfig = customElements.define('py-config', PyConfig); |
16 |
| -const xPyEnv = customElements.define('py-env', PyEnv); |
17 |
| -/* eslint-disable @typescript-eslint/no-unused-vars */ |
18 |
| - |
19 |
| -// As first thing, loop for application configs |
20 |
| -logger.info('checking for py-config'); |
21 |
| -const config: PyConfig = document.querySelector('py-config'); |
22 |
| -if (!config) { |
23 |
| - const loader = document.createElement('py-config'); |
24 |
| - document.body.append(loader); |
| 16 | +// XXX this should be killed eventually |
| 17 | +let runtimeSpec: Runtime; |
| 18 | +runtimeLoaded.subscribe(value => { |
| 19 | + runtimeSpec = value; |
| 20 | +}); |
| 21 | + |
| 22 | + |
| 23 | +class PyScriptApp { |
| 24 | + |
| 25 | + config: AppConfig; |
| 26 | + |
| 27 | + main() { |
| 28 | + this.loadConfig(); |
| 29 | + this.initialize(); |
| 30 | + |
| 31 | + /* eslint-disable @typescript-eslint/no-unused-vars */ |
| 32 | + const xPyScript = customElements.define('py-script', PyScript); |
| 33 | + const xPyLoader = customElements.define('py-loader', PyLoader); |
| 34 | + const xPyEnv = customElements.define('py-env', PyEnv); |
| 35 | + /* eslint-disable @typescript-eslint/no-unused-vars */ |
| 36 | + |
| 37 | + // add loader to the page body |
| 38 | + logger.info('add py-loader'); |
| 39 | + const loader = <PyLoader>document.createElement('py-loader'); |
| 40 | + document.body.append(loader); |
| 41 | + globalLoader.set(loader); |
| 42 | + } |
| 43 | + |
| 44 | + loadConfig() { |
| 45 | + // find the <py-config> tag. If not found, we get null which means |
| 46 | + // "use the default config" |
| 47 | + // XXX: we should actively complain if there are multiple <py-config> |
| 48 | + // and show a big error. PRs welcome :) |
| 49 | + logger.info('searching for <py-config>'); |
| 50 | + const el = document.querySelector('py-config'); |
| 51 | + this.config = loadConfigFromElement(el); |
| 52 | + logger.info('config loaded:\n' + JSON.stringify(this.config, null, 2)); |
| 53 | + } |
| 54 | + |
| 55 | + initialize() { |
| 56 | + addInitializer(this.loadPackages); |
| 57 | + addInitializer(this.loadPaths); |
| 58 | + this.loadRuntimes(); |
| 59 | + } |
| 60 | + |
| 61 | + loadPackages = async () => { |
| 62 | + logger.info("Packages to install: ", this.config.packages); |
| 63 | + await runtimeSpec.installPackage(this.config.packages); |
| 64 | + } |
| 65 | + |
| 66 | + loadPaths = async () => { |
| 67 | + const paths = this.config.paths; |
| 68 | + logger.info("Paths to load: ", paths) |
| 69 | + for (const singleFile of paths) { |
| 70 | + logger.info(` loading path: ${singleFile}`); |
| 71 | + try { |
| 72 | + await runtimeSpec.loadFromFile(singleFile); |
| 73 | + } catch (e) { |
| 74 | + //Should we still export full error contents to console? |
| 75 | + handleFetchError(<Error>e, singleFile); |
| 76 | + } |
| 77 | + } |
| 78 | + logger.info("All paths loaded"); |
| 79 | + } |
| 80 | + |
| 81 | + loadRuntimes() { |
| 82 | + logger.info('Initializing runtimes'); |
| 83 | + for (const runtime of this.config.runtimes) { |
| 84 | + const runtimeObj: Runtime = new PyodideRuntime(this.config, runtime.src, |
| 85 | + runtime.name, runtime.lang); |
| 86 | + const script = document.createElement('script'); // create a script DOM node |
| 87 | + script.src = runtimeObj.src; // set its src to the provided URL |
| 88 | + script.addEventListener('load', () => { |
| 89 | + void runtimeObj.initialize(); |
| 90 | + }); |
| 91 | + document.head.appendChild(script); |
| 92 | + } |
| 93 | + } |
| 94 | + |
| 95 | +} |
| 96 | + |
| 97 | +function pyscript_get_config() { |
| 98 | + return globalApp.config; |
25 | 99 | }
|
| 100 | +globalExport('pyscript_get_config', pyscript_get_config); |
26 | 101 |
|
27 |
| -// add loader to the page body |
28 |
| -logger.info('add py-loader'); |
29 |
| -const loader = <PyLoader>document.createElement('py-loader'); |
30 |
| -document.body.append(loader); |
31 |
| -globalLoader.set(loader); |
| 102 | +// main entry point of execution |
| 103 | +const globalApp = new PyScriptApp(); |
| 104 | +globalApp.main(); |
0 commit comments