|
<script lang="ts"> |
|
import "@gradio/theme/reset.css"; |
|
import "@gradio/theme/global.css"; |
|
import "@gradio/theme/pollen.css"; |
|
import "@gradio/theme/typography.css"; |
|
|
|
import { onDestroy, SvelteComponent } from "svelte"; |
|
import Index from "@self/spa"; |
|
import Playground from "./Playground.svelte"; |
|
import ErrorDisplay from "./ErrorDisplay.svelte"; |
|
import type { ThemeMode } from "@gradio/core"; |
|
import { WorkerProxy, type WorkerProxyOptions } from "@gradio/wasm"; |
|
import { FAKE_LITE_HOST } from "@gradio/wasm/network"; |
|
import { Client } from "@gradio/client"; |
|
import { wasm_proxied_fetch } from "./fetch"; |
|
import { wasm_proxied_stream_factory } from "./sse"; |
|
import { wasm_proxied_mount_css, mount_prebuilt_css } from "./css"; |
|
import type { mount_css } from "@gradio/core"; |
|
|
|
|
|
import gradioWheel from "gradio.whl"; |
|
import gradioClientWheel from "gradio_client.whl"; |
|
|
|
export let info: boolean; |
|
export let container: boolean; |
|
export let is_embed: boolean; |
|
export let initial_height: string; |
|
export let eager: boolean; |
|
export let version: string; |
|
export let theme_mode: ThemeMode | null; |
|
export let autoscroll: boolean; |
|
export let control_page_title: boolean; |
|
export let app_mode: boolean; |
|
|
|
|
|
export let files: WorkerProxyOptions["files"] | undefined; |
|
export let requirements: WorkerProxyOptions["requirements"] | undefined; |
|
export let code: string | undefined; |
|
export let entrypoint: string | undefined; |
|
export let sharedWorkerMode: boolean | undefined; |
|
|
|
|
|
export let playground = false; |
|
export let layout: string | null; |
|
|
|
const worker_proxy = new WorkerProxy({ |
|
gradioWheelUrl: new URL(gradioWheel, import.meta.url).href, |
|
gradioClientWheelUrl: new URL(gradioClientWheel, import.meta.url).href, |
|
files: files ?? {}, |
|
requirements: requirements ?? [], |
|
sharedWorkerMode: sharedWorkerMode ?? false |
|
}); |
|
onDestroy(() => { |
|
worker_proxy.terminate(); |
|
}); |
|
|
|
let error: Error | null = null; |
|
|
|
const wrapFunctionWithAppLogic = <TArgs extends any[], TRet extends any>( |
|
func: (...args: TArgs) => Promise<TRet> |
|
): ((...args: TArgs) => Promise<TRet>) => { |
|
return async (...args: TArgs) => { |
|
try { |
|
error = null; |
|
const retval = await func(...args); |
|
refresh_index_component(); |
|
return retval; |
|
} catch (err) { |
|
error = err as Error; |
|
throw err; |
|
} |
|
}; |
|
}; |
|
worker_proxy.runPythonCode = wrapFunctionWithAppLogic( |
|
worker_proxy.runPythonCode.bind(worker_proxy) |
|
); |
|
worker_proxy.runPythonFile = wrapFunctionWithAppLogic( |
|
worker_proxy.runPythonFile.bind(worker_proxy) |
|
); |
|
worker_proxy.writeFile = wrapFunctionWithAppLogic( |
|
worker_proxy.writeFile.bind(worker_proxy) |
|
); |
|
worker_proxy.renameFile = wrapFunctionWithAppLogic( |
|
worker_proxy.renameFile.bind(worker_proxy) |
|
); |
|
worker_proxy.unlink = wrapFunctionWithAppLogic( |
|
worker_proxy.unlink.bind(worker_proxy) |
|
); |
|
worker_proxy.install = wrapFunctionWithAppLogic( |
|
worker_proxy.install.bind(worker_proxy) |
|
); |
|
|
|
worker_proxy.addEventListener("initialization-error", (event) => { |
|
error = (event as CustomEvent).detail; |
|
}); |
|
|
|
|
|
|
|
|
|
|
|
if (code != null) { |
|
worker_proxy.runPythonCode(code); |
|
} else if (entrypoint != null) { |
|
worker_proxy.runPythonFile(entrypoint); |
|
} else { |
|
throw new Error("Either code or entrypoint must be provided."); |
|
} |
|
|
|
mount_prebuilt_css(document.head); |
|
|
|
class LiteClient extends Client { |
|
fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> { |
|
return wasm_proxied_fetch(worker_proxy, input, init); |
|
} |
|
|
|
stream(url: URL): EventSource { |
|
return wasm_proxied_stream_factory(worker_proxy, url); |
|
} |
|
} |
|
|
|
const overridden_mount_css: typeof mount_css = async (url, target) => { |
|
return wasm_proxied_mount_css(worker_proxy, url, target); |
|
}; |
|
|
|
let index_component_key = 0; |
|
function refresh_index_component(): void { |
|
index_component_key += 1; |
|
} |
|
|
|
let playground_component: SvelteComponent | null = null; |
|
$: playground_component?.$on("code", (event) => { |
|
const { code } = event.detail; |
|
worker_proxy.runPythonCode(code); |
|
}); |
|
|
|
export const run_code = worker_proxy.runPythonCode; |
|
export const run_file = worker_proxy.runPythonFile; |
|
export const write = worker_proxy.writeFile; |
|
export const rename = worker_proxy.renameFile; |
|
export const unlink = worker_proxy.unlink; |
|
export const install = worker_proxy.install; |
|
</script> |
|
|
|
{#if playground} |
|
<Playground |
|
bind:this={playground_component} |
|
{worker_proxy} |
|
{layout} |
|
{code} |
|
{is_embed} |
|
> |
|
{#key index_component_key} |
|
{#if error} |
|
<ErrorDisplay {error} is_embed /> |
|
{:else} |
|
<Index |
|
space={null} |
|
src={`http://${FAKE_LITE_HOST}/`} |
|
{info} |
|
{container} |
|
{is_embed} |
|
{initial_height} |
|
{eager} |
|
{version} |
|
{theme_mode} |
|
{autoscroll} |
|
{control_page_title} |
|
{app_mode} |
|
{worker_proxy} |
|
Client={LiteClient} |
|
mount_css={overridden_mount_css} |
|
/> |
|
{/if} |
|
{/key} |
|
</Playground> |
|
{:else} |
|
{#key index_component_key} |
|
{#if error} |
|
<ErrorDisplay {error} {is_embed} /> |
|
{:else} |
|
<Index |
|
space={null} |
|
src={`http://${FAKE_LITE_HOST}/`} |
|
{info} |
|
{container} |
|
{is_embed} |
|
{initial_height} |
|
{eager} |
|
{version} |
|
{theme_mode} |
|
{autoscroll} |
|
{control_page_title} |
|
{app_mode} |
|
{worker_proxy} |
|
Client={LiteClient} |
|
mount_css={overridden_mount_css} |
|
/> |
|
{/if} |
|
{/key} |
|
{/if} |
|
|