node support for js client (#3692)

* bundle js client + gen types

* changeset

* changeset

* fix bugs

* fix deps

* fix deps

* format

* fix ci

* fix types
This commit is contained in:
pngwn 2023-04-03 14:33:01 +01:00 committed by GitHub
parent f46f5f9867
commit 48e8b113f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 1207 additions and 217 deletions

View File

@ -0,0 +1,5 @@
---
"@gradio/client": patch
---
Ensure client works in node, create ESM bundle and generate typescript declaration files.

View File

@ -32,6 +32,8 @@ jobs:
registry-url: "https://registry.npmjs.org"
- name: install dependencies
run: pnpm install
- name: Build packages
run: pnpm --filter @gradio/client build
- name: Setup npmrc
run: echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc
- name: create and publish versions

View File

@ -35,6 +35,8 @@ jobs:
run: pnpm format:check
- name: build css
run: pnpm css
- name: build client
run: pnpm --filter @gradio/client build
- name: typecheck
run: pnpm ts:check
- name: unit tests

View File

@ -3,7 +3,28 @@
"version": "0.0.1",
"description": "Gradio UI packages",
"type": "module",
"main": "src/index.ts",
"main": "dist/index.js",
"author": "",
"license": "ISC"
"license": "ISC",
"exports": {
".": {
"import": "./dist/index.js"
},
"./package.json": "./package.json"
},
"dependencies": {
"ws": "^8.13.0"
},
"devDependencies": {
"@types/ws": "^8.5.4",
"esbuild": "^0.17.14"
},
"scripts": {
"bundle": "vite build --ssr",
"generate_types": "tsc",
"build": "pnpm bundle && pnpm generate_types"
},
"engines": {
"node": ">=18.0.0"
}
}

View File

@ -18,13 +18,13 @@ import type {
SpaceStatusCallback
} from "./types";
import type { Config } from "../../../globals";
import type { Config } from "./types";
type event = <K extends EventType>(
eventType: K,
listener: EventListener<K>
) => ReturnType<predict>;
type predict = (endpoint: string, payload: Payload) => {};
) => client_return;
type predict = (endpoint: string, payload: Payload) => Promise<unknown>;
type client_return = {
predict: predict;
@ -86,6 +86,16 @@ export async function client(
cancel
};
if (
typeof window === "undefined" ||
!("WebSocket" in window) ||
window.WebSocket.CLOSING !== 2
) {
const ws = await import("ws");
//@ts-ignore
global.WebSocket = ws.WebSocket;
}
const listener_map: ListenerMap<EventType> = {};
const { ws_protocol, http_protocol, host, space_id } =
await process_endpoint(app_reference);
@ -150,7 +160,6 @@ export async function client(
if (space_status_callback) space_status_callback(status);
if (status.status === "running")
try {
console.log(host);
config = await resolve_config(`${http_protocol}//${host}`);
res(config_success(config));
} catch (e) {
@ -192,8 +201,8 @@ export async function client(
typeof payload.fn_index === "number"
? payload.fn_index
: api_map[trimmed_endpoint];
if (skip_queue(fn_index, config)) {
console.log("SKIP");
fire_event({
type: "status",
endpoint,
@ -346,14 +355,18 @@ export async function client(
function skip_queue(id: number, config: Config) {
return (
!(config?.dependencies?.[id].queue === null
!(config?.dependencies?.[id]?.queue === null
? config.enable_queue
: config?.dependencies?.[id].queue) || false
: config?.dependencies?.[id]?.queue) || false
);
}
async function resolve_config(endpoint?: string): Promise<Config> {
if (window.gradio_config && location.origin !== "http://localhost:9876") {
if (
typeof window !== "undefined" &&
window.gradio_config &&
location.origin !== "http://localhost:9876"
) {
const path = window.gradio_config.root;
const config = window.gradio_config;
config.root = endpoint + config.root;

31
client/js/src/globals.d.ts vendored Normal file
View File

@ -0,0 +1,31 @@
declare global {
interface Window {
__gradio_mode__: "app" | "website";
launchGradio: Function;
launchGradioFromSpaces: Function;
gradio_config: Config;
scoped_css_attach: (link: HTMLLinkElement) => void;
__is_colab__: boolean;
}
}
export interface Config {
auth_required: boolean | undefined;
auth_message: string;
components: any[];
css: string | null;
dependencies: any[];
dev_mode: boolean;
enable_queue: boolean;
layout: any;
mode: "blocks" | "interface";
root: string;
theme: string;
title: string;
version: string;
is_space: boolean;
is_colab: boolean;
show_api: boolean;
stylesheets: string[];
path: string;
}

View File

@ -21,7 +21,7 @@ export interface Config {
export interface Payload {
data: Array<unknown>;
fn_index: number;
fn_index?: number;
}
export interface PostResponse {

10
client/js/tsconfig.json Normal file
View File

@ -0,0 +1,10 @@
{
"include": ["src/**/*"],
"compilerOptions": {
"allowJs": true,
"declaration": true,
"emitDeclarationOnly": true,
"outDir": "dist",
"declarationMap": true
}
}

23
client/js/vite.config.js Normal file
View File

@ -0,0 +1,23 @@
import { defineConfig } from "vite";
export default defineConfig({
build: {
minify: true,
lib: {
entry: "src/index.ts",
formats: ["es"]
},
rollupOptions: {
input: "src/index.ts",
output: {
dir: "dist"
}
}
},
ssr: {
target: "node",
format: "esm",
noExternal: "ws"
}
});

View File

@ -45,9 +45,7 @@
"d3-dsv": "^3.0.1",
"mime-types": "^2.1.34",
"postcss": "^8.4.21",
"postcss-prefix-selector": "^1.16.0",
"svelte": "^3.25.1",
"svelte-i18n": "^3.3.13"
"postcss-prefix-selector": "^1.16.0"
},
"msw": {
"workerDirectory": "public"

View File

@ -384,7 +384,8 @@
<script
async
defer
src="https://www.googletagmanager.com/gtag/js?id=UA-156449732-1"></script>
src="https://www.googletagmanager.com/gtag/js?id=UA-156449732-1"
></script>
{/if}
</svelte:head>
@ -442,7 +443,7 @@
set_api_docs_visible(false);
}}
/>
<div class="api-docs-wrap ">
<div class="api-docs-wrap">
<ApiDocs
on:close={() => {
set_api_docs_visible(false);

View File

@ -107,7 +107,7 @@
</script>
{#if active_api_count}
<div class="banner-wrap ">
<div class="banner-wrap">
<ApiBanner on:close {root} {active_api_count} />
</div>
<div class="docs-wrap">

View File

@ -11,7 +11,7 @@
<div class="input-checkbox-group">
<BlockTitle>{label}</BlockTitle>
{#each choices as choice, i}
<button class="checkbox-item " class:selected={original.includes(choice)}>
<button class="checkbox-item" class:selected={original.includes(choice)}>
<div
class="checkbox"
style={"background-color: " + getSaliencyColor(interpretation[i][0])}

View File

@ -13,7 +13,7 @@
<div class="input-slider">
<BlockTitle>{label}</BlockTitle>
<input type="range" disabled min={minimum} max={maximum} {step} />
<div class="range ">
<div class="range">
{#each interpretation as interpret_value}
<div style={"background-color: " + getSaliencyColor(interpret_value)} />
{/each}

View File

@ -14,7 +14,7 @@ export function process_langs() {
for (const lang in langs) {
const code = (lang.split("/").pop() as string).split(".").shift() as string;
_langs[code] = langs[lang].default;
_langs[code] = (langs[lang] as Record<string, any>).default;
}
return _langs;

View File

@ -175,7 +175,7 @@
<button
bind:this={el[i]}
on:click={() => (selected_image = i)}
class="thumbnail-item thumbnail-small "
class="thumbnail-item thumbnail-small"
class:selected={selected_image === i}
>
<img

View File

@ -120,7 +120,7 @@
<Square />
</div>
{:else}
<div class="icon ">
<div class="icon">
<Circle />
</div>
{/if}

View File

@ -32,7 +32,7 @@
dispatch("select", { index: i, value: confidence_set.label });
}}
>
<div class="inner-wrap ">
<div class="inner-wrap">
<div class="bar" style="width: {confidence_set.confidence * 100}%" />
<div class="label">
<div class="text">{confidence_set.label}</div>

View File

@ -20,7 +20,7 @@
</script>
<nav class="inline-block">
<ul class="flex flex-col px-6 ">
<ul class="flex flex-col px-6">
{#each comp_routes as [section, comps]}
<li>
<h2 class="text-xs uppercase font-bold">{section}</h2>

View File

@ -70,7 +70,7 @@
fill="#FF7C00"
/>
</svg>
<h1 class="font-semibold ">workbench</h1>
<h1 class="font-semibold">workbench</h1>
<div class="flex self-end ml-auto cursor-pointer">
<p
on:click={() => (mode = "light")}

View File

@ -4,10 +4,10 @@
"description": "Gradio UI packages",
"scripts": {
"workbench": "pnpm --filter @gradio/workbench dev",
"dev": "pnpm css && pnpm --filter @gradio/app dev",
"dev": "pnpm css && pnpm --filter @gradio/client build && pnpm --filter @gradio/app dev",
"css": "pnpm --filter @gradio/theme generate",
"build": "pnpm css && pnpm --filter @gradio/app build:local --emptyOutDir",
"build:cdn": "pnpm --filter @gradio/app build:cdn --emptyOutDir",
"build": "pnpm css && pnpm --filter @gradio/client build && pnpm --filter @gradio/app build:local --emptyOutDir",
"build:cdn": "pnpm --filter @gradio/client build && pnpm --filter @gradio/app build:cdn --emptyOutDir",
"build:website": "pnpm --filter @gradio/app build:website --emptyOutDir",
"build:cdn-local": "TEST_CDN=TRUE pnpm build:cdn",
"preview:cdn-server": "sirv ../gradio/templates/cdn --single --port=4321 --cors",
@ -16,13 +16,12 @@
"format:check": "prettier --config .config/.prettierrc.json --ignore-path .config/.prettierignore --check --plugin-search-dir=. .",
"format:write": "prettier --config .config/.prettierrc.json --ignore-path .config/.prettierignore --write --plugin-search-dir=. .",
"ts:check": "svelte-check --tsconfig tsconfig.json",
"test": "vitest dev --config .config/vitest.config.ts",
"test:run": "vitest run --config .config/vitest.config.ts",
"test": "pnpm --filter @gradio/client build && vitest dev --config .config/vitest.config.ts",
"test:run": "pnpm --filter @gradio/client build && vitest run --config .config/vitest.config.ts",
"test:browser": "pnpm --filter @gradio/app test:browser:full",
"test:browser:full": "run-s build test:browser",
"test:browser:debug": "pnpm --filter @gradio/app test:browser:debug",
"ci:publish": "pnpm publish --no-git-checks --access public -r",
"testy": "pnpm --filter @gradio/app test"
"ci:publish": "pnpm publish --no-git-checks --access public -r"
},
"type": "module",
"author": "",
@ -56,18 +55,18 @@
"postcss-prefix-selector": "^1.16.0",
"prettier": "^2.6.2",
"prettier-plugin-css-order": "^1.3.0",
"prettier-plugin-svelte": "^2.7.0",
"prettier-plugin-svelte": "^2.10.0",
"sirv": "^2.0.2",
"sirv-cli": "^2.0.2",
"svelte": "^3.49.0",
"svelte-check": "^2.8.0",
"svelte-i18n": "^3.3.13",
"svelte-preprocess": "^4.10.6",
"svelte": "^3.57.0",
"svelte-check": "^3.1.4",
"svelte-i18n": "^3.6.0",
"svelte-preprocess": "^5.0.3",
"tailwindcss": "^3.1.6",
"tinyspy": "^0.3.0",
"typescript": "^4.7.4",
"vite": "^2.9.5",
"vitest": "^0.12.7"
"vite": "^4.2.1",
"vitest": "^0.29.8"
},
"devDependencies": {
"@types/three": "^0.138.0"

File diff suppressed because it is too large Load Diff