@gradio/client 0.16.0 → 0.18.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 (84) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/README.md +49 -43
  3. package/dist/client.d.ts +63 -70
  4. package/dist/client.d.ts.map +1 -1
  5. package/dist/constants.d.ts +23 -0
  6. package/dist/constants.d.ts.map +1 -0
  7. package/dist/helpers/api_info.d.ts +25 -0
  8. package/dist/helpers/api_info.d.ts.map +1 -0
  9. package/dist/helpers/data.d.ts +8 -0
  10. package/dist/helpers/data.d.ts.map +1 -0
  11. package/dist/{utils.d.ts → helpers/init_helpers.d.ts} +6 -18
  12. package/dist/helpers/init_helpers.d.ts.map +1 -0
  13. package/dist/helpers/spaces.d.ts +7 -0
  14. package/dist/helpers/spaces.d.ts.map +1 -0
  15. package/dist/index.d.ts +8 -4
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +1628 -1398
  18. package/dist/test/handlers.d.ts +3 -0
  19. package/dist/test/handlers.d.ts.map +1 -0
  20. package/dist/test/mock_eventsource.d.ts +2 -0
  21. package/dist/test/mock_eventsource.d.ts.map +1 -0
  22. package/dist/test/server.d.ts +2 -0
  23. package/dist/test/server.d.ts.map +1 -0
  24. package/dist/test/test_data.d.ts +76 -0
  25. package/dist/test/test_data.d.ts.map +1 -0
  26. package/dist/types.d.ts +153 -49
  27. package/dist/types.d.ts.map +1 -1
  28. package/dist/upload.d.ts +2 -2
  29. package/dist/upload.d.ts.map +1 -1
  30. package/dist/utils/duplicate.d.ts +4 -0
  31. package/dist/utils/duplicate.d.ts.map +1 -0
  32. package/dist/utils/handle_blob.d.ts +4 -0
  33. package/dist/utils/handle_blob.d.ts.map +1 -0
  34. package/dist/utils/post_data.d.ts +4 -0
  35. package/dist/utils/post_data.d.ts.map +1 -0
  36. package/dist/utils/predict.d.ts +4 -0
  37. package/dist/utils/predict.d.ts.map +1 -0
  38. package/dist/utils/stream.d.ts +8 -0
  39. package/dist/utils/stream.d.ts.map +1 -0
  40. package/dist/utils/submit.d.ts +4 -0
  41. package/dist/utils/submit.d.ts.map +1 -0
  42. package/dist/utils/upload_files.d.ts +4 -0
  43. package/dist/utils/upload_files.d.ts.map +1 -0
  44. package/dist/utils/view_api.d.ts +3 -0
  45. package/dist/utils/view_api.d.ts.map +1 -0
  46. package/dist/{wrapper-6f348d45.js → wrapper-CviSselG.js} +259 -17
  47. package/package.json +10 -3
  48. package/src/client.ts +314 -1691
  49. package/src/constants.ts +27 -0
  50. package/src/globals.d.ts +2 -21
  51. package/src/helpers/api_info.ts +300 -0
  52. package/src/helpers/data.ts +133 -0
  53. package/src/helpers/init_helpers.ts +130 -0
  54. package/src/helpers/spaces.ts +197 -0
  55. package/src/index.ts +16 -10
  56. package/src/test/api_info.test.ts +456 -0
  57. package/src/test/data.test.ts +281 -0
  58. package/src/test/handlers.ts +438 -0
  59. package/src/test/init.test.ts +139 -0
  60. package/src/test/init_helpers.test.ts +94 -0
  61. package/src/test/mock_eventsource.ts +11 -0
  62. package/src/test/post_data.test.ts +45 -0
  63. package/src/test/server.ts +6 -0
  64. package/src/test/spaces.test.ts +145 -0
  65. package/src/test/stream.test.ts +67 -0
  66. package/src/test/test_data.ts +557 -0
  67. package/src/test/upload_files.test.ts +42 -0
  68. package/src/test/view_api.test.ts +53 -0
  69. package/src/types.ts +201 -59
  70. package/src/upload.ts +19 -15
  71. package/src/utils/duplicate.ts +104 -0
  72. package/src/utils/handle_blob.ts +47 -0
  73. package/src/utils/post_data.ts +37 -0
  74. package/src/utils/predict.ts +56 -0
  75. package/src/utils/stream.ts +175 -0
  76. package/src/utils/submit.ts +697 -0
  77. package/src/utils/upload_files.ts +51 -0
  78. package/src/utils/view_api.ts +67 -0
  79. package/src/vite-env.d.ts +1 -0
  80. package/tsconfig.json +15 -2
  81. package/vite.config.js +11 -17
  82. package/dist/utils.d.ts.map +0 -1
  83. package/src/client.node-test.ts +0 -172
  84. package/src/utils.ts +0 -314
@@ -0,0 +1,697 @@
1
+ /* eslint-disable complexity */
2
+ import type {
3
+ Status,
4
+ Payload,
5
+ EventType,
6
+ ListenerMap,
7
+ SubmitReturn,
8
+ EventListener,
9
+ Event,
10
+ JsApiData,
11
+ EndpointInfo,
12
+ ApiInfo,
13
+ Config,
14
+ Dependency
15
+ } from "../types";
16
+
17
+ import { skip_queue, post_message } from "../helpers/data";
18
+ import { resolve_root } from "../helpers/init_helpers";
19
+ import { handle_message, process_endpoint } from "../helpers/api_info";
20
+ import { BROKEN_CONNECTION_MSG, QUEUE_FULL_MSG } from "../constants";
21
+ import { apply_diff_stream, close_stream } from "./stream";
22
+ import { Client } from "../client";
23
+
24
+ export function submit(
25
+ this: Client,
26
+ endpoint: string | number,
27
+ data: unknown[],
28
+ event_data?: unknown,
29
+ trigger_id?: number | null
30
+ ): SubmitReturn {
31
+ try {
32
+ const { hf_token } = this.options;
33
+ const {
34
+ fetch,
35
+ app_reference,
36
+ config,
37
+ session_hash,
38
+ api_info,
39
+ api_map,
40
+ stream_status,
41
+ pending_stream_messages,
42
+ pending_diff_streams,
43
+ event_callbacks,
44
+ unclosed_events,
45
+ post_data
46
+ } = this;
47
+
48
+ if (!api_info) throw new Error("No API found");
49
+ if (!config) throw new Error("Could not resolve app config");
50
+
51
+ let { fn_index, endpoint_info, dependency } = get_endpoint_info(
52
+ api_info,
53
+ endpoint,
54
+ api_map,
55
+ config
56
+ );
57
+
58
+ let websocket: WebSocket;
59
+ let stream: EventSource | null;
60
+ let protocol = config.protocol ?? "ws";
61
+
62
+ const _endpoint = typeof endpoint === "number" ? "/predict" : endpoint;
63
+ let payload: Payload;
64
+ let event_id: string | null = null;
65
+ let complete: Status | undefined | false = false;
66
+ const listener_map: ListenerMap<EventType> = {};
67
+ let last_status: Record<string, Status["stage"]> = {};
68
+ let url_params =
69
+ typeof window !== "undefined"
70
+ ? new URLSearchParams(window.location.search).toString()
71
+ : "";
72
+
73
+ // event subscription methods
74
+ function fire_event<K extends EventType>(event: Event<K>): void {
75
+ const narrowed_listener_map: ListenerMap<K> = listener_map;
76
+ const listeners = narrowed_listener_map[event.type] || [];
77
+ listeners?.forEach((l) => l(event));
78
+ }
79
+
80
+ function on<K extends EventType>(
81
+ eventType: K,
82
+ listener: EventListener<K>
83
+ ): SubmitReturn {
84
+ const narrowed_listener_map: ListenerMap<K> = listener_map;
85
+ const listeners = narrowed_listener_map[eventType] || [];
86
+ narrowed_listener_map[eventType] = listeners;
87
+ listeners?.push(listener);
88
+
89
+ return { on, off, cancel, destroy };
90
+ }
91
+
92
+ function off<K extends EventType>(
93
+ eventType: K,
94
+ listener: EventListener<K>
95
+ ): SubmitReturn {
96
+ const narrowed_listener_map: ListenerMap<K> = listener_map;
97
+ let listeners = narrowed_listener_map[eventType] || [];
98
+ listeners = listeners?.filter((l) => l !== listener);
99
+ narrowed_listener_map[eventType] = listeners;
100
+ return { on, off, cancel, destroy };
101
+ }
102
+
103
+ async function cancel(): Promise<void> {
104
+ const _status: Status = {
105
+ stage: "complete",
106
+ queue: false,
107
+ time: new Date()
108
+ };
109
+ complete = _status;
110
+ fire_event({
111
+ ..._status,
112
+ type: "status",
113
+ endpoint: _endpoint,
114
+ fn_index: fn_index
115
+ });
116
+
117
+ let cancel_request = {};
118
+ if (protocol === "ws") {
119
+ if (websocket && websocket.readyState === 0) {
120
+ websocket.addEventListener("open", () => {
121
+ websocket.close();
122
+ });
123
+ } else {
124
+ websocket.close();
125
+ }
126
+ cancel_request = { fn_index, session_hash };
127
+ } else {
128
+ stream?.close();
129
+ cancel_request = { event_id };
130
+ }
131
+
132
+ try {
133
+ if (!config) {
134
+ throw new Error("Could not resolve app config");
135
+ }
136
+
137
+ await fetch(`${config.root}/reset`, {
138
+ headers: { "Content-Type": "application/json" },
139
+ method: "POST",
140
+ body: JSON.stringify(cancel_request)
141
+ });
142
+ } catch (e) {
143
+ console.warn(
144
+ "The `/reset` endpoint could not be called. Subsequent endpoint results may be unreliable."
145
+ );
146
+ }
147
+ }
148
+
149
+ function destroy(): void {
150
+ for (const event_type in listener_map) {
151
+ listener_map &&
152
+ listener_map[event_type as "data" | "status"]?.forEach((fn) => {
153
+ off(event_type as "data" | "status", fn);
154
+ });
155
+ }
156
+ }
157
+
158
+ this.handle_blob(config.root, data, endpoint_info).then(
159
+ async (_payload) => {
160
+ payload = {
161
+ data: _payload || [],
162
+ event_data,
163
+ fn_index,
164
+ trigger_id
165
+ };
166
+ if (skip_queue(fn_index, config)) {
167
+ fire_event({
168
+ type: "status",
169
+ endpoint: _endpoint,
170
+ stage: "pending",
171
+ queue: false,
172
+ fn_index,
173
+ time: new Date()
174
+ });
175
+
176
+ post_data(
177
+ `${config.root}/run${
178
+ _endpoint.startsWith("/") ? _endpoint : `/${_endpoint}`
179
+ }${url_params ? "?" + url_params : ""}`,
180
+ {
181
+ ...payload,
182
+ session_hash
183
+ }
184
+ )
185
+ .then(([output, status_code]: any) => {
186
+ const data = output.data;
187
+ if (status_code == 200) {
188
+ fire_event({
189
+ type: "data",
190
+ endpoint: _endpoint,
191
+ fn_index,
192
+ data: data,
193
+ time: new Date(),
194
+ event_data,
195
+ trigger_id
196
+ });
197
+
198
+ fire_event({
199
+ type: "status",
200
+ endpoint: _endpoint,
201
+ fn_index,
202
+ stage: "complete",
203
+ eta: output.average_duration,
204
+ queue: false,
205
+ time: new Date()
206
+ });
207
+ } else {
208
+ fire_event({
209
+ type: "status",
210
+ stage: "error",
211
+ endpoint: _endpoint,
212
+ fn_index,
213
+ message: output.error,
214
+ queue: false,
215
+ time: new Date()
216
+ });
217
+ }
218
+ })
219
+ .catch((e) => {
220
+ fire_event({
221
+ type: "status",
222
+ stage: "error",
223
+ message: e.message,
224
+ endpoint: _endpoint,
225
+ fn_index,
226
+ queue: false,
227
+ time: new Date()
228
+ });
229
+ });
230
+ } else if (protocol == "ws") {
231
+ const { ws_protocol, host } = await process_endpoint(
232
+ app_reference,
233
+ hf_token
234
+ );
235
+
236
+ fire_event({
237
+ type: "status",
238
+ stage: "pending",
239
+ queue: true,
240
+ endpoint: _endpoint,
241
+ fn_index,
242
+ time: new Date()
243
+ });
244
+
245
+ let url = new URL(
246
+ `${ws_protocol}://${resolve_root(
247
+ host,
248
+ config.path as string,
249
+ true
250
+ )}/queue/join${url_params ? "?" + url_params : ""}`
251
+ );
252
+
253
+ if (this.jwt) {
254
+ url.searchParams.set("__sign", this.jwt);
255
+ }
256
+
257
+ websocket = new WebSocket(url);
258
+
259
+ websocket.onclose = (evt) => {
260
+ if (!evt.wasClean) {
261
+ fire_event({
262
+ type: "status",
263
+ stage: "error",
264
+ broken: true,
265
+ message: BROKEN_CONNECTION_MSG,
266
+ queue: true,
267
+ endpoint: _endpoint,
268
+ fn_index,
269
+ time: new Date()
270
+ });
271
+ }
272
+ };
273
+
274
+ websocket.onmessage = function (event) {
275
+ const _data = JSON.parse(event.data);
276
+ const { type, status, data } = handle_message(
277
+ _data,
278
+ last_status[fn_index]
279
+ );
280
+
281
+ if (type === "update" && status && !complete) {
282
+ // call 'status' listeners
283
+ fire_event({
284
+ type: "status",
285
+ endpoint: _endpoint,
286
+ fn_index,
287
+ time: new Date(),
288
+ ...status
289
+ });
290
+ if (status.stage === "error") {
291
+ websocket.close();
292
+ }
293
+ } else if (type === "hash") {
294
+ websocket.send(JSON.stringify({ fn_index, session_hash }));
295
+ return;
296
+ } else if (type === "data") {
297
+ websocket.send(JSON.stringify({ ...payload, session_hash }));
298
+ } else if (type === "complete") {
299
+ complete = status;
300
+ } else if (type === "log") {
301
+ fire_event({
302
+ type: "log",
303
+ log: data.log,
304
+ level: data.level,
305
+ endpoint: _endpoint,
306
+ fn_index
307
+ });
308
+ } else if (type === "generating") {
309
+ fire_event({
310
+ type: "status",
311
+ time: new Date(),
312
+ ...status,
313
+ stage: status?.stage!,
314
+ queue: true,
315
+ endpoint: _endpoint,
316
+ fn_index
317
+ });
318
+ }
319
+ if (data) {
320
+ fire_event({
321
+ type: "data",
322
+ time: new Date(),
323
+ data: data.data,
324
+ endpoint: _endpoint,
325
+ fn_index,
326
+ event_data,
327
+ trigger_id
328
+ });
329
+
330
+ if (complete) {
331
+ fire_event({
332
+ type: "status",
333
+ time: new Date(),
334
+ ...complete,
335
+ stage: status?.stage!,
336
+ queue: true,
337
+ endpoint: _endpoint,
338
+ fn_index
339
+ });
340
+ websocket.close();
341
+ }
342
+ }
343
+ };
344
+
345
+ // different ws contract for gradio versions older than 3.6.0
346
+ //@ts-ignore
347
+ if (semiver(config.version || "2.0.0", "3.6") < 0) {
348
+ addEventListener("open", () =>
349
+ websocket.send(JSON.stringify({ hash: session_hash }))
350
+ );
351
+ }
352
+ } else if (protocol == "sse") {
353
+ fire_event({
354
+ type: "status",
355
+ stage: "pending",
356
+ queue: true,
357
+ endpoint: _endpoint,
358
+ fn_index,
359
+ time: new Date()
360
+ });
361
+ var params = new URLSearchParams({
362
+ fn_index: fn_index.toString(),
363
+ session_hash: session_hash
364
+ }).toString();
365
+ let url = new URL(
366
+ `${config.root}/queue/join?${
367
+ url_params ? url_params + "&" : ""
368
+ }${params}`
369
+ );
370
+
371
+ if (this.jwt) {
372
+ url.searchParams.set("__sign", this.jwt);
373
+ }
374
+
375
+ stream = this.stream_factory(url);
376
+
377
+ if (!stream) {
378
+ return Promise.reject(
379
+ new Error("Cannot connect to SSE endpoint: " + url.toString())
380
+ );
381
+ }
382
+
383
+ stream.onmessage = async function (event: MessageEvent) {
384
+ const _data = JSON.parse(event.data);
385
+ const { type, status, data } = handle_message(
386
+ _data,
387
+ last_status[fn_index]
388
+ );
389
+
390
+ if (type === "update" && status && !complete) {
391
+ // call 'status' listeners
392
+ fire_event({
393
+ type: "status",
394
+ endpoint: _endpoint,
395
+ fn_index,
396
+ time: new Date(),
397
+ ...status
398
+ });
399
+ if (status.stage === "error") {
400
+ stream?.close();
401
+ }
402
+ } else if (type === "data") {
403
+ event_id = _data.event_id as string;
404
+ let [_, status] = await post_data(`${config.root}/queue/data`, {
405
+ ...payload,
406
+ session_hash,
407
+ event_id
408
+ });
409
+ if (status !== 200) {
410
+ fire_event({
411
+ type: "status",
412
+ stage: "error",
413
+ message: BROKEN_CONNECTION_MSG,
414
+ queue: true,
415
+ endpoint: _endpoint,
416
+ fn_index,
417
+ time: new Date()
418
+ });
419
+ stream?.close();
420
+ }
421
+ } else if (type === "complete") {
422
+ complete = status;
423
+ } else if (type === "log") {
424
+ fire_event({
425
+ type: "log",
426
+ log: data.log,
427
+ level: data.level,
428
+ endpoint: _endpoint,
429
+ fn_index
430
+ });
431
+ } else if (type === "generating") {
432
+ fire_event({
433
+ type: "status",
434
+ time: new Date(),
435
+ ...status,
436
+ stage: status?.stage!,
437
+ queue: true,
438
+ endpoint: _endpoint,
439
+ fn_index
440
+ });
441
+ }
442
+ if (data) {
443
+ fire_event({
444
+ type: "data",
445
+ time: new Date(),
446
+ data: data.data,
447
+ endpoint: _endpoint,
448
+ fn_index,
449
+ event_data,
450
+ trigger_id
451
+ });
452
+
453
+ if (complete) {
454
+ fire_event({
455
+ type: "status",
456
+ time: new Date(),
457
+ ...complete,
458
+ stage: status?.stage!,
459
+ queue: true,
460
+ endpoint: _endpoint,
461
+ fn_index
462
+ });
463
+ stream?.close();
464
+ }
465
+ }
466
+ };
467
+ } else if (
468
+ protocol == "sse_v1" ||
469
+ protocol == "sse_v2" ||
470
+ protocol == "sse_v2.1" ||
471
+ protocol == "sse_v3"
472
+ ) {
473
+ // latest API format. v2 introduces sending diffs for intermediate outputs in generative functions, which makes payloads lighter.
474
+ // v3 only closes the stream when the backend sends the close stream message.
475
+ fire_event({
476
+ type: "status",
477
+ stage: "pending",
478
+ queue: true,
479
+ endpoint: _endpoint,
480
+ fn_index,
481
+ time: new Date()
482
+ });
483
+ let hostname = "";
484
+ if (typeof window !== "undefined") {
485
+ hostname = window?.location?.hostname;
486
+ }
487
+
488
+ let hfhubdev = "dev.spaces.huggingface.tech";
489
+ const origin = hostname.includes(".dev.")
490
+ ? `https://moon-${hostname.split(".")[1]}.${hfhubdev}`
491
+ : `https://huggingface.co`;
492
+ const zerogpu_auth_promise =
493
+ dependency.zerogpu && window.parent != window && config.space_id
494
+ ? post_message<Headers>("zerogpu-headers", origin)
495
+ : Promise.resolve(null);
496
+ const post_data_promise = zerogpu_auth_promise.then((headers) => {
497
+ return post_data(
498
+ `${config.root}/queue/join?${url_params}`,
499
+ {
500
+ ...payload,
501
+ session_hash
502
+ },
503
+ headers
504
+ );
505
+ });
506
+ post_data_promise.then(([response, status]: any) => {
507
+ if (status === 503) {
508
+ fire_event({
509
+ type: "status",
510
+ stage: "error",
511
+ message: QUEUE_FULL_MSG,
512
+ queue: true,
513
+ endpoint: _endpoint,
514
+ fn_index,
515
+ time: new Date()
516
+ });
517
+ } else if (status !== 200) {
518
+ fire_event({
519
+ type: "status",
520
+ stage: "error",
521
+ message: BROKEN_CONNECTION_MSG,
522
+ queue: true,
523
+ endpoint: _endpoint,
524
+ fn_index,
525
+ time: new Date()
526
+ });
527
+ } else {
528
+ event_id = response.event_id as string;
529
+ let callback = async function (_data: object): Promise<void> {
530
+ try {
531
+ const { type, status, data } = handle_message(
532
+ _data,
533
+ last_status[fn_index]
534
+ );
535
+
536
+ if (type == "heartbeat") {
537
+ return;
538
+ }
539
+
540
+ if (type === "update" && status && !complete) {
541
+ // call 'status' listeners
542
+ fire_event({
543
+ type: "status",
544
+ endpoint: _endpoint,
545
+ fn_index,
546
+ time: new Date(),
547
+ ...status
548
+ });
549
+ } else if (type === "complete") {
550
+ complete = status;
551
+ } else if (type == "unexpected_error") {
552
+ console.error("Unexpected error", status?.message);
553
+ fire_event({
554
+ type: "status",
555
+ stage: "error",
556
+ message:
557
+ status?.message || "An Unexpected Error Occurred!",
558
+ queue: true,
559
+ endpoint: _endpoint,
560
+ fn_index,
561
+ time: new Date()
562
+ });
563
+ } else if (type === "log") {
564
+ fire_event({
565
+ type: "log",
566
+ log: data.log,
567
+ level: data.level,
568
+ endpoint: _endpoint,
569
+ fn_index
570
+ });
571
+ return;
572
+ } else if (type === "generating") {
573
+ fire_event({
574
+ type: "status",
575
+ time: new Date(),
576
+ ...status,
577
+ stage: status?.stage!,
578
+ queue: true,
579
+ endpoint: _endpoint,
580
+ fn_index
581
+ });
582
+ if (
583
+ data &&
584
+ ["sse_v2", "sse_v2.1", "sse_v3"].includes(protocol)
585
+ ) {
586
+ apply_diff_stream(pending_diff_streams, event_id!, data);
587
+ }
588
+ }
589
+ if (data) {
590
+ fire_event({
591
+ type: "data",
592
+ time: new Date(),
593
+ data: data.data,
594
+ endpoint: _endpoint,
595
+ fn_index
596
+ });
597
+
598
+ if (complete) {
599
+ fire_event({
600
+ type: "status",
601
+ time: new Date(),
602
+ ...complete,
603
+ stage: status?.stage!,
604
+ queue: true,
605
+ endpoint: _endpoint,
606
+ fn_index
607
+ });
608
+ }
609
+ }
610
+
611
+ if (
612
+ status?.stage === "complete" ||
613
+ status?.stage === "error"
614
+ ) {
615
+ if (event_callbacks[event_id!]) {
616
+ delete event_callbacks[event_id!];
617
+ }
618
+ if (event_id! in pending_diff_streams) {
619
+ delete pending_diff_streams[event_id!];
620
+ }
621
+ }
622
+ } catch (e) {
623
+ console.error("Unexpected client exception", e);
624
+ fire_event({
625
+ type: "status",
626
+ stage: "error",
627
+ message: "An Unexpected Error Occurred!",
628
+ queue: true,
629
+ endpoint: _endpoint,
630
+ fn_index,
631
+ time: new Date()
632
+ });
633
+ if (["sse_v2", "sse_v2.1"].includes(protocol)) {
634
+ close_stream(stream_status, stream);
635
+ stream_status.open = false;
636
+ }
637
+ }
638
+ };
639
+
640
+ if (event_id in pending_stream_messages) {
641
+ pending_stream_messages[event_id].forEach((msg) =>
642
+ callback(msg)
643
+ );
644
+ delete pending_stream_messages[event_id];
645
+ }
646
+ // @ts-ignore
647
+ event_callbacks[event_id] = callback;
648
+ unclosed_events.add(event_id);
649
+ if (!stream_status.open) {
650
+ this.open_stream();
651
+ }
652
+ }
653
+ });
654
+ }
655
+ }
656
+ );
657
+
658
+ return { on, off, cancel, destroy };
659
+ } catch (error) {
660
+ console.error("Submit function encountered an error:", error);
661
+ throw error;
662
+ }
663
+ }
664
+
665
+ function get_endpoint_info(
666
+ api_info: ApiInfo<JsApiData>,
667
+ endpoint: string | number,
668
+ api_map: Record<string, number>,
669
+ config: Config
670
+ ): {
671
+ fn_index: number;
672
+ endpoint_info: EndpointInfo<JsApiData>;
673
+ dependency: Dependency;
674
+ } {
675
+ let fn_index: number;
676
+ let endpoint_info: EndpointInfo<JsApiData>;
677
+ let dependency: Dependency;
678
+
679
+ if (typeof endpoint === "number") {
680
+ fn_index = endpoint;
681
+ endpoint_info = api_info.unnamed_endpoints[fn_index];
682
+ dependency = config.dependencies[endpoint];
683
+ } else {
684
+ const trimmed_endpoint = endpoint.replace(/^\//, "");
685
+
686
+ fn_index = api_map[trimmed_endpoint];
687
+ endpoint_info = api_info.named_endpoints[endpoint.trim()];
688
+ dependency = config.dependencies[api_map[trimmed_endpoint]];
689
+ }
690
+
691
+ if (typeof fn_index !== "number") {
692
+ throw new Error(
693
+ "There is no endpoint matching that name of fn_index matching that number."
694
+ );
695
+ }
696
+ return { fn_index, endpoint_info, dependency };
697
+ }