Skip to content

Conversation

@Mishieck
Copy link

@Mishieck Mishieck commented Nov 9, 2025

I added the ability to extend the WebuiBridge with extension types. I added support for callback extensions. So, when callbacks have been bound on the backend, the types for those callbacks can be reflected on the frontend. The types can be added to the global scope using the following code:

import type { CallbackAttributes, WithExtensions } from "path/to/webui.ts";

declare global {
  export const webui: WithExtensions<{ callbacks: Callbacks }>;
}

type Callbacks = {
  init: CallbackAttributes<[], void>;
  dbGetOne: CallbackAttributes<[id: string], Uint8Array>;
  exit: CallbackAttributes<[], void>;
};

When any one of the callbacks is called, the name, arguments, and return value will be type-checked. The following code snippet shows valid function calls:

webui.call("dbGetOne", "item-id"); // Returns Promise<Uint8Array>
// or 
webui.dbGet0ne("item-id");

It would be helpful to publish the bridge as its own package on NPM or JSR so that it can be used easily on the frontend. This way, one could import it using a path like @webui-dev/bridge instead of writing a long path to the module.

- Make `WebuiBridge` generic so that it takes types for extensions.
- Apply the types to `WebuiBridge.call` method.
@AlbertShown
Copy link
Member

When any one of the callbacks is called, the name, arguments, and return value will be type-checked.

Thank you for the PR, but I still confused a bit, what do you mean exactly? Can you give a full complete example of use?

It would be helpful to publish the bridge as its own package on NPM or JSR

No, it's not possible due to two main reasons, one is that webui.js is generated by WebUI core differently according to user's callbacks, random tokens, random IDs etc..., The second reason is that WebUI is a desktop app, so it may be used in an offline PC.

@AlbertShown
Copy link
Member

AlbertShown commented Nov 10, 2025

Right now, you can do:

dbGetOne("item-id").then((response) => {
    // ...
});

Or

const response = await dbGetOne("item-id");

@Mishieck
Copy link
Author

Thank you for your response. An example of how to use this is Deno WebUI Todo Vanilla. In the provided repo, the bridge was copied to ./src/client/bridge and the types were used in ./src/client/global.d.ts.

The PR is meant to provide type checking for applications that use TypeScript for the frontend. Such applications compile to JavaScript before being used in the browser. Since the bridge is only used for types, none of the bridge code used for this purpose will be present in the final code. If the user used @webui-dev/bridge to import the types, it still will not matter because the package @webui-dev/bridge will be a dev dependency and will be completely removed in the desktop app.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants