From 00025643c87882e70d451ec8ca7c8ab5144af0e7 Mon Sep 17 00:00:00 2001 From: Mishieck Date: Wed, 29 Oct 2025 21:31:57 +0200 Subject: [PATCH 1/3] feat(bridge): add types for extensions - Make `WebuiBridge` generic so that it takes types for extensions. - Apply the types to `WebuiBridge.call` method. --- bridge/webui.ts | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/bridge/webui.ts b/bridge/webui.ts index 1993f809c..66b9e967d 100644 --- a/bridge/webui.ts +++ b/bridge/webui.ts @@ -19,7 +19,23 @@ import { AsyncFunction, addRefreshableEventListener } from './utils.ts'; type DataTypes = string | number | boolean | Uint8Array; -class WebuiBridge { +/** The signature of a WebUI callback. */ +export type CallbackSignature = { + /** The arguments of a callback. */ + args: Array; + + /** The return value of a callback. */ + output: DataTypes | void; +}; + +/** Extensions of WebuiBridge. */ +export type Extensions = { + /** Callbacks that are callable from the frontend. */ + callbacks: Record; + // More entries maybe +}; + +class WebuiBridge { // WebUI Settings #secure: boolean; #token: number; @@ -920,7 +936,10 @@ class WebuiBridge { * @return - Response of the backend callback string * @example - const res = await webui.call("myID", 123, true, "Hi", new Uint8Array([0x42, 0x43, 0x44])) */ - async call(fn: string, ...args: DataTypes[]): Promise { + async call( + fn: K, + ...args: Ext["callbacks"][K]["args"] + ): Promise { if (!fn) return Promise.reject(new SyntaxError('No binding name is provided')); if (!this.#wsIsConnected()) return Promise.reject(new Error('WebSocket is not connected')); From 0f2d88d35a7160c6255cbd49b5ebff7e17a3c2fb Mon Sep 17 00:00:00 2001 From: Mishieck Date: Tue, 4 Nov 2025 05:55:05 +0200 Subject: [PATCH 2/3] feat(bridge): add a callback utility type --- bridge/webui.ts | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/bridge/webui.ts b/bridge/webui.ts index 66b9e967d..bacd61ff4 100644 --- a/bridge/webui.ts +++ b/bridge/webui.ts @@ -17,21 +17,23 @@ //@ts-ignore use *.ts import real extension import { AsyncFunction, addRefreshableEventListener } from './utils.ts'; -type DataTypes = string | number | boolean | Uint8Array; +export type DataTypes = string | number | boolean | Uint8Array; +export type Params = Array; +export type Output = DataTypes | void; -/** The signature of a WebUI callback. */ -export type CallbackSignature = { - /** The arguments of a callback. */ - args: Array; +/** Attributes of a user defined bridge callback. */ +export type Callback

= { + /** The parameters of the callback. */ + parameters: P; - /** The return value of a callback. */ - output: DataTypes | void; + /** The return value of the callback. */ + output: O; }; /** Extensions of WebuiBridge. */ export type Extensions = { /** Callbacks that are callable from the frontend. */ - callbacks: Record; + callbacks: Record; // More entries maybe }; @@ -938,7 +940,7 @@ class WebuiBridge { */ async call( fn: K, - ...args: Ext["callbacks"][K]["args"] + ...args: Ext["callbacks"][K]["parameters"] ): Promise { if (!fn) return Promise.reject(new SyntaxError('No binding name is provided')); From e2fd0abe053c39750f921d2946bba99fad953843 Mon Sep 17 00:00:00 2001 From: Mishieck Date: Fri, 7 Nov 2025 06:16:48 +0200 Subject: [PATCH 3/3] feat(bridge): add utility type for extending WebuiBridge --- bridge/webui.ts | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/bridge/webui.ts b/bridge/webui.ts index bacd61ff4..15e01ce72 100644 --- a/bridge/webui.ts +++ b/bridge/webui.ts @@ -21,8 +21,11 @@ export type DataTypes = string | number | boolean | Uint8Array; export type Params = Array; export type Output = DataTypes | void; -/** Attributes of a user defined bridge callback. */ -export type Callback

= { +/** Attributes of a user-defined bridge callback. */ +export type CallbackAttributes< + P extends Params = Params, + O extends Output = Output +> = { /** The parameters of the callback. */ parameters: P; @@ -30,13 +33,27 @@ export type Callback

= { output: O; }; +/** A user-defined bridge callback. */ +export type Callback< + Attributes extends CallbackAttributes = CallbackAttributes +> = (...params: Attributes['parameters']) => Promise; + /** Extensions of WebuiBridge. */ export type Extensions = { /** Callbacks that are callable from the frontend. */ - callbacks: Record; + callbacks: Record; // More entries maybe }; +/** Converts extensions to an interface that can be added to `WebuiBridge`. */ +export type ExtensionsToInterface = { + [Name in keyof Ext['callbacks']]: Callback; +}; + +/** Adds extensions to `WebuiBridge`. */ +export type WithExtensions = WebuiBridge & + ExtensionsToInterface; + class WebuiBridge { // WebUI Settings #secure: boolean; @@ -938,10 +955,10 @@ class WebuiBridge { * @return - Response of the backend callback string * @example - const res = await webui.call("myID", 123, true, "Hi", new Uint8Array([0x42, 0x43, 0x44])) */ - async call( + async call( fn: K, - ...args: Ext["callbacks"][K]["parameters"] - ): Promise { + ...args: Ext['callbacks'][K]['parameters'] + ): Promise { if (!fn) return Promise.reject(new SyntaxError('No binding name is provided')); if (!this.#wsIsConnected()) return Promise.reject(new Error('WebSocket is not connected'));