@gradio/client 0.20.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CHANGELOG.md +201 -0
  2. package/README.md +21 -36
  3. package/dist/client.d.ts +6 -7
  4. package/dist/client.d.ts.map +1 -1
  5. package/dist/constants.d.ts +3 -0
  6. package/dist/constants.d.ts.map +1 -1
  7. package/dist/helpers/data.d.ts +15 -1
  8. package/dist/helpers/data.d.ts.map +1 -1
  9. package/dist/helpers/init_helpers.d.ts.map +1 -1
  10. package/dist/helpers/spaces.d.ts.map +1 -1
  11. package/dist/index.d.ts +2 -1
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +496 -114
  14. package/dist/test/handlers.d.ts +1 -0
  15. package/dist/test/handlers.d.ts.map +1 -1
  16. package/dist/test/test_data.d.ts.map +1 -1
  17. package/dist/types.d.ts +93 -24
  18. package/dist/types.d.ts.map +1 -1
  19. package/dist/utils/handle_blob.d.ts +2 -1
  20. package/dist/utils/handle_blob.d.ts.map +1 -1
  21. package/dist/utils/predict.d.ts +2 -2
  22. package/dist/utils/predict.d.ts.map +1 -1
  23. package/dist/utils/stream.d.ts +2 -1
  24. package/dist/utils/stream.d.ts.map +1 -1
  25. package/dist/utils/submit.d.ts +2 -2
  26. package/dist/utils/submit.d.ts.map +1 -1
  27. package/index.html +39 -0
  28. package/package.json +5 -2
  29. package/src/client.ts +40 -35
  30. package/src/constants.ts +4 -0
  31. package/src/helpers/api_info.ts +1 -1
  32. package/src/helpers/data.ts +124 -10
  33. package/src/helpers/init_helpers.ts +5 -0
  34. package/src/helpers/spaces.ts +2 -1
  35. package/src/index.ts +6 -1
  36. package/src/test/api_info.test.ts +0 -1
  37. package/src/test/data.test.ts +201 -26
  38. package/src/test/handlers.ts +9 -1
  39. package/src/test/stream.test.ts +12 -10
  40. package/src/test/test_data.ts +8 -5
  41. package/src/test/upload_files.test.ts +1 -1
  42. package/src/types.ts +110 -26
  43. package/src/utils/handle_blob.ts +91 -1
  44. package/src/utils/predict.ts +15 -16
  45. package/src/utils/stream.ts +66 -13
  46. package/src/utils/submit.ts +156 -63
  47. package/src/utils/upload_files.ts +1 -1
  48. package/vite.config.js +37 -24
@@ -2,19 +2,16 @@
2
2
  import type {
3
3
  Status,
4
4
  Payload,
5
- EventType,
6
- ListenerMap,
7
- SubmitReturn,
8
- EventListener,
9
- Event,
5
+ GradioEvent,
10
6
  JsApiData,
11
7
  EndpointInfo,
12
8
  ApiInfo,
13
9
  Config,
14
- Dependency
10
+ Dependency,
11
+ SubmitIterable
15
12
  } from "../types";
16
13
 
17
- import { skip_queue, post_message } from "../helpers/data";
14
+ import { skip_queue, post_message, handle_payload } from "../helpers/data";
18
15
  import { resolve_root } from "../helpers/init_helpers";
19
16
  import {
20
17
  handle_message,
@@ -31,8 +28,9 @@ export function submit(
31
28
  endpoint: string | number,
32
29
  data: unknown[] | Record<string, unknown>,
33
30
  event_data?: unknown,
34
- trigger_id?: number | null
35
- ): SubmitReturn {
31
+ trigger_id?: number | null,
32
+ all_events?: boolean
33
+ ): SubmitIterable<GradioEvent> {
36
34
  try {
37
35
  const { hf_token } = this.options;
38
36
  const {
@@ -47,9 +45,12 @@ export function submit(
47
45
  pending_diff_streams,
48
46
  event_callbacks,
49
47
  unclosed_events,
50
- post_data
48
+ post_data,
49
+ options
51
50
  } = this;
52
51
 
52
+ const that = this;
53
+
53
54
  if (!api_info) throw new Error("No API found");
54
55
  if (!config) throw new Error("Could not resolve app config");
55
56
 
@@ -70,41 +71,26 @@ export function submit(
70
71
  let payload: Payload;
71
72
  let event_id: string | null = null;
72
73
  let complete: Status | undefined | false = false;
73
- const listener_map: ListenerMap<EventType> = {};
74
74
  let last_status: Record<string, Status["stage"]> = {};
75
75
  let url_params =
76
- typeof window !== "undefined"
76
+ typeof window !== "undefined" && typeof document !== "undefined"
77
77
  ? new URLSearchParams(window.location.search).toString()
78
78
  : "";
79
79
 
80
- // event subscription methods
81
- function fire_event<K extends EventType>(event: Event<K>): void {
82
- const narrowed_listener_map: ListenerMap<K> = listener_map;
83
- const listeners = narrowed_listener_map[event.type] || [];
84
- listeners?.forEach((l) => l(event));
85
- }
80
+ const events_to_publish =
81
+ options?.events?.reduce(
82
+ (acc, event) => {
83
+ acc[event] = true;
84
+ return acc;
85
+ },
86
+ {} as Record<string, boolean>
87
+ ) || {};
86
88
 
87
- function on<K extends EventType>(
88
- eventType: K,
89
- listener: EventListener<K>
90
- ): SubmitReturn {
91
- const narrowed_listener_map: ListenerMap<K> = listener_map;
92
- const listeners = narrowed_listener_map[eventType] || [];
93
- narrowed_listener_map[eventType] = listeners;
94
- listeners?.push(listener);
95
-
96
- return { on, off, cancel, destroy };
97
- }
98
-
99
- function off<K extends EventType>(
100
- eventType: K,
101
- listener: EventListener<K>
102
- ): SubmitReturn {
103
- const narrowed_listener_map: ListenerMap<K> = listener_map;
104
- let listeners = narrowed_listener_map[eventType] || [];
105
- listeners = listeners?.filter((l) => l !== listener);
106
- narrowed_listener_map[eventType] = listeners;
107
- return { on, off, cancel, destroy };
89
+ // event subscription methods
90
+ function fire_event(event: GradioEvent): void {
91
+ if (all_events || events_to_publish[event.type]) {
92
+ push_event(event);
93
+ }
108
94
  }
109
95
 
110
96
  async function cancel(): Promise<void> {
@@ -121,6 +107,7 @@ export function submit(
121
107
  fn_index: fn_index
122
108
  });
123
109
 
110
+ let reset_request = {};
124
111
  let cancel_request = {};
125
112
  if (protocol === "ws") {
126
113
  if (websocket && websocket.readyState === 0) {
@@ -130,10 +117,12 @@ export function submit(
130
117
  } else {
131
118
  websocket.close();
132
119
  }
133
- cancel_request = { fn_index, session_hash };
120
+ reset_request = { fn_index, session_hash };
134
121
  } else {
135
- stream?.close();
136
- cancel_request = { event_id };
122
+ close_stream(stream_status, that.abort_controller);
123
+ close();
124
+ reset_request = { event_id };
125
+ cancel_request = { event_id, session_hash, fn_index };
137
126
  }
138
127
 
139
128
  try {
@@ -141,10 +130,18 @@ export function submit(
141
130
  throw new Error("Could not resolve app config");
142
131
  }
143
132
 
133
+ if ("event_id" in cancel_request) {
134
+ await fetch(`${config.root}/cancel`, {
135
+ headers: { "Content-Type": "application/json" },
136
+ method: "POST",
137
+ body: JSON.stringify(cancel_request)
138
+ });
139
+ }
140
+
144
141
  await fetch(`${config.root}/reset`, {
145
142
  headers: { "Content-Type": "application/json" },
146
143
  method: "POST",
147
- body: JSON.stringify(cancel_request)
144
+ body: JSON.stringify(reset_request)
148
145
  });
149
146
  } catch (e) {
150
147
  console.warn(
@@ -153,15 +150,6 @@ export function submit(
153
150
  }
154
151
  }
155
152
 
156
- function destroy(): void {
157
- for (const event_type in listener_map) {
158
- listener_map &&
159
- listener_map[event_type as "data" | "status"]?.forEach((fn) => {
160
- off(event_type as "data" | "status", fn);
161
- });
162
- }
163
- }
164
-
165
153
  const resolve_heartbeat = async (config: Config): Promise<void> => {
166
154
  await this._resolve_hearbeat(config);
167
155
  };
@@ -193,8 +181,15 @@ export function submit(
193
181
 
194
182
  this.handle_blob(config.root, resolved_data, endpoint_info).then(
195
183
  async (_payload) => {
184
+ let input_data = handle_payload(
185
+ _payload,
186
+ dependency,
187
+ config.components,
188
+ "input",
189
+ true
190
+ );
196
191
  payload = {
197
- data: _payload || [],
192
+ data: input_data || [],
198
193
  event_data,
199
194
  fn_index,
200
195
  trigger_id
@@ -225,7 +220,13 @@ export function submit(
225
220
  type: "data",
226
221
  endpoint: _endpoint,
227
222
  fn_index,
228
- data: data,
223
+ data: handle_payload(
224
+ data,
225
+ dependency,
226
+ config.components,
227
+ "output",
228
+ options.with_null_state
229
+ ),
229
230
  time: new Date(),
230
231
  event_data,
231
232
  trigger_id
@@ -359,7 +360,13 @@ export function submit(
359
360
  fire_event({
360
361
  type: "data",
361
362
  time: new Date(),
362
- data: data.data,
363
+ data: handle_payload(
364
+ data.data,
365
+ dependency,
366
+ config.components,
367
+ "output",
368
+ options.with_null_state
369
+ ),
363
370
  endpoint: _endpoint,
364
371
  fn_index,
365
372
  event_data,
@@ -411,7 +418,7 @@ export function submit(
411
418
  url.searchParams.set("__sign", this.jwt);
412
419
  }
413
420
 
414
- stream = await this.stream(url);
421
+ stream = this.stream(url);
415
422
 
416
423
  if (!stream) {
417
424
  return Promise.reject(
@@ -437,6 +444,7 @@ export function submit(
437
444
  });
438
445
  if (status.stage === "error") {
439
446
  stream?.close();
447
+ close();
440
448
  }
441
449
  } else if (type === "data") {
442
450
  event_id = _data.event_id as string;
@@ -456,6 +464,7 @@ export function submit(
456
464
  time: new Date()
457
465
  });
458
466
  stream?.close();
467
+ close();
459
468
  }
460
469
  } else if (type === "complete") {
461
470
  complete = status;
@@ -482,7 +491,13 @@ export function submit(
482
491
  fire_event({
483
492
  type: "data",
484
493
  time: new Date(),
485
- data: data.data,
494
+ data: handle_payload(
495
+ data.data,
496
+ dependency,
497
+ config.components,
498
+ "output",
499
+ options.with_null_state
500
+ ),
486
501
  endpoint: _endpoint,
487
502
  fn_index,
488
503
  event_data,
@@ -500,6 +515,7 @@ export function submit(
500
515
  fn_index
501
516
  });
502
517
  stream?.close();
518
+ close();
503
519
  }
504
520
  }
505
521
  };
@@ -520,7 +536,10 @@ export function submit(
520
536
  time: new Date()
521
537
  });
522
538
  let hostname = "";
523
- if (typeof window !== "undefined") {
539
+ if (
540
+ typeof window !== "undefined" &&
541
+ typeof document !== "undefined"
542
+ ) {
524
543
  hostname = window?.location?.hostname;
525
544
  }
526
545
 
@@ -530,7 +549,9 @@ export function submit(
530
549
  : `https://huggingface.co`;
531
550
 
532
551
  const is_iframe =
533
- typeof window !== "undefined" && window.parent != window;
552
+ typeof window !== "undefined" &&
553
+ typeof document !== "undefined" &&
554
+ window.parent != window;
534
555
  const is_zerogpu_space = dependency.zerogpu && config.space_id;
535
556
  const zerogpu_auth_promise =
536
557
  is_iframe && is_zerogpu_space
@@ -633,7 +654,13 @@ export function submit(
633
654
  fire_event({
634
655
  type: "data",
635
656
  time: new Date(),
636
- data: data.data,
657
+ data: handle_payload(
658
+ data.data,
659
+ dependency,
660
+ config.components,
661
+ "output",
662
+ options.with_null_state
663
+ ),
637
664
  endpoint: _endpoint,
638
665
  fn_index
639
666
  });
@@ -676,9 +703,10 @@ export function submit(
676
703
  fn_index,
677
704
  time: new Date()
678
705
  });
679
- if (["sse_v2", "sse_v2.1"].includes(protocol)) {
680
- close_stream(stream_status, stream);
706
+ if (["sse_v2", "sse_v2.1", "sse_v3"].includes(protocol)) {
707
+ close_stream(stream_status, that.abort_controller);
681
708
  stream_status.open = false;
709
+ close();
682
710
  }
683
711
  }
684
712
  };
@@ -701,13 +729,78 @@ export function submit(
701
729
  }
702
730
  );
703
731
 
704
- return { on, off, cancel, destroy };
732
+ let done = false;
733
+ const values: (IteratorResult<GradioEvent> | PromiseLike<never>)[] = [];
734
+ const resolvers: ((
735
+ value: IteratorResult<GradioEvent> | PromiseLike<never>
736
+ ) => void)[] = [];
737
+
738
+ function close(): void {
739
+ done = true;
740
+ while (resolvers.length > 0)
741
+ (resolvers.shift() as (typeof resolvers)[0])({
742
+ value: undefined,
743
+ done: true
744
+ });
745
+ }
746
+
747
+ function push(
748
+ data: { value: GradioEvent; done: boolean } | PromiseLike<never>
749
+ ): void {
750
+ if (done) return;
751
+ if (resolvers.length > 0) {
752
+ (resolvers.shift() as (typeof resolvers)[0])(data);
753
+ } else {
754
+ values.push(data);
755
+ }
756
+ }
757
+
758
+ function push_error(error: unknown): void {
759
+ push(thenable_reject(error));
760
+ close();
761
+ }
762
+
763
+ function push_event(event: GradioEvent): void {
764
+ push({ value: event, done: false });
765
+ }
766
+
767
+ function next(): Promise<IteratorResult<GradioEvent, unknown>> {
768
+ if (values.length > 0)
769
+ return Promise.resolve(values.shift() as (typeof values)[0]);
770
+ if (done) return Promise.resolve({ value: undefined, done: true });
771
+ return new Promise((resolve) => resolvers.push(resolve));
772
+ }
773
+
774
+ const iterator = {
775
+ [Symbol.asyncIterator]: () => iterator,
776
+ next,
777
+ throw: async (value: unknown) => {
778
+ push_error(value);
779
+ return next();
780
+ },
781
+ return: async () => {
782
+ close();
783
+ return next();
784
+ },
785
+ cancel
786
+ };
787
+
788
+ return iterator;
705
789
  } catch (error) {
706
790
  console.error("Submit function encountered an error:", error);
707
791
  throw error;
708
792
  }
709
793
  }
710
794
 
795
+ function thenable_reject<T>(error: T): PromiseLike<never> {
796
+ return {
797
+ then: (
798
+ resolve: (value: never) => PromiseLike<never>,
799
+ reject: (error: T) => PromiseLike<never>
800
+ ) => reject(error)
801
+ };
802
+ }
803
+
711
804
  function get_endpoint_info(
712
805
  api_info: ApiInfo<JsApiData>,
713
806
  endpoint: string | number,
@@ -27,7 +27,7 @@ export async function upload_files(
27
27
  });
28
28
  try {
29
29
  const upload_url = upload_id
30
- ? `${root_url}/upload?upload_id=${upload_id}`
30
+ ? `${root_url}/${UPLOAD_URL}?upload_id=${upload_id}`
31
31
  : `${root_url}/${UPLOAD_URL}`;
32
32
 
33
33
  response = await this.fetch(upload_url, {
package/vite.config.js CHANGED
@@ -3,30 +3,43 @@ import { svelte } from "@sveltejs/vite-plugin-svelte";
3
3
 
4
4
  const TEST_MODE = process.env.TEST_MODE || "happy-dom";
5
5
 
6
- export default defineConfig({
7
- build: {
8
- lib: {
9
- entry: "src/index.ts",
10
- formats: ["es"],
11
- fileName: (format) => `index.${format}.js`
12
- },
13
- rollupOptions: {
14
- input: "src/index.ts",
15
- output: {
16
- dir: "dist"
6
+ export default defineConfig(({ mode }) => {
7
+ if (mode === "preview") {
8
+ return {
9
+ entry: "index.html"
10
+ };
11
+ }
12
+ return {
13
+ build: {
14
+ lib: {
15
+ entry: "src/index.ts",
16
+ formats: ["es"],
17
+ fileName: (format) => `index.${format}.js`
18
+ },
19
+ rollupOptions: {
20
+ input: "src/index.ts",
21
+ output: {
22
+ dir: "dist"
23
+ }
17
24
  }
18
- }
19
- },
20
- plugins: [svelte()],
25
+ },
26
+ plugins: [svelte()],
21
27
 
22
- mode: process.env.MODE || "development",
23
- test: {
24
- include: ["./src/test/*.test.*"],
25
- environment: TEST_MODE
26
- },
27
- ssr: {
28
- target: "node",
29
- format: "esm",
30
- noExternal: ["ws", "semiver", "bufferutil", "@gradio/upload"]
31
- }
28
+ mode: process.env.MODE || "development",
29
+ test: {
30
+ include: ["./src/test/*.test.*"],
31
+ environment: TEST_MODE
32
+ },
33
+ ssr: {
34
+ target: "node",
35
+ format: "esm",
36
+ noExternal: [
37
+ "ws",
38
+ "semiver",
39
+ "bufferutil",
40
+ "@gradio/upload",
41
+ "fetch-event-stream"
42
+ ]
43
+ }
44
+ };
32
45
  });